def save_to_stream(output_stream): mod = CFG_pb2.Module() num_subs, num_blocks, num_insts = 0, 0, 0 exclude_blocks = set() for sub in program.subroutines(): num_subs += 1 if program.Subroutine.VISIBILITY_IMPORTED == sub.visibility: exclude_blocks.update(sub.blocks) log.debug("Not serializing {} blocks".format(len(exclude_blocks))) referenced_blocks = set() for block in program.basic_blocks(): if block in exclude_blocks: continue if not len(block.instructions): referenced_blocks.add(block) continue num_blocks += 1 log.info("Serializing block {:08x}.".format(block.ea)) b = mod.blocks.add() b.address = block.ea b.is_addressable = block.address_is_taken for inst in block: i = b.instructions.add() i.address = inst.ea i.bytes = inst.bytes num_insts += 1 for block in referenced_blocks: mod.referenced_blocks.add(block.ea) for sub in program.subroutines(): if not sub.name: continue if program.Subroutine.VISIBILITY_INTERNAL == sub.visibility: continue nb = mod.named_blocks.add() nb.name = sub.name nb.address = sub.ea if program.Subroutine.VISIBILITY_IMPORTED == sub.visibility: nb.visibility = CFG_pb2.IMPORTED elif program.Subroutine.VISIBILITY_EXPORTED == sub.visibility: nb.visibility = CFG_pb2.EXPORTED log.info("Serializing {} subroutines".format(num_subs)) log.info("Serializing {} blocks".format(num_blocks)) log.info("Serializing {} instructions".format(num_insts)) output_stream.write(mod.SerializeToString())
def analyse_function_returns(): """Find all function call instructions, and mark the blocks associated with their return addresses as having their addresses taken.""" log.info("Analysing targets of function call return instructions") for block in program.basic_blocks(): term_inst = block.terminator if not term_inst or not term_inst.is_function_call(): continue return_target_block = program.get_basic_block(term_inst.next_ea) return_target_block.address_is_taken = True
def analyse_indirect_jumps(): """Scan through the code looking for jump tables.""" log.info("Analysing indirect jump instructions") blocks = set(program.basic_blocks()) seen = set() while len(blocks): block = blocks.pop() if block in seen: continue seen.add(block) term_inst = block.terminator if term_inst.is_indirect_jump(): analyse_indirect_jump(block, term_inst, blocks)
def analyse_callbacks(): """Analyse functions that are used as callbacks.""" global POSSIBLE_CODE_REFS log.info("Analysing callbacks") for ea in POSSIBLE_CODE_REFS: if program.has_basic_block(ea): block = program.get_basic_block(ea) if not block.address_is_taken: block.address_is_taken = True log.info("Block {:08x} is a callback".format(ea)) for block in program.basic_blocks(): if not block.address_is_taken: if len(tuple(idautils.DataRefsTo(block.ea))): block.address_is_taken = True log.info("Block {:08x} is a callback".format(block.ea))
def analyse_callbacks(): """Analyse functions that are used as callbacks.""" global POSSIBLE_CODE_REFS log.info("Analysing callbacks") for ea in POSSIBLE_CODE_REFS: if program.has_basic_block(ea): block = program.get_basic_block(ea) if not block.address_is_taken: block.address_is_taken = True log.info("Block {:08x} is a callback (1)".format(ea)) for block in program.basic_blocks(): if not block.address_is_taken: if len(tuple(idautils.DataRefsTo(block.ea))): block.address_is_taken = True log.info("Block {:08x} is a callback (2)".format(block.ea))
def save_to_stream(output_stream): mod = CFG_pb2.Module() num_subs, num_blocks, num_insts = 0, 0, 0 exclude_blocks = set() for sub in program.subroutines(): num_subs += 1 if program.Subroutine.VISIBILITY_IMPORTED == sub.visibility: exclude_blocks.update(sub.blocks) log.debug("Not serializing {} blocks".format(len(exclude_blocks))) referenced_blocks = set() addressed_blocks = set() for block in program.basic_blocks(): if block in exclude_blocks: continue if not len(block.instructions): referenced_blocks.add(block) log.error("Block {:08x} has no instructions.".format(block.ea)) continue num_blocks += 1 log.info("Serializing block {:08x}.".format(block.ea)) b = mod.blocks.add() b.address = block.ea if block.address_is_taken: addressed_blocks.add(block) for inst in block: i = b.instructions.add() i.address = inst.ea i.bytes = inst.bytes num_insts += 1 for block in addressed_blocks: mod.addressed_blocks.append(block.ea) for block in referenced_blocks: mod.referenced_blocks.append(block.ea) for sub in program.subroutines(): if not sub.name: continue if program.Subroutine.VISIBILITY_INTERNAL == sub.visibility: continue nb = mod.named_blocks.add() nb.name = sub.name nb.address = sub.ea if program.Subroutine.VISIBILITY_IMPORTED == sub.visibility: nb.visibility = CFG_pb2.IMPORTED elif program.Subroutine.VISIBILITY_EXPORTED == sub.visibility: nb.visibility = CFG_pb2.EXPORTED log.info("Serializing {} subroutines".format(num_subs)) log.info("Serializing {} blocks".format(num_blocks)) log.info("Serializing {} instructions".format(num_insts)) output_stream.write(mod.SerializeToString())