1.二进制搜索12 34 56 78,往后偏移8字节后开始的4字节是code_bytes长度,之后是库文件名,以00结尾,之后就是code_bytes。

si = struct.pack("iiii",
    0x78563412, # a magic value,
    self.optimize,
    self.unbuffered,
    len(code_bytes),
) + relative_arcname + "\000"
script_bytes = si + code_bytes + '\000\000'

2.把code_bytes拿出来,在python中反序列化后找到需要code obj的再序列化。code obj可能嵌套code obj,用inspect.getmembers(code_obj)去找到list中的code obj位置,再dump出来。

>>>import marshal
>>>mylist=marshal.load(open("dumpfile", "r"))
>>>marshal.dump(mylist[1], open("main.pyo","w"))

3.pyo文件加上8字节header就可以反编译了。前 4 个字节代表 Python 版本号,后 4 个字节是 timestamp。文件头可以是:03 F3 0D 0A 37 77 83 56 。