Path: blob/master/modules/nops/x64/simple.rb
19516 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Nop67def initialize8super(9'Name' => 'Simple',10'Alias' => 'x64_simple',11'Description' => 'An x64 single/multi byte NOP instruction generator.',12'Author' => [ 'sf' ],13'License' => MSF_LICENSE,14'Arch' => ARCH_X64)1516register_advanced_options([ OptBool.new('RandomNops', [ false, 'Generate a random NOP sled', true ]) ])17register_advanced_options([ OptBool.new('MultiByte', [ false, 'Generate a multi byte instruction NOP sled', false ]) ])18end1920# This instruction list is far from complete (Only single byte instructions and some multi byte ADD/MOV instructions are used).21# A more complete list might warrant an pseudo assembler (Rex::Arch::X64) instead of hardcoding these.22INSTRUCTIONS = [23[ "\x90", 0, 'nop' ],24[ "\x91", 0, 'xchg eax, ecx' ],25[ "\x92", 0, 'xchg eax, edx' ],26[ "\x93", 0, 'xchg eax, ebx' ],27[ "\x94", 0, 'xchg eax, esp' ],28[ "\x95", 0, 'xchg eax, ebp' ],29[ "\x96", 0, 'xchg eax, esi' ],30[ "\x97", 0, 'xchg eax, edi' ],31[ "\x98", 0, 'cwde' ],32[ "\x99", 0, 'cdq' ],33[ "\x9B", 0, 'wait' ],34[ "\x9C", 0, 'pushfq' ],35[ "\x9D", 0, 'popfq' ],36[ "\x9E", 0, 'sahf' ],37[ "\x9F", 0, 'lahf' ],38[ "\xFC", 0, 'cld' ],39[ "\xFD", 0, 'std' ],40[ "\xF8", 0, 'clc' ],41[ "\xF9", 0, 'cmc' ],42[ "\x50", 0, 'push rax' ],43[ "\x51", 0, 'push rcx' ],44[ "\x52", 0, 'push rdx' ],45[ "\x53", 0, 'push rbx' ],46[ "\x54", 0, 'push rsp' ],47[ "\x55", 0, 'push rbp' ],48[ "\x56", 0, 'push rsi' ],49[ "\x57", 0, 'push rdi' ],50[ "\x58", 0, 'pop rax' ],51[ "\x59", 0, 'pop rcx' ],52[ "\x5A", 0, 'pop rdx' ],53[ "\x5B", 0, 'pop rbx' ],54[ "\x5C", 0, 'pop rsp' ],55[ "\x5D", 0, 'pop rbp' ],56[ "\x5E", 0, 'pop rsi' ],57[ "\x5F", 0, 'pop rdi' ],58[ "\x04", 1, 'add al, 0x??' ],59[ "\x80\xC3", 1, 'add bl, 0x??' ],60[ "\x80\xC1", 1, 'add cl, 0x??' ],61[ "\x80\xC2", 1, 'add dl, 0x??' ],62[ "\x80\xC4", 1, 'add ah, 0x??' ],63[ "\x80\xC7", 1, 'add bh, 0x??' ],64[ "\x80\xC5", 1, 'add ch, 0x??' ],65[ "\x80\xC6", 1, 'add dh, 0x??' ],66[ "\x66\x05", 2, 'add ax, 0x????' ],67[ "\x66\x81\xC3", 2, 'add bx, 0x????' ],68[ "\x66\x81\xC1", 2, 'add cx, 0x????' ],69[ "\x66\x81\xC2", 2, 'add dx, 0x????' ],70[ "\x66\x81\xC6", 2, 'add si, 0x????' ],71[ "\x66\x81\xC7", 2, 'add di, 0x????' ],72[ "\x66\x41\x81\xC0", 2, 'add r8w, 0x????' ],73[ "\x66\x41\x81\xC1", 2, 'add r9w, 0x????' ],74[ "\x66\x41\x81\xC2", 2, 'add r10w, 0x????' ],75[ "\x66\x41\x81\xC3", 2, 'add r11w, 0x????' ],76[ "\x66\x41\x81\xC4", 2, 'add r12w, 0x????' ],77[ "\x66\x41\x81\xC5", 2, 'add r13w, 0x????' ],78[ "\x66\x41\x81\xC6", 2, 'add r14w, 0x????' ],79[ "\x66\x41\x81\xC7", 2, 'add r15w, 0x????' ],80[ "\x05", 4, 'add eax, 0x????????' ],81[ "\x81\xC3", 4, 'add ebx, 0x????????' ],82[ "\x81\xC1", 4, 'add ecx, 0x????????' ],83[ "\x81\xC2", 4, 'add edx, 0x????????' ],84[ "\x81\xC6", 4, 'add esi, 0x????????' ],85[ "\x81\xC7", 4, 'add edi, 0x????????' ],86[ "\x41\x81\xC0", 4, 'add r8d, 0x????????' ],87[ "\x41\x81\xC1", 4, 'add r9d, 0x????????' ],88[ "\x41\x81\xC2", 4, 'add r10d, 0x????????' ],89[ "\x41\x81\xC3", 4, 'add r11d, 0x????????' ],90[ "\x41\x81\xC4", 4, 'add r12d, 0x????????' ],91[ "\x41\x81\xC5", 4, 'add r13d, 0x????????' ],92[ "\x41\x81\xC6", 4, 'add r14d, 0x????????' ],93[ "\x41\x81\xC7", 4, 'add r15d, 0x????????' ],94[ "\x48\xB8", 8, 'mov rax, 0x????????????????' ],95[ "\x48\xBB", 8, 'mov rbx, 0x????????????????' ],96[ "\x48\xB9", 8, 'mov rcx, 0x????????????????' ],97[ "\x48\xBA", 8, 'mov rdx, 0x????????????????' ],98[ "\x48\xBE", 8, 'mov rsi, 0x????????????????' ],99[ "\x48\xBF", 8, 'mov rdi, 0x????????????????' ],100[ "\x49\xB8", 8, 'mov r8, 0x????????????????' ],101[ "\x49\xB9", 8, 'mov r8, 0x????????????????' ],102[ "\x49\xBA", 8, 'mov r10, 0x????????????????' ],103[ "\x49\xBB", 8, 'mov r11, 0x????????????????' ],104[ "\x49\xBC", 8, 'mov r12, 0x????????????????' ],105[ "\x49\xBD", 8, 'mov r13, 0x????????????????' ],106[ "\x49\xBE", 8, 'mov r14, 0x????????????????' ],107[ "\x49\xBF", 8, 'mov r15, 0x????????????????' ],108]109110I_OP = 0111I_SIZE = 1112I_TEXT = 2113114REGISTERS = [115[ 'rsp', 'esp', 'sp' ],116[ 'rbp', 'ebp', 'bp' ],117[ 'rax', 'eax', 'ax', 'al', 'ah' ],118[ 'rbx', 'ebx', 'bx', 'bl', 'bh' ],119[ 'rcx', 'ecx', 'cx', 'cl', 'ch' ],120[ 'rdx', 'edx', 'dx', 'dl', 'dh' ],121[ 'rsi', 'esi', 'si' ],122[ 'rdi', 'edi', 'di' ],123[ 'r8', 'r8d', 'r8w', 'r8b' ],124[ 'r9', 'r9d', 'r9w', 'r9b' ],125[ 'r10', 'r10d', 'r10w', 'r10b' ],126[ 'r11', 'r11d', 'r11w', 'r11b' ],127[ 'r12', 'r12d', 'r12w', 'r12b' ],128[ 'r13', 'r13d', 'r13w', 'r13b' ],129[ 'r14', 'r14d', 'r14w', 'r14b' ],130[ 'r15', 'r15d', 'r15w', 'r15b' ],131]132133def generate_random_sled(length, instructions, badchars, badregs)134opcodes_stack = []135total_size = 0136sled = ''137try_count = 0138139# Fixup SaveRegisters so for example, if we wish to preserve RSP we also should also preserve ESP and SP140REGISTERS.each { |reg| reg.each { |x| badregs += reg if badregs.include?(x) } }141badregs = badregs.uniq142143# If we are preserving RSP we should avoid all PUSH/POP instructions...144if badregs.include?('rsp')145badregs.push('push')146badregs.push('pop')147end148149# Loop while we still have bytes to fill in the sled...150loop do151# Pick a random instruction and see if we can use it...152instruction = instructions[rand(instructions.length)]153154# Avoid using any bad mnemonics/registers...155try_another = false156badregs.each do |bad|157try_another = true if instruction[I_TEXT].include?(bad.downcase)158break if try_another159end160next if try_another161162# Get the first bytes of the chosen instructions opcodes...163opcodes = instruction[I_OP]164165# If their are additional bytes to append, do it now...1661.upto(instruction[I_SIZE]) do |_i|167opcodes += Rex::Text.rand_char(badchars)168end169170# If we have gone over the requested sled length, try again.171if total_size + opcodes.length > length172try_count -= 1173174# If we have tried unsuccessfully 32 times we start unwinding the chosen opcode_stack to speed things up175if try_count == 0176pop_count = 4177while opcodes_stack.length && pop_count178total_size -= opcodes_stack.pop.length179pop_count -= 1180end181end182next183end184185# Reset the try_count for the next iteration.186try_count = 32187188# save the opcodes we just generated.189opcodes_stack.push(opcodes)190191# Increment the total size appropriately.192total_size += opcodes.length193194# Once we have generated the requested amount of bytes we can finish.195break if total_size == length196end197198# Now that we have chosen all the instructions to use we must generate the actual sled.199opcodes_stack.each do |opcodes_|200sled += opcodes_201end202203return sled204end205206def generate_sled(length, opts)207badchars = opts['BadChars'] || ''208random = opts['Random'] || datastore['RandomNops']209badregs = opts['SaveRegisters'] || []210good_instructions = []211sled = ''212213# Weed out any instructions which will contain a bad char/instruction...214INSTRUCTIONS.each do |instruction|215good = true216# If the instruction contains some bad chars we wont use it...217badchars.each_char do |bc|218if instruction[I_OP].include?(bc)219good = false220break221end222end223# if we are only to generate single byte instructions, weed out the multi byte ones...224good = false if (instruction[I_SIZE] > 0) && !datastore['MultiByte']225226good_instructions.push(instruction) if good227end228229# After we have pruned the instruction list we can proceed to generate a sled...230if good_instructions.empty?231# If we are left with no valid instructions to use we simple can't generate a sled.232sled = nil233elsif !random234if !badchars.include?("\x90")235sled += "\x90" * length236else237sled = nil238end239else240sled += generate_random_sled(length, good_instructions, badchars, badregs)241end242243return sled244end245end246247248