## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## ### # # This class implements single-byte NOP generation for X86. It takes from # ADMmutate and from spoonfu. # ### class MetasploitModule < Msf::Nop SINGLE_BYTE_SLED = { # opcode affected registers # ------ ------------------ "\x90" => nil , # nop "\x97" => [ 'eax', 'edi' ], # xchg eax,edi "\x96" => [ 'eax', 'esi' ], # xchg eax,esi "\x95" => [ 'eax', 'ebp' ], # xchg eax,ebp "\x93" => [ 'eax', 'ebx' ], # xchg eax,ebx "\x92" => [ 'eax', 'edx' ], # xchg eax,edx "\x91" => [ 'eax', 'ecx' ], # xchg eax,ecx "\x99" => [ 'edx' ], # cdq "\x4d" => [ 'ebp' ], # dec ebp "\x48" => [ 'eax' ], # dec eax "\x47" => [ 'edi' ], # inc edi "\x4f" => [ 'edi' ], # dec edi "\x40" => [ 'eax' ], # inc eax "\x41" => [ 'ecx' ], # inc ecx "\x37" => [ 'eax' ], # aaa "\x3f" => [ 'eax' ], # aas "\x27" => [ 'eax' ], # daa "\x2f" => [ 'eax' ], # das "\x46" => [ 'esi' ], # inc esi "\x4e" => [ 'esi' ], # dec esi "\xfc" => nil , # cld "\xfd" => nil , # std "\xf8" => nil , # clc "\xf9" => nil , # stc "\xf5" => nil , # cmc "\x98" => [ 'eax' ], # cwde "\x9f" => [ 'eax' ], # lahf "\x4a" => [ 'edx' ], # dec edx "\x44" => [ 'esp', 'align' ], # inc esp "\x42" => [ 'edx' ], # inc edx "\x43" => [ 'ebx' ], # inc ebx "\x49" => [ 'ecx' ], # dec ecx "\x4b" => [ 'ebx' ], # dec ebx "\x45" => [ 'ebp' ], # inc ebp "\x4c" => [ 'esp', 'align' ], # dec esp "\x9b" => nil , # wait "\x60" => [ 'esp' ], # pusha "\x0e" => [ 'esp', 'align' ], # push cs "\x1e" => [ 'esp', 'align' ], # push ds "\x50" => [ 'esp' ], # push eax "\x55" => [ 'esp' ], # push ebp "\x53" => [ 'esp' ], # push ebx "\x51" => [ 'esp' ], # push ecx "\x57" => [ 'esp' ], # push edi "\x52" => [ 'esp' ], # push edx "\x06" => [ 'esp', 'align' ], # push es "\x56" => [ 'esp' ], # push esi "\x54" => [ 'esp' ], # push esp "\x16" => [ 'esp', 'align' ], # push ss "\x58" => [ 'esp', 'eax' ], # pop eax "\x5d" => [ 'esp', 'ebp' ], # pop ebp "\x5b" => [ 'esp', 'ebx' ], # pop ebx "\x59" => [ 'esp', 'ecx' ], # pop ecx "\x5f" => [ 'esp', 'edi' ], # pop edi "\x5a" => [ 'esp', 'edx' ], # pop edx "\x5e" => [ 'esp', 'esi' ], # pop esi "\xd6" => [ 'eax' ], # salc } def initialize super( 'Name' => 'Single Byte', 'Alias' => 'ia32_singlebyte', 'Description' => 'Single-byte NOP generator', 'Author' => 'spoonm', 'License' => MSF_LICENSE, 'Arch' => ARCH_X86) register_advanced_options( [ OptBool.new('RandomNops', [ false, "Generate a random NOP sled", true ]) ]) end # Generate a single-byte NOP sled for X86 def generate_sled(length, opts = {}) sled_hash = SINGLE_BYTE_SLED sled_max_idx = sled_hash.length sled_cur_idx = 0 out_sled = '' random = opts['Random'] badchars = opts['BadChars'] || '' badregs = opts['SaveRegisters'] || [] # Did someone specify random NOPs in the environment? if (!random and datastore['RandomNops']) random = datastore['RandomNops'] end # Generate the whole sled... 1.upto(length) { |current| cur_char = nil threshold = 0 # Keep snagging characters until we find one that satisfies both the # bad character and bad register requirements begin sled_cur_idx = rand(sled_max_idx) if (random == true) cur_char = sled_hash.keys[sled_cur_idx] sled_cur_idx += 1 if (random == false) sled_cur_idx = 0 if (sled_cur_idx >= sled_max_idx) # Make sure that we haven't gone over the sled repeat threshold if ((threshold += 1) > self.nop_repeat_threshold) return nil end end while ((badchars.include?(cur_char)) or ((sled_hash[cur_char]) and ((sled_hash[cur_char] & badregs).length > 0))) # Add the character to the sled now that it's passed our checks out_sled += cur_char } # If the sled fails to entirely generate itself, then that's bogus, # man... if (out_sled.length != length) return nil end return out_sled end end