Python Reverse Engineering
Hands-on reversing with Python: ELF/PE parsing, strings/imports/entropy, disassembly, Frida, and Python bytecode (.pyc / PyInstaller). Language idioms belong in python-patterns.
When to activate
- Mapping why an ELF/PE fails, what malware does, or how a stripped binary is laid out.
- Extracting strings, imports, entropy regions, entrypoints, section flags.
- Instrumenting runtime with Frida (host Python, hooks in GumJS).
- Recovering logic from
.pyc,__pycache__, or a PyInstaller/py2exe-style bundle. - Diffing two binary versions (hardening, packing, payload change).
Core principles
- Triage before disassembly: strings, imports, entropy, then hotspots.
- Match interpreter to bytecode:
marshal/disonly on the same CPython version as the.pyc; otherwisexdis/pydisasm. - Do not execute recovered code on the analysis host;
disis read-only,execis not. - Frida injects GumJS, not Python. Host API:
attach/spawn/create_script. - Entropy flags packing: high-entropy blobs are compressed/encrypted until proven otherwise.
Outcome expectations
- File type, arch, and layout (sections, entry, imports) are known.
- Suspicious APIs and high-entropy regions are listed with offsets.
.pycpayloads are disassembled with a version-matched tool; decompile is opportunistic.- Frida hooks attach (or spawn) without using removed Frida 16 static
Module.*APIs.
Recommended workflow
- Triage: ELF / PE / Mach-O /
.pyc/ PyInstaller overlay. Packed Python →references/pyc-bytecode.mdfirst. - Headers: parse ELF/PE (or LIEF when you will rewrite). Load
references/binary-formats.md. - Sections / imports / strings / entropy:
references/static-analysis.md,references/pwntools-reference.md. - Disassemble hotspots:
references/capstone.md(Capstone) orELF.disasm(returns a string). - Runtime: Frida when static is insufficient —
references/frida-basics.md. Spawn if the interesting path is before a stable attach. - Custom scripts: IAT dump, entropy map, section diff —
references/custom-tooling.md.
Pyarmor, custom opcode maps, and Nuitka-as-native: keep the Python-API path here; load reversing-technique languages.md for those packer-specific recoveries.
Quick review checklist
- Magic/arch parsed; file offsets vs VAs are not mixed.
- Imports enumerated; ordinal-only PE imports are not assumed to have names.
- Strings and entropy scanned before wide disassembly.
.pycmagic matches the interpreter (orpydisasmwas used).- Frida scripts use
Process.getModuleByName/Module.getGlobalExportByName(Frida 17+).
Anti-patterns
- Blind Capstone over the whole file (alignment, data-in-code, packing).
marshal.loadsof a.pycincluding the 16-byte header, or on the wrong Python version.- Treating
uncompyle6as valid past 3.8, orpycdcas guaranteed on 3.13–3.14. Module.findExportByName/ staticModule.getExportByName(removed in Frida 17).Interceptor.replacewithonEnter/onLeave(that isattach; replace takes aNativeCallback).
Resources
Load on demand:
references/binary-formats.md— load when parsing or patching ELF/PE/Mach-O headers and sectionsreferences/pwntools-reference.md— load when usingELF,search,read,disasm,context.binaryreferences/static-analysis.md— load for strings, imports, entropy, suspicious APIsreferences/capstone.md— load when decoding instructions or scanning gadgetsreferences/frida-basics.md— load when attaching/spawning and hooking (Frida 17+ JS API)references/pyc-bytecode.md— load for.pyc,marshal/dis, xdis, PyInstaller unpackreferences/custom-tooling.md— load when writing a reusable IAT/entropy/diff script