Galactic Shooter: A Run of the Mill Stealer
In general, malware specifically designed to smash and grab don't take a lot of effort to make. They tend to be small executables that will package up passwords, credit card data, cookies, and any other useful on-disk artifacts before sending them off to a C2.
In my case, my sample brought in a live one: the secondary objective of this stealer was to leave the door open for further on-keyboard access.
Let's take a look at GalacticShooter.exe [a2077125de69b773350e3d1875f71d5433d85bcaa4f1fccce75a59a78cfef668]. As of June '23, we're sitting at 5/66 on VT.
Immediately, we already have some suspicious DNS resolutions:
Overall, VT doesn't help us much. At the time of upload, I didn't see any other popular tools with telemetry that would be constructive either. Into the sandbox it goes.
On first execution, what greets the user is this obnoxious galaxy print background and a box to enter a beta tester key, obviously there is no beta tester key.
From the shell commands and process structure, we can assume that this is an Electron process.
Note: this is not the first execution that I will be referring to lower down, this screenshot was taken on the fourth or fifth execution of the sample so the PIDs don't line up to what I mention below.
Preemptively, as we know absolutely nothing about the executable going in, we set Process Monitor to record during the entire execution of the sample. At the same time, Wireshark was capturing all traffic to and from my VM network.
Knowing initially it was a stealer, I went ahead and grepped through the procmon log for
password
. Immediately, we find something interesting.
"4:04:25.7873536 PM","GalacticShooter.exe","1580","CreateFile","C:\Users\USER\AppData\Local\Temp\epsilon-USER\Passwords.txt","SUCCESS","Desired Access: Append Data/Add Subdirectory/Create Pipe Instance, Write EA, Read Attributes, Write Attributes, Read Control, Synchronize, Disposition: OpenIf, Options: Synchronous IO Non-Alert, Attributes: N, ShareMode: Read, Write, Delete, AllocationSize: 0, OpenResult: Created"
Narrowing our search down to only the call
WriteFile
from
GalacticShooter.exe
with the string "epsilon" in it returns the unique files:
C:\Users\USER\AppData\Local\Temp\epsilon-USER\Passwords.txt
C:\Users\USER\AppData\Local\Temp\epsilon-USER\Cookies\Chrome_Default.txt
C:\Users\USER\AppData\Local\Temp\epsilon-USER\Cookies\Edge_Default.txt
C:\Users\USER\AppData\Local\Temp\epsilon-USER\Credit Cards.txt
C:\Users\USER\AppData\Local\Temp\epsilon-USER\Autofill Data.txt
C:\Users\USER\AppData\Local\Temp\epsilon-USER.zip
As each event is recorded sequentially, we know that the process will create a file for passwords, browser cookies, saved browser credit card data, browser autofill data, then zip them all into
epsilon-USER.zip
. From the first write event of
Passwords.txt
to the deletion of
epsilon-USER.zip
is about 5 seconds. Given a wide time-frame, we have the opportunity to snag it for ourselves when the files write to disk.
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\USER\AppData\Local\Temp\"
$watcher.Filter = "epsilon-USER.zip"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$action = { $path = $Event.SourceEventArgs.FullPath
cp $path "C:\Users\USER\Desktop\yoinked\"
echo "success"
}
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 1}
[I found this on superuser](https://superuser.com/questions/226828/how-to-monitor-a-folder-and-trigger-a-command-line-action-when-a-file-is-created) then just adjusted it to my use-case. The
GalacticShooter.exe
process does not perform a check to ensure the data is not a duplicate and thus, after minor trial and error, we can snag the files.
Each file should have a list parsed out from Chrome & Edge (the only two browsers installed on this VM) of any autofill data, credit cards, or passwords found. As both browsers are unused, the data is empty but packaged up and sent off to its C2 regardless.
Each file within the Temp directory in the previous screenshot were created by
GalacticShooter.exe
, further reinforcing its Electron behavior. The folder
2OcB46IRbVtah4ccWieleL6owgA
also contains the child process
GalacticShooter.exe
that we saw above in Process Hacker.
This child process
\2OcB46IRbVtah4ccWieleL6owgA\GalacticShooter.exe
[38c81e9d17174f56bf3c22e5994d341ad041254ada2743160b69d893b8d51eda] has even less prevalence in VT. It
does, however, offer us a bit of insight into the greater campaign.
Checking the VT graph for this hash, we see it has 20 files listed as potential parents, some unique ones are below:
PARENT |
SHA256 |
Palowarn_DEMO.exe |
3862b39cbaca21c0a4e1c4ee09c83ab8dca7fdafe90486115ca30d74339aa435 |
TBMSetup.exe |
1fb52505b4b5a857d33c65dbc433cb8259312ee91a9fd23f8a6b7820e5426c18 |
TBM_Setup.exe |
09f0a812f6e111d15cb40ab484cb696f3f510247e618c73add4f445f267cef76 |
Saturne-SpoofX.exe |
0c69121b796701d5f1643ca0358f975b551004425b467f8ccd52b0cbcaa7d161 |
Condo_Generator.exe |
04fb70c81a5f3f2c2310e0ff166b2b2956fb035db81091cc02931bc8e54804f3 |
GalacticShooter.exe |
16c05c50696d648176dfc86b0648c1a74fe166d5fe86640800a4a3571c4bd1d5 |
SearchDB.exe |
729fdc841c88f8601f6ba2986404a83c8e4011a4323eb5e8b3e1131809238051 |
TBMSetup (6).exe |
6badc9e07c43dc30a4d7400aa79ba6ddbe77b7fe80f38579466d03fde4e71c03 |
Damned-setup.exe |
6f9f967e210b482c08bf47f9f67cefcb4cd94ce4be64c2b8fc1c0b150863be7f |
Damned-Setup.exe |
5a27e4815f753c751ff45d1e998084e4c17769694a2a812f2cc88ae4837098d4 |
TBMSetup.exe |
67335f9c7fca83065c6289963e3d059d4691d2eb32e217f2ba4d6b072fc9fb8b |
damned.exe |
39292b5820555e73fa5d1ed6c39334f021391c2dab4bf8012fa2ad92a4f55228 |
Interspace.exe |
11b58a18b74ae1e0bcf4952f8854020351aaed16df9d467d14e5ef5ebfeca610 |
Finally caving from my endless grepping to using a GUI, Libre was actually helpful here to sort through the CSV. Firstly, we can re-create our process tree by sorting down to only
Process Create operations:
GalacticShooter (PID 8148)
-> GalaticShooter (PID 1580)
-> GalacticShooter (PID 1580)
"[.]\AppData\Local\Temp\2OcB46IRbVtah4ccWieleL6owgA\GalacticShooter.exe" --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --user-data-dir="C:\Users\USER\AppData\Roaming\GalacticShooter" --mojo-platform-channel-handle=1948 --field-trial
-> GalacticShooter (PID 1580)
"[.]\AppData\Local\Temp\2OcB46IRbVtah4ccWieleL6owgA\GalacticShooter.exe" --type=renderer --user-data-dir="C:\Users\USER\AppData\Roaming\GalacticShooter" --app-path="C:\Users\USER\AppData\Local\Temp\2OcB46IRbVtah4ccWieleL6owgA\resources\app.asar" --enable-sandbox --lang=en-US --device-scale-factor=1 -
Reviewing
QueryDirectory calls shows that
PID 8148, the parent that we downloaded and executed, creates the directory
C:\Users\USER\AppData\Local\Temp\nssC2CF.tmp\
, a connection is made to a Cloudflare IP address, the directory is filled with
7z-out
files for the secondary executable that will then be unpacked to
\Temp\2OcB46IRbVtah4ccWieleL6owgA\
and house our child process (this also houses vulkan drivers, a ton of keyboard language packs, and Electron dependencies which confirms the earlier assumption). After downloading the second-stage, it is executed to handle the data exfiltration from browsers.
Here we see PID
1580, the child, making outbound connections to:
- rentry.co
- We can corroborate the amount of traffic against this domain by checking Wireshark.
Statistics -> Resolved Addresses -> string search
tells that rentry.co
resolved to 198.251.88.130
.
- We can compare the address in
Statistics -> Endpoints -> IPv4
, which shows that we had a total conversation size with this server of 6.6KB.
- A quick Google search shows that
rentry.co
is a throwaway pastebin, likely hosts a link to the secondary stage where our second process gets pulled down from.
- In Wireshark, the traffic to this domain was directed at
198.251.88.130
, a PonyNet IP.
- mia09s26-in-f10.1e100.net
1e100.net
is a [Google-owned server](https://support.google.com/faqs/answer/174717?hl=en).
- Could be traffic against a GCP host? Unclear.
- 81.59.117.34.bc.googleusercontent.com
- Interestingly,
81.59.117.34
is a T-Mobile IP address geo-located in the Netherlands
- There is no traffic directly recorded in Wireshark against this IP.
- There is, however, traffic in Wireshark against
142.250.189.138
almost immediately after the executable ran.
- 162.159.135.232
- Cloudflare IP
- High abuse rating
- 162.159.135.233
- Cloudflare IP
- High abuse rating for njRAT
Both Cloudflare IPs have pretty hefty traffic, amounting to
64MB~:
Throughout the Wireshark capture, there is a brief connection made within the first 100 packets for
ipinfo.net
(34.117.59.81), likely identifying my public VPN node when the process first launched, logging the public IP in the trove of data sent up to the Cloudflare IPs.
All hosts received data from the box based on the identical
TCP Send events:
If we compare the
TCP Send events against the
WriteFile events we found earlier, the timeline starts to make sense: PID
1580 writes the goods to a ZIP file, upload it through the Cloudflare IPs, then removes it from disk once complete.
If we next filter by the operation
CreateFIle, we can map out exactly what the process wants to find:
1.
Brave,
Chrome,
Edge,
Opera,
Vivaldi,
Yandex
1. Extension MetaMask, an Eth wallet (nkbihfbeogaeaoehlefnkodbefgpgknn)
2. Extension Phantom, an NFT wallet (bfnaelmomeimhlpmgjnjophhpkkoljpa)
3. Extension Binance Wallet, a generic coin wallet (fhbohimaelbohpjbbldcngcnapndodjp)
4. Extension Coinbase Wallet, a generic coin wallet (hnfanknocfeofbddgcijnmhnfnkdnaad)
5. Coin98 Wallet, a generic coin wallet (aeachknmefphepccionboohckonoeemg)
6. Crypto.com wallet, a generic coin wallet (hifafgmccdpekplomjjkcfgodnhcellj)
7. Login data, web data, cookies
2.
Firefox
1. Queries Profiles
3.
Exodus Wallet
1. Checks if folder exists in Appdata
4.
FileZilla
1. Checks if Filezilla.xml exists in Appdata
5.
Discord
1. Discord PTB
2. Discord Canary
3. Discord Development
4. Better Discord
5. Lightcord
6.
Telegram
1.
tdata
folder
After all potential credential locations have been discovered, each are copied over into
\Appdata\Local\Temp\
and zipped into a file of the naming convention
, then the original files are deleted from disk. In my case, it was Epsilon-USER.zip.
While taking initial triage of the warez, I had left the process running in my sandbox. About 20 minutes into my analysis, my Windows VM snapped to 800 x 600 resolution and my processes began closing by themselves. Admittedly, rather than take a snapshot to preserve any forensic data, my IR 'nam flashbacks kicked in and I unplugged the NIC. I did, however, leave Wireshark running throughout the entire session.
Assumably, whomever touched my box during analysis was spooked off by the amount of PowerShell windows & monitoring processes were open at the time as any subsequent executions with my same hostname/username never baited another incoming connection: truly a poor time to catch me pretending to be an end-user.
Though it is unclear which is my actual user, the below sheet is a quick glance through my Wireshark traffic looking for my culprit. Quite a few IPs were tagged by tools as Shifter Proxy, which allows paid members to use residential proxies to anonymize traffic.
"Address": "198.251.88.130",
ponynet AS 53667
rentry resolve point
"Address": "142.250.189.138",
GOOG IP with no abuse
AS 15169 ( GOOGLE )
box reached out starting at packet 41
prob traffic against 81.59.117.34.bc.googleusercontent.com
"Address": "34.117.59.81",
AS 396982 ( GOOGLE-CLOUD-PLATFORM )
actual GCP IP, C2?
resolves to ipinfo.net
"Address": "162.159.135.232",
CF IP
"Address": "162.159.135.233",
CF IP
"Address": "104.18.21.229",
CF IP
"Address": "104.18.10.128",
CF IP
"Address": "142.250.189.142",
AS 15169 ( GOOGLE )
shifter proxy - SP
traffic lasts less than 20 packets towards ends of capture, begins from localhost, all https
looks like a cert download?
STRING: http://crl.pki.goog/gtsr1/gtsr1.crl
STRING: http://ocsp.pki.goog/gts1c301.
STRING: *.google.com..*.appengine.google.com. *.bdn.dev..*.origin-test.bdn.dev..*.cloud.google.com..*.crowdsource.google.com.[TRUNCATED]
"Address": "34.104.35.123",
GCP IP
4 sequential packets: FIN, ACK -> ACK -> FIN, PSH, ACK -> ACK
client -> server
resolves to edgedl.me.gvt1.com, 123.35.104.34.bc.googleusercontent.com - sho
"Address": "162.243.25.33",
digitalocean IP
only 1 packet here, server -> client: RST, ACK
contextually nowhere near any above sessions in wireshark, could be unrelated
In conclusion, stealers today have become quite simple and streamlined in their goals:
1. Trick a user into double-clicking a user process by enticing them with the promise of a game no one else has
2. Pillage their browsers and local apps for any data worth taking
3. Zip them up and ship them off to a C2
4. Erase tracks
This sample did something different: rather than clean up, they purposefully leave the process there to utilize as a RAT later when the user might not be active but the host is online.