class Rex::MachScan::Scanner::JmpRegScanner
Public Instance Methods
_build_byte_list(base, regnums)
click to toggle source
build a list for regex of the possible bytes, based on a base byte and a list of register numbers..
# File lib/rex/machscan/scanner.rb, line 73 def _build_byte_list(base, regnums) regnums.collect { |regnum| Regexp.escape((base | regnum).chr) }.join('') end
_parse_ret(data)
click to toggle source
# File lib/rex/machscan/scanner.rb, line 87 def _parse_ret(data) if data.length == 1 return "ret" else return "retn 0x%04x" % data[1, 2].unpack('v')[0] end end
_ret_size(offset)
click to toggle source
# File lib/rex/machscan/scanner.rb, line 77 def _ret_size(offset) case mach.read(offset, 1) when "\xc3" return 1 when "\xc2" return 3 end $stderr.puts("Invalid return instruction") end
config(param)
click to toggle source
# File lib/rex/machscan/scanner.rb, line 52 def config(param) regnums = param['args'] # build a list of the call bytes calls = _build_byte_list(0xd0, regnums - [4]) # note call esp's don't work.. jmps = _build_byte_list(0xe0, regnums) pushs1 = _build_byte_list(0x50, regnums) pushs2 = _build_byte_list(0xf0, regnums) regexstr = '(' if !calls.empty? regexstr += "\xff[#{calls}]|" end regexstr += "\xff[#{jmps}]|([#{pushs1}]|\xff[#{pushs2}])(\xc3|\xc2..))" self.regex = Regexp.new(regexstr, nil, 'n') end
scan_segment(segment, param={})
click to toggle source
# File lib/rex/machscan/scanner.rb, line 95 def scan_segment(segment, param={}) base_addr = segment.vmaddr segment_offset = segment.fileoff offset = segment_offset hits = [] while (offset = mach.index(regex, offset)) != nil vaddr = base_addr + (offset - segment_offset) message = '' parse_ret = false byte1 = mach.read(offset, 1).unpack("C*")[0] if byte1 == 0xff byte2 = mach.read(offset+1, 1).unpack("C*")[0] regname = Rex::Arch::X86.reg_name32(byte2 & 0x7) case byte2 & 0xf8 when 0xd0 message = "call #{regname}" offset += 2 when 0xe0 message = "jmp #{regname}" offset += 2 when 0xf0 retsize = _ret_size(offset+2) message = "push #{regname}; " + _parse_ret(mach.read(offset+2, retsize)) offset += 2 + retsize else raise "wtf" end else regname = Rex::Arch::X86.reg_name32(byte1 & 0x7) retsize = _ret_size(offset+1) message = "push #{regname}; " + _parse_ret(mach.read(offset+1, retsize)) offset += 1 + retsize end hits << [ vaddr, message ] end return hits end