#!/usr/bin/env python3 """Read the project's own Python code objects out of a PyInstaller 6 onefile exe (CArchive -> entry scripts + PYZ archive). Run with Python 3.12 (same bytecode version as the exes). Usage: exe_modules.py APP.exe (prints the names)""" import sys, struct, zlib, marshal MAGIC = b"MEI\014\013\012\013\016"; CK = "!8sIIII64s"; CKL = struct.calcsize(CK); TE = "!IIIIBc"; TEL = struct.calcsize(TE) def carchive(b): end = b.rfind(MAGIC); _, pkg_len, toc_off, toc_len, _, _ = struct.unpack(CK, b[end:end + CKL]); start = end + CKL - pkg_len toc = []; p = start + toc_off while p < start + toc_off + toc_len: el, doff, dlen, ulen, cf, tc = struct.unpack(TE, b[p:p + TEL]); name = b[p + TEL:p + el].rstrip(b"\0").decode() data = b[start + doff:start + doff + dlen]; toc.append((name, tc, zlib.decompress(data) if cf else data)); p += el return toc def own_code(path): """returns {name: code object} for entry scripts (type 's') and PYZ modules starting with eddycoin""" out = {} for name, tc, data in carchive(open(path, "rb").read()): if tc == b"s" and not name.startswith("pyi"): out["script:" + name] = marshal.loads(data) if tc == b"z": off = struct.unpack("!i", data[8:12])[0]; toc = marshal.loads(data[off:]) for mn, (typ, pos, ln) in (toc if isinstance(toc, list) else toc.items()): if mn.startswith("eddycoin"): out["module:" + mn] = marshal.loads(zlib.decompress(data[pos:pos + ln])) return out if __name__ == "__main__": for k, c in own_code(sys.argv[1]).items(): print(k, c.co_filename)