今天整理电脑时发现了一个由python生成的exe文件,打开后疯狂弹窗,不禁产生想要将其反编译的想法

image-20230111201608758

首先需要使用pyinstxtractor.py文件将其从exe反编译pyc文件,在cmd中输入

1
python pyinstxtractor.py Game_001.exe

运行截图如下

image-20230111201909475

生成了一个文件夹

image-20230111201946858

内部文件如下,大多是dll和pyd文件,PYZ-00.pyz_extracted文件夹,里面为引入的依赖库。我们接下来需要的是Game_001文件和struct文件

image-20230111202922134

用记事本打开可以发现大部分字符为乱码,不过也能从中获取到一部分信息,我们从中看见了B站网页和tkinter的踪迹

image-20230111202139075

经过对比Game_001struct两个文件可以发现,Game_001缺少了第一行的16个字节,这16个字节表示这python编译的版本和时间信息,我们需要在Game_001中将这16个字节补上,并且加上后缀pyc,由此得到Game_001.pyc文件。

一般python文件的魔法头如下

python 2.7 - 03 F3 0D 0A

python 3.6 - 33 0D 0D 0A

python 3.7 - 42 0D 0D 0A

python 3.8 - 55 0D 0D 0A

python 3.9+ - 61 0D 0D 0A

image-20230111202649512

image-20230111202705075

使用uncompyle6反编译发现失败

image-20230111205515841

使用pycdc反编译发现成功了

首先在github中下载pycdc源码zrax/pycdc: C++ python bytecode disassembler and decompiler (github.com),之后使用vscode cmake构建

image-20230112172841289

cmake构建成功后会在./build下生成pycdc.exe文件

image-20230112172944704

在命令行中输入pycdc.exe Game_001.pyc > Game_001.py即可得到编译后的源码

image-20230112173255219

或者使用在线反编译工具python反编译 - 在线工具 (tool.lu)(该工具由pycdc构建),发现成功了

image-20230111221503926

得到的代码如下

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
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9

import tkinter.messagebox as tkinter
import webbrowser
import os
from threading import Thread
from multiprocessing import Process

def work_01():
for i in range(10):
webbrowser.open('https://www.bilibili.com/video/BV1Cx411z73B?from=search&seid=1469035168910513716')


def work_02():
for i in range(30):
tkinter.messagebox.showerror('Giao!', 'Error!!!Giao!Giao!Giao!')


def Multi_thread(M_work):
thread_list = []
for i in range(os.cpu_count()):
program = Thread(M_work, **('target',))
thread_list.append(program)
program.start()
for program in thread_list:
program.join()


def Multi_process(M_work):
thread_list = []
for i in range(os.cpu_count()):
program = Process(M_work, **('target',))
thread_list.append(program)
program.start()
for program in thread_list:
program.join()

if __name__ == '__main__':
print('本机CPU为:', os.cpu_count(), '核')
tkinter.messagebox.showerror('警告!', '将耳机插入体验更佳!')
Multi_thread(work_01)
Multi_process(work_02)