# This file is part of Metasm, the Ruby assembly manipulation suite # Copyright (C) 2006-2011 Yoann GUILLOT # # Licence is LGPL, see LICENCE in the top-level directory # metasm dasm plugin # scan for a given asm instruction sequence (all encodings) # add the G dasm-gui shortcut, the input change ';' for line splits def findgadget_asm_to_regex(asm) fullre = '' asm = asm.gsub(';', "\n") sc = Shellcode.new(@cpu) sc.parse asm sc.source.each { |i| case i when Data opts_edata = i.encode(@cpu.endianness) when Instruction opts_edata = @cpu.encode_instruction(sc, i) else raise "cant scan for #{i}" end opts_edata = [opts_edata] if opts_edata.kind_of?(EncodedData) opts_re = opts_edata.map { |ed| # Regexp.escape ed.data, with relocs replaced with '.' re = '' off = 0 ed.reloc.sort.each { |o, rel| re << Regexp.escape(ed.data[off...o]) re << ('.' * rel.length) off = o + rel.length } re << Regexp.escape(ed.data[off..-1]) } fullre << '(' << opts_re.join('|') << ')' } Regexp.new(fullre, Regexp::MULTILINE, 'n') end # parse asm to a regexp, return the list of addresses matching def findgadget_asm(asm) pattern_scan(findgadget_asm_to_regex(asm)) end def findgadget_prompt gui.inputbox("source for the gadget - separate with ;") { |asm| lst = findgadget_asm(asm) list = [['address', 'section']] sections = section_info list += lst.map { |addr| # [name, addr, len, misc] if s = sections.find { |s_| s_[1] <= addr and s_[1] + s_[2] > addr } s = s[0] else s = '?' end [Expression[addr], s] } gui.listwindow("gadgetscan for #{asm}", list) { |args| gui.focus_addr(args[0]) } } end if gui gui.keyboard_callback[?G] = lambda { |*a| findgadget_prompt } w = gui.toplevel w.addsubmenu(w.find_menu('Actions'), 'Scan for _Gadget', 'G') { findgadget_prompt } w.update_menu :success end