Torg Grabber: Anatomy of a New Credential Stealer


TL;DR
It started with a lie. A sample walked into the lab wearing a Vidar label like a cheap suit two sizes too small. We pulled the threads, and the whole thing came apart. What fell out was a previously unknown information stealer we named Torg Grabber – 334 samples compiled over three months, a rapid evolution from Telegram dead drops through an encrypted TCP protocol nobody asked for, all the way to a production-grade REST API that worked like a Swiss watch dipped in poison. Over 40 operator tags pulled from the binaries – a mix of nicknames, date-encoded batch IDs, and confirmed Telegram user IDs – fingerprinted individual MaaS customers and confirmed what we already suspected: this was a builder-and-panel operation, crime as a service, infrastructure included. OSINT resolution of the numeric tags peeled back the curtain on eight operators as Telegram accounts buried up to their necks in the Russian cybercrime ecosystem. The bot tokens gave us the developer accounts behind the whole show. Nobody said crime doesn’t pay, but nobody said it doesn’t leave fingerprints either.
The misclassification that started It all
The sample came in on a Tuesday in early February, wearing the name Vidar Stealer the way a pickpocket wears a priest’s collar. It didn’t fit. A 747 KB PE64 binary compiled with MinGW/GCC – when Vidar v17.9 is a 32-bit MSVC job that, as a colleague put it, “looks significantly different.” That was like saying a Great Dane looks significantly different from a Pekingese. You didn’t need a magnifying glass.
A deeper look turned up a self-identifying debug string – "grabber v1.0" – sitting in the binary like a monogrammed handkerchief left at a crime scene. The C2 protocol was all wrong for Vidar: REST API endpoints (/api/auth, /api/upload/chunk), ChaCha20 encryption, HMAC-SHA256 authentication. This wasn’t Vidar any more than I was the Queen of England.
We ran it against StealC v2 for good measure – similar endpoint patterns on the surface, the way all gin joints look alike from the sidewalk. Zero protocol overlap. Different endpoint structure, different communication model, different encryption. This was something new, something nobody had put a name to yet.
So we named it ourselves. Torg Grabber – “Torg” from its most-used C2 domain technologytorg.com (Russian “торг” = trade, marketplace – fitting for a business that trades in other people’s secrets), and “Grabber” from the malware’s own vocabulary (GRABBER_HOST, GRABBER_TAG, "grabber v1.0"). If a thing names itself, you ought to listen.
Timeline: Two months of rapid development
Three hundred thirty-four samples. Three months. It was like watching a time-lapse film of a weed growing through concrete. The corpus told the story of a malware operation spinning up in real time, stumbling forward with the reckless confidence of a man who knows exactly what he’s doing and doesn’t much care who’s watching.

Three exfiltration mechanisms. Three ways to get the goods out. Each one a little smarter than the last, the way a burglar graduates from smashing windows to picking locks to making copies of the key.
Phase 1: Telegram Bot API (Dec 9–11, 2025)
The earliest builds were small and nervous, the way a rookie’s hands shake on his first job. Compact little things, 270 to 313 KB, that grabbed credentials, stuffed them into a ZIP archive, and shipped the whole package to a private Telegram channel via sendDocument. No encryption beyond TLS. A User-Agent: TG header about as subtle as a neon sign in a funeral parlor. Five retry attempts, and if the ZIP upload choked, a fallback to plaintext sendMessage – the digital equivalent of shouting your secrets across a crowded room.
Twenty-five samples, eight bot tokens, eight private channels, each with two or three members. This was the prototype phase: fast to set up, zero infrastructure cost, and about as durable as a paper umbrella in a monsoon. Telegram can revoke tokens on a whim, and the API calls stick out in traffic logs like a tall man in a short crowd.
Phase 2: GRAB Binary TCP Protocol (Dec 17–20, 2025)
Four samples. A narrow four-day window. This was the experimental phase – somebody had an idea, and they were going to see if it could walk before they taught it to run.
Instead of HTTP, the malware opened a raw TCP socket to *.tara.net.bd on port 50443 and spoke a custom binary protocol that had all the charm of a coded knock on a speakeasy door:
- A 9-byte frame: 4-byte
GRABmagic, 1-byte type, 4-byte length - ChaCha20-Poly1305 AEAD encryption with HMAC-SHA256 key derivation
- SHA-256 hash of the payload sent before the encrypted data
- 64 KB chunks with 5-second retry intervals
The C2 hostnames were bk.tara.net.bd and raketa.tara.net.bd – “raketa” being Russian for “rocket,” because even criminals have a sense of poetry. Both under a Bangladesh TLD but geolocated to Turkey, which made about as much geographic sense as a polar bear in Havana. The encryption key was hardcoded: 0123456789abcdef repeated. A test key. Development builds, still warm from the compiler.
See Appendix A, Figure A1
Technically sophisticated – proper AEAD, authenticated handshakes, chunked transfer. The kind of work that said the developer knew cryptography the way a safecracker knows tumblers. But it was abandoned after four builds. Running a custom TCP protocol at scale turned out to be harder than hiding behind Cloudflare, which is to say, harder than letting somebody else do the heavy lifting. Some lessons you only need to learn once.
Phase 3: REST API over HTTPS (Dec 18 onward)
This was the production rig. The real thing. No more rehearsals.
The malware performs a JSON registration at /api/auth, sending along a machine fingerprint – GPU, wallpaper hash, hardware ID, antivirus product – like a new inmate checking into prison with his personal effects. In return, it gets configuration, a session token, and sometimes shellcode, because some operators like to bring their own party favors. Then comes the upload: stolen data, chunked over HTTPS, ChaCha20-encrypted, routed through Cloudflare. Each request carries an HMAC-SHA256 X-Auth-Token header, because even thieves want to know they’re talking to the right fence.
See Appendix A, Figure A2
Over two months, the binary fattened up from ~410 KB to ~747 KB, the way a confidence man’s wallet thickens over a good season. The additions were considerable: a 20 KB ChaCha20-encrypted Reflective DLL for bypassing Chrome 127+ App-Bound Encryption across 7 Chromium browsers via their IElevator COM interfaces; 20 direct NT syscall wrappers with PRNG-obfuscated tables; and an ever-growing shopping list of collection targets – 850 browser extensions alone consuming ~213 KB of binary space, like a burglar’s toolkit that takes up half the trunk. Two size epochs are visible – a ~160 KB jump around January 21 that marks a major feature release as clearly as a new coat of paint on an old building. The newest builds kept rolling off the line daily through February 2026, each one a little bigger, a little meaner, a little hungrier.
The loader chain: From dropper to stealer
Torg Grabber doesn’t show up at the party alone. It arrives wrapped in layers, the way a bad idea shows up wrapped in good intentions — three skins of encryption and obfuscation to peel away before the stealer ever touches memory. Each skin has a job. The outer one: crypter-level polymorphism, the kind that makes every sample look like a different animal. The middle: reflective PE loading, never leaving fingerprints on disk. The innermost: the stealer itself, finally naked and ready to work.
Stage 0: The Dropper
The outermost layer changes its face depending on who’s handing it out. Telemetry from our userbase paints the picture – several lure families, all funneling into the same loader chain like tributaries feeding a dirty river:
- Fake game cheats:
CrimsonLoader.exe, RivalMods.exe - Cracked software: R
elease-app-x64.rar→Set-up.exe,Aerovora.zip,Terraria_1.4.5.zip - ClickFix clipboard: PowerShell one-liner via Google Apps Script (see full chain below)
Regardless of the lure, the final dropper drops a randomly-named executable into C:\Windows\ – v4jkqh.exe, hkjpy08.exe, ln3dkgz.exe, en3v4ior.exe – names that look like someone fell asleep on the keyboard. This pattern is consistent across 78 distinct samples in our telemetry. The crypter stage. The thing that gets you in the door.
Before it spawns the next stage, the dropper does something clever. Configuration propagation. It sets environment variables that carry the operator’s whole setup across process boundaries — the way a con man memorizes his cover story before he walks into the bank:
One compiled stealer, a hundred operators. The dropper injects identity at runtime. Crime as a service, served by environment variables.
Stage 1: Self-Extracting Loader
The first code stage is a MinGW-compiled PE64 with an encrypted overlay pasted on the end — beyond the section data, like a secret message written on the back of a photograph. The overlay structure lives in the file’s last 8 bytes. You have to read backwards to find the beginning:
See Appendix B, Listing B1
The extraction pipeline runs like a three-card monte:
- Hex decode — Custom hex encoding: 3 bytes per output byte, two hex digits plus a separator. Lower entropy than raw ciphertext. The kind of detail that evades entropy detection the way a whisper evades a crowded room.
- AES-256-CBC decrypt — Key and IV pulled from the overlay. Every build gets its own key material. The builder doesn’t recycle.
- Parse decrypted buffer — A uint32 skip count, then null-terminated API name strings (
NtWriteVirtualMemory,NtProtectVirtualMemory), then the shellcode. The loader resolves those NT APIs at runtime and injects the shellcode into memory using direct syscalls. No imports. Clean hands.
Stage 2: Reflective PE Loader
The shellcode from Stage 1 is a PE in disguise. A reflective loader carrying the final Torg Grabber payload as an encrypted blob in .rdata — about 793 KB of trouble. This stage runs entirely in memory. It never touches disk. The kind of ghost that leaves no footprints.
Dynamic API Resolution
The loader finds every Windows API it needs by walking the PEB — Process Environment Block — and parsing export tables. No GetProcAddress in the import table. Static analysis looks at the binary and sees nothing. It’s the malware equivalent of paying cash.
AES-256-CBC Decryption
The blob gets decrypted first. AES-256-CBC, hardcoded 256-bit key, 128-bit IV. Each build carries different constants. Fingerprints:
See Appendix B, Listing B2
Four Cascaded Byte Transforms
After AES comes the garnish. Four byte-level transforms in sequence. Reversible arithmetic over GF(2^8). The constants vary by build; the structure never does:
| Step | Operation | Constant | Purpose |
| 1 | byte = (byte + K₁) & 0xFF | 0x7C / 0xAC | Additive shift |
| 2 | byte = byte ^ K₂ | 0x68 / 0x58 | XOR mask |
| 3 | byte = ROR(byte, 2) / ROL(byte, 2) | 2 bits | Bit rotation |
| 4 | byte = (byte * K₃) & 0xFF | 0xC5 / 0xCD | Modular multiply |
Five layers total with AES. Simple XOR-key recovery goes home empty. Automated decryption without the right constants hits a wall.
Anti-Analysis: NOP-Equivalent Functions
Between decryption stages, the loader calls functions that look busy. Multi-register shuffles. Conditional branches. Memory loads. Complex enough to make a decompiler sweat. Net effect: zero. They’re NOPs dressed up for the opera:
Several of these stubs get called between each decryption stage and before the memmove. Dead code padding the call graph like sawdust in a cheap sausage.
The Hidden memmove: PE Reassembly from Non-Contiguous Chunks
The operation that matters most — and the one you’re most likely to miss. After the byte transforms, a single memmove stitches the final PE together from two pieces that weren’t sitting next to each other:
See Appendix B, Listing B3
Skip the memmove and you get a PE with a poisoned .idata section and 110 KB of overlay garbage. It loads into IDA. It crashes when you run it. The encryption stuffed junk between the two halves — any automated extractor has to know exactly where to cut and paste. Final size: 0xA6E00 = 683,520 bytes. Hardcoded in the loader as a VirtualAlloc parameter.
Manual PE Mapping
After reassembly, the loader maps the PE the old-fashioned way. Reflective loading 101:
- Allocate —
VirtualAlloc(PAGE_READWRITE)forSizeOfImagebytes - Copy headers — first
SizeOfHeadersbytes - Map sections — to their virtual addresses (
VirtualAddress + base) - Process relocations — apply delta from preferred
ImageBaseto actual allocation - Resolve imports — walk the Import Directory,
LoadLibraryAandGetProcAddressfor each DLL/function - Set section permissions —
VirtualProtectwithPAGE_EXECUTE_READ,PAGE_READONLY,PAGE_READWRITE - Call entry point —
AddressOfEntryPoint + base
The stealer PE never hits disk. It lives only in memory, mapped inside the loader’s process. A ghost inside a ghost.
Stage 3: Torg Grabber
The final payload. 683 KB PE64. MinGW/GCC. Seven hundred thirty-seven functions in fifteen categories, organized like a filing cabinet in a detective’s office — everything in its place:
See Appendix B, Listing B4 (Stage 3: Torg Grabber).]
Execution starts at main_data_collection_and_exfil. The orchestrator. The one running the show:
- Reads configuration —
GRABBER_*environment variables, set by the dropper, with hardcoded fallbacks for the forgetful - Profiles the system — MachineGuid, GPU, process list, antivirus (46 signatures across 24 products), VM/sandbox detection, CIS locale check
- Creates a mutex —
Local\<MachineGuid>so only one instance runs at a time - Registers with C2 — POST to
/api/authwith ChaCha20-encrypted JSON, gets a session ID and maybe streaming config - Resolves NT syscalls — parses
ntdll.dll exports, builds PRNG-obfuscated syscall table - Collects data — 25 Chromium browsers, 8 Firefox, 850 extensions, Discord, Steam, Telegram, VPN, FTP, email, password managers, wallets, screenshot, installed software, Desktop/Documents files
- Exfiltrates — archives to in-memory ZIP or streams chunks, uploads via chunked HTTPS with ChaCha20 and HMAC-SHA256
The stealer can also take shellcode from the C2 at registration. decrypt_and_execute_shellcode handles ChaCha20-decrypted, zlib-compressed payloads — allocates executable memory via NtAllocateVirtualMemory, runs it. Arbitrary post-exploitation without a new binary. Before execution, export_config_to_env writes the config back to environment variables so any child process inherits the operator’s settings.
Configuration propagation: The environment variable chain
One pattern runs through the whole chain: configuration travels by environment variable. The dropper sets GRABBER_*. The stealer reads it at startup (init_grabber_config_from_env). Before process injection — ABE bypass, shellcode — the stealer writes the config back to env vars (export_config_to_env). Child processes inherit. No recompilation. One payload, many operators:
See Appendix B, Listing B5
The stealer binary is operator-agnostic. The builder customizes the dropper. The dropper does the rest.
In the Wild: Observed infection chain
Static analysis gives you the stages. Behavioral telemetry gives you the story. We captured the full delivery chain on a real victim machine — January 30, 2026 — from initial social engineering through PowerShell stages to stealer execution. The whole show, start to finish.
The ClickFix Initial Access
Before the InnoSetup dropper. Before the PowerShell. A clipboard hijack. The victim hits a malicious Google Apps Script page:
https://n-3t7yxs7pcq6bihciyqway6qnhvhrol2fgy2tdaa-0lu-script.googleusercontent.com/blank
The page drops a PowerShell command into the clipboard and tells the victim to paste. Classic ClickFix. The 309-byte payload (SHA256: 07b96e5c...e6c26edebf, detected as HTML:Clipboard-A) triggers the base64-encoded stager download from j0o.pw/core2. The clipboard payload was captured along with the dropped stager — the missing link between the social engineering and the PowerShell chain.
Full Process Tree
See Appendix B, Listing B6
Stage by Stage
0. ClickFix clipboard attack — The victim visits a Google Apps Script page (n-3t7yxs7pcq6bihciyqway6qnhvhrol2fgy2tdaa-0lu-script.googleusercontent.com) with a fake verification or update prompt. The page silently copies a PowerShell command to the clipboard and tells the user to hit Win+R and paste. That 309-byte payload (HTML:Clipboard-A) kicks off everything — the Chrome InnoSetup download and the hidden PowerShell downloader both trace back to that paste. Google Apps Script: trusted domain, free hosting, URLs you can’t blocklist without catching the whole neighborhood in the net.
1. Dropper download — Chrome pulls GAPI_Update.exe from Dropbox (uc0be8c69...dl.dropboxusercontent.com). 60 MB InnoSetup. Extracts benign DLLs (msvcp140.dll, vcruntime140.dll, WebView2Loader.dll) to %LOCALAPPDATA%\Connector\. Looks like a real install. Looks like a lot of things that aren’t.
2. Hidden PowerShell BITS downloader — A PowerShell process with -W Hidden -E <base64>. The decoded command uses BITS Transfer — Windows’ Background Intelligent Transfer Service — to grab the next script:
BITS runs through svchost.exe, not PowerShell. Legitimate Windows service. Many endpoint tools never look. The script runs, then deletes itself. Fileless delivery. No artifact left behind but the memory of the thing.
The sys.ps1 stager — decoded content:
Live payloads downloaded from both endpoints (infrastructure still serving as of February 8, 2026): /core is 6,944 bytes (SHA256: a7fafc75...079fa3e2, VT); /core2 is 6,972 bytes (94c964eb...cd800fd). Same structure: base64-wrapped payload, $e = [System.Convert]::FromBase64String('...'); Invoke-Expression [System.Text.Encoding]::UTF8.GetString($e).
3. Fake “Windows Security Update” progress bar — The script brings the console to the foreground with Add-TypeP/Invoke:
See Appendix B, Listing B7
Add-Type compiles via csc.exe — producing pvxhy3qg.cmdline and bz2ytolk.cmdline invocations in the process tree. Not AMSI bypass. Just bringing the window forward and resizing to 80x20. Then an animated ASCII progress bar. 420 seconds. Seven minutes. 24 milestones. The victim watches. The real work happens in the background.
See Appendix B, Listing B8
4. XOR-encrypted triple loader download — While the progress bar ticks, a background Start-Job downloads three loaders via BITS Transfer, Invoke-RestMethod as fallback. Each file: base64 blob decrypted with a 256-byte repeating XOR key:
See Appendix B, Listing B9
Base64 decode. XOR each byte against the key, cycling every 256. We verified: both t4e.pw/res1.php (2.6 MB) and t4e.pw/res4.php (2.7 MB) decrypt to valid PE64 with MZ headers. Three loaders, executed sequentially with 30–41 second delays. Hidden.
Endpoint versioning: /core uses res{1–3}, /core2 uses res{4–6}. Domains split: j0o.pw = stagers, t4e.pw/re3.pw = loaders.
| Stager version | Loader 1 | Loader 2 | Loader 3 |
| /core (6,944 B) | t4e.pw/res1.php | t4e.pw/res2.php | re3.pw/res3.php |
| /core2 (6,972 B) | t4e.pw/res4.php | t4e.pw/res5.php | re3.pw/res6.php |
5. Loader execution and unpacking chain — Decrypted loaders land in %LOCALAPPDATA%\Microsoft\Windows\UpdateCache\ as updateWeb_Microsoft_v7028111.exe and kin. Fake version strings: “Breathtaking Output 383” / “Global Channel Port Limited”. Server-side polymorphism. Fresh build per download.
Complete unpacking chain: seven layers — base64 → XOR → AES-CBC overlay → hex-encoding → CTR cipher → LZNT1 → AES-CBC + byte transforms. Both chains deliver the same 683 KB stealer, compiled 19 minutes apart:
See Appendix B, Listing B10
Binary comparison: .data section byte-for-byte identical. .text differs by 48 bytes. Campaign IDs: “meow” vs “gapi”.
6. Detection — The captured instance (eee3f818..., 13 MB) spawned twice. First instance proceeded with extraction. Second spawned dllhost.exe. Behavioral detection terminated the second instance as the loader tried to disable Event Tracing for Windows before execution.
New Infrastructure: The PowerShell C2 Layer
Four domains. Delivery and exfiltration split like a good heist crew:
| Domain | Role | Endpoints | IP | Protocol |
| j0o.pw | Stager only | /core, /core2 | 84.200.125.231 | HTTPS |
| t4e.pw | Loader only | /res1.php–/res5.php | 84.200.125.231 | HTTPS |
| re3.pw | Loader only | /res3.php, /res6.php | 84.200.125.231 | HTTPS |
| si-dodgei.digital | Stealer C2 | /api/auth, /api/upload/* | 104.21.50.122 (Cloudflare) | HTTPS |
All three .pw domains hit the same IP (84.200.125.231). j0o.pw and t4e.pw registered January 28, 2026 — same day, PublicDomainRegistry.com, orderbox-dns.com DNS, Let’s Encrypt certs issued together. Palau TLD. Short names. Disposable. SOA emails: ellisdtum@gmx.com, jameyjswoeste@gmx.com. GMX. Throwaway.
Infrastructure still live as of February 8, 2026. Server-side polymorphism confirmed. si-dodgei.digital = new stealer C2 — registered December 24, PDR, Cloudflare. Separate delivery and exfiltration. Bad burns on the loader side don’t touch active stealers. Burns on the stealer C2 don’t touch the delivery pipeline. Operational resilience. The kind of planning that keeps you in business.
Technical highlights
Direct syscalls with PRNG obfuscation
The malware resolves NT syscall numbers the hard way – parsing ntdll.dll’s export table straight from the PEB, scanning for syscall; ret byte patterns, and storing the results in a table encrypted with a custom PRNG. The seed comes from QueryPerformanceCounter, PID, TID, and stack ASLR – four sources of randomness stirred together like a bartender making a cocktail that nobody ordered. Twenty syscalls wrapped, covering process injection for ABE key extraction, file I/O for prying open locked browser databases, and process termination for killing browsers that have the bad manners to hold file locks while someone’s trying to rob them.
App-Bound Encryption bypass: A 20 KB reflective DLL
Starting with Chrome 127 in July 2024, Google introduced Application Bound Encryption (ABE) – the browser’s master encryption key chained to the browser’s own process identity via a Windows Elevation Service COM interface. A neat trick. Credentials could only be decrypted from within a trusted browser process. It was the kind of lock that made honest people feel safe and dishonest people feel challenged.
Torg Grabber solved it with a lockpick that weighed exactly 19,968 bytes. A ChaCha20-encrypted Reflective DLLburied in the .rdata section like a razor blade in an apple.
See Appendix A, Figure A3
The Encrypted Payload
The DLL sits at a fixed offset in .rdata as an undifferentiated byte blob – no PE headers showing, nothing to catch the eye in static analysis. It might as well have been a patch of wallpaper. The parent function decrypts it in-place with a custom ChaCha20 implementation: hardcoded 256-bit key, 96-bit nonce, 312 blocks of 64 bytes. After decryption, the MZ and PE signatures emerge like a face surfacing in dark water, and the code walks the export directory looking for one specific string: ReflectiveLoader.
We extracted and decrypted the payload. It had the following particulars:
| Property | Value |
| Size | 19,968 bytes (0x4E00) |
| Architecture | x64 PE32+ |
| Compiler | GCC 15.2.0 (MSYS2 MinGW-w64) |
| Exports | ReflectiveLoader, GetIp |
| Sections | 10 (.text, .data, .rdata, .pdata, .xdata, .bss, .edata, .idata, .tls, .reloc) |
The ReflectiveLoader export is textbook reflective injection: it walks backwards from GetIp() to find its own MZ header, resolves LoadLibraryA, GetProcAddress, and VirtualAlloc from kernel32.dll via PEB walking and ROR13 export name hashing, maps sections, processes relocations, resolves imports, flushes the instruction cache, and calls DllMain. Standard procedure. The kind of thing they’d teach in school if schools taught this sort of thing.
Browser Detection and COM Elevation
Once loaded, the DLL spawns a worker thread that reaches back to the parent through a named pipe and collects the ABE-encrypted key material. Then it figures out where it’s living. A call to GetModuleFileNameW, the path lowercased and matched against a list of known executables and installation directories – like a kidnapping victim recognizing the room by the wallpaper:
| Browser | Process / Path Match | Own CLSID | IID Variants | Vtable Offset |
| Edge | msedge.exe, \microsoft\edge\ | {1FCBE96C-...} | 2 | +64 |
| Chrome | chrome.exe, \google\chrome\ | {708860E0-...} | 3 | +40 |
| Brave | brave.exe, \brave-browser\ | {576B31AF-...} | 2 | +40 |
| Avast | avastbrowser.exe, \avast software\browser\ | {EAD34EE8-...} | 1 | +40 |
| AVG | avgbrowser.exe, \avg\browser\ | {EDC3300F-...} | 1 | +40 |
| Vivaldi | vivaldi.exe, \vivaldi\ | Chrome’s CLSID | 3 | +40 |
| Opera | opera.exe, \opera software\ | Chrome’s CLSID | 3 | +40 |
Each Chromium-based browser that implements ABE registers its own Elevation Service COM class with a browser-specific CLSID. The DLL carries five of these like a skeleton key ring: Chrome, Edge, Brave, Avast, AVG. For Vivaldi, Opera, and any unknown Chromium fork that wanders into the crosshairs, it falls back to Chrome’s CLSID and hopes for the best.
There’s a wrinkle, though, and it matters: Edge uses a different vtable layout. Extra methods in the interface push DecryptData to vtable offset +64 – method index 8 – instead of the standard +40, method index 5. Everyone else lines up neatly. Edge has to be different. The DLL handles this with a branch on browser type ID, because in this line of work, the details are what keep you out of trouble or put you in it.
After creating the COM object with CoCreateInstance(CLSCTX_LOCAL_SERVER), the DLL calls CoSetProxyBlanket with RPC_C_AUTHN_LEVEL_PKT_PRIVACY and EOAC_DYNAMIC_CLOAKING to set the security context, then invokes IElevator::DecryptData with the encrypted key wrapped in a BSTR. When it works – and it works more often than Google would like – the method hands back a 32-byte BSTR: the AES-256 master key. The keys to the kingdom, delivered through the kingdom’s own front door.
The Response
The decrypted master key is packed into a 44-byte response and written back through the named pipe, neat as a coroner’s report:
The DLL carries debug logging – [DLL] Detected: Chrome, [DLL] Elevator object created with IID variant 2, [DLL] Master key extracted successfully! – that gets buffered and sent back with the key. Development artifacts left in the production code, like a carpenter’s pencil marks under the paint. Sloppy, maybe, but also human. After the response goes through, the parent process terminates the suspended browser and uses the recovered master key to decrypt the Chromium encrypted_key from Local State, which unlocks the credential entries in Login Data, Cookies, and Web Data. The vault door swings open. Everything inside belongs to someone else.
Corpus-Wide ABE Timeline
The encrypted DLL blob runs hot with entropy in the PE’s .rdata section, and the parent binary always carries the string "ReflectiveLoader" – both traits as distinctive as a scar. We didn’t need to decrypt anything to spot ABE capability across all 139 samples. Automated triage told the story:
| Phase | Samples | ABE Bypass | Blob Size |
| Telegram Bot API (Dec 9–11) | 25 | None | – |
| GRAB TCP Protocol (Dec 17–20) | 4 | None | – |
| REST API, first build (Dec 18) | 1 | None | – |
| REST API, production (Dec 22+) | 109 | All | 18–20 KB |
| GRABBER variant w/o ABE (Feb 3) | 1 | None | – |
The ABE bypass shipped with the very first dedicated C2 domain build – attackzombie.com, December 22, 2025 – and rode along in every REST API sample since. Not a later addition. A launch feature. The developers considered it essential equipment, the way a safecracker considers a stethoscope. The lone exception was a 122 KB safeguss.com sample from February 3 that looked more like a stripped loader than the full stealer – a scout, not the army.
The encrypted blob grew over time, the way a pickpocket’s ambition grows:
See Appendix A, Figure A4
The 18-to-19 KB growth around December 29 lines up with the addition of Avast and AVG Secure Browser CLSIDs. Two 20 KB blobs flickered into existence on January 26–27 and then vanished – an experimental build that got trimmed back, like a line of dialogue that didn’t make the final cut.
Operator tags: Fingerprinting the MaaS customers
Every REST API build carries an operator tag – a short string identifying the customer, sent as the first field in the C2 registration. A calling card. A signature on the dotted line. The tag is resolved through a two-tier mechanism: the malware checks the GRABBER_TAG environment variable first, and only falls back to a hardcoded default if the env var comes up empty:
In older builds, the fallback tag sits in .rdata between the mutex format string "Local\%s" and the C2 domain – as conspicuous as a name tag at a criminal convention. In newer builds, the compiler inlines short tags as mov immediates (e.g., mov dword ptr [rip+disp], 73756564h for “deus”), and the longest tags use mov rax, imm64. Even the machine code has an opinion about how to keep a secret.
At runtime, the resolved tag gets copied into a 640-byte registration structure and shipped off to /api/auth along with the machine’s vital statistics:
A brief experiment – five samples across three days in early February – pushed the idea further: the payload read everything from environment variables. GRABBER_HOST, GRABBER_TAG, GRABBER_ANTI_SNG,GRABBER_ANTI_VM, GRABBER_STREAMING. One binary to serve them all. A universal key. At first it looked like the experiment died after three days – subsequent builds went back to hardcoded domains and tags. But starting Feb 10, the env-var mechanism came back for good: every build from Feb 10 onward includes GRABBER_* env var support alongside hardcoded defaults, and the builder simultaneously switched all operators from plaintext .rdata strings to compiler-inlined mov immediates. A unified builder update. The stealer became truly operator-agnostic – the way a gun doesn’t care whose hand it’s in.
Across the corpus, we extracted over 40 distinct operator tags. The most active:
| Count | Tag | Type | Domains Used With |
| 42x | 5197705037 | Telegram ID (confirmed) | gogenbydet.cc, technologytorg.com, bbcplay.top, playbergs.info |
| 24x | 8172045377 | Telegram ID (confirmed) | gogenbydet.cc, bbcplay.top, playbergs.info |
| 24x | main1402_2 | Date-encoded batch | evasivestars.com |
| 19x | 0902 | Numeric (build ID?) | evasivestars.com |
| 16x | 5362456016 | Telegram ID (confirmed) | gogenbydet.cc, bbcplay.top, playbergs.info |
| 15x | main1402 | Date-encoded batch | evasivestars.com |
| 14x | 5551690712 | Telegram ID (confirmed) | gogenbydet.cc, bbcplay.top |
| 9x | Main | Nickname | sinixproduction.com, startbuldingship.com, technologytorg.com |
| 9x | 578510323 | Telegram ID (confirmed) | gogenbydet.cc |
| 7x | Den | Nickname | technologytorg.com, attackzombie.com |
| 7x | 7612929707 | Numeric (unresolved) | gogenbydet.cc, bbcplay.top, playbergs.info |
| 6x | Deus | Nickname | attackzombie.com, technologytorg.com, safeguss.com |
| 5x | main2402_1 | Date-encoded batch | evasivestars.com |
| 4x | Gapi | Nickname | si-dodgei.digital, avanpost-fi.digital |
| 3x | Gd | Initials | technologytorg.com, attackzombie.com |
| 3x | 7287445517 | Telegram ID (confirmed) | gogenbydet.cc |
| 3x | main_new | Nickname | evasivestars.com, wulingyuanparkzone.com |
| 3x | main2002_2 | Date-encoded batch | evasivestars.com |
| 3x | Meow | Nickname | si-dodgei.digital |
| 2x | 7488523544 | Telegram ID (confirmed) | playbergs.info |
| 2x | 8251115314 | Numeric (unresolved) | playbergs.info |
| 2x | 7694683550 | Numeric (unresolved) | gogenbydet.cc, playbergs.info |
| 2x | main2 | Nickname | technologytorg.com |
| 2x | BB1 | Nickname | safeguss.com |
| 2x | main7 | Nickname | evasivestars.com |
| 2x | main2302_1 | Date-encoded batch | evasivestars.com |
| 2x | pb2 | Nickname | safeguss.com |
| 2x | deus_auto | Nickname | wulingyuanparkzone.com |
| 2x | capha2 | Nickname | safeguss.com |
Three kinds of tags now: nicknames (den, deus, gd, tf, main, BB1, BattleBuild, capha2, pb2) – the kind of names men give themselves when they think nobody’s looking. Date-encoded batch IDs (main1402, main1402_2, main2002_2, main2302_1,main2402_1 – where the digits encode the build date as DDMM) – evasivestars.com alone received 74 samples through this mechanism, each tag a timestamp on a factory floor. And numeric Telegram user IDs that we confirmed by running eight of twelve through the TelegramDB OSINT database. The C2 panel uses the IDs to route stolen-goods notifications to the operator’s Telegram. The main/main2/main5/main7/main_new/main10 progression suggests a developer tag, while the date-encoded variants (main1402 = Feb 14 batch) indicate automated nightly builds. The deus lineage evolved through deus_new3, deus_new4, and deus_auto on wulingyuanparkzone.com – iterative testing, like a man trying on aliases until one fits.
Unmasking the Operators
Running the numeric tags through TelegramDB was like pulling masks off at a costume party. Underneath, the faces were about what you’d expect:
| Tag | Telegram Name | Username | Previous Usernames | Notable |
| 5197705037 | F̲a̲s̲o̲L̲’ | @Pi55_0ff | @SCAMHERE1 | Top operator, 42 samples. Previous username is a confession |
| 8172045377 | финфанфун | @ytcel | @zxcnork, @jxnxdxsxxm | 24 samples. Russian display name |
| 578510323 | (hidden) | @mamontovv | @reportmamont, @mamont0w, @rukoeb_3000 | 9 samples. “Мамонт” = Russian for a scam victim. Premium |
| 5551690712 | L1man | @ezbonus22 | @hydrosh0t, @lox3526tyrk | 14 samples. “лох” = Russian for sucker |
| 7287445517 | ANRILOV | PAYPAL | @anrilovfck | @cryptowoma, @ebalvseh11 | 3 samples. Bio: “PAYPAL WORK | MALWARE MONSTER”. Premium |
| 5362456016 | Tony Montana | @scarface_logs | @G5zvkr | 16 samples. Bio links @NoMetaRu (logs marketplace). Profile pic: Scarface still with “SCARFACE LOGS” overlay. Premium, DC4 |
| 7488523544 | 123 1 | @scamsomebody | @declineeeeed, @dennnied1 | 2 samples. Username literally @scamsomebody. Previous names reference declining/denying – chargebacks? Premium |
| 1527633244 | (hidden) | @wordpress20 | @teamphoenixs, @sneqixolod | 1 sample. “teamphoenix” – possibly group-affiliated |
| 7694683550 | (not indexed) | – | – | 2 samples. A ghost |
| 8598114766 | (not indexed) | – | – | 1 sample |
| 8251115314 | (not indexed) | – | – | 2 samples |
| 8402108450 | (not indexed) | – | – | 1 sample |
The username histories read like a glossary of Russian cybercrime slang. “Мамонт” – mammoth – is what they call a scam victim, from the expression “мамонт пришел,” the mammoth has arrived. “Лох” – sucker, mark, the one holding the short end. @SCAMHERE1 needs no translation in any language. One operator’s public bio announces “PAYPAL WORK | MALWARE MONSTER” with the quiet pride of a man who put his occupation on his tax return. @scarface_logs– “Tony Montana” – links to @NoMetaRu, a logs marketplace, and uses a Scarface movie still with “SCARFACE LOGS” branding as a profile picture. Subtle as a brick through a window. The newest arrival, @scamsomebody, leaves even less to interpretation, with previous usernames @declineeeeed and @dennnied1 suggesting chargeback fraud experience – the kind of resume you don’t put on LinkedIn. Four carry Telegram Premium – these aren’t burner accounts tossed after a single job. These are established identities, permanent residents in the Russian cybercrime neighborhood, the kind of people who pay rent and expect the landlord to fix the plumbing.
All eight resolved accounts were still publicly accessible at the time of writing (Mar 2026). Nobody had bothered to draw the curtains.
Several tags appear across multiple C2 domains. den shows up on builds for both technologytorg.com and attackzombie.com.deus spans three domains. Most strikingly, we observed a full domain rotation chain for the numeric-ID operators: gogenbydet.cc (Dec 22 – Feb 12) → bbcplay.top (Feb 12 – Feb 22) → playbergs.info (Feb 22 – present). Operators 5197705037, 8172045377, 5362456016, 7612929707, and 7694683550 all followed this migration path, like a parade of regulars moving to a new bar every ten days. New operators (7488523544, 8251115314, 8402108450) appeared directly on playbergs.info – fresh faces who never knew the old place. The tags identify operators, not infrastructure, and the seamless migration suggests the panel backend can redirect operators to new domains without breaking stride. The early Telegram and GRAB TCP builds predate the mechanism entirely – no tags, no calling cards, just the raw proto-malware feeling its way in the dark.
The env-var mechanism combined with hardcoded fallbacks is the smoking gun for the MaaS model. The builder can bake operator-specific values into the binary or delegate everything to the dropper, letting a single compiled payload serve any customer who walks through the door. It’s the franchise model, applied to crime.
C2 infrastructure
Eighteen C2 domains identified over twelve weeks, most tucked behind Cloudflare like witnesses in a protection program:
| Domain | Registered | Samples | Notes |
| gogenbydet.cc | Dec 22 | 74 | Dominant Jan–Feb; operators migrated out |
| evasivestars.com | ~Feb 2 | 74 | Exploded via date-encoded batch builds |
| bbcplay.top | Feb 11 | 33 | Active Feb 12–22; PDR registrar; fake Chrome installer delivery |
| technologytorg.com | Dec 24 | 33 | Contains “torg” – where the name came from |
| playbergs.info | Feb 22 | 18 | Current primary for numeric-ID operators; NiceNic registrar |
| attackzombie.com | Dec 16 | 10 | First dedicated C2, the one that started it |
| safeguss.com | ~Feb 3 | 7 | Growing; operators pb2, capha2, BB1, deus |
| si-dodgei.digital | Dec 24 | 5 | Stealer C2 for delivery chain; PDR registrar |
| wulingyuanparkzone.com | Feb 3 | 5 | deus lineage operators; 22-char domain spans 3 mov immediates |
| sinixproduction.com | 2021 (!) | 3 | An old domain with a new purpose |
| avanpost-fi.digital | ~Feb 19 | 2 | gapi operator (same as si-dodgei.digital); PDR registrar |
| 50elk.com | Jun 2024 (!) | 2 | Different C2 backend (/api/machine/set-files-r); NiceNic registrar; VT 10/93 |
| new-app-techno.com | Feb 3 | 1 | Operator File_23; Realtime Register (PDR reseller); Cloudflare |
| findyour-dreams.com | Dec 28 | 1 | |
| startbuldingship.com | Jan 5 | 1 | Typo: “bulding” – even criminals can’t spell |
| quick-neo.com | Oct 2025 | 1 | /api/machine/set-files-r backend (earliest sample); pre-staged domain |
The C2 infrastructure tells a story of domain rotation – organized, deliberate, like a crew that knows when to move. gogenbydet.cc dominated from late January through early February, then operators migrated to bbcplay.top (Feb 12–22), which was in turn replaced by playbergs.info (Feb 22 – present). Meanwhile, evasivestars.com quietly became the highest-volume domain through automated batch builds with date-encoded operator tags, now tied with gogenbydet.cc at 74 samples each – a factory nobody noticed because it didn’t make noise. A separate infrastructure cluster uses .digital TLD domains (si-dodgei.digital, avanpost-fi.digital) registered through the same PDR registrar, both serving the gapi/meow operator. Combined with the operator tags and the GRABBER_HOST environment variable, the picture is clear enough to read without glasses: Malware-as-a-Service, a builder model where each customer gets a binary with their name and C2 address baked in. The twelve numeric operator tags – eight confirmed as live Telegram accounts – prove the panel routes stolen data notifications straight to the operator’s phone. The Telegram-only exfiltration model didn’t die; it evolved into a notification layer sitting on top of the REST API architecture. Old habits don’t die. They get promoted.
Registrar clustering and WHOIS overlap
Three major registrar clusters emerged, and the WHOIS data gave us a gift – direct registrant identity links across multiple domains, wrapped up with a bow:
| Registrar | Domains | WHOIS Registrant | VT Detections |
| Global Domain Group#3956 | technologytorg.com, safeguss.com, evasivestars.com | Redacted; all three registered within 6 weeks (Dec 24 – Feb 2) | 11/93, 0/93, 0/93 |
| NiceNIC (HK) #3765 | gogenbydet.cc, findyour-dreams.com, playbergs.info,50elk.com | Same registrant name hash 1f8f4166599d23ee across all four; two email clusters: 9253e579452ffad5s@(gogenbydet/findyour-dreams) and 6eb609d996e182a6s@ (playbergs/50elk). 50elk.comregistered Jun 2024 (pre-staged); Peru registrant. | 1/93, 8/93, 2/93, 10/93 |
| Registrar.eu (NL)#1647 | attackzombie.com | Whois Privacy Protection Foundation (NL) | 8/93 |
| Dynadot #472 | sinixproduction.com | Super Privacy Service LTD; domain from 2021, repurposed Jan 2026 | 0/93 |
| Realtime Register (NL) #839 | startbuldingship.com, new-app-techno.com | Finland / Germany (Thüringen); PDR reseller for new-app-techno.com; startbuldingship.com suspended | 0/93, 1/93 |
| PDR / PublicDomainRegistry#303 | si-dodgei.digital, bbcplay.top, avanpost-fi.digital | GDPR-masked (Germany) / “Filip Cooper” (Seychelles); three C2 domains through same registrar; si-dodgei.digital and avanpost-fi.digital share .digital TLD and gapi operator | 0/93, 0/93, 0/93 |
| Hostinger #1636 | wulingyuanparkzone.com | Lithuania | 0/93 |
| Dominet/Aliyun (HK)#3775 | quick-neo.com | Malaysia; registered Oct 2025 – 2 months before first sample | 2/93 |
The NiceNIC cluster was the strongest find – and it grew. All four domains share the exact same registrant name hash (1f8f4166599d23ee), split into two email-address pairs: gogenbydet.cc/findyour-dreams.com (email 9253e579452ffad5s@, Hong Kong/Ohio registrants) and playbergs.info/50elk.com (email 6eb609d996e182a6s@, Hong Kong/Peru registrants). The shared name hash proves all four were registered by the same individual despite claiming different countries. Same hand, same pen, four different post offices. Notably, 50elk.com was registered in June 2024 – eight months before the first Torg Grabber sample – and carries 10/93 VT detections with 2,000–4,000 daily malware hits, suggesting it was already in the business before being repurposed as a Torg Grabber C2. The Global Domain Group cluster includes three domains, all registered within a six-week window. The PDR cluster now holds three domains: si-dodgei.digital (Dec 24), bbcplay.top(Feb 11), and avanpost-fi.digital (Feb 19). The .digital pair is particularly telling – both serve the same gapi/meow operator and share the same TLD, confirming they’re managed by the same infrastructure operator. The Realtime Register cluster now includes two domains: startbuldingship.com (Jan 5, Finland, suspended) and new-app-techno.com (Feb 3, Germany/Thüringen), the latter sold through PDR as reseller – creating a cross-link to the PDR cluster, the way one lie always connects to another. The operation used eight registrars across Hong Kong, the US, the Netherlands, Germany, the Seychelles, Peru, Finland, and Lithuania – diversifying against takedowns the way a smart investor diversifies against market crashes.
Three domains stuck out like sore thumbs in a velvet glove:
sinixproduction.comwas registered in January 2021 – five years before Torg Grabber drew its first breath. Its nameservers were switched to Cloudflare on January 13, 2026. An acquired domain, or a compromised one. Either way, it had a past, and its past wasn’t in malware.50elk.com, registered June 17, 2024 via NiceNic, carried 2,000–4,000 daily malware hits in our domain reputation data before Torg Grabber even existed. Deep analysis in IDA Pro reveals these builds use a completely different C2 backend –POST /api/machine/set-files-rwith multipart form-data uploads – rather than Torg Grabber’s native REST API. Despite the different exfiltration protocol, the binaries share the fullGRABBER_*environment variable framework, anti-VM/anti-CIS checks, and mutex pattern. They self-identify as "grabber v1.0" with plaintext debug messages in.rdata. See A Parallel Backend:/api/machine/set-files-rfor details.quick-neo.com, registered October 30, 2025, pre-dates all known samples by six weeks and carries a Cloudflare Radar rank of 10,000 and a Cisco Umbrella rank of ~242,000. IDA Pro analysis confirms its December 18 sample uses the same/api/machine/set-files-rbackend as the50elk.combuilds – making it the earliest known sample with this protocol, from the same week the REST API transition began. See A Parallel Backend:/api/machine/set-files-rfor details.
The GRAB TCP server
The two experimental GRAB protocol domains – bk.tara.net.bd and raketa.tara.net.bd – resolve to 190.92.174.248, hosted by WHG Hosting Services Ltd (AS199404, UK company, IP geolocated to India). Unlike the REST API domains, this one isn’t hiding behind Cloudflare. It uses a Let’s Encrypt wildcard for *.tara.net.bd and shares the server with potshilpo.shop, a Bangladesh-based domain. Shared hosting. The developer phase, where you don’t yet have the budget or the paranoia for dedicated infrastructure. BitDefender and G-Data flag tara.net.bd as malware. Someone noticed, even if not everyone.
What VT sees: Distribution and delivery
VirusTotal’s communicating files for the three busiest C2 domains tell the story of how Torg Grabber reaches its victims. The delivery mechanism is the oldest trick in the book, dressed up with a fresh coat of paint: trojanized installers, ZIP-packaged lures, digital candy left on the doorstep.
Fantasy-themed lures (technologytorg.com): The ten most recent communicating files are 87–113 MB ZIP installers wearing auto-generated fantasy names like costumes at a masquerade: Aerovora.zip, Nebulax.zip, Pyroxis.zip, Ignisyn.zip, Aetherion.zip, Zephyrion.zip, Aquathea.zip, Nebulynx.zip, Luminavora.zip. The naming convention had the mechanical creativity of a builder script that read too many sci-fi paperbacks.
Pirated software lures (gogenbydet.cc): Multiple 166 MB ZIPs labeled Terraria_1.4.5.zip and Setup.zip – bait for people who want something for nothing, which is most people. A smaller loader .zip at 31 MB suggested a more targeted delivery chain, something with a shorter fuse.
Numeric-ID lures (attackzombie.com): Smaller 3 MB ZIPs with numeric filenames – 24323350, 24353240, 24427545 – plus installer .zip. A simpler naming scheme from the earliest REST API domain, back when the operation was still figuring out its wardrobe.
Droppers on disk turn up as randomly-named executables in C:\Windows\: v4jkqh.exe, hkjpy08.exe, we4osct.exe, bfp2w6.exe. The naming pattern of a crypter or loader that doesn’t want to be remembered – digital aliases, disposable as matchbook covers.
VT label noise: The communicating files are variously tagged Trojan.dacic/vidar, trojan.aotera, trojan. cryptagent, and even trojan.aotera/rhadamanthys – a mess of misattribution that brought Torg Grabber to our attention in the first place. None of these labels fit. They reflect the industry’s reflex of pinning unknown stealers to familiar family names, the way a police sketch ends up looking like everybody and nobody.
All dedicated C2 domains share the same Cloudflare JARM fingerprint (27d40d40d00...525c) and use Google Trust Services TLS certificates. Matching suits. Same tailor.
Attribution: Following the Telegram trail
The 19 early Telegram-exfiltrating samples came with hardcoded bot tokens and channel IDs, carried openly in the binary like monogrammed luggage at an airport. By querying the Telegram Bot API, we obtained bot metadata, channel information, and – the prize – the Telegram accounts of the channel creators. The people who set up the drops. The hands behind the curtain.
See Appendix A, Figure A5
The Bots
| Bot | Username | Status |
| 8247426625 | @trtest12bot | Live |
| 8284437818 | @gr_bot_life_bot | Live |
| 8456437646 | @lalllaland_bot | Live |
| 8471726820 | @palayodd_bot | Live |
| 4 others | (unknown) | Revoked |
Four bots still alive and ticking, tokens unrevoked, as of February 8, 2026. All eight channels private, two to three members each – the bot and one or two humans. Small operations. Tight circles. The kind of crew where everyone knows everyone and nobody knows anyone outside.
The Operators
Each exfiltration channel has a creator – the Telegram account that set up the room and invited the bot. We found four:
| Username | Display Name | User ID | Channel | Notable |
| @ChaChaGuru | Pope Robinson | 7863185848 | “BkChannel” | ChaCha20 in the username |
| @OneCC_team | OneCC | 7983438838 | “playodd” | Bio: “Selling CC>First hand>Sniffed” |
| @the_01G | X I | 7960359642 | “land” | |
| (none) | Lauriev Hontisorknnd | 8214631236 | “1 kanal” | “1 kanal” = “channel 1” – the test run |
@ChaChaGuru was the lead we couldn’t ignore. The username is a direct reference to ChaCha20 – the stream cipher that runs through Torg Grabber’s veins like blood type. It encrypts the C2 payloads. It protects the GRAB protocol. It wraps the shellcode. And the “Bk” in “BkChannel” matches bk.tara.net.bd, the GRAB TCP domain. Two connections. Both pointing the same direction. This wasn’t circumstantial evidence; it was a man leaving his business card at the scene.
@OneCC_team presented as a group identity, and their public bio – “Selling CC>First hand>Sniffed” – was an open advertisement for stolen credit card sales. Not even coded. Just stated, plainly, the way a butcher advertises pork chops. Their profile photo history traced a career arc from an Amazon delivery truck through “OMG” and Bitcoin/AML imagery to a Guy Fawkes mask – a trajectory from e-commerce fraud through cryptocurrency crime to the anonymous hacking persona, documented in selfies.
All four creator accounts carry user IDs in the 7.8–8.2 billion range – created in the same timeframe, shortly before the bots themselves. The channel called “1 kanal” (Russian for “channel 1”) by “Lauriev Hontisorknnd” – a name as fabricated as a three-dollar bill – was the test channel. The first attempt. The rough draft.
What Torg Grabber steals
The stealer’s appetite is broad, and it’s getting broader. It wants everything, and it’s not shy about asking.
Here’s the rap sheet:
- Browser credentials: 25 Chromium-based browsers (Chrome, Edge, Brave, Opera, Vivaldi, Yandex, CocCoc, CryptoTab, and 17 others that never thought they’d end up on a list like this) and 8 Firefox-family browsers, with AES-GCM, DPAPI, and ABE support. Plus harvesting of credentials previously extracted by the “Underground” tool – a standalone credential extraction tool whose output Torg Grabber scavenges like a jackal following a lion (see below)
- Browser extensions – 850 total: Three hardcoded lists. 728 wallet extensions covering every crypto wallet from MetaMask and Phantom down to ShibaWallet and xMetaCene. 103 password/2FA extensions – LastPass, 1Password, Bitwarden, and every authenticator app that ever tried to keep someone safe. 19 notes extensions, because sometimes people write their passwords on sticky notes, even digital ones. Full lists in the IOC repository
- Desktop wallets: 30+ standalone applications – Exodus, Atomic, Electrum, Monero, Daedalus. The whole menagerie
- Messaging: Discord tokens (LevelDB scanning), Telegram session data, Steam configs
- Credentials: VPN configs from 8 providers, FTP clients (5), email (Thunderbird, Outlook), password managers (7), gaming platforms (6)
- System profiling: Hardware fingerprint, installed software, process list, screenshot, environment variables, and AV detection scanning 46 process signatures across 24 products – Kaspersky, Avast, ESET, CrowdStrike, SentinelOne, Windows Defender. It wants to know who’s watching before it starts working, the way a burglar checks for dogs before climbing the fence
- File grabbing: Pattern-based collection from Desktop and Documents with C2-configurable rules
- Arbitrary code execution: The C2 can deliver ChaCha-encrypted, zlib-compressed shellcode at registration. Just in case everything else wasn’t enough
850 browser extensions: Casting the widest net
Perhaps the most striking thing about Torg Grabber isn’t what it does, but how much of it there is. Eight hundred and fifty extension IDs, hardcoded into the binary, organized into three tidy categories like a catalog for a store that sells things that don’t belong to it:
| Category | Count | Archive Path | What They Steal |
| Wallet | 728 | Wallet/Extension/ | Crypto wallet seeds, keys, session data |
| Password/2FA | 103 | Password/ | Password vaults, TOTP secrets, MFA tokens |
| Notes | 19 | Notes/ | Saved notes – and the passwords people hide in them |
The 728 wallet extensions cover essentially every crypto wallet ever conceived by human optimism. The marquee names are all there – MetaMask, Phantom, TrustWallet, Coinbase, Binance, Exodus, TronLink, Ronin, OKX, Keplr, Rabby, Sui, Solflare. But the list doesn’t stop at the big names. It keeps going, deep into the long tail, past projects with install counts you could fit in a phone booth – ShibaWallet, xMetaCene, Elli Sui Wallet. The kind of thoroughness that suggests the list was scraped from the Web Store rather than curated by hand. Nobody sits down and types 728 extension IDs one by one. Not even a criminal.
The 103 password extensions are equally comprehensive. The majors – LastPass, 1Password, Bitwarden, KeePass, NordPass, Dashlane, ProtonPass, Enpass – plus niche products like Psono, Pleasant Password Server, and heylogin. And here’s the twist: 31 two-factor authentication extensions are in the mix. 2FAAuth, GAuth, TOTP Authenticator, Akamai MFA. The stealer doesn’t just want the password. It wants the second factor too. The lock and the key and the deadbolt and the chain. Everything that stands between the victim and complete exposure.
For each matched extension, the malware vacuums data from three locations: 1. Local Extension Settings/ – the extension’s LevelDB storage 2. IndexedDB/ – any IndexedDB databases matching the extension ID 3. Sync Extension Settings/ – synced data, if the user has Chrome Sync enabled
The archive paths include a DJB2 hash of the browser name – Wallet/Extension/MetaMask/C-Chrome-a1b2c3d4/ – to keep stolen credentials from different browsers filed separately. Organized crime, in the most literal sense.
The full extension lists are published in the IOC repository. Defenders and extension developers can use them. Everyone else can marvel at the ambition.
Harvesting a previous tool: “Underground”
Early Torg Grabber builds contained code to harvest credentials from C:\ProgramData\Underground – a path that, at first glance, had the look of an anti-detect browser’s home directory. We spent some time chasing that theory. Turns out we were looking at it wrong. The way you sometimes look at a shadow on the wall and see a man, but when the light shifts it’s just a coat on a hook.
What “underground” really is
We recovered a number of C:\ProgramData\Underground\logs.txt files from infected machines. The logs told a different story. “Underground” isn’t a browser at all. It’s a standalone credential extraction tool with a two-stage architecture that bears a family resemblance to Torg Grabber’s own ABE bypass – the kind of resemblance that makes you check if they had the same father:
- Host process (injector) – enumerates installed browsers, creates a suspended browser process, performs reflective DLL injection, and talks to the injected payload through named pipes
- Injected DLL (reflective loader) – runs inside the browser process, decrypts the ABE-protected master key via Chrome’s COM Elevator service, then dumps credentials to JSON files
The log output documents the full chain: browser enumeration, suspended process creation, ReflectiveLoader injection, named pipe setup (\\.\pipe\chrome.nacl.*, \\.\pipe\mojo.*), ABE key decryption via COM, profile enumeration, and credential extraction. It writes its take as JSON files and plaintext token files to C:\ProgramData\Underground. Neat. Professional. The kind of work that leaves receipts.
What Torg Grabber harvests
When Torg Grabber finds this directory – and on machines where the operators have been running their toolkit, it will – it parses three types of JSON output files left behind by the Underground tool:
- Passwords – {
"origin":"..."} objects with URLs, usernames, and passwords - Cookies – {
"domain":"..."} objects with full cookie metadata - Payment cards – {
"card_number":"..."} objects with card details
It also collects three token files (gaming_tokens.txt, media_tokens.txt, social_tokens.txt) containing session tokens for various platforms. Double-dipping. Credentials that were already extracted once, stolen again for the archive.
The connection
The architectural overlap between Underground and Torg Grabber is the kind of thing that makes you sit up in your chair. Both use reflective DLL injection into suspended browser processes. Both use named pipe IPC. Both do COM-based ABE bypass. The blueprints are close enough to be cousins.
But the DLL-side log strings are completely different – Torg Grabber’s abe_decrypt.dll uses [DLL] prefixed messages that don’t appear anywhere in Underground’s logs, and the host-side injector strings from Underground are absent from abe_decrypt.dll. Different binaries. Same school of thought. This rules out a shared executable but points toward a shared codebase, a common author, or tools from the same ecosystem – bought from the same shelf in the same underground marketplace.
The working hypothesis: the operators who deploy Torg Grabber also ran the Underground tool on infected machines – either as a precursor or running alongside. Torg Grabber’s JSON parsers then scavenge whatever Underground left behind, like a second shift coming in to clean out what the first shift missed. This is consistent with the MaaS model: operators run multiple tools, and a good stealer picks up everything, even another tool’s leftovers.
The CIS cleanup twist
When the malware detects a CIS locale – Russia, Ukraine, Belarus, Kazakhstan, and the rest of the old neighborhood – it doesn’t merely skip collection. It actively deletes the entire Underground directory:
On CIS machines, this erases the Underground tool’s logs and extracted credentials – destroying evidence of the operators’ own activities. Not protecting fellow criminals’ data. Covering their own tracks. The kind of cleanup you do when you’ve been in someone’s house and you want to make sure nobody knows you were there.
Gone in a day: The underground-to-ABE swap
Corpus-wide analysis turned up a fact as clean and cold as a knife: Underground harvesting and the ABE bypass are perfectly mutually exclusive. Not a single sample in 139 builds contains both.
| Feature | Samples | Date Range | Binary Size |
| Underground harvesting | 30 | Dec 9 – Dec 20 | 265 – 525 KB |
| ABE bypass | 109 | Dec 22 – Feb 7 | 411 – 747 KB |
| Both | 0 | – | – |
The last Underground build compiled on December 20 at 15:45 UTC. The first ABE bypass build appeared 38 hours later, on December 22 at 06:32 UTC. Not a gradual transition. Not a slow fade. A clean break. One feature walked out the door and another walked in, and they didn’t even pass each other in the hallway.
The logic reads like a business decision – and it was one. Once Torg Grabber gained its own built-in ABE bypass, there was no longer any need to scavenge credentials from a separate tool. The developers replaced a dependency on external tooling with native capability, the way a restaurant that used to buy bread from down the street puts in its own oven. The timing lines up with the December 22 pivot to production REST API infrastructure. Everything changed at once, because when you’re going to jump, you might as well jump with both feet.
A parallel backend: /api/machine/set-files-r
Three samples. Two domains. A completely different C2 protocol than the rest of the corpus, and yet the same malware framework underneath — like finding two different keys in the same man’s pocket, both opening different doors. quick-neo.com in December, 50elk.com in February. This wasn’t some late experiment cooked up after the main line had settled. The quick-neo.com sample landed the same week the REST API transition began. The /api/machine/set-files-r backend was running in parallel from day one. Two horses in the same race, and nobody had bothered to tell the program.
| Date | Domain | Backend | Size | Features |
| Dec 18, 2025 | quick-neo.com | machine_api | 266 KB | Underground browser, no ABE, plaintext .rdata |
| Feb 17, 2026 | 50elk.com (×2) | machine_api | 712 KB | GRABBER_* env vars, ABE bypass, plaintext .rdata |
The jump from 266 KB to 712 KB — nearly triple — and the feature additions along the way — ABE bypass, env vars, string encryption — mirror the main Torg line’s evolution over the same stretch. Same playbook. Different stage. This wasn’t a dead fork. Somebody was feeding it.
What they share with standard Torg Grabber
The familiar framework is present across both:
- Anti-analysis: GPU-based anti-VM (EnumDisplayDevicesA against vendor blocklist), locale-based anti-CIS (GetLocaleInfoA against blocklist), Local{MachineGuid} mutex.
- Build tag: “grabber v1.0” – logged at startup alongside a timestamp.
- GRABBER_* environment variables (Feb 17 builds only): GRABBER_HOST, GRABBER_TAG, GRABBER_ANTI_SNG, GRABBER_ANTI_VM, GRABBER_STREAMING, GRABBER_HWID, GRABBER_GPU, GRABBER_SESSION – same set, same defaults (HWID → c479d3ea-cedd-43ef-af74-dc6163e5dad7, GPU → Radeon RX550/550 Series). The Dec 18 build pre-dates the env var mechanism.
What is different: The C2 protocol
| Standard Torg Grabber | machine_api builds | |
| Registration | POST /api/auth with HWID, operator tag, ChaCha20 key exchange | Stubbed out – auth function returns 1unconditionally |
| Upload endpoint | /api/upload/chunk (chunked), /api/stream/* | POST /api/machine/set-files-r |
| Content type | ChaCha20-encrypted + HMAC-SHA256 authenticated chunks | Multipart form-data (boundary=----UploadBoundary9876543210) |
| Upload field | Encrypted binary stream | zip_file – raw ZIP bytes |
| Port | 443 (HTTPS via Cloudflare) | 443 (HTTPS, direct – no Cloudflare) |
| User-Agent | Custom ("Mozilla/5.0 ... grabber/1.0" variants) | Plain "Mozilla/5.0" |
| Error handling | Retry with exponential backoff | HTTP 200 → success; 403/400 → abort immediately |
| Archives sent | Single encrypted stream | Two separate uploads: main.zip, files.zip |
The /api/machine/set-files-r endpoint does not match any publicly documented stealer family’s C2 protocol. A ghost in the machine, and the machine wasn’t talking.
The Collection pipeline
Standard Torg sends single encrypted archive; machine_api builds construct two ZIP archives with distinct folder layout:
files.zip: Additional file grabber results.
The collection functions produce numbered debug log entries ([1] Creating ZIP buffer…, [2] Generating UserInfo…, etc.) — more structured than standard Torg’s free-form debug strings. The kind of organization that suggests someone was keeping score.
Plaintext strings throughout
Unlike the main Torg line — which progressively moved from plaintext .rdata to compiler-inlined mov immediates — both machine_api samples keep all strings as plaintext in .rdata. C2 domain, endpoint path, debug messages like “[#] Killed ALL %s processes: %d”. Everything out in the open. This branch never got the string hardening. Either they didn’t care, or they didn’t get the memo.
Interpretation
The quick-neo.com discovery settles the timeline. The /api/machine/set-files-r backend isn’t a late experiment — it’s contemporary with the earliest REST API builds. December 18 is the same day attackzombie.com samples first appeared. Two backends shipped from the same codebase on the same day. Like a man with two passports, both valid.
The ten-week gap between quick-neo.com (Dec 18, 266 KB) and 50elk.com (Feb 17, 712 KB) tells the rest of the story. The machine_api line tracked the main Torg evolution: ABE bypass added, env var framework integrated, binary nearly tripled in size. Not a dead fork. Actively maintained. Parallel development, same hands on both levers.
Two readings remain:
- Operator-specific panel. Under the MaaS model, one customer runs a panel at /api/machine/set-files-r while the majority use the standard REST API panel.
- Developer’s own backend. The /api/machine/set-files-r panel is the developer’s original infrastructure, while the REST API was built for the MaaS product.
Either way, the GRABBER_* environment variable framework and anti-analysis suite are the stable identity anchors — they persist across different C2 backends, string protection schemes, and collection pipeline layouts. The backend protocol itself is modular and swappable. The face changes. The fingerprints don’t.
Conclusion
Torg Grabber is a case study in velocity. Three months from prototype to production. Four exfiltration mechanisms tried – Telegram Bot API, GRAB TCP, REST API, and the parallel /api/machine/set-files-r backend – each one a rung on a ladder that only goes up. Eighteen C2 domains across eight registrars. A binary that nearly tripled in size while its developers were still registering the domains it would phone home to. It was like watching someone build an airplane while it was already taxiing down the runway.
The Telegram breadcrumbs left behind by the early builds – bot tokens, channel metadata, and an operator whose username literally namedrops the malware’s signature encryption algorithm – provided a window into the human side of the operation. These aren’t ghosts. They’re people, with Telegram Premium subscriptions and public bios that read like job applications for a criminal enterprise.
By resolving the numeric operator tags through OSINT databases, we put faces to eight of twelve MaaS customers. The faces weren’t pretty. Usernames referencing scamming (@SCAMHERE1, @scamsomebody), victims (@mamontovv, from “мамонт” – the mammoth, the mark, the one who showed up), suckers (@lox3526tyrk, from “лох” – the word speaks for itself), and stolen-credential marketplaces (@scarface_logs linking to @NoMetaRu). Four carry Telegram Premium – established actors, not disposable identities. Combined with the developer accounts recovered from the bot tokens, the picture is unusually complete. Both sides of a MaaS operation, buyer and seller, laid out under the light.
The observed delivery chain tells its own story – from a ClickFix clipboard attack hosted on Google Apps Script, through a multi-stage PowerShell stager with a fake progress bar and XOR-encrypted BITS transfers, to three polymorphic MinGW loaders served from disposable .pw domains. The delivery infrastructure is as carefully engineered as the stealer itself. Strict role separation between domains – stagers on j0o.pw, encrypted loaders on t4e.pw/re3.pw, exfiltration on the main C2 cluster – provides operational resilience: burning one domain doesn’t touch the others. The use of trusted platforms (Google Apps Script, Dropbox) for initial access and server-side polymorphism for loader generation makes static blocking about as effective as putting up a “No Trespassing” sign at a public park.
The family remains under active development. New C2 domains registered weekly. Builds compiled daily – 334 samples and counting, each one a fresh fingerprint. The operator base growing, 40+ tags and rising, new customers walking through the door. What initially looked like a three-day experiment with environment-variable configuration has since become the standard: every build from Feb 10 onward ships with GRABBER_* env var support and compiler-inlined string assignments, replacing the earlier plaintext .rdata approach. The most significant operational shift is the domain rotation chain (gogenbydet.cc → bbcplay.top → playbergs.info), where entire operator groups migrate to fresh infrastructure roughly every ten days – a cadence that makes domain-based blocking a losing game. Meanwhile, evasivestars.com has become a mass-build factory with date-encoded batch tags, suggesting automated deployment pipelines. We’ll keep watching. These are the kind of people who don’t stop until someone stops them.