Just a few tips and tricks for analyzing python malware...


  • 21a9b4859121afcf6690c2c15b795094986c0a20c36a356c3915f107ec41f67a UnpacMe


Creal Stealer

Creal Stealer is an open source Python stealer shared on GitHub Ayhuuu/Creal-Stealer). Though the stealer is open source the developer operates a Telegram channel which offers a "Premium" version of the stealer if you contact them.


The stealer has a simple discord webhook upload config where the operator can specify a discord to upload the stolen information. According to the developer the stealer is undetected in VirusTotal but this is obviously not the case in practice.

The following stealer feaures are listed on the GitHub page.

  • Discord Information ⚔️
    • Nitro
    • Badges
    • Billing
    • Email
    • Phone
    • HQ Friends
    • HQ Guilds
    • Gift Codes
  • General Functions
    • Check if being run in a VirusTotal sandbox
    • Adds file to startup
    • Anti-Debug / Anti-VM / Anti-RDP / Blue Screen if detect
  • Discord Injection
    • Send token, password, email and billing on login or when email/password is changed
  • Browser Data
    • Cookies
    • Passwords
    • Histories
    • Autofills
    • Bookmarks
    • Credit/Debit Cards
    • From Chrome, Edge, Brave, Opera GX, and more...
  • Crypto Data
    • Extensions (MetaMask, Phantom, Trust Wallet, Coinbase Wallet, Binance Wallet and +40 wallets supported)
    • Softwares (Exodus, Atomic, Guarda, Electrum, Zcash, Armory, Binance, Coinomi)
    • Seedphrases and backup codes
  • Application Data
    • Steam
    • Riot Games
    • Telegram
  • System Information ⚙️
    • User
    • System
    • Disk
    • Network
  • File Stealer
    • Grabs Seed Phrases, Tokens, Private Keys, Recovery Codes, Backup Codes, 2FA codes


Though we are analyzing a creal sample a similar process can be followed for most python malware.


The malware comes bundled in a PyInstaller EXE which can be extracted using [https://github.com/pyinstxtractor/pyinstxtractor-ng]. Once extracted the bundled python interpreter, libraries, and compiled python files (.pyc) will be accessible.

The Python interpreter DLL will have the Python version name listed in its name. Determining the version is important for the next step in the analysis process. We can also see the creal.pyc compiled Creal stealer module has been dumped.

Decompiling Python PYC

Depending on the Python version determined in the previous step Karsten's excellent CPython Bytecode Reference Chart can be used to determine the correct decompiler tool to use. Personally I prefer pycdc because it can be easily modified to handle any version.


Currently pycdc cannot decompile python versions above 3.9 however it can disassemble them pycdas. This will return the disassembled python which is readable but not as easy to follow as the lifted python code.

In our case the sample is using Python 3.12 and when we attempt to decompile it with pycdc we get some errors and only partial code recovery.

Unsupported opcode: BEFORE_WITH
Unsupported opcode: LOAD_FAST_CHECK
Unsupported opcode: BINARY_SLICE
Unsupported opcode: JUMP_BACKWARD
Unsupported opcode: JUMP_BACKWARD
Unsupported opcode: JUMP_BACKWARD
Patched Pycdc

We can modify pycdc to patch out the instruction case statement default return in ASTRee.cpp which causes the analysis to halt when an unknown instruction is encountered. By patching the return we force the analysis to continue.

Note this will produce incorrect decompiled code, but depending on which instructions are missing the code may end up very readable, and the disassembly can be used to fill in the gaps. In our case we can fully recover the discord hook url https[:]//discord[.]com/api/webhooks/1221491784937373859/LiPQTxogVAKpzUO2MXT3CjiqF4qFWy_HT3DpUCrG4D8E0ZVZAGR_3uHvfQog2a0DFQyV' and the majority of the code!