76 lines
1.8 KiB
Ruby
76 lines
1.8 KiB
Ruby
# 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
|