published on

Malware Analysis: The Fake SilentPatch That Stole Everything

Here’s a fun story for you all: the other day I was talking with a friend, Silent. He’s pretty well known on the internet, makes a bunch of patches for old games, all that jazz.

When suddenly, this happened:

Another fun day

So, what is the big deal? Well this website, vibecoded because the fun never stops, is impersonating something Silent releases called the SilentPatch. It’s a series of patch for old games, fixing bugs that the developers never really cared to fix, in this case pre PS3 3D GTA games.

So far so good you may be thinking, this website even gives you an all-in-one installer to make your life easier!

The installer packs an electron app, which contains obfuscated self-decrypting js which contains an encrypted Windows executable, which contains a virtualized LZMA routine that unpacks itself.

So, yes, perhaps a little overengineered for a game patch.

Oh and it also contains a small stealer that exfiltrates everything on your computer, among other things: browser data, Windows credentials, cryptocurrency wallets, password dbs, VPN, FTP, basically every file under the sun, clipboard and screen shots for good measure. Kind of forgot that bit.

Oh and there’s blockchain involved too!

The installer

The malware starts with a bog standard NSIS installer. So far so good, a 7z command later and we’re in. It installs an electron app, so guess it’s back to the js mines time today.

The resources folder contains app.asar, elevate.exe and gpu_01vy0n.dat. Hrmmmmm this is sketchy but let’s not get ahead of ourselves first. Let’s try to understand what this application does! Let’s extract the asar and –

Oh no

JS mines day

Removing the JavaScript camouflage

As seen above, it’s heavily obfuscated. How much you may ask? string tables, RC4, constant obfuscation, false branches and a small bytecode interpreter.

Thankfully, code-level obfuscation is a mostly solved problem and I could readily deobfuscate the javascript to understandable levels with existing tools (heck even web apps could produce somewhat comprehensible results).

In a nutshell:

  1. kom3zmm6y0p.js checks the system and rejects some hostnames, VMs GPUs and CPU count.
  2. alre28.js calls PowerShell’s Add-MpPreference to add a Defender exclusion for AppData.
  3. eqstr1czicw7h5o.js reads resources/gpu_01vy0n.dat and decrypts it with AES into %USERPROFILE%/AppData/.cf4kvz7t/5aaygzq9gl.exe
  4. pscwm7u1.js launches the decrypted stealer

After more digging around, I found the key and IV used to decrypt this file. Additionally, the first 67 bytes were skipped. The key material is:

Key: 11f56b461452e697571d19e69964473d9c27206bd57f6b8a5c95cf0c42796a15 IV: 0afa4d2bc5469bd327ff56f24c5aaf69

The binary can be readily decrypted with the following command:

tail -c +67 'gpu_01vy0n.dat' | openssl enc -d -aes-256-cbc -K 11f56b461452e697571d19e69964473d9c27206bd57f6b8a5c95cf0c42796a15 -iv 0afa4d2bc5469bd327ff56f24c5aaf69 -out 'gpu_01vy0n.decrypted.bin'

Payload

As one does, the first thing I did was uploading this sample on virustotal. DetectItEasy found signs of VMProtect usage which, for the uninitiated, means it’s going to be a long night. Loading the sample into Ghidra didn’t help much either, as the binary was obviously heavily obfuscated.

At this point I looked at available anti-VMProtect tools but none seemed to really fit my criterias, so I started manually reversing the logic based on publically available info (went far along to realize there was an LZMA decompressor at least) until I found VMPStatic. I cannot begin to state how thankful I am that not only this tool exists but that it managed to get a PR to support the version of VMProtect used a day before I looked at this malware, talk about luck.

Now, VMProtect has multiple kind of protections. VMPStatic focuses only on the packing side of things, and not the actual virtualization, so it isn’t a full deo bfuscation, but it’s useful enough to figure out how the malware worked.

Looking at the unpacked code, I noticed new small helper functions that were called hundred of times. I first found one to load exported calls. The way it is done in this binary is that, instead of storing the name of the function it wants to call, it stores a hash of it. It then loops through all the functions exposed by the DLL, hash them and compare them to see if it can find the one it wants.

h = 0xa1d83ff2;

for (byte c : export)
    h = h*0x21+c;

return h^0x23f72079;

Another set of wrappers turned out to be small string decoders and helped me figure out the most important routines of the malware. By writing some helpers reimplementing them and letting them run on the new unpacked session I managed to decrypt the strings used by the malware, huzzah!

[...]
0x14004d258	wide_ror7_mix	Bitwarden
0x14004d270	wide_ror3_xor	KeePass
0x14004d280	wide_sub_ror5	AuthyDesktop
0x14004d2a0	wide_ror7_mix	WinAuth
0x14004d2b0	wide_sub_ror5	_Local
0x14004d2c0	byte_nswap_mix	[PWMANAGERS]\r\n
0x14004d2e0	byte_ror1_xor	.txt,.md,.csv,.json,.doc,.docx,.xls,.xlsx,.pdf,.
cfg,.kdbx
0x14004d31c	byte_sub_ror3	FG_
[...]

From here on out, it was just a matter of following the XREFs and trying to understand back the logic of the binary.

Its main logic is relatively simple, all things considered:

main() {
    if (bad_environment())
        panic();

    backend = blockchain_shenanigans();
    if (!connect_https(backend) || !campaign_is_active())
        exit();

    upload_hwid();
    get_browser();
    get_wallets();
    get_vpn();
    get_screen();
    upload_data();
    send_completion_pulse();
    process_remote_tasks_if_present();
}

It’s the epitome of a stealer in that is very much in steals everything under the sun. Basically every recognized extension in any default folder is exfiltrated, cryptocurrency wallets but also vpn data, browser passwords, steam accounts up to roblox (lol).

Blockchain

One thing I forgot to mention so far is that this is a blockchain powered malware! Thank god to technical progress!

It does an eth_call against a smart contract deployed on something called Polygon, a cheaper ethereum based blockchain from what I understood, and it executes locally on an RPC node the “smart contract” that returns a static value.

The contract used and the RPC nodes are:

0xBfeF14d8BC5f9E02B0e7057b37dc92BB370e3AFF

polygon.drpc.org
polygon-bor-rpc.publicnode.com
poly.api.pocket.network
polygon.lava.build
polygon-public.nodies.app

This static value is in the format IV||ciphertext that, once decrypted, gives out the actual website used by the malware as its C2.

You can find included below the script I used to retrieve the domain.

[nix-shell:/tmp]$ ./decrypt_backend.sh 
sso.travel-track.xyz:443

[nix-shell:/tmp]$ cat decrypt_backend.sh 
#!/usr/bin/env bash
result="$(
  curl -fsS https://polygon.drpc.org/ \
    -H 'Content-Type: application/json' \
    --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xBfeF14d8BC5f9E02B0e7057b37dc92BB370e3AFF","data":"0xf581b6e3"},"latest"],"id":1}' |
  jq -er '.result'
)" || exit 1

res="${result#0x}"

packed="$(
  printf '%s' "${res:128}" |
    xxd -r -p |
    tr -d '\000'
)"

iv="${packed:0:32}"
ciphertext="${packed:32:64}"

printf '%s' "$ciphertext" |
  xxd -r -p |
  openssl enc -d -aes-256-cbc \
    -K 212546ea10b2ed790f740ceeabec094a6ade21d38676b4923ea742b134cfd2fe \
    -iv "$iv"

printf '\n'

After that it’s as described in the pseudocode before. It first checks whether /app/status returns active, and then exfiltrates them using metrics like endpoints as listed below:

/app/metrics/bbwzk.wfff
/app/blobs/bbwzk.wfff
/app/pulse/bbwzk.wfff

I think the malware was programmed this way as an anti-takedown measure, so the campaign domain can be rotated as needed if taken down.

So what is it?

Well this seems quite high effort for a stealer campaign, oddly targetted with a purpose made website and all the obfuscation you’ve seen above. That makes me think of a MaaS campaign (Malware as a Service).

Looking up it seems to me derived either from OmniStealer or Remus Stealer, the latter of which seems to fit more closely the C2 weird blockchain setup that this sample uses.

I uploaded the following samples to virustotal:

Conclusion

Well if it isn’t goofy ol’ me writing a blog post after… 6 years?? By this time I’ll be retired when I write the next one heh. For my govern I’ve been busy, I’m in the final year of a PhD at the french atomic energy comission and, uh, yeah. I think that’s enough :D

All in all though I’m quite happy about what I managed to do, I thought I’d be quite rusty given I haven’t done malware analysis in years but, for a day of work, I’m quite happy of myself heh.

Anyways don’t click random links, don’t send your data to the DPRK and check out Silent’s work.