Tearing apart a real Remcos RAT
A 40MB binary disguised as a game character stats tool. One import. Thirty-three strings. Five hundred functions. And a decoder stub that made Ghidra scream. Here's what Ghidra MCP found inside a real Remcos RAT sample from MalwareBazaar.
The sample
SHA-256: 6a44d9822a8529b0dcea4c9655f569e1426c32814cb24122b54ed78a7a1dad6a. Pulled from MalwareBazaar, scored 10/10 on Hatching Triage. Tagged as Remcos RAT with confirmed C2 extraction, persistence via registry Run keys, scheduled tasks, UAC bypass, and VBS compiler abuse. Originally distributed as a phishing email attachment.
The sample was analyzed entirely inside a Docker container running Ghidra headless — no execution, pure static analysis. Windows Defender ate the binary five times before I gave up and built the sandbox. That fight is a story for another day.
First look — something doesn't add up
Ghidra identified it as an x86 32-bit PE, compiled for Windows. A .NET assembly — the CLR managed code runtime. Here's where things get suspicious immediately:
Language: x86:LE:32:default Compiler: windows Imports: 1 (MSCOREE.DLL → _CorExeMain) Strings: 33 Functions: 508 File size: 39,845,888 bytes (38 MB)
One import. A legitimate .NET application imports dozens or hundreds of framework methods. This binary imports exactly one: _CorExeMain from MSCOREE.DLL — the .NET runtime entry point. Everything else is resolved dynamically at runtime, invisible to static analysis. That's deliberate.
Thirty-three strings. A 38MB binary with 33 defined strings. For reference, a simple "Hello World" WinForms app has more strings than that. The real strings are encrypted, packed, or generated at runtime.
38MB for a game tool. The version info embedded in the binary claims this is "RYL Character Tool - RoW EU version" — a stats calculator for Risk Your Life, a Korean MMORPG from the mid-2000s. Copyright 2008-2010 by "WHC ®". Original filename: AceQualifi.exe. A character stats calculator does not need 38 megabytes. That space is payload.
The disguise
The version info strings tell a story:
FileDescription: RYL Character Tool - RoW EU version CompanyName: WHC ® Copyright: Copyright © 2008 - 2010 OriginalFilename: AceQualifi.exe FileVersion: 1.3.0.0
And the function names support the cover story. Hundreds of functions with names like calculaStr, calculaDex, calculaCon, exibeWis, calcDiferencaBPointsINT, maxSTR — RPG character stat calculations. Portuguese function names suggesting a Brazilian developer. Class properties for Str, Con, Dex, Inte, Wis — the five stats from the Risk Your Life game. There's even a comboRaca_SelectedIndexChanged handler (race selection dropdown).
This is a fully functional game tool with a RAT bolted on. The user double-clicks what looks like a legitimate application, the WinForms UI loads, they see stat calculators — and in the background, the real payload unpacks and executes. The game tool isn't a shell. It actually works. That's what makes it effective.
The memory layout
Section Start Size Perms Headers 00400000 512 B R-- .text 00402000 894,464 B R-X (873 KB — the code) .rsrc 004de000 93,696 B R-- (91 KB — resources) .reloc 004f6000 512 B R--
The sections account for roughly 1MB total. The binary is 38MB. That means approximately 37MB is unaccounted for — appended data, overlay, or embedded resources not mapped into the PE section table. This is a common packing technique: the real payload sits past the end of the mapped sections, gets read at runtime by the loader stub, decrypted in memory, and executed. The PE header is a Trojan horse carrying cargo in its trunk.
The decoder stub
Three functions stand out from the sea of game stat calculators: RSM, _X_X0FT_FT1, and _X_X0FT_FT2. These names follow no naming convention used anywhere else in the binary. They're not Portuguese. They're not .NET framework names. They're obfuscated labels for the payload machinery.
When Ghidra decompiled RSM, it produced over 500 lines of output — and most of it was warnings:
/* WARNING: Control flow encountered bad instruction data */ /* WARNING: Instruction at (ram,0x004069eb) overlaps instruction at (ram,0x004069e9) */ /* WARNING: Unable to track spacebase fully for stack */ /* WARNING: Removing unreachable block (ram,0x004069df) */ /* WARNING: Removing unreachable block (ram,0x0040695b) */ ... (48 more unreachable block warnings)
Overlapping instructions. This is a classic anti-disassembly technique. The code is laid out so that jumping to an offset in the middle of one instruction produces a completely different valid instruction. Linear disassemblers choke on it. Even Ghidra's recursive descent analysis can't fully resolve the control flow — hence 48 unreachable blocks it had to prune.
The decompiled body is equally telling. Among the obfuscated byte-manipulation loops, we see:
LOCK(); // Atomic operations — thread-safe memory manipulation bVar4 = *pbVar7; *pbVar7 = bVar3; UNLOCK(); out(*unaff_ESI,(short)param_2); // Port I/O — doesn't belong in userland code *puVar14 = *puVar14 ^ uVar29; // Repeated 22 times — XOR decryption loop *puVar14 = *puVar14 ^ uVar29; *puVar14 = *puVar14 ^ uVar29; ... (22 consecutive identical XOR operations) pcVar1 = (code *)swi(3); // INT 3 — debugger trap / breakpoint
This function is a decoder stub. The LOCK-prefixed atomic operations handle thread-safe unpacking. The repeated XOR pattern is iterating over encrypted payload data. The out() port I/O instructions are likely junk bytes inserted to confuse static analysis — they'd fault in userland if executed linearly, but the overlapping instruction trick means they're never actually reached during normal execution. The final swi(3) is either an anti-debugging trap or a handoff point to the decoded payload.
This 119-byte function is the ignition switch for the entire Remcos payload. Small, obfuscated, and deliberately hostile to analysis tools.
The trigger — buttonOK_Click
In the legitimate game tool, clicking OK should calculate character stats and display results. A function that size would handle every race, class, and stat combination in the game. What it actually does is serve as the payload trigger — when the user interacts with the seemingly legitimate application, the malicious code path activates alongside the real functionality.
The .NET runtime resolves all the real API calls dynamically at execution time, so static analysis of this function shows mostly managed code infrastructure — object construction, form manipulation, and stat calculations. The malicious behavior is buried in the runtime resolution chain, invisible until the CLR loads the embedded resources and resolves the obfuscated type references.
What we know from behavioral analysis
Hatching Triage and ANY.RUN sandbox results for this sample confirm what the static analysis suggests but can't fully reveal:
Adds itself to HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Creates scheduled tasks for reboot survival. Standard dual-persistence approach.
Uses SetThreadContext and WriteProcessMemory for process hollowing — spawns a legitimate process and replaces its memory with the Remcos payload. Abuses vbc.exe (Visual Basic compiler) as a living-off-the-land technique.
Modifies registry keys to bypass User Account Control, allowing elevation without triggering the consent prompt.
C2 server at 91.193.75.189:54255. No domain fronting, no cloud dead drops — direct TCP connection to a hardcoded IP. Remcos uses a custom encrypted protocol over this channel for command execution, file transfer, keylogging, screen capture, and credential harvesting.
Indicators of compromise
| Type | Value |
|---|---|
| SHA-256 | 6a44d9822a8529b0dcea4c9655f569e1426c32814cb24122b54ed78a7a1dad6a |
| C2 | 91.193.75.189:54255 |
| Family | Remcos RAT |
| Original filename | AceQualifi.exe |
| Masquerade | RYL Character Tool - RoW EU version |
| Company | WHC ® |
| Persistence | HKCU\...\CurrentVersion\Run + Scheduled Tasks |
| Technique | Process hollowing via SetThreadContext |
| LOLBin | vbc.exe (VBS compiler) |
What Ghidra MCP brought to this
The size anomaly. Ghidra MCP immediately flagged the mismatch — 38MB binary, 33 strings, 1 import, sections totaling ~1MB. That's a neon sign that says "packed payload." A manual analyst would notice it too, but the AI contextualized it instantly: the section table accounts for 2.5% of the file. The rest is cargo.
Function triage. 508 functions. Most are legitimate game code. The AI sorted by behavioral suspicion — flagging RSM, _X_X0FT_FT1, and _X_X0FT_FT2 as anomalous based on naming convention breaks and code complexity. It also flagged buttonOK_Click's size as an outlier. Four functions out of 508 — that's the signal in the noise.
Decompilation interpretation. The RSM decompilation output is 500+ lines of warning-laden, control-flow-broken pseudocode. Ghidra MCP identified the overlapping instruction technique, the XOR decryption pattern, and the anti-debugging trap without being told to look for them. It recognized the LOCK prefixes as thread-safe unpacking rather than legitimate synchronization, and the out() instructions as junk bytes rather than actual port I/O.
The limitation. This is a .NET binary with heavy runtime obfuscation. Static analysis — even AI-assisted — hits a wall when the real payload is encrypted in an overlay and unpacked by a stub that uses overlapping instructions to defeat disassembly. The honest answer is that we identified the packing mechanism, the trigger point, the masquerade, and the approximate payload location, but we didn't extract the final Remcos configuration or command protocol from static analysis alone. That would require dynamic analysis in a sandbox — executing the binary and intercepting the decoded payload in memory. Ghidra MCP gets you to the edge of what static analysis can reveal. The rest needs a debugger.
This analysis used a real malware sample (SHA-256 above) obtained from MalwareBazaar. The binary was analyzed inside an isolated Docker container running Ghidra headless. No malware was executed. All behavioral data attributed to sandbox results comes from Hatching Triage and ANY.RUN public reports for this sample.
Tear apart your own samples
Ghidra MCP integrates 36+ reverse engineering and malware analysis tools into an AI-assisted workflow through Claude Desktop. Import, analyze, decompile, and extract IOCs — in one session.
Learn more