Created
July 11, 2016 16:30
-
-
Save 4577/0aa92c0d77d6f87768e1ce78250ea815 to your computer and use it in GitHub Desktop.
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/python3 | |
#-*- encoding: Utf-8 -*- | |
from re import sub, match | |
from struct import pack | |
from urllib.request import Request, urlopen | |
# From objdump output, reconstruct a basic ELF file with symbols suitable for IDA. | |
level = 1 | |
api_key = 'YOU API KEY HERE' | |
# ELF reference: | |
# https://en.wikipedia.org/wiki/Executable_and_Linkable_Format | |
# https://docs.oracle.com/cd/E19683-01/817-3677/6mj8mbtc9/index.html | |
symbols = [] | |
code = b'' | |
url = 'https://www.stockfighter.io/trainer/resource/level_%d.od' % level | |
auth = {'X-Starfighter-Authorization': api_key} | |
with urlopen(Request(url, headers=auth)) as fd: | |
for line in fd: | |
symbol = match(b'([0-9a-f]+) <(.+)>:', line) | |
if symbol: | |
symbols.append((int(symbol.group(1), 16), | |
symbol.group(2))) | |
inst = match(b' *([0-9a-f]+):\t([0-9a-f ]+)', line) | |
if inst: | |
code += b'\x00' * (int(inst.group(1), 16) - len(code)) | |
code += bytes.fromhex(inst.group(2).decode('ascii')) | |
secnames = b'.text\0.symtab\0.strtab\0' | |
strtab = b'\0' + b'\0'.join(i[1] for i in symbols) + secnames | |
# Loading symbols: determine whether we look at a function or only a routine | |
afterAFunc = False | |
symtab = pack('<3I2BH', 0, 0, 0, 0, 0, 0) | |
for i, (addr, name) in enumerate(symbols): | |
end = symbols[i + 1][0] if i + 1 < len(symbols) else len(code) | |
endsWithRet = (code[end - 2:end] == b'\x08\x95' # RET | |
or code[end - 4:end - 2] == b'\x0C\x94') # JMP | |
symtab += pack('<3I2BH', strtab.index(name), addr, 0, | |
1 + (afterAFunc and endsWithRet), 0, 1) | |
afterAFunc = endsWithRet | |
# Double the number of bytes in the segment, otherwise IDA will ignore | |
# symbols located after the first half of it. | |
code += b'\0' * len(code) | |
shdr = pack('<10I', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | |
shdr += pack('<10I', strtab.index(b'.text\0'), 1, 2 | 4, 0, 52 + 32, len(code), 0, 0, 0, 0) | |
shdr += pack('<10I', strtab.index(b'.symtab\0'), 2, 0, 0, 52 + 32 + len(code) + 160, len(symtab), 3, len(symbols) + 1, 0, 16) | |
shdr += pack('<10I', strtab.index(b'.strtab\0'), 3, 32, 0, 52 + 32 + len(code) + 160 + len(symtab), len(strtab), 0, 0, 0, 0) | |
# Load one segment; the code from objdump only, from right after the file+program header | |
phdr = pack('<8I', 1, 52 + 32, 0, 0, len(code), len(code), 0, 0) | |
ehdr = pack('<4s4B8x2H5I6H', b'\x7fELF', 1, 1, 1, 0, 2, 83, 1, 0xf2, 52, 52 + 32 + len(code), 5, 52, 32, 1, 40, 4, 3) | |
with open('level_%d.elf' % level, 'wb') as fd: | |
fd.write(ehdr + phdr + code + shdr + symtab + strtab) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment