正常的pyc文件使用uncompyle6或者在线的反编译工具即可反编译出源代码,然而有些别人动力手脚的pyc却不能使用工具直接反编译,这里从动手脚开始,学习一下
- pyc文件的二进制描述(可参考KDr2.com)
1 03f3 0d0a 版本 2 76e2 d458 时间 3 63 block 4 0000 0000 argument 5 0000 0000 nlocals 6 0200 0000 栈空间 7 4000 0000 flags 8 73 类型 string 9 2300 0000 长度 35 bytes 10 64 00 00 LOAD_CONST 0 //从这里开始是具体的代码 11 84 00 00 MAKE_FUNCTION 0 12 5a 00 00 STORE_NAME 0 13 65 01 00 LOAD_NAME 1 14 64 01 00 LOAD_CONST 1 15 6b 02 00 COMPARE_OP 2 16 72 1f 00 POP_JUMP_IF_FALSE 17 65 00 00 LOAD_NAME 0 18 83 00 00 CALL_FUNCTION 0 19 01 POP_TOP 20 6e 00 00 JUMP_FORWARD 0 21 64 02 00 LOAD_CONST 2 22 53 RETURN_VALUE
其中目前我们比较关注的是长度,因为如果修改了其源代码,则长度必随之改变,因此这个数值也要随之修改
- 通过代码混淆实现的基本的代码保护
我们可以通过在程序的入口处添加一些指令,使其就不会影响程序的正常执行,但可以阻止反编译器反编译。这些指令可以是无指令跳转
0 JUMP_ABSOLUTE 6 [71 06 00]
在Python中对应的字节码为 0x71 0x03 0x00,因此也要将code_string的长度增加3个字节。另外,还有
0 LOAD_CONST [64 FF FF] 65535 (FAKE!)
第二条指令的意思是加载code object常量表的第65535项到栈顶。在上述.pyc中,常量表的长度为2,下标65535已超出常量表的范围,所以这是条非法指令。但由于
第一条绝对跳转的存在,第二条指令永远都不会被执行。通常的反汇编器如dis会尽全力列举有用的信息,但并不能理解实际执行的控制流,当反汇编器尝试反汇编第
二条指令时,会试着去读取code object常量表的第65535项并且抛出一个’tuple index out of range’的异常。
- 应对以上简单的代码混淆的策略
对于可执行的pyc,我们可以使用pycdump工具进行转储,可根据相应的提示,利用010 editor进行修改,然后再使用uncompyle6进行正常的反编译