闲来无事,帮朋友逆向了一个使用Pyinstall打包的程序,记录一下踩到的坑
步骤
首先尝试直接使用pyinstxtractor.py
进行解包,但是遇到了一个错误
1 2
| [+] Processing .\***** [!] Error : Unsupported pyinstaller version or not a pyinstaller archive
|
在这个步骤上我卡了很久,最后在pyinstxtractor的GitHub wiki找到了信息。原来是在解包之前需要进行一步操作。Wiki原文
1
| objcopy --dump-section pydata=pydata.dump testfile.elf
|
执行这条命令之后产生pydata.dump
,再用pyinstxtractor.py
解包即可
出现以下提示表示解包成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [+] Processing .\pydata.dump [+] Pyinstaller version: 2.1+ [+] Python version: 38 [+] Length of package: 8097846 bytes [+] Found 57 files in CArchive [+] Beginning extraction...please standby [+] Possible entry point: pyiboot01_bootstrap.pyc [+] Possible entry point: pyi_rth_multiprocessing.pyc [+] Possible entry point: pyi_rth_certifi.pyc [+] Possible entry point: poolgui.pyc [+] Found 420 files in PYZ archive [+] Successfully extracted pyinstaller archive: .\pydata.dump
You can now use a python decompiler on the pyc files within the extracted directory
|
我们可以在解包后的文件夹内找到许多pyc文件。找到入口文件后输入以下代码即可反编译为py文件
1
| uncompyle6 .\xxx.pyc > .\xxx.py
|
其中,uncompyle6
是开源软件,可以使用pip安装。但是还未支持python3.9。如果是python3.9的pyc文件只能手动查阅字节码。
虽然uncompyle6
能够反编译python代码,但是很多情况下他是无法完全反编译出全部代码的,例如样本中的例子(部分信息已打码)
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| L. 378 1206 LOAD_GLOBAL socket 1208 LOAD_METHOD gethostname 1210 CALL_METHOD_0 0 '' 1212 STORE_FAST 'hostname'
L. 379 1214 LOAD_GLOBAL socket 1216 LOAD_METHOD gethostbyname 1218 LOAD_FAST 'hostname' 1220 CALL_METHOD_1 1 '' 1222 STORE_FAST 'local_host_ip'
L. 381 1224 BUILD_MAP_0 0 1226 STORE_FAST 'headers'
L. 383 1228 LOAD_GLOBAL str 1230 LOAD_GLOBAL sys_userAddress 1232 CALL_FUNCTION_1 1 ''
L. 384 1234 LOAD_GLOBAL str 1236 LOAD_FAST 'sys_totalPlotsNb' 1238 CALL_FUNCTION_1 1 ''
L. 385 1240 LOAD_GLOBAL str 1242 LOAD_FAST 'sys_poolPoints' 1244 CALL_FUNCTION_1 1 ''
L. 386 1246 LOAD_GLOBAL str 1248 LOAD_GLOBAL sys_softVersion 1250 CALL_FUNCTION_1 1 ''
L. 387 1252 LOAD_GLOBAL str 1254 LOAD_FAST 'local_host_ip' 1256 CALL_FUNCTION_1 1 ''
L. 388 1258 LOAD_GLOBAL str 1260 LOAD_FAST 'hostname' 1262 CALL_FUNCTION_1 1 ''
L. 389 1264 LOAD_GLOBAL str 1266 LOAD_FAST 'sys_trustScore' 1268 CALL_FUNCTION_1 1 ''
L. 390 1270 LOAD_GLOBAL str 1272 LOAD_FAST 'hash_uniquePlotsLibraryId' 1274 CALL_FUNCTION_1 1 ''
L. 382 1276 LOAD_CONST ('address', 'plots', 'points', 'version', 'local', 'hostname', 'trust', 'hash') 1278 BUILD_CONST_KEY_MAP_8 8 1280 STORE_FAST 'data'
L. 392 1282 LOAD_GLOBAL requests 1284 LOAD_ATTR post 1286 LOAD_STR '这里是一个URL' 1288 LOAD_FAST 'headers' 1290 LOAD_FAST 'data' 1292 LOAD_CONST ('headers', 'data') 1294 CALL_FUNCTION_KW_3 3 '3 total positional and keyword args' 1296 STORE_FAST 'response' 1298 POP_BLOCK 1300 JUMP_FORWARD 1332 'to 1332' 1302_0 COME_FROM_FINALLY 1204 '1204'
|
虽然这不是一眼可看出是什么作用的源代码,但是经过简单的思考还是能猜出这段代码的含义
关于Python字节码的信息可以到官方文档找到,这东西比汇编语言简单多了!
样本信息
样本是一个Linux平台下使用Pyinstall的python程序
sha256: 548a89c3f5a8846ae7a9aedda09018cb32f07cb333d9970d314b7c5ef60fb724