Case Study
The GlorySprout ads surfaced on the XSS forum at the beginning of March 2024 (the name makes me think of beansprout; perhaps the seller behind the stealer is a vegetarian).
The stealer, developed in C++, is available for purchase at $300, offering lifetime access and 20 days of crypting service, which encrypts the stealer’s payload to evade detection. Similar to other stealers, it includes a pre-built loader, Anti-CIS execution, and a Grabber module (which is non-functional). While the stealer advertises AntiVM and keylogging capabilities, I have not witnessed either in action or code. Additionally, it features support for log backup and log banning, allowing for the exclusion of logs from specified countries or IPs.
What particularly captured my attention regarding this stealer was that an individual, who prefers to stay anonymous, informed me it’s a clone of Taurus Stealer and shared some interesting files with me.
Taurus Stealer Backstory
Let’s talk a little about Taurus Stealer Project. It first appeared for sale on XSS in April 2020.
The stealer is written in C++ with a Golang panel. It was sold for $150 for lifetime (I guess the pricing was different in 2020).
One of the XSS users claims that the panel is very similar to Predator The Thief stealer. You can read a nice writeup on Predator Stealer here.
The Predator stealer shares many similarities with Taurus Stealer, including encryption in C2 communication, Bot ID formatting, the Anti-VM feature, and naming conventions for log files, as well as resemblances in the panel GUI. However, to refocus, Taurus Stealer terminated their project around 2021. The cracked version of Taurus Stealer is being sold on Telegram, and there’s information suggesting that Taurus Stealer sold their source code, which could explain these parallels.
Now, let’s confirm the theories…
Below is the screenshot of GlorySprout panel:
And this is the Taurus Stealer panel:
Can you spot the similarities and differences? :)
There is a great writeup on Taurus Stealer out there by Outpost24 that you can access here.
I will focus on the brief analysis of GlorySprout so we can make some conclusions later.
GlorySprout Technical Analysis
GlorySprout dynamically resolves APIs through API hashing, targeting libraries such as shell32.dll, user32.dll, ole32.dll, crypt32.dll, advapi32.dll, ktmw32.dll, and wininet.dll. This hashing process involves operations such as multiplication, addition, XOR, and shifting.
The reproduced Python code for API hashing:
The stealer accesses the hashed API values via specific offsets.
The Anti-CIS function is shown below:
The stealer exists if any of the language identifiers is found.
The stealer obfuscates the strings via XOR and arithmetic operations such as substitution.
The persistence is created via scheduled task named \WindowsDefender\Updater with ComSpec (cmd.exe) spawning the command /c schtasks /create /F /sc minute /mo 1 /tn "\WindowsDefender\Updater" /tr ". If the loader module is used, the task runs the dropped secondary payload from %TEMP% folder.
If the loader module is configured, the retrieved payload name (8 characters) would be randomly generated via the function below from the predefined string aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ.
The function described is also used to generate the filename parameter in a Content-Disposition header for C2 communications as well as the RC4 key for the ZIP archive with collected data.
But the function to generate random string doesn’t always generate random strings and we will come back to it in the C2 communications section.
The C2 address of the stealer is retrieved from the resource section of the decrypted/unpacked payload.
C2 Communication
Communication with the C2 server is performed via port 80. Upon checking in with the C2 server, the infected machine sends out the POST request “/cfg/data=
The base64-encoding set of characters is obfuscated as shown below.
Now, interestingly enough, the RC4 key for the initial check-in does not change depsite using the randomization, because the initial state value remains constant, which is 0xC40DF552. If we try the randomization function with Python and using the initial state value, we get the same value, which is IDaJhCHdIlfHcldJ.
The reproduced Python code for randomization function:
After the check-in, the server responds with an encrypted configuration, where the first 10 bytes is the RC4 key.
The decrypted conguration looks like this:
Here is an example breakdown of the configuration (0: stands for disabled, 1: stands for enabled):
- 1: Grab browser history
- 1: Grab screenshot
- 1: Grab cryptowallets recursively from %AppData% folder (Cryptowallets supported based on the analysis: Electrum, MultiBit, Armory, Ethereum, Bytecoin, Jaxx, Atomic, Exodus, DashCore, Bitcoin, WalletWasabi, Daedalus Mainnet, Monerom )
- 1: Grab Steam sessions
- 1: Grab BattleNet account information
- 1: Grab Telegram session
- 1: Grab Discord session
- 1: Grab Skype messages
- 1: Grab Jabber accounts from %AppData% folder
- 1: Grab Foxmail accounts
- 1: Grab Outlook accounts
- 1: Grab FileZilla data
- 1: Grab WinFTP accounts
- 1: Grab WinSCP accounts
- 1: Grab Authy
- 0: Grab NordVPN
- 0: Unknown placeholder
- 1: Anti-VM
- 1: Self-deletion (self-delete after sending the logs to C2): self-deletion performs with the command “C:\Windows\system32\cmd.exe” /c ping google.com && erase C:\Users\username\Desktop\payload.exe” . Pinging introduces the delay, likely to guarantee the successful full execution of the payload.
- loader_URL - contains the link to the secondary payload
- 1: Only with crypto - the loader payload only runs if cryptowallets are present on the machine
- 1: Autorun - creates the persistence for a secondary payload
- 1: Start after creating - runs the secondary payload after dropping it in %TEMP% folder
After receiving the configuration, the infected machine sends out the POST request with /log/ parameter containing the ZIP archive with collected data to C2 server as shown below:
The data is encrypted the same way, with RC4 and Base64-encoded.
The server sends 200 OK response to the machine and the machine ends the communication with the POST request containing /loader/complete/?data=1 .
Additional Information
As mentioned before, the panel of the stealer is written in Golang. The panel also utilizes SQL databases to process configuration and data. The stealer makes use of sqlx library, a popular extension for Go’s standard database/sql package designed to make it easier to work with SQL databases.
Interesting usernames found in mysql database:
It’s worth nothing that the database contains the mention of taurus. At this point, we can make a confident assessment that it’s a clone of Taurus Stealer code based on the technical analysis.
The example of the collected log:
General/forms.txt - contains the decrypted browser passwords. The browser passwords are decrypted on the server.
Conclusion
Based on the GlorySprout analysis, it is confidently assessed that the individual behind GlorySprout cloned the code of the Taurus Stealer project and modified it according to their specific needs and requirements. A notable difference is that GlorySprout, unlike Taurus Stealer (according to the version analyzed by Outpost24), does not download additional DLL dependencies from C2 servers. Additionally, GlorySprout lacks the Anti-VM feature that is present in Taurus Stealer. GlorySprout is likely to fade away e and fail to achieve the popularity of other stealers currently on the market.
Indicators Of Compromise
Name | Indicators |
---|---|
GlorySprout | 3952a294b831e8738f70c2caea5e0559 |
C2 | 147.78.103.197 |
C2 | 45.138.16.167 |
GlorySprout | d295c4f639d581851aea8fbcc1ea0989 |
Detection
You can also access the Yara rule here
References
https://fumik0.com/2019/12/25/lets-play-again-with-predator-the-thief/ https://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/ https://github.com/RussianPanda95/Yara-Rules/blob/main/GlorySprout/win_mal_GlorySprout_Stealer.yar