PythonUncompyle6反编译⼯具使⽤与MagicNumber详解
Python Uncompyle6 反编译⼯具使⽤与 Magic Number 详解
最近在i春秋刷MISC题的时候,做到了好⼏道有pyc⽂件需要反编译的题,也了解到了⼀个⾮常神的Python反编译⼯具
——Python Uncompyle6。虽然只⽤到了其中的⼀个功能,但它留给我的印象却⼗分友善。通过命令⾏调⽤,较为⽅便;⽀持Python 编译器版本丰富,⼏乎涵盖了所有版本;最主要的优点是:不会卡Bug。(与Pycdc相⽐友善很多~~(可能只是我技术⽐较
菜)~~)。
另外,在部分题⽬中,使⽤pyinstaller导出的pyc⽂件会将⽂件的Magic Number和时间戳信息抹去,反编译时⼯具会报错,我们需要⼿动添加Magic Number与时间戳,时间戳可以随便添加(全0也可以),但是每个版本Python编译的pyc⽂件Magic Number 都不同,需要我们⼿动查找与填充,下⾯将介绍⼀个⽅便获取Magic Number的⽅法(⽹上有关Magic Number对照的信息太少了)
Uncompyle6 介绍
Uncompyle6,是⼀个Python原⽣的跨版本反编译器,是decompyle, uncompyle, uncompyle2的后继版本。
Uncompyle6能够将Python⼆进制⽂件pyc, pyo反编译为对应的源代码。⽀持Python 1.0-3.8版本的反编译,拥有较好的逻辑处理和解析能⼒。
Uncompyle6 安装与使⽤
安装不⽤多说,上pip完事
pip install uncompyle6
使⽤也⾮常简单,在命令⾏中,uncompyle6加上需要反编译的⽂件参数即可,注意使⽤-o 选项输出到⽂件中
uncompyle6 -o test.py test.pyc
下班表情包这会将test.pyc⽂件反编译,并输出到test.py⽂件中
注:如果遇到错误,可能因为pyc⽂件⽣成时,头部的magic number被清理,需要另外补上,请看下⼀节内容
Magic Number in Python
⼀开始,因为不知道版本号对应的Magic Number,我以前将⼀些版本的Python环境下载,再编译,逐个对照,现在想来,笨办法实锤。
Magic Number
通过⼀个开源的Python虚拟机解包⼯具Pyinstxtractor的源码中关于Magic Number的内容,似乎找到了⼀点头绪。
Magic Number的⽣成和其他操作,似乎在importlib库中的util⽂件中,查看⼀下util⽂件
发现⼜是从.bootstrap_external中引⽤的,再跳⼀次
作文400字⼀些Magic Number的介绍注释
Magic Number 已知列表,在⽂末附上
接下来就算找到了Magic Number的版本对照表。但是,我们知道的Magic Number是四字节⼆进制数据,应该如何转换?再往下找,在注释后⾯的代码⾥,我们找到了样例
MAGIC_NUMBER =(3413).to_bytes(2,'little')+b'\r\n'
_RAW_MAGIC_NUMBER =int.from_bytes(MAGIC_NUMBER,'little')# For import.c
这⾥的3413就是Python 3.8b4版本的Magic Number,执⾏⼀下,就得到了四字节的⼆进制码0x0A0D0D55。其他版本的对应⼆进制码,可以按照上⾯步骤计算得到。
注意:四字节的Magic Number为⼩端序,注意区分
Pyc⽂件修复
我们已经得到了Magic Number 的⼆进制码,下⾯就可以修复pyc⽂件了
再次⽤到pyinstxtractor源码,找到输出pyc⽂件部分
在Python3.7及以上版本的编译后⼆进制⽂件中,头部除了四字节Magic Number,还有四个字节的空位和⼋个字节的时间戳+⼤⼩信息,后者对⽂件反编译没有影响,全部填充0即可;
Python3.3 - Python3.7(包含3.3)版本中,只需要Magic Number和⼋位时间戳+⼤⼩信息
Python3.3 以下的版本中,只有Magic Number和四位时间戳
⽤Winhex修复⽂件,在头部写⼊(⾮覆盖)上述格式的内容,就可以进⾏反编译了
附录 Magic Number 对照表
Known values:
# Python 1.5: 20121
如何养虾# Python 1.5.1: 20121
# Python 1.5.2: 20121
# Python 1.6: 50428
# Python 2.0: 50823
# Python 2.0.1: 50823
# Python 2.1: 60202
# Python 2.1.1: 60202
# Python 2.1.2: 60202
# Python 2.2: 60717
# Python 2.3a0: 62011
# Python 2.3a0: 62021
# Python 2.3a0: 62011 (!)
# Python 2.4a0: 62041
# Python 2.4a3: 62051
# Python 2.4b1: 62061
# Python 2.5a0: 62071
# Python 2.5a0: 62081 (ast-branch)
# Python 2.5a0: 62091 (with)
左顾右盼类似的成语# Python 2.5a0: 62092 (changed WITH_CLEANUP opcode)
# Python 2.5b3: 62101 (fix wrong code: for x, in ...)
# Python 2.5b3: 62111 (fix wrong code: x += yield)
# Python 2.5c1: 62121 (fix wrong lnotab with for loops and
# storing constants that should have been removed)
# Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp)
朝鲜跟韩国# Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode)
# Python 2.6a1: 62161 (WITH_CLEANUP optimization)
# Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND)
# Python 2.7a0: 62181 (optimize conditional branches:
# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE)
# Python 2.7a0 62191 (introduce SETUP_WITH)
# Python 2.7a0 62201 (introduce BUILD_SET)
# Python 2.7a0 62211 (introduce MAP_ADD and SET_ADD)
# Python 3000: 3000
# 3010 (removed UNARY_CONVERT)
# 3020 (added BUILD_SET)
# 3030 (added keyword-only parameters)
# 3040 (added signature annotations)
# 3050 (print becomes a function)
# 3060 (PEP 3115 metaclass syntax)
# 3061 (string literals become unicode)
# 3071 (PEP 3109 rai changes)
# 3081 (PEP 3137 make __file__ and __name__ unicode)
毕命
# 3091 (kill str8 interning)
# 3101 (merge from 2.6a0, e 62151)
# 3103 (__file__ points to source file)
# Python 3.0a4: 3111 (WITH_CLEANUP optimization).
# Python 3.0b1: 3131 (lexical exception stacking, including POP_EXCEPT
#3021)
# Python 3.1a1: 3141 (optimize list, t and dict comprehensions:
# change LIST_APPEND and SET_ADD, add MAP_ADD #2183)
# Python 3.1a1: 3151 (optimize conditional branches:
# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE
借条怎么写
#4715)
# Python 3.2a1: 3160 (add SETUP_WITH #6101)
# tag: cpython-32
# Python 3.2a2: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR #9225) # tag: cpython-32
# Python 3.2a3 3180 (add DELETE_DEREF #4617)
# Python 3.3a1 3190 (__class__ super closure changed)
# Python 3.3a1 3200 (PEP 3155 __qualname__ added #13448)
# Python 3.3a1 3210 (added size modulo 2**32 to the pyc header #13645)
# Python 3.3a2 3220 (changed PEP 380 implementation #14230)
# Python 3.3a4 3230 (revert changes to implicit __class__ closure #14857)
# Python 3.4a1 3250 (evaluate positional default arguments before
# keyword-only defaults #16967)
# Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override
# free vars #17853)
# Python 3.4a1 3270 (various tweaks to the __class__ closure #12370)
# Python 3.4a1 3280 (remove implicit class argument)
# Python 3.4a4 3290 (changes to __qualname__ computation #19301)
诺诺连声# Python 3.4a4 3300 (more changes to __qualname__ computation #19301)
# Python 3.4rc2 3310 (alter __qualname__ computation #20625)
# Python 3.5a1 3320 (PEP 465: Matrix multiplication operator #21176)
# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations #2292)
# Python 3.5b2 3340 (fix dictionary display evaluation order #11205)
# Python 3.5b3 3350 (add GET_YIELD_FROM_ITER opcode #24400)
# Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286)
# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483)
# Python 3.6a1 3361 (lineno delta _lnotab becomes signed #26107)
# Python 3.6a2 3370 (16 bit wordcode #26647)
# Python 3.6a2 3371 (add BUILD_CONST_KEY_MAP opcode #27140)
# Python 3.6a2 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE
# #27095)
# Python 3.6b1 3373 (add BUILD_STRING opcode #27078)
# Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes # #27985)
# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL #27213)
# Python 3.6b1 3377 (t __class__ cell from type.__new__ #23722)
# Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257)
# Python 3.6rc1 3379 (more thorough __class__ validation #23722)
# Python 3.7a1 3390 (add LOAD_METHOD and CALL_METHOD opcodes #26110)
# Python 3.7a2 3391 (update GET_AITER #31709)
# Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650)
# Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550)
# Python 3.7b5 3394 (restored docstring as the first stmt in the body;
# this might affected the first line number #32911)
# Python 3.8a1 3400 (move frame block handling to compiler #17611)
# Python 3.8a1 3401 (add END_ASYNC_FOR #33041)
# Python 3.8a1 3410 (PEP570 Python Positional-Only Parameters #36540)
# Python 3.8b2 3411 (Rever evaluation order of key: value in dict
# comprehensions #35224)
# Python 3.8b2 3412 (Swap the position of positional args and positional # only args in ast.arguments #37593)
# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830)