逆python--pyc文件结构及pyc混淆基础

本文探讨了Python的pyc文件产生原理,详细分析了PyCodeObject结构,包括其二进制文件结构。此外,文章还介绍了如何通过反编译工具和dis模块对pyc文件进行解题和混淆,特别是利用JUMP指令进行代码混淆以逃避反编译。最后,文章提到了Python源码保护方法和进一步研究的方向。
摘要由CSDN通过智能技术生成

复现创客re-pyc题,理解python编译原理

pyc文件产生

  1. Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。;
  2. Python是解释型语言,没有严格意义上的编译和汇编过程。但是一般编写好的.py源文件,由python解释器翻译成以.pyc为结尾的字节码文件,该文件可由python虚拟机直接运行;
    3.pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的;
  3. 根据python源码中提供的opcode,可以根据pyc文件反编译出py文件源码;
  4. 加载模块时,如果同时存在.py和.pyc,Python会尝试使用.pyc,如果.pyc的编译时间早于.py的修改时间,则重新编译.py并更新.pyc;

PyCodeObject结构

Python代码的编译结果就是PyCodeObject对象。PyCodeObject对象可以由虚拟机加载后直接运行,而pyc文件就是PyCodeObject对象在硬盘上的保存形式。

PyCodeObject对象一般包含的属性名称及数据类型如下,每个属性在虚拟机执行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;

python中使用marshal.dump的方法将PyCodeObject对象转化为对应的二进制文件结构。PyCodeObject对象中的每一个属性及值都会按照一定的顺序表示在二进制文件里。

PyCodeObject每个字段在二进制文件中的结构如图1:
PyCodeObject每个字段在二进制文件中的结构

byte表示占用1个字节,long表示占用4个字节,bytes表示该字段可能占用1到多个字节。

pyc文件结构主要包括两部分:pyc文件头部表示和PyCodeObject对象部分。上述即PyCodeObject对象的二进制部分,pyc文件头部较简单,在python2中只占用4个字节包含两个字段magic和mtime,完整的pyc文件结构见图2:
完整的pyc文件结构

python提供内置的类库实现把py文件编译为pyc文件, py_compile 模块。
```javascript
# -*- coding: cp936 -*-
#python 27
 
#办法一:IDLE(实现见图3)
import py_compile #加r前缀进行转义
py_compile.compile(r'D:\test.py') #py文件完整的路径.
 
办法二:#cmd命令符下操作步骤
1、打开cmd,切换到 cd c:\\python34
2、运行
     1)python -m py_compile D:\test.py   #跟随完整路径
     2)python -m py_compile /root/src/{file1,file2}.py   #这是同时转换多个文件
3、会在需转译文件的目录下生成一个“__pycache__”目录/test.cpython-34.pyc文件
#-m 相当于脚本中的import,这里的-m py_compile 相当于上面的 import py_compile

解题

打开题目pyc文件,依照上述分析文件结构,找到PyCodeObjectData

>>> f = open('8.pyc','rb')
>>> b_data = f.read()
>>> PyCodeObjectData = b_data[8:]
>>> b_data
'\x03\xf3\r\n[9\xd6_c\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00@\x00\x00\x00s)\x00\x00\x00q\x06\x00d\x90\x00d\x00\x00\x84\x00\x00Z\x00\x00e\x01\x00d\x01\x00k\x02\x00r\x1f\x00e\x00\x00\x83\x00\x00\x01n\x00\x00d\x02\x00S(\x03\x00\x00\x00c\x00\x00\x00\x00\x04\x00\x00\x00+\x00\x00\x00C\x00\x00\x00sD\x01\x00\x00t\x00\x00d\x01\x00\x83\x01\x00}\x00\x00d\x02\x00g\x01\x00d\x03\x00\x14}\x01\x00d\x04\x00d\x05\x00d\x06\x00d\x07\x00d\x08\x00d\t\x00d\n\x00d\x0b\x00d\x0b\x00d\x0c\x00d\r\x00d\x0e\x00d\x0c\x00d\x0f\x00d\x10\x00d\x11\x00d\x0f\x00d\x12\x00d\r\x00d\x10\x00d\n\x00d\x0e\x00d\x13\x00d\x0e\x00d\x10\x00d\x13\x00d\r\x00d\x14\x00d\x0c\x00d\x10\x00d\x15\x00d\n\x00d\x12\x00d\x14\x00d\x11\x00d\x16\x00d\x17\x00d\x18\x00d\x14\x00d\x14\x00d\x17\x00d\x0b\x00d\x19\x00g+\x00}\x02\x00t\x01\x00|\x00\x00\x83\x01\x00d\x03\x00k\x03\x00r\xc1\x00d\x1a\x00GHt\x02\x00\x83\x00\x00\x01n\x00\x00xw\x00t\x03\x00t\x01\x00|\x00\x00\x83\x01\x00\x83\x01\x00D]c\x00}\x03\x00t\x04\x00|\x00\x00|\x03\x00\x19\x83\x01\x00d\x1b\x00A|\x01\x00|\x03\x00<|\x01\x00|\x03\x00\x19d\x1c\x00?|\x01\x00|\x03\x00\x19d\x1c\x00>Ad\x1d\x00@|\x01\x00|\x03\x00<|\x01\x00|\x03\x00\x19|\x02\x00|\x03\x00\x19k\x03\x00r\xd4\x00d\x1e\x00GHt\x02\x00\x83\x00\x00\x01q\xd4\x00q\xd4\x00Wd\x1f\x00GHd\x00\x00S( \x00\x00\x00Ns\x14\x00\x00\x00plz input your flag:i\x00\x00\x00\x00i+\x00\x00\x00i\x87\x00\x00\x00i\x97\x00\x00\x00i\x17\x00\x00\x00if\x00\x00\x00iG\x00\x00\x00i\x94\x00\x00\x00i`\x00\x00\x00iP\x00\x00\x00i \x00\x00\x00i\x10\x00\x00\x00i\x05\x00\x00\x00ie\x00\x00\x00i\xf1\x00\x00\x00i\xa0\x00\x00\x00ip\x00\x00\x00i\xb0\x00\x00\x00iE\x00\x00\x00i5\x00\x00\x00i\x15\x00\x00\x00iu\x00\x00\x00i0\x00\x00\x00i\xf4\x00\x00\x00t\x05\x00\x00\x00errori2\x00\x00\x00i\x04\x00\x00\x00i\xff\x00\x00\x00t\x05\x00\x00\x00wrongt\x04\x00\x00\x00true(\x05\x00\x00\x00t\t\x00\x00\x00raw_inputt\x03\x00\x00\x00lent\x04\x00\x00\x00exitt\x05\x00\x00\x00ranget\x03\x00\x00\x00ord(\x04\x00\x00\x00t\x01\x00\x00\x00at\x04\x00\x00\x00tempt\x06\x00\x00\x00resultt\x01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值