Created
September 11, 2024 06:07
-
-
Save prozacchiwawa/cd7b3d4cd9a4721868337cef9ecf0f93 to your computer and use it in GitHub Desktop.
Make an elf file that pretends to have specific functions at specific addresses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from elftools.elf.elffile import ELFFile | |
from pathlib import Path | |
import struct | |
import subprocess | |
# Steps | |
# | |
# 0) Read definitions with addresses | |
# 1) Write C source for all of our definitions | |
# 2) Compile C source to object file | |
# 3) Open elf object file | |
# 4) Set type to ET_EXEC | |
# 5) Iterate names from definitions: | |
# 6) Find symbol | |
# 7) Set st_value and st_shndx according to definitions. | |
# 8) Write! | |
# | |
# { "fff00100": { "name": ..., "info": ..., "decl": "int test_proto(void *x, int y)" }, | |
# "StructDef": "struct StructDef { ... }" | |
# } | |
def isxdigit(s): | |
return all(map(lambda x: x in '0123456789abcdefABCDEF', s)) | |
def create_elf(outelf, outc, address, json): | |
c_text = [] | |
by_name = {} | |
top_address = None | |
for key, value in json.items(): | |
if not isxdigit(key): | |
c_text.append(value) | |
c_text.append(';\n') | |
for key, value in json.items(): | |
if isxdigit(key): | |
addr = int(key, 16) | |
if top_address is None or top_address < addr: | |
top_address = addr + 4 | |
by_name[value['name']] = addr | |
# Is an address with a definition | |
if 'decl' in value: | |
# Has a declaration | |
c_text.append(value['decl']) | |
c_text.append(' { }\n') | |
else: | |
c_text.append(f'void *{value["name"]}()') | |
c_text.append(';\n') | |
with open(outc, 'w') as c_file: | |
for s in c_text: | |
c_file.write(s) | |
# Compile to object file | |
out = subprocess.check_output(['powerpc-linux-gnu-gcc','-c','-g','-gdwarf',outc]) | |
p = Path(outc) | |
outo = p.with_suffix('.o') | |
patches = [] | |
symtab_section_id = None | |
text_section_id = None | |
# Read the elf file | |
with ELFFile(open(outo,'rb')) as elf: | |
for i in range(elf.num_sections()): | |
ts = elf.get_section(i) | |
if ts.name == '.text': | |
text_section_id = i | |
symtab = elf.get_section_by_name('.symtab') | |
symtab_offset = symtab.header.sh_offset | |
symtab_entsize = symtab.header.sh_entsize | |
for i in range(symtab.num_symbols()): | |
sym = symtab.get_symbol(i) | |
if sym.name in by_name: | |
symaddr = by_name[sym.name] | |
patches.append({"offset":symtab_offset + (i * symtab_entsize), "shndx": text_section_id, "value":symaddr - address}) | |
with open(outo,'rb+') as elf: | |
elf_header_bytes = elf.read(52) | |
elf_header = struct.unpack( | |
'>16sHHIIIIIHHHHHH', elf_header_bytes | |
) | |
(e_ident, e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx) = elf_header | |
offset_of_text_section_entry = e_shoff + (text_section_id * e_shentsize) | |
# Write ET_EXEC | |
elf.seek(16) | |
elf.write(struct.pack('>H', 2)) | |
# Change section size and type for .text | |
elf.seek(offset_of_text_section_entry + 4) | |
elf.write(struct.pack('>I', 8)) | |
elf.seek(offset_of_text_section_entry + 20) | |
elf.write(struct.pack('>I', top_address - address)) | |
# For each patch in patches, write it out | |
for p in patches: | |
elf.seek(p['offset'] + 4) | |
elf.write(struct.pack('>I', p['value'])) | |
elf.seek(p['offset'] + 8) | |
elf.write(struct.pack('>I', 4)) | |
elf.seek(p['offset'] + 14) | |
elf.write(struct.pack('>H', p['shndx'])) | |
if __name__ == '__main__': | |
import sys | |
import json | |
import argparse | |
parser = argparse.ArgumentParser() | |
parser.add_argument('address') | |
parser.add_argument('json') | |
args = parser.parse_args() | |
p = Path(args.json) | |
outelf = p.with_suffix('.elf') | |
outc = p.with_suffix('.c') | |
create_elf(outelf, outc, int(args.address, 16), json.load(open(args.json))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment