Python逆向
- 可以参考 这篇博客
- 常见类型
- pyc 文件是 python 在编译过程中出现的主要中间过程文件。pyc 文件是二进制的,类似 java 的字节码,可以由 python 虚拟机直接执行的。
pyc结构体
- pyc文件结构主要包括两部分:pyc文件头部表示和PyCodeObject对象部分。上面对PyCodeObject对象的二进制部分已经有了了解,pyc文件头部比较简单,在python2中只占用4个字节包含两个字段magic和mtime,完整的pyc文件结构见下图
typedef struct {
PyObject_HEAD
int co_argcount; /* 位置参数个数 */
int co_nlocals; /* 局部变量个数 */
int co_stacksize; /* 栈大小 */
int co_flags;
PyObject *co_code; /* 字节码指令序列 */
PyObject *co_consts; /* 所有常量集合 */
PyObject *co_names; /* 所有符号名称集合 */
PyObject *co_varnames; /* 局部变量名称集合 */
PyObject *co_freevars; /* 闭包用的的变量名集合 */
PyObject *co_cellvars; /* 内部嵌套函数引用的变量名集合 */
/* The rest doesn’t count for hash/cmp */
PyObject *co_filename; /* 代码所在文件名 */
PyObject *co_name; /* 模块名|函数名|类名 */
int co_firstlineno; /* 代码块在文件中的起始行号 */
PyObject *co_lnotab; /* 字节码指令和行号的对应关系 */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
} PyCodeObject;
- opcode.h文件,其中存储着所有opcode以及其对应的值,通过010 editor搜索确定花指令的位置
- 去花后正确修改co_code的值
import dis
import marshal
f=open("xxx.pyc","rb")
b_data=f.read()
f.close()
PyCodeObjectData=b_data[16:]
code=marshal.loads(PyCodeObjectData)
print(len(code.co_code))
直接给一个pyc文件
- uncompyle6.exe xxx.pyc 但是uncompyle6只支持到py3.8
- 更高版本的python反编译用pycdc,这里给个 安装教程
给了个txt里面是pyc字节码
import dis
import marshal
f=open("xxx.pyc","rb")
b_data=f.read()
f.close()
PyCodeObjectData=b_data[16:]
Pyobj=marshal.loads(PyCodeObjectData)
dis.dis(Pyobj)
不同的 Python 版本会有不同的 PyObject_HEAD,相应的上面的python脚本也要进行对应的处理,以下是各版本的文件头: Python 版本 十六进制文件头 Python 2.7 03f30d0a00000000 Python 3.0 3b0c0d0a00000000 Python 3.1 4f0c0d0a00000000 Python 3.2 6c0c0d0a00000000 Python 3.3 9e0c0d0a0000000000000000 Python 3.4 ee0c0d0a0000000000000000 Python 3.5 170d0d0a0000000000000000 Python 3.6 330d0d0a0000000000000000 Python 3.7 420d0d0a000000000000000000000000 Python 3.8 550d0d0a000000000000000000000000 Python 3.9 610d0d0a000000000000000000000000 Python 3.10 6f0d0d0a000000000000000000000000 Python 3.11 a70d0d0a000000000000000000000000
- 得到类似汇编的东西后只能手动逆向了, python字节码的含义
打包成exe的py文件类
- 通过脚本 pyinstxtractor.py 变成结构体+一个文件,把时间属性和版本的魔术字放回去保存
- 有一些pyc需要修补一下文件头,可以和struct.pyc一起拖入010中对比一下