Reversing Synasploit.exe
Posted 2021/06/28
A few months ago an unknown user joined our school’s cubing club’s Discord server and dropped a piece of malware in one of the text channels. The user was quickly banned but I downloaded a copy of the malware for future analysis (VirusTotal). This was my first dive into malware analysis and reverse engineering as I have always focused on forensics and some cryptography in CTFs.
Basic Analysis
Looking through strings of the file I found many references to Python so I thought this executable may have been created by PyInstaller.
Running pyinstxtractor extracted .pyc
files from the executable and .pyd
files containing the Python modules the program used. With many of the other .pyc
files being standard modules it became clear that CloudBot.pyc
contained the compiled Python bytecode for the malware.
Reversing the Bytecode
I have decompiled a few .pyc
files in the past using the uncompyle6 decompiler but running file
on CloudBot.pyc
revealed that it was compiled using Python 3.9 which uncompyle6 does not support currently.
I tried using dis to disassemble the bytecode but was met with an IndexError from an invalid opcode.
I switched to using Decompyle++‘s disassembler (I have since switched to xdis which has better formatting) which gave me the full bytecode for the program and functions. With no available decompilers I translated the bytecode to equivalent Python source code.
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 |
|
The bytecode for the program was pretty simple to reverse but the bulk of the program lies in the main()
function. Things to note from this code is that the malware only runs on Windows and it targets the storage locations of Discord, Chrome, Opera, Brave, and Yandex browsers. Not all the translated code will be included in this post, I do not wish to share functional malware code on this site, just a breakdown on how scrapers like these work
getheaders()
1 2 3 4 5 6 7 8 |
|
Simple method that generates headers for the malware’s API requests
getuserdata()
Retrieves the username, user ID, avatar, email, and phone number
gettokens()
Finds Discord authentication tokens from the local storage of browsers and Discord client
getdeveloper()
Gets the author of the program who is wodx
. Tries to retrieve more information about the author from a pastebin that was taken down
getip()
Gets the IP address of the device
getavatar()
Finds the avatar URL
gethwid()
Calls wmic csproduct get uuid
to get the HWID
getfriends()
Gets a list of all of the infected user’s friends
getchat()
Gets a list of all channels the infected user is in
has_payment_methods()
Finds if there are payment methods associated with the infected account
send_message()
Function to send messages using the Discord API
spread()
Sends a copy of the malware to all of the infected user’s Discord friends
main()
This function contains the bulk of the program. The function starts by getting the target IP, Windows username, and hostname. It then proceeds to look through the local storage of all the browsers mentioned above looking for discord tokens using the gettokens()
function. If a valid token is found then it finds information about that user using the getuserdata()
, getavatar()
, and has_payment_methods()
functions. This data is then sent in an embed to a hardcoded Discord webhook address. If the constant self_spread
is set to True
then the malware also runs the spread()
method.
Conclusions
From this analysis I learnt how to reverse Python bytecode and executables. The spread of Discord token scrapers like this program is concerning especially since the source code of many of these pieces of malware can be found on GitHub for script kiddies to use. Steven also managed to find a repo with a variant using the same webhook address as the executable that I analysed. I think this goes without saying but don’t run suspicious executables that get sent over messages.