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中引⽤的,再跳⼀次
⼀些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 raise changes)
#                    3081 (PEP 3137 make __file__ and __name__ unicode)
#                    3091 (kill str8 interning)
#                    3101 (merge from 2.6a0, see 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, set and dict comprehensions:python虚拟机
#                        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 (set __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 (Reverse 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)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。