Python Hunting
Triaging this unknown python stealer with some breakpoints
Overview
We are going to be analyzing an unknown python stealer that comes bundled as a pyinstaller. Initially we took the standard static approach of extracting and decompiling the python code but the decompiler did not fully work (python version 3.11) and the python code was heavily obfuscated. Normally we would use a trick of replacing eval
and exec
with print
statements in the python runtime as a way to simply deobfuscate the script but the fact that it was not correctly decompiled makes this difficult. Instead we are going to approach it dynamically.
References
Sample
2a19ba63e85ce75d5f2d884011dfc94f616b176ed89a67c1acc0fe2179e8b591
UnpacMe
Analysis
- First extracting the pyinstaller we can see that the main python file is called
mPSCzi.pyc
and the bundled python dll is python 3.11 - Decompiling with pylingual show us the obfuscated code (snip below)
strpjab = tvnboaswivayssk - sjeqavagljouxg
tzvzwyilyuilob = fmikzvuexqgiygyrsw - laswhphcwhrgd
nvpvfxkszm = tvxzshhdfwer * tvnboaswivayssk
mxszwtywur = stzhmggz - mguyywdexiw
eval(bmurybzixs('d3NqcmN3Z3JweGlrYXp6biArIGpsc2h6cmlndCArIG92Z2hjZ3JpZ2JicCArIHh3Y3l1d3hmdnRlICsgZnl5bGp4eGV0ICsgYWZtanVwb2V3ICsgamZ5cG5mciArIGxhc3docGhjd2hyZ2QgKyBwZ3Z0YWp4ZWl5YWxyZyArIHN0emhtZ2d6ICsgc2plcWF2YWdsam91eGcgKyB0dnh6c2hoZGZ3ZXIgKyBnZXZzem9lcHpmd3B4YSArIG5saWxkdWliYnpuICsgbndiaHFobWZlcmZ6ZnV1ICsgdnV4Y2h5a3RuICsgenJvdXRndmdoY2FxbXJzYXUgKyB0dm5ib2Fzd2l2YXlzc2sgKyBmbWlrenZ1ZXhxZ2l5Z3lyc3cgKyB3d2l0ZG55ZyArIG1ndXl5d2RleGl3').decode())
Dynamic Analysis
Our dynamic approach will be to directly load the compiled script using the regular python interpreter instead of the pysintaller binary. This will allow us to load symbols for the python dll and attach to it with a debugger. Using the debugger we will break on the function PyParser_ASTFromString
which is the internal method used for dynamically compiling python called by eval
and exec
.
- Dumping the strings from the python 3.11 dll we can see the specific version is 3.11.9
- We need the install the exact version so that we can run the compiled
mPSCzi.pyc
file - We can then add a break point on
PyParser_ASTFromString
and add a log command in the breakpoint to log the first argument (the python code){s:utf8(rcx, A00000)}
- With this we can then see all of the evaled code is then dumped into the log
The dumped code can be found here pastebin
import base64
ZWHmjDkfVvkVdclV = 'bWdzdHN0dWRpby5zaG9w'
RYBTeAeZbiUOxeloi = base64.b64decode(ZWHmjDkfVvkVdclV).decode()
print(f'https://{RYBTeAeZbiUOxeloi}/sunrise')
print(f'https://{RYBTeAeZbiUOxeloi}/luminous')