module TurboRex::Utils::DisassemblerHelper

Public Instance Methods

_disassemble_executable_sections(pe, method=:disassemble_fast_deep) click to toggle source
# File lib/turborex/utils.rb, line 97
def _disassemble_executable_sections(pe, method=:disassemble_fast_deep)
  dasm = pe.disassembler
  executable_sections = pe.section_info.select {|s| s.last.to_s.split(',').include?('MEM_EXECUTE')}
  unless executable_sections.empty?
    add_dasm_all_method(dasm)
    executable_sections.each do |name, address, len|
      dasm.dasm_all(address, len, method)
    end

    addrtolabel(dasm)
    dasm
  end
end
add_dasm_all_method(dasm) click to toggle source
# File lib/turborex/utils.rb, line 44
def add_dasm_all_method(dasm)
  dasm.instance_eval %(
    def dasm_all(addrstart, length, method=:disassemble_fast_deep)
      s = get_section_at(addrstart)
      return if not s
      s = s[0]
      boff = s.ptr
      off = 0
      while off < length
        if di = di_at(addrstart + off)
          off += di.bin_length
        elsif @decoded[addrstart+off]
          off += 1
        else
          s.ptr = boff+off
          maydi = cpu.decode_instruction(s, 0)
          if not maydi
            off += 1
          elsif maydi.instruction.to_s =~ /nop|lea (.*), \[\1(?:\+0)?\]|mov (.*), \2|int 3/
            off += maydi.bin_length
          else
            send(method, addrstart+off)
          end
        end
      end

      count = 0
      off = 0
      while off < length
        addr = addrstart+off
        if di = di_at(addr)
          if di.block_head?
            b = di.block
            if not @function[addr] and b.from_subfuncret.to_a.empty? and b.from_normal.to_a.empty?
              l = auto_label_at(addr, 'sub_orph')
              @function[addrstart+off] = Metasm::DecodedFunction.new
              @function[addrstart+off].finalized = true
              detect_function_thunk(addr)
              count += 1
            end
          end
          off += di.bin_length
        else
          off += 1
        end
      end

    end
  )

  dasm
end
addrtolabel(dasm) click to toggle source

github.com/jjyg/metasm/blob/master/samples/dasm-plugins/imm2off.rb

# File lib/turborex/utils.rb, line 23
def addrtolabel(dasm)
  bp = dasm.prog_binding.invert
  dasm.decoded.each_value do |di|
    next unless di.is_a?(Metasm::DecodedInstruction)

    di.each_expr do |e|
      next unless e.is_a?(Metasm::Expression)

      if l = bp[e.lexpr]
        dasm.add_xref(e.lexpr, Metasm::Xref.new(:addr, di.address))
        e.lexpr = Metasm::Expression[l]
      end
      if l = bp[e.rexpr]
        dasm.add_xref(e.rexpr, Metasm::Xref.new(:addr, di.address))
        e.rexpr = (e.lexpr ? Metasm::Expression[l] : l)
      end
    end
  end
  nil
end
backtrace(addr, dasm, e, narg={}) click to toggle source

github.com/jjyg/metasm/blob/2a088ff85e5b873570bc284a97ddd9f8b3b0a03a/metasm/gui/dasm_main.rb#L413

# File lib/turborex/utils.rb, line 112
def backtrace(addr, dasm, e, narg={})
  bd = {}
  expr = Metasm::IndExpression.parse_string(e)
  registers = (begin
                  dasm.cpu.dbg_register_list.map(&:to_s)
                rescue StandardError
                  []
                end)
  expr.externals.grep(String).each do |w|
    bd[w] = w.downcase.to_sym if registers.include? w.downcase
  end

  expr = expr.bind(bd).reduce do |e_|
    e_.len ||= dasm.cpu.size / 8 if e_.is_a? Metasm::Indirection; nil
  end

  log = []
  found = []
  bt_opts = { log: log }
  bt_opts.merge!(narg)
  dasm.backtrace(expr, addr, bt_opts)
  if found_log = log.assoc(:found)
    found_log[1].each do |expr|
      found << dasm.resolve(expr)
    end
  end

  [found, log]
end
solve_cppobj_call(dasm, di) click to toggle source
# File lib/turborex/utils.rb, line 142
def solve_cppobj_call(dasm, di)
  return unless di.opcode.props[:saveip]  
  fptr = dasm.get_xrefs_x(di)
  return if fptr.to_a.length != 1
  fptr = ::Metasm::Expression[fptr.first].reduce_rec
  return unless fptr.kind_of? ::Metasm::Indirection
  return unless fptr.pointer.lexpr.kind_of? Symbol  
  return unless fptr.pointer.rexpr.kind_of? Integer
  log = []
  vtbl = dasm.backtrace(fptr.pointer.lexpr, di.address, log: log)
  vtbl.delete ::Metasm::Expression::Unknown

  if vtbl.empty?
    r = log.reverse_each.detect {|l| l[0] != :found && l[2] != ::Metasm::Expression[:unknown]}
    vtbl =  r[2].reduce_rec
  else
    vtbl = vtbl.first
  end

  vtbl = ::Metasm::Expression[vtbl].reduce_rec
  return unless vtbl.kind_of? ::Metasm::Indirection
  obj = vtbl.pointer
  ptr_size = @dasm.program.cpu.size / 8
  [obj, vtbl, fptr.pointer.rexpr / ptr_size]
end
solve_guard_icall(dasm, di) click to toggle source
# File lib/turborex/utils.rb, line 168
def solve_guard_icall(dasm, di)
  return unless di.opcode.props[:saveip]  
  fptr = dasm.get_xrefs_x(di)
  return if fptr.to_a.length != 1
  fptr = ::Metasm::Expression[fptr.first].reduce_rec
  return unless fptr.kind_of? ::Metasm::Indirection

  v = case dasm.cpu.size
  when 32
     dasm.program.decode_loadconfig.guard_check_icall
  when 64
     dasm.program.decode_loadconfig.guard_dispatch_icall
  end

  #f = dasm.decode_dword(dasm.normalize(dasm.prog_binding[v.to_s])).to_s
  if v == fptr.pointer
    case dasm.cpu.size
    when 32
      expr = :ecx
    when 64
      expr = :rax
    end

    log = []
    res = dasm.backtrace(expr, di.address, log: log)
    res.delete ::Metasm::Expression::Unknown
    if res.empty?
      r = log.reverse_each.detect {|l| l[0] != :found && l[2] != ::Metasm::Expression[:unknown]}
      return r[2].reduce_rec
    end

    return res.first
  end
end