require 'metasm' include Metasm def find_tail(dasm, lastaddr, maxlen) tails = [] tails << [dasm.disassemble_instruction(lastaddr)] (1..maxlen).each { |i| di = dasm.disassemble_instruction(lastaddr-i) next if not di # invalid instruction next if di.opcode.props[:setip] or di.opcode.props[:stopexec] # jmp/jnz/ret/call next if not tail = tails.find { |t| di.next_addr == t.first.address } # does not fit in tail tails << ([di] + tail) } tails end ARGV.each { |file| dasm = AutoExe.decode_file(file).disassembler dasm.cpu = Ia32.new('386_common') # ignore weird instrs (in/out/sldt/mmx) rets = dasm.pattern_scan(/\xc2|\xc3/) puts "[+] found #{rets.length} rets" tails = [] rets.each { |retaddr| tails.concat find_tail(dasm, retaddr, 8) } puts "[+] found #{tails.length} tails" tails.each { |tail| puts tail puts } }