Skip to content

Instantly share code, notes, and snippets.

@4577
Created July 11, 2016 16:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 4577/0aa92c0d77d6f87768e1ce78250ea815 to your computer and use it in GitHub Desktop.
Save 4577/0aa92c0d77d6f87768e1ce78250ea815 to your computer and use it in GitHub Desktop.
#!/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