class Rex::RopBuilder::RopCollect
Public Class Methods
new(file="")
click to toggle source
Calls superclass method
Rex::RopBuilder::RopBase::new
# File lib/rex/ropbuilder/rop.rb, line 90 def initialize(file="") @stdio = Rex::Ui::Text::Output::Stdio.new @file = file if not file.empty? @bin = Metasm::AutoExe.decode_file(file) if not file.empty? @disassembler = @bin.disassembler if not @bin.nil? if @disassembler @disassembler.cpu = Metasm::Ia32.new('386_common') end super() end
Public Instance Methods
collect(depth, pattern)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 101 def collect(depth, pattern) matches = [] gadgets = [] # find matches by scanning for the pattern matches = @disassembler.pattern_scan(pattern) if @bin.kind_of?(Metasm::PE) @bin.sections.each do |section| next if section.characteristics.include? 'MEM_EXECUTE' # delete matches if the address is outside the virtual address space matches.delete_if do |ea| va = section.virtaddr + @bin.optheader.image_base ea >= va and ea < va + section.virtsize end end elsif @bin.kind_of?(Metasm::ELF) @bin.segments.each do |seg| next if seg.flags.include? 'X' matches.delete_if do |ea| ea >= seg.vaddr and ea < seg.vaddr + seg.memsz end end elsif @bin.kind_of?(Metasm::MachO) @bin.segments.each do |seg| next if seg.initprot.include? 'EXECUTE' matches.delete_if do |ea| ea >= seg.virtaddr and ea < seg.virtaddr + seg.filesize end end end gadgets = process_gadgets(matches, depth) gadgets.each do |gadget| @gadgets << gadget end gadgets end
color_pattern(gadget, disasm, addrs, p)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 164 def color_pattern(gadget, disasm, addrs, p) idx = disasm.index(p) if idx.nil? print_msg(gadget[:disasm]) return end disasm = disasm.insert(idx, "%bld%grn") asm = "" cnt = 0 colors = false disasm.each_line do |line| # if we find this then we are in the matching area if line.index(/\%bld\%grn/) colors = true end asm << "%clr" + addrs[cnt] + "\t" # color the remaining parts of the gadget if colors and line.index("%bld%grn").nil? asm << "%bld%grn" + line else asm << line end cnt += 1 end asm << "%clr\n" print_msg(asm) end
pattern_search(pattern)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 139 def pattern_search(pattern) p = Regexp.new("(" + pattern + ")") matches = [] @gadgets.each do |gadget| disasm = "" addrs = [] gadget[:disasm].each_line do |line| addr, asm = line.split("\t", 2) addrs << addr disasm << asm end if gadget[:raw] =~ p or gadget[:disasm] =~ p or disasm =~ p matches << {:gadget => gadget, :disasm => disasm, :addrs => addrs} end end matches.each do |match| @stdio.print_status("gadget with address: %bld%cya#{match[:gadget][:address]}%clr matched") color_pattern(match[:gadget], match[:disasm], match[:addrs], p) end matches end
process_gadgets(rets, num)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 196 def process_gadgets(rets, num) ret = {} gadgets = [] tmp = [] rets.each do |ea| insn = @disassembler.disassemble_instruction(ea) next if not insn xtra = insn.bin_length num.downto(0) do |x| addr = ea - x # get the disassembled instruction at this address di = @disassembler.disassemble_instruction(addr) # skip invalid instructions next if not di next if di.opcode.props[:setip] next if di.opcode.props[:stopexec] # get raw bytes buf = @disassembler.read_raw_data(addr, x + xtra) # make sure disassembling forward leads to our instruction next if not ends_with_addr(buf, addr, ea) dasm = "" while addr <= ea di = @disassembler.disassemble_instruction(addr) dasm << ("0x%08x:\t" % addr) + di.instruction.to_s + "\n" addr = addr + di.bin_length end if not tmp.include?(ea) tmp << ea else next end # otherwise, we create a new tailchunk and add it to the list ret = {:file => @file, :address => ("0x%08x" % (ea - x)), :raw => buf, :disasm => dasm} gadgets << ret end end gadgets end
Private Instance Methods
ends_with_addr(raw, base, addr)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 246 def ends_with_addr(raw, base, addr) dasm2 = Metasm::Shellcode.decode(raw, @disassembler.cpu).disassembler offset = 0 while ((di = dasm2.disassemble_instruction(offset))) return true if (base + offset) == addr return false if di.opcode.props[:setip] return false if di.opcode.props[:stopexec] offset = di.next_addr end false end
raw_instructions(raw)
click to toggle source
# File lib/rex/ropbuilder/rop.rb, line 258 def raw_instructions(raw) insns = [] d2 = Metasm::Shellcode.decode(raw, @disassembler.cpu).disassembler addr = 0 while ((di = d2.disassemble_instruction(addr))) insns << di.instruction addr = di.next_addr end insns end