def build_function_cfg(functions, insns, bbs, header, file_data): g = networkx.DiGraph() bb_entries = [ bb["first_insn"] for bb in bbs ] for e in bb_entries: g.add_node(e) for bb in bbs: bb_end = bb["last_insn"] last_insn = None targets = [] for c, i in enumerate(insns): if i["addr"] == bb_end: last_insn = c break if last_insn: if insns[last_insn]["group"] in ("exec"): #and insns[last_insn]["mnem"] not in ("call", "callcc"): target = re_lib.resolve_target_operand(insns[last_insn], header, file_data, functions) if target: targets.append(target) if insns[last_insn]["mnem"] not in ("jmp", "ret", "retn") and last_insn < len(insns) - 1: targets.append(insns[last_insn+1]["addr"]) elif insns[last_insn]["mnem"] not in ("ret", "retn") and last_insn < len(insns) - 1: targets.append(insns[last_insn+1]["addr"]) for t in targets: if t in bb_entries: g.add_edge(bb["first_insn"], t) if g.size() == 0: g = None return g
def find_function_call_targets( insns, header, file_data ): targets = set() for a in insns: if a["mnem"] in ("call", "callcc"): target = re_lib.resolve_target_operand( a, header, file_data ) if target: targets.add(target) return targets
def find_targets(insns, header, file_data, functions): targets = set() for a in insns: if a["group"] in ("exec"): target = re_lib.resolve_target_operand(a, header, file_data, functions) if target: targets.add(target) return targets
def find_jump_targets( insns, header, file_data ): targets = set() for a in insns[:-1]: if a["group"] in ("exec") and a["mnem"] not in ("call", "callcc", "ret", "retn"): target = re_lib.resolve_target_operand( a, header, file_data ) if target: targets.add(target) return targets
def process(oid, opts): logger.debug("process()") header = api.get_field("object_header", oid, "header") if not header: return False disasm = api.get_field("disassembly", oid, "insns") if not disasm: return False file_data = api.get_field(api.source(oid), oid, "data") if not file_data: return False internal_functions = api.retrieve("function_extract", oid) mapping = {} imps = {} ord_map = api.load_reference("ordinal_map") src_type = api.get_field("src_type", oid, "type") if src_type == "PE": imports = header.symbol_table for i in imports: if isinstance(imports[i]['name'], str): # we have a name imps[i] = imports[i]['name'] else: # we have an ordinal dll_name = imports[i]["dll"].lower() if dll_name in ord_map: if imports[i]['name'] in ord_map[dll_name]: imps[i] = ord_map[dll_name][imports[i]['name']] if i not in imps: imps[i] = dll_name + ":Ordinal " + str(imports[i]['name']) data = { "system_calls":{}, "internal_functions":{}, "unresolved_calls":{} } # Find location of jump table. Calls in program will call these stubs which then # jump to external functions. for i in disasm: insn = disasm[i] if insn["mnem"] in ("jmp"): target_op = insn.get("d_op", None) if not target_op: continue if isinstance(target_op["data"], int): target = target_op["data"] elif "disp" in target_op["data"]: target = target_op["data"]["disp"] else: continue if target in imps: mapping[insn["addr"]] = imps[target] data["system_calls"][i] = imps[target] for i in disasm: insn = disasm[i] target = 0 if insn["mnem"] in ("call", "callcc"): if insn['d_op']['type'] == 'eff_addr' and not insn['d_op']['data']['base']: target = insn['d_op']['data']['disp'] else: target = re_lib.resolve_target_operand(insn, header, file_data, internal_functions) if target in mapping: data["system_calls"][i] = mapping[target] elif target in imps: data["system_calls"][i] = imps[target] elif target in internal_functions: data["internal_functions"][i] = internal_functions[target]["name"] else: data["unresolved_calls"][i] = target api.store(name, oid, data, opts) return True