Follow-Along: Analysis of the Snake Keylogger
In the last post, we analyzed a recent sample that acted as a loader for Snake Keylogger. The post concluded with the dumping of the final payload after 3 unpacking layers.
In this post, we’ll take a closer look at the keylogger payload, detailing key functionality as well as noting indicators of compromise (IoCs) that can be used to better detect the malware family.
Initial Triage
File Name
snake.dumped
Hashes
MD5: d19ef48d7f6d470b405e3577b65131b4
SHA1: f53b620e189662da1daf92a874c5510e64a5f0f3
SHA-256: a4dea87c44153bb33ce223c0193582b6ef2e73f17d632ecb4392fcb2830fa7ec
Anti-Virus Detection Rate (46⁄71)
At the time of writing, the sample being analyzed has not been submitted to Virustotal (VT). An attempt was made to search for it by the hashes listed above, but no reports were found. This does not mean that the AV engines would not detect it via signatures or heuristics. As a result, I uploaded the file to VT to allow for quick static detections of the file.
The resulting detection count is greater than that which had been seen in the packed sample analyzed in the last post (46 detections unpacked, 22 detections packed). This is to be expected, as it is the reason why threat actors utilize packers/crypters: to decrease the risk of their malware being detected on victim machines.
Architecture
Looking at the file in Detect It Easy (DIE), we can see it appears to be a 32-bit executable. The entropy is not quite high enough for DIE to claim it to be packed, but it isn’t low either.
In the conclusion of the previous post, we were able to see strings and imports that suggested the file we are analyzing now is unpacked; but that does not mean it is unobfuscated. We can expect a few forms of obfuscation.
Firstly, CLR (the virtual-machine on which .NET code runs) bytecode could still be encrypted. That code only gets decrypted at run-time and as such would not be able to be analyzed by dnSpy statically. This is similar to the form of obfuscation we dealt with in the last post with the most differentiating factor being that decrypted code is not loaded as entirely new assemblies (which can then be dumped, as we had done). This makes it much harder to analyze.
Class, method, variable, and function name stripping or renaming can contribute to the borderline entropy value. With this method of obfuscation, names that would be descriptive of the code to be executed are replaced with syntactically-correct but undescriptive names that are intentionally hard to decipher and discern from each other. The types of function and class names we saw in the last post could very likely still be present. Once the obfuscator replaces those names in the protected assembly, there is usually no way that any form of deobfuscation can bring them back to their original state. We can still expect some level of this type of obfuscation in the code.
Resources
One interesting resource is found: YFGGCVyufgtwfyuTGFWTVFAUYVF.Resources.resources. However, the size of it is quite small (180 bytes), making it less likely to be an entire assembly which will usually be measured in kilobytes. Throwing it into DIE and bintext yielded no identified type or interesting strings, respectively.
Sections
Nothing appeared unusual with the sections of the executable. No unusual size differences or abnormal section names were found.
Imports
Looking through the imported libraries and functions, we can notice potential indicators of several different types of malware functionality.
Evasion through NTDLL Functions
The import of ntdll.dll is highly unusual. kernel32.dll contains functions that wrap those within ntdll.dll, so programs do not usually import the latter directly. Malware authors sometimes utilize the NT versions of Win32 API functions in order to evade analysis by AV or analysts that hook/breakpoint on kernel32.dll wrapper functions.
Data Encryption
Although Snake Keylogger is not known as providing ransomware features, from the image above, we can expect that the malware may try to use some of the features in the Crypt32 or bcrypt libraries in order to encrypt data on disk or in transit to the command and control (C2) server. That may hinder analysis and should be expected.
Keylogger Functions
The highlighted functions show several functions that -when imported in conjunction with each other- indicate keylogger features. Keyloggers will often set a windows hook with a keyboard procedure in order to be notified of keypresses. Certain keyboard events like a space, backspace, control, etc. are represented as virtual keys as they do not produce a character by themselves. A keylogger then listens to these events/keypresses and logs them to a file or memory buffer before sending them to the C2 server.
Clipboard Stealer
In the image above, we can also see imports of functions such as GetClipboardData and IsClipboardFormatAvailable. These functions suggest that the malware may attempt to determine if the data in the clipboard is in a text format using the latter function before copying it with the former.
This type of functionality may be included to target users that utilize password managers. When a user attempts to log into an application, their password manager will copy the credential directly to their clipboard, bypassing the keyboard, rendering useless those keyloggers that only listen for keypresses. By waiting on a paste event, the malware may be able to steal the credential, bypassing the password manager.
Runtime Function Importing, Arbitrary Program Execution, and More
Several bits of functionality can be inferred from the imports highlighted above.
Firstly, we can see the two functions: GetProcAddress and LoadLibrary. These functions are commonly seen in malware in order to import additional Win32 API functions at runtime.
Malware authors use this method in order to help evade static analysis of imports, as we have been doing. Library and function names that the malware author wants to hide from a malware analyst or AV will be encrypted or encoded to hinder static analysis. At runtime, the program will use LoadLibrary to import the desired library (if not already loaded) and receive a handle. They’ll then use GetProcAddress with the handle in order to import the desired function.
This method of evasion ultimately hides the dynamically-resolved functions from the Import Address Table (IAT), a structure in the PE file that tools like pestudio use to list out imports.
The Send function looks like it may be application-defined code designed to send data to the C2.
Likewise, set_UseShellExecute also appears to be application-defined, and may be used as part of configuration-parsing in order to set the availability of the program’s ability to execute arbitrary programs.
The KeyUp and KeyDown functions may be the KeyboardProcapplication-defined callback implementations used in conjunction with the keylogging features documented above.
Finally, the Wekakekakd function import is abnormal and, despite claiming to originate from ntdll.dll, is not a function documented by Microsoft or listed in NT Undocumented Functions.
Kill Program
A suspicious application-defined function named Kill is listed, a possible indicator that the Snake Keylogger may have the functionality to kill foreign processes such as security software.
Anti-Debug
An interesting function import listed was discovered named getTicks. This may be indicative of anti-debug functionality.
In order to hinder dynamic analysis, some malware authors may include functionality to capture the delta of time incurred between the execution of two blocks of code. Malware analysts will oftentimes set breakpoints in order to analyze some feature. If this breakpoint lies between the time initially captured, and the time that the value will be compared against, the delta will be significant when measured in milliseconds. This delta will be compared against some pre-defined standard (found in development when a debugger wasn’t running) in order to determine whether there is a large difference in the timing. If found, the malware will usually terminate or perform some benign functionality to hide its true purpose
The set_Expect100Continue function may be related to the potential anti-debug feature. .
System Enumeration
The imported functions highlighted above may be indicative of system enumeration and identification functionality. Oftentimes, when a malware infects a computer, it will try to identify the machine on which it landed and send that information back to the C2. This will help the malware operator discern juicy targets, or machines that may just be analyst boxes. In the former case, the operator can investigate further and perhaps dynamically trigger additional features (e.g. run a later-stage malware). In the latter case, the operator may have either pre-defined rulesets to match against or may simply manually trigger an uninfection of the machine.
Version
The version information embedded in the file lists a jibberish filename and description, additional malicious indicators.
Strings
The following strings showed strong indicators that the malware is Snake Keylogger, with strings explicitly saying “Snake Keylogger”. Other strings are present that are indicators for malware functionality, such as:
- Targeting specific applications for credential theft
- System Enumeration
- Process Execution
- Wi-Fi credential theft
- Potential data-exfiltration
- Email addresses
- Telegram URL
Indications of targeted applications, anti-virus software, system enumeration, process execution, and Wi-Fi credential theft
Load
Add
Send
Replace
Create
Delete
Write
Kill
Control
Run
/C choice /C Y /N /D Y /T 3 & Del “
11.0.0.0
17.0.0.0
17.0.3.0
Software
software\microsoft\windows\currentversion\run
Software\Microsoft\Office\15.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676
Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging
Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676
Software\Microsoft\Windows Messaging
Subsystem\Profiles\9375CFF0413111d3B88A00104B2A6676
Software\Microsoft\Office\16.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A667 6
SOFTWARE\Classes\Foxmail.url.mailto\Shell\open\command
Software\Microsoft\Windows NT\CurrentVersion
get_Name
set_FileName
get_MachineName
get_OSFullName
get_FullName
get_UserName
get_ProcessName
GetProcessesByName
.txt
mail.stilltech.ro
chrome
wireshark
cmd.exe
POST
user-agent
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR1.0.3705;)
.png
POP3 Password
SMTP Password
SMTP Server
Foxmail.exe
\FileZilla\recentservers.xml
\FileZilla\recentservers.xml
Port
.purple\accounts.xml
netsh
Open Network
.log
\mozglue.dll
\nss3.dll
/sendMessage?chat_id=
/sendDocument?chat_id=
&caption=
aaalogshsindgdaLogndta
add_KeyDown
remove_KeyDown
KeyLogger
KeyLoggerEventArgsEventHandler
KeyLoggerEventArgs
FFLogins
get_logins
set_logins
sqlite_master_entry
$#TheHashHere%&
Avconsol
Ave32
Avgctrl
Avkserv
Avnt
Avp
Avp32
Avpcc
Avpdos32
Avpm
Avptc32
Avpupd
Avsched32
AVSYNMGR
Avwin95
Avwupd32
Blackd
Blackice
Cfiadmin
Cfiaudit
Cfinet
Cfinet32
Claw95
Claw95cf
Cleaner
Cleaner3
Defwatch
Dvp95
Dvp95_0
Ecengine
Esafe
Espwatch
F-Agnt95
Findviru
Fprot
F-Prot
F-Prot95
Fp-Win
Jedi
Lockdown2000
Lookout
MCAFEE
Moolive
Mpftray
N32scanw
NAVAPSVC
NAVAPW32
NAVLU32
Navnt
NAVRUNR
Navw32
Navwnt
NeoWatch
NISSERV
Nisum
Nmain
Normist
NORTON
Nupgrade
Nvc95
Padmin
Pavcl
Pavsched
Pavw
PCCIOMON
PCCMAIN
Pccwin98
Pcfwallicon
Persfw
POP3TRAP
PVIEW95
Rav7
Rav7win
Rescue
Safeweb
Scan32
Scan95
Scanpm
Scrscan
Serv95
Smc
SMCSERVICE
Snort
Sphinx
Sweep95
SYMPROXYSVC
Tbscan
Tca
Tds2-98
Tds2-Nt
TermiNET
Vet95
Vettray
Vscan40
Vsecomr
Vshwin32
Vsstat
Webscanx
WEBTRAP
Wfindv32
Zonealarm
LOCKDOWN2000
RESCUE32
LUCOMSERVER
avgcc
avgamsvr
avgupsvc
avgw
avgcc32
avgserv
avgserv9
avgserv9schedapp
avgemc
ashwebsv
ashdisp
ashmaisv
ashserv
aswUpdSv
symwsc
norton
Norton Auto-Protect
norton_av
norton_av
nortonav
ccsetmgr
ccevtmgr
avadmin
avcenter
avgnt
avguard
avnotify
avscan
guardgui
nod32krn
nod32kui
clamscan
clamTray
clamWin
freshclam
oladdin
sigtool
w9xpopen
cmgrdian
alogserv
mcshield
vshwin32
avconsol
vsstat
avsynmgr
avcmd
avconfig
licmgr
sched
preupd
MsMpEng
MSASCui
Avira.Systray
POST
Current IP Address:
Client IP:
Clipboard |
| Snake
Pc Name:
| Snake Keylogger
$%TelegramDv$
| Snake Keylogger
Screenshot
\SnakeKeylogger
\SnakeKeylogger
Screenshot Logs ID
keystroke Logs ID - Keystrokes
Passwords ID
E-Mail:
PSWD:
IMAP Password
HTTP Password
Outlook
POP3Account
POP3Password
\Local State
“encrypted_key”:“(.*?)”
\Kinza\User Data\Default\Login Data
logins
origin_url
username_value
password_value
USR:
\Sputnik\Sputnik\User Data\Default\Login Data
\SalamWeb\User Data\Default\Login Data
\MapleStudio\ChromePlus\User Data\Default\Login Data
\QIP Surf\User Data\Default\Login Data
\BlackHawk\User Data\Default\Login Data
\7Star\7Star\User Data\Default\Login Data
\Fenrir Inc\Sleipnir5\setting\modules\ChromiumViewer\Default\Login Data
\CatalinaGroup\Citrio\User Data\Default\Login Data
\Google\Chrome SxS\User Data\Default\Login Data
\Google\Chrome\User Data\Default\Login Data
\Coowon\Coowon\User Data\Default\Login Data
\CocCoc\Browser\User Data\Default\Login Data
\uCozMedia\Uran\User Data\Default\Login Data
\Tencent\QQBrowser\User Data\Default\Login Data
\Orbitum\User Data\Default\Login Data
\Slimjet\User Data\Default\Login Data
\Iridium\User Data\Default\Login Data
\Vivaldi\User Data\Default\Login Data
\Chromium\User Data\Default\Login Data
\GhostBrowser\User Data\Default\Login Data
\CentBrowser\User Data\Default\Login Data
\Xvast\User Data\Default\Login Data
\Chedot\User Data\Default\Login Data
\SuperBird\User Data\Default\Login Data
\360Browser\Browser\User Data\Default\Login Data
\360Chrome\Chrome\User Data\Default\Login Data
\Comodo\Dragon\User Data\Default\Login Data
\BraveSoftware\Brave-Browser\User Data\Default\Login Data
——– Snake Keylogger ——–
Found From: Brave
Host: \Torch\User Data\Default\Login Data
\Torch\User Data\Default\Login Data
\UCBrowser\User Data_i18n\Default\UC Login Data.18
wow_logins
\Blisk\User Data\Default\Login Data
\Epic Privacy Browser\User Data\Default\Login Data
\Yandex\YandexBrowser\User Data\Default\Ya Login Data
\Nichrome\User Data\Default\Login Data
\Amigo\User Data\Default\Login Data
\Kometa\User Data\Default\Login Data
\Xpom\User Data\Default\Login Data
\Elements Browser\User Data\Default\Login Data
\Microsoft\Edge\User Data\Default\Login Data
\Liebao7\User Data\Default\EncryptedStorage
\AVAST Software\Browser\User Data\Default\Login Data
DigitalProductID
All User Profile * : (?
WiFi Name:
wlan show profile name=”
” key=clear
wlan show profile
\discord\Local Storage\leveldb
Mozilla\Firefox\Profiles
logins.json
Waterfox\Profiles
Thunderbird\Profiles
Mozilla\SeaMonkey\Profiles
Comodo\IceDragon\Profiles
8pecxstudios\Cyberfox\Profiles
FlashPeak\SlimBrowser\Profiles
Mozilla\icecat\Profiles
PostboxApp\Profiles
Moonchild Productions\Pale Moon\Profiles
PROGRAMFILES
\Mozilla Thunderbird
\Mozilla Firefox
\SeaMonkey
\Comodo\IceDragon
\Cyberfox
\Pale Moon
\Waterfox Current
\SlimBrowser
\Postbox
Static Analysis
Deobfuscating
Dropping the file into dnSpy, we can see immediately that the file still has elements of obfuscation. With few exceptions, the namespaces, class, and function names have all ben obfuscated.
The DLL was then thrown into de4dot, a .NET deobfuscator, in an attempt to clean up the code and create readable names for namespaces/classes/functions.
Obfuscators do not typically leave metadata that allow for a complete reversal of all the changes made. There is usually some form of type information lost, as shown above. The names of namespaces, classes, and functions are now readable, but are not the original values as written by the malware author. We still have the job of deciphering the meaning of each. As we go along, we can rename namespaces/classes/functions/variables in order to make the mental load easier on ourselves or other analysts.
⚠️
Even though we've been able to use automation to decompile and deobfuscate a lot of the malware, there are a few things we should be aware of before we proceed further.
Firstly, we don't want to get lost in the rabbit hole that is a plethora of code. A lot of code could still be unreferenced junk code intended to confuse analysts that try to analyze it, thereby hindering analysis. We want to try to avoid those traps.
Other code may be unnecessarily complex, either by design of an obfuscator or by poorly-written code on the part of the malware author. We don't necessarily need to understand every line of the code, thereby wasting mental energy, as we do need to get an overall grasp of the functionality present.
Our goal in this analysis is to determine the major features of the malware, as well as how it achieves that functionality. Not every line of code needs to be analzyed critically. Keeping this goal at the front of mind ensures we get the most for our time and effort.
When analyzing native malware with tools such as IDA Pro, my usual approach would be to start with string references to find the interesting functions. However, dnSpy does not make such an approach easy or possible, so I had to change my approach.
Symbol Renaming and Usage Analysis
I started by quickly viewing each class in the assembly, finding core functionality, and renaming the class and it’s parent namespace something more descriptive.
To rename a class and its parent namespace, simply right-click on the target class name and select Edit Type.
To rename a function/method, right-click on the target and select Edit Method…
After quickly reviewing and renaming the compiled code, the result looked like this:
At times, determining the purpose of a function, variable, or class can be non-trivial. Malware authors will sometimes insert junk code to bloat the size of the program in order to hinder analysis or judgment of the program as being benign/malicious. A lot of the time, that code will look needlessly complex with superfluous loops, with primitive types such as integers, floats, or characters being manipulated without references to other useful functions in the program. At other times, the code could actually be useful, but still unreferenced and so unused by the program either as another mental trap for analysts or for other unknown reasons (e.g. feature is not complete).
In any case, it can be hard to judge sometimes whether you should pay particular attention to a block of code, or disregard it. To help with this task, dnSpy provides a useful feature to Analyze usage of a symbol. With it, you can see how a variable, function, or class is referenced, either by assignment, getting, or calling.
To use the feature, simply right click on the target symbol and click the Analyze button in the context menu that appears. A drop-down will appear in the window below that will show you how the symbol is referenced.
In this way, I was able to determine how this particular attribute was used, discovering it to be referenced by two functions that I had determined to be used to kill open Chrome and Firefox instances.
Configuration
After working through the code and setting descriptive names on namespaces, classes, functions, and variables, the configuration for the program was identified as being stored in the code itself, not in a separate resource. Within the class where the Main method resides, a number of attributes are used as the configuration.
Here, we can see a number of interesting settings the control the behavior of the program:
- C2 protocol
- SMTP
- FTP
- Telegram
- C2 protocol credentials
- (Optional) Data encryption key: Used to encrypt credentials before being sent to C2
- (Boolean) Data encryption flag: Enables/disables encryption of credentials in transit
- System Identification
- Current process list at startup
Core Functionality
Looking at the Main function (entry point), we can see a clearer picture of the program’s functionality.
The main things seen were:
- Credential Theft
- Clipboard Theft
- Keylogging
- Periodic Screenshots
In seeing this, it’s clear that despite its name, Snake Keylogger is far more than just a key-logger, and could be classified as an information stealer (infostealer) as well.
Credential Theft
An assessment of the applications targeted as well as how the program is structured is strongly indicative of the sample belonging to the Snake Keylogger family. A full list of targeted applications will be below; to summarize, the sample appears to target the following types of programs:
Snippet showing code to steal Chrome credentials. Similar code is found with modified registry keys for Chromium-based browser theft. Theft of Gecko-based browsers not shown
Web Browsers
Chromium-based (e.g. Chrome)
Gecko-based (e.g. Firefox)
Snippet showing code to steal Outlook credentials. Theft of credentials for Thunderbird not shown
Mail
Outlook
Thunderbird
Snippet showing code to steal Discord token. Pidgin-theft not shown
Chat
Discord
Pidgin
- FTP
- FileZilla
- Windows Key
- Wi-Fi Networks
Targeted Application List
Gecko-based Browsers Targeted
Firefox
Waterfox
SeaMonkey
IceDragon
CyberFox
SlimBrowser
PaleMoon
Chromium-based Browsers Targeted
- Kinza browser (Japan)
Sputnik browser (Russia)
SalamWeb browser (Islamic)
CoolNovo browser
QIP Surf browser
Blackhawk browser
7 Star browser (China)
Sleipnir browser
Citrio browser
Chrome Canary
Chrome
CooWon browser
CocCoc browser (Vietnam)
Uran Browser
QQ Browser (China)
Orbitum browser
Slimjet browser
Iridium browser
Vivaldi browser
Iron browser
Chromium
Ghost Browser
Cent
Xvast
Chedot
SuperBird
360 Browser
Comodo
Brave
Torch
UC Browser
Blisk
Epic Privacy Browser
Yandex
Nichrome
Amigo
Kometa
xpom
Elements
Edge
Avast Secure Browser
Miscellaneous Browsers Targeted
- Opera
Mail Applications Targeted
Outlook
Thunderbird
Chat Applications Targeted
Discord
Pidgin
Clipboard Theft
Using a timer, the malware will periodically retrieve the contents of the clipboard, formatting the hyperlinks before storing the data in an instance variable. With another timer, Snake Keylogger will periodically send the contents of that stored data to the C2 server using the configured C2 protocol (only code for FTP is shown, but others apply) as seen below.
Keylogging
Unsurprisingly, as it’s in the name, the malware performs keylogging, using the same pattern of a timer to periodically send the data to the C2. As expected from the import analysis, the malware makes use of Windows hooks and keyboard procedures to be asynchronously notified of key events.
When the function above is called, the keylogger is started in the background, running continuously. Another timer is created that periodically sends the contents of the key log to the C2.
Snippet of function to send keylogs to C2. FTP protocol is shown above, but the app will attempt to send using SMTP or Telegram if configured
Screenshots
Using a timer, the malware will also attempt to periodically take screenshots, perhaps for system identification purposes in order to find targets of interest vs malware analysts.
Interestingly, when it takes the screenshot, a directory named SnakeKeylogger will be created in the current user’s documents directory with the image being saved to a file named Screenshot.png. Unlike the other features, the data isn’t buffered for some time before sending it to the C2 with a different timer. The screenshot is sent immediately to the C2 and then the directory containing the image will be deleted.
This SnakeKeylogger directory being created in the user’s documents directory is a very strong indicator of malicious activity that can be attributed to this malware family. As a result, the event of the directory’s creation or deletion presents a great detection opportunity for threat hunting.
Unused or Unconfigured Functionality
Interestingly, several features are present within this sample that don’t appear to be referenced anywhere. This could be due to a number of reasons. It could be a result of the operator opting not to enable these features, there could be code that isn’t in its final state, or the code could potentially be triggered by a different component (e.g. loader).
One indicator that the code triggering these features was deliberately removed or disabled is the empty functions interspersed throughout the Main function, as shown above.
In any case, the unused features include:
- Persistence via Run key
- Anti-Anti-Virus
- Killing Chrome + Firefox
- Enumerating Drives
- Enumerating Microsoft Access database files
- Calculating total disk space across all storage drives
- Calculating total physical memory
- “Melt” (i.e. delete originating file)
- Get WAN (Internet) IP
Conclusion
Throughout this analysis, we’ve found very strong indicators that this sample belongs to the Snake Keylogger functionality, from strings found, to the communication protocols and targeted applications. We’ve confirmed that this family of malware possesses far more than simple key-logging features. The features could be summarized as:
- Credential Theft
- Clipboard Theft
- Keylogging
- Periodic Screenshots
It can send data back to the operator across three different C2 channels:
- SMTP (the chosen C2 in this case)
- FTP
- Telegram
A strong indicator of infection can be found in the malware’s creation of a SnakeKeylogger directory in the current user’s documents directory during the periodic screenshot.
Several other potential features of the malware were also documented, but do not appear to be activated for this particular sample. Those features include:
- Persistence via Run key
- Anti-Anti-Virus (killing security product processes)
- Killing Chrome + Firefox (possibly to steal sessions or cookies) after flushing to disk
- Enumerating Drives
- Enumerating Microsoft Access database files
- Calculating total disk space across all storage drives (possibel indicator of analysis for malware operator)
- Calculating total physical memory (another possible indicator of analysis for malware operator)
- “Melt” (i.e. delete originating file)
- Get WAN (Internet) IP
The original hypothesis of anti-analysis through CPU ticks was not validated. No anti-debug feature was found in the sample, unconfigured or otherwise.
If you’re interested in learning how to use AWS, Cloudflare, Google Workspace and more with modern DevOps practices in order to create a hybrid cloud/on-prem malware lab, check out my book on Cyber Range Essentials!