66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
"""
|
|
RE (reverse engineering) skeleton — copy & fill. (p4-team style)
|
|
|
|
Common p4 patterns:
|
|
* Extract bytes from a .rodata / data dump (IDA "db 30h" lines) -> often just
|
|
RSA key material. See 'reversing_is_amazing': parse the bytes, RSA.importKey,
|
|
then decrypt the given ciphertext.
|
|
* Symbolic execution / path constraint solving with angr.
|
|
* Binary parsing / patching with lief; emulation with unicorn.
|
|
"""
|
|
import re
|
|
|
|
# ---- pattern A: RSA key from an IDA/Ghidra byte dump ----
|
|
def bytes_from_rodata(dump_text):
|
|
"""Parse lines like: .rodata:0000 db 30h, 82h, 2, 5Ch ; comment"""
|
|
out = []
|
|
for line in dump_text.splitlines():
|
|
m = re.search(r"\bdb\b\s+(.*)", line)
|
|
if not m:
|
|
continue
|
|
body = m.group(1).split(";")[0]
|
|
for tok in re.findall(r"([0-9a-fA-F]+)h?|(\d+)", body):
|
|
val = tok[0] or tok[1]
|
|
try:
|
|
out.append(int(val, 16) if (tok[0] and val.endswith("h")) or
|
|
(tok[0] and not val.isdigit()) else int(val))
|
|
except ValueError:
|
|
pass
|
|
return bytes(out)
|
|
|
|
|
|
def solve_rsa_from_dump(dump_text, ciphertext_int):
|
|
from Crypto.PublicKey import RSA
|
|
from Crypto.Util.number import long_to_bytes
|
|
data = bytes_from_rodata(dump_text)
|
|
key = RSA.importKey(bytearray(data))
|
|
return long_to_bytes(pow(ciphertext_int, key.e, key.n))
|
|
|
|
|
|
# ---- pattern B: angr symbolic execution (uncomment & adapt) ----
|
|
"""
|
|
import angr, claripy
|
|
def solve_with_angr(binary, find_addr, avoid_addr, input_len=20):
|
|
proj = angr.Project(binary, auto_load_libs=False)
|
|
sim = proj.factory.entry_state()
|
|
flag = sim.solver.BVS('flag', input_len*8)
|
|
for i in range(input_len):
|
|
sim.memory.store(sim.regs.rsp + i, flag.get_byte(i))
|
|
sim = proj.factory.simgr(sim)
|
|
sim.explore(find=find_addr, avoid=avoid_addr)
|
|
if sim.found:
|
|
return sim.found[0].solver.eval(flag, cast_to=bytes)
|
|
"""
|
|
|
|
# ---- pattern C: lief parse / patch ----
|
|
"""
|
|
import lief
|
|
def parse(binary):
|
|
f = lief.parse(binary)
|
|
for sym in f.symbols: print(sym.name, hex(sym.value))
|
|
"""
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise NotImplementedError("pick a pattern above and fill it in")
|