Пример #1
0
def find_imported_subroutines():
    """Find the address of all imported functions."""

    # Collect addresses of imported code.
    imported_eas = set()
    num_imports = idaapi.get_import_module_qty()
    for i in xrange(num_imports):
        idaapi.enum_import_names(i, lambda ea, name, ord: imported_eas.add(ea))

    # Mark IDA-identified stuff imported stuff as imported.
    for ea in imported_eas:
        if not program.has_subroutine(ea):
            log.error(
                "No subroutine associated with import {:08x}.".format(ea))
            continue
        sub = program.get_subroutine(ea)
        sub.visibility = program.Subroutine.VISIBILITY_IMPORTED

    # Mark functions in code sections marked as external as being imported.
    for sub in program.subroutines():
        if program.Subroutine.VISIBILITY_INTERNAL != sub.visibility:
            continue

        if has_segment_type(sub.ea, idc.SEG_XTRN):
            log.debug("Subroutine {:08x} is imported".format(sub.ea))
            sub.visibility = program.Subroutine.VISIBILITY_IMPORTED
            if sub.name:
                log.info("Found imported subroutine {} at {:08x}".format(
                    sub.name, sub.ea))
Пример #2
0
def find_imported_subroutines():
  """Find the address of all imported functions."""

  # Collect addresses of imported code.
  imported_eas = set()
  num_imports = idaapi.get_import_module_qty()
  for i in xrange(num_imports):
    idaapi.enum_import_names(i, lambda ea, name, ord: imported_eas.add(ea))

  # Mark IDA-identified stuff imported stuff as imported.
  for ea in imported_eas:
    if not program.has_subroutine(ea):
      log.error("No subroutine associated with import {:08x}.".format(ea))
      continue
    sub = program.get_subroutine(ea)
    sub.visibility = program.Subroutine.VISIBILITY_IMPORTED

  # Mark functions in code sections marked as external as being imported.
  for sub in program.subroutines():
    if program.Subroutine.VISIBILITY_INTERNAL != sub.visibility:
      continue

    if has_segment_type(sub.ea, idc.SEG_XTRN):
      log.debug("Subroutine {:08x} is imported".format(sub.ea))
      sub.visibility = program.Subroutine.VISIBILITY_IMPORTED
      if sub.name:
        log.info("Found imported subroutine {} at {:08x}".format(
            sub.name, sub.ea))
Пример #3
0
def find_exported_subroutines():
    """Find the functions that are exported to other binaries."""
    exported_eas = find_exported_eas()
    for ea in exported_eas:
        if not program.has_subroutine(ea):
            continue

        sub = program.get_subroutine(ea)
        if program.Subroutine.VISIBILITY_INTERNAL != sub.visibility:
            continue

        sub.visibility = program.Subroutine.VISIBILITY_EXPORTED
        if sub.name:
            log.info("Found exported subroutine {} at {:08x}".format(
                sub.name, sub.ea))

        mark_entry_block_address_taken(sub)
Пример #4
0
def find_exported_subroutines():
  """Find the functions that are exported to other binaries."""
  exported_eas = find_exported_eas()
  for ea in exported_eas:
    if not program.has_subroutine(ea):
      continue

    sub = program.get_subroutine(ea)
    if program.Subroutine.VISIBILITY_INTERNAL != sub.visibility:
      continue 

    sub.visibility = program.Subroutine.VISIBILITY_EXPORTED
    if sub.name:
      log.info("Found exported subroutine {} at {:08x}".format(
          sub.name, sub.ea))

    mark_entry_block_address_taken(sub)
Пример #5
0
def analyse_subroutine(sub):
    """Goes through the basic blocks of an identified function."""
    if len(sub.blocks):
        return  # We've already processed this subroutine.

    log.info("Analysing subroutine {} at {:08x}".format(sub.name, sub.ea))
    block_head_eas = set()
    block_head_eas.add(sub.ea)

    # Try to get IDA to give us function information.
    f = idaapi.get_func(sub.ea)
    if f:
        for b in idaapi.FlowChart(f):
            block_head_eas.add(b.startEA)

        for chunk_start_ea, chunk_end_ea in idautils.Chunks(sub.ea):
            block_head_eas.add(chunk_start_ea)
    else:
        log.warning("IDA does not recognise subroutine at {:08x}".format(
            sub.ea))

    # Iteratively scan for block heads. This will do linear sweeps looking for
    # block terminators. These linear sweeps do not consider flows incoming
    # flows from existing blocks that logically split a block into two.
    found_block_eas = set()
    while len(block_head_eas):
        block_head_ea = block_head_eas.pop()
        if block_head_ea in found_block_eas:
            continue

        found_block_eas.add(block_head_ea)

        # Try to make sure that analysis will terminate if we accidentally
        # walk through a noreturn call.
        if block_head_ea != sub.ea and program.has_subroutine(block_head_ea):
            continue

        log.debug("Found block head at {:08x}".format(block_head_ea))

        if program.has_basic_block(block_head_ea):
            existing_block = program.get_basic_block(block_head_ea)
            term_inst = existing_block.terminator
            assert term_inst is not None
        else:
            term_inst = find_linear_terminator(block_head_ea)

        log.debug("Linear terminator of {:08x} is {:08x}".format(
            block_head_ea, term_inst.ea))

        succ_eas = tuple(get_static_successors(term_inst))
        if succ_eas:
            log.debug("Static successors of {:08x} are {}".format(
                term_inst.ea,
                ", ".join("{:08x}".format(sea) for sea in succ_eas)))
            block_head_eas.update(succ_eas)

    # Create blocks associated with this subroutine for each block
    # head that the prior analysis discovered.
    blocks = []
    for block_head_ea in found_block_eas:
        if block_head_ea != sub.ea and program.has_subroutine(block_head_ea):
            continue
        block = sub.get_basic_block(block_head_ea)
        blocks.append(block)

    log.debug("Subroutine {:08x} has {} blocks".format(sub.ea, len(blocks)))

    # Analyse the blocks
    blocks.sort(key=lambda b: b.ea)
    for block in blocks:
        analyse_block(sub, block)
        log.debug("Block at {:08x} has {} instructions".format(
            block.ea, len(block.instructions)))
Пример #6
0
def analyse_subroutine(sub):
  """Goes through the basic blocks of an identified function."""
  if len(sub.blocks):
    return  # We've already processed this subroutine.

  log.info("Analysing subroutine {} at {:08x}".format(sub.name, sub.ea))
  block_head_eas = set()
  block_head_eas.add(sub.ea)

  # Try to get IDA to give us function information.
  f = idaapi.get_func(sub.ea)
  if f:
    for b in idaapi.FlowChart(f):
      block_head_eas.add(b.startEA)

    for chunk_start_ea, chunk_end_ea in idautils.Chunks(sub.ea):
      block_head_eas.add(chunk_start_ea)
  else:
    log.warning("IDA does not recognise subroutine at {:08x}".format(sub.ea))

  # Iteratively scan for block heads. This will do linear sweeps looking for
  # block terminators. These linear sweeps do not consider flows incoming
  # flows from existing blocks that logically split a block into two.
  found_block_eas = set()
  while len(block_head_eas):
    block_head_ea = block_head_eas.pop()
    if block_head_ea in found_block_eas:
      continue

    if not is_code(block_head_ea):
      log.error("Block head at {:08x} is not code.".format(block_head_ea))
      continue

    found_block_eas.add(block_head_ea)

    # Try to make sure that analysis will terminate if we accidentally 
    # walk through a noreturn call.
    if block_head_ea != sub.ea and program.has_subroutine(block_head_ea):
      continue

    log.debug("Found block head at {:08x}".format(block_head_ea))

    if program.has_basic_block(block_head_ea):
      existing_block = program.get_basic_block(block_head_ea)
      term_inst = existing_block.terminator
      assert term_inst is not None
    else:
      term_inst = find_linear_terminator(block_head_ea)

    if not term_inst:
      log.error("Block at {:08x} has no terminator!".format(block_head_ea))
      found_block_eas.remove(block_head_ea)
      continue

    log.debug("Linear terminator of {:08x} is {:08x}".format(
        block_head_ea, term_inst.ea))
    
    succ_eas = tuple(get_static_successors(term_inst))
    if succ_eas:
      log.debug("Static successors of {:08x} are {}".format(
          term_inst.ea, ", ".join("{:08x}".format(sea) for sea in succ_eas)))
      block_head_eas.update(succ_eas)

  # Create blocks associated with this subroutine for each block
  # head that the prior analysis discovered.
  blocks = []
  for block_head_ea in found_block_eas:
    if block_head_ea != sub.ea and program.has_subroutine(block_head_ea):
      continue
    block = sub.get_basic_block(block_head_ea)
    blocks.append(block)

  log.debug("Subroutine {:08x} has {} blocks".format(sub.ea, len(blocks)))

  # Analyse the blocks
  blocks.sort(key=lambda b: b.ea)
  for block in blocks:
    analyse_block(sub, block)
    log.debug("Block at {:08x} has {} instructions".format(
        block.ea, len(block.instructions)))