[Litctf 2024] ezPython!!!

今天见到一道python打包成exe文件的逆向题,虽然很简单,但是安装工具遇到了一些麻烦

将.exe文件反编译为pyc文件

.pyinstxtractor.py工具安装地址:https://sourceforge.net/projects/pyinstallerextractor/

先将pyinstxtractor.py工具与我们要反编译的.exe文件放入同一个工作目录下,在终端输入python pyinstxtractor.py 文件名.py

😕因为python版本问题,imp模块无法安装,需要替换为importlibc,(pip install importlib)但是又提示importlibc没有get_magic方法,需要替换为importlib.util.MAGIC_NUMBER,又又提示module ‘importlib’ has no attribute ‘util’,于是写上from importlib.util import find_spec 成功

发现工作目录下多了一个名为文件名.exe_extracted的文件夹,进入该文件夹,里面有许许多多后缀为.dll.pyd的文件,还有一个名为PYZ-00.pyz_extracted的文件夹,这个文件夹里放的是程序引入的依赖库

找到与exe文件同名的文件和struct文件,手动添加.pyc,用010editor打开,文件是没有Magic Number的,需要手动添加

结果

根据上面可以看出程序的py版本,根据版本填充magic number

Python3.3 以下版本: 只有Magic Number和四位时间戳
Python3.3(包含) - Python3.7(不包含)版本: 4个字节的magic num + 8个字节的时间戳,这个时间戳可以全是0。
Python3.7(包含)版本: 4个字节的magic num + 4个字节的空白数据 + 4个字节的时间戳 + 4个字节的文件长度,除了magic num,其它数据可以全是0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
enum PycMagic {
# 小端序,要倒过来写
MAGIC_1_0 = 0x00999902,
MAGIC_1_1 = 0x00999903, /* Also covers 1.2 */
MAGIC_1_3 = 0x0A0D2E89,
MAGIC_1_4 = 0x0A0D1704,
MAGIC_1_5 = 0x0A0D4E99,
MAGIC_1_6 = 0x0A0DC4FC,

MAGIC_2_0 = 0x0A0DC687,
MAGIC_2_1 = 0x0A0DEB2A,
MAGIC_2_2 = 0x0A0DED2D,
MAGIC_2_3 = 0x0A0DF23B,
MAGIC_2_4 = 0x0A0DF26D,
MAGIC_2_5 = 0x0A0DF2B3,
MAGIC_2_6 = 0x0A0DF2D1,
MAGIC_2_7 = 0x0A0DF303,

MAGIC_3_0 = 0x0A0D0C3A,
MAGIC_3_1 = 0x0A0D0C4E,
MAGIC_3_2 = 0x0A0D0C6C,
MAGIC_3_3 = 0x0A0D0C9E,
MAGIC_3_4 = 0x0A0D0CEE,
MAGIC_3_5 = 0x0A0D0D16,
MAGIC_3_5_3 = 0x0A0D0D17,
MAGIC_3_6 = 0x0A0D0D33,
MAGIC_3_7 = 0x0A0D0D42,
MAGIC_3_8 = 0x0A0D0D55,
MAGIC_3_9 = 0x0A0D0D61,
MAGIC_3_10 = 0x0A0D0D6F,
MAGIC_3_11 = 0x0A0D0DA7,
MAGIC_3_12 = 0x0A0D0DCB,

INVALID = 0,
};

pyc文件转py源码

uncompyle6 现仅适用于 Python 2.4 到 3.8 版本

安装:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple uncompyle6==3.9.0

uncompyle6 -o 文件名.py 文件名.pyc

😕但是这道题要用到的是pycdc,安装包:git clone https://github.com/zrax/pycdc.git ,不过下载的是源码,需要用cmake编译,在生成的build文件夹中找到pycdc.exe

将pyc文件与pacdc.exe放在同一目录,终端.\pycdc.exe 文件名.pyc

得到源码:

jieguo

好像是base64编码,但是引用的是自己编写的模块,应该是换表了

🤔上面我们说PYZ-00.pyz_extracted的文件夹里放的是程序引入的依赖库,果然找到了Litctfbase64.pyc,尝试用pycdc还原,但是提示CreateObject: Got unsupported type 0x0
Error loading file Litctfbase64.pyc: bad cast

😖没找到解决办法

用010editor查看16进制:

jieguo

😮突然发现这个文件是带magic number的,直接复制就行了

有一串可疑的字符串,可能是映射表,不过不知道从哪里开始

然后打开一个pyc在线反编译的网站,得到了字符串:

jieguo

直接base64解码就好了

py是如何转换成exe的呢

pyinstaller打包

首先安装加密打包程序所使用的库tinyaes,这里用了清华源并且指定使用了1.0.3版本库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tinyaes==1.0.3

移动到脚本文件夹下:pyinstaller -F 测试脚本.py –key 123456

加密后结果只有入口脚本反编译成功,被依赖的脚本均被加密,无法直接被反编译