def is_valid(bv: bn.binaryview.BinaryView): sym = bv.get_symbol_by_raw_name("__elf_interp") if sym is None: return False else: var = bv.get_data_var_at(sym.address) return b"test_debug_info_parsing" == bv.read(sym.address, var.type.width - 1)
def restore_symbols(view: binaryninja.binaryview.BinaryView, gopclntab: binaryninja.binaryview.Section) -> None: ptr_size = view.address_size """ the .gopclntab table (starting at .gopclntab + 8) consists of N pc0 func0 pc1 func1 pc2 func2 ... pc(N-1) func(N-1) pcN N := no of elemements in table pcX := pointer to the function funcX := pointer to struct Func struct Func { uintptr entry; // start pc int32 name; // name (offset to C string) int32 args; // size of arguments passed to function int32 frame; // size of function frame, including saved caller PC int32 pcsp; // pcsp table (offset to pcvalue table) int32 pcfile; // pcfile table (offset to pcvalue table) int32 pcln; // pcln table (offset to pcvalue table) int32 nfuncdata; // number of entries in funcdata list int32 npcdata; // number of entries in pcdata list }; src: https://docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o/pub """ # validate magic bytes magic_bytes_found = view.read(gopclntab.start, 4) magic_bytes_expected = b'\xfb\xff\xff\xff' if magic_bytes_expected != magic_bytes_found: log_error("Invalid .gopclntab section. Aborting!") return # get number of elements and calculate last address size_addr = gopclntab.start + 8 # skip first 8 bytes size = get_pointer_LE(view, size_addr) start_addr = size_addr + ptr_size end_addr = gopclntab.start + 8 + ptr_size + (size * ptr_size * 2) # iterate over the table and restore function names for current_addr in range(start_addr, end_addr, 2 * ptr_size): function_addr = get_pointer_LE(view, current_addr) struct_func_offset = get_pointer_LE(view, current_addr + ptr_size) name_str_offset = get_dword_LE( view, gopclntab.start + struct_func_offset + ptr_size) name_addr = gopclntab.start + name_str_offset function_name = view.get_ascii_string_at(name_addr) if not function_name: continue log_info( f'found name "{function_name}" for function starting at 0x{function_addr:x}' ) function = view.get_function_at(function_addr) if not function: view.create_user_function(function_addr) function = view.get_function_at(function_addr) new_func_comment = function_name.value if function.comment: new_func_comment += "\n\n{}".format(function.comment) function.comment = new_func_comment function.name = sanitize_func_name(function_name.value)
def find_segment(bv: binaryninja.binaryview.BinaryView, name: str) -> List[Tuple[int, int]]: """ Try to find the segment from name :ivar name: name of segment :ret: Start ant end address """ result = [] for sn in bv.sections: sec = bv.get_section_by_name(sn) if sec.name == name: result.append((sec.start, sec.end)) return result
def find_wevt_template(bv: binaryninja.binaryview.BinaryView, start: int, end: int) -> Stream: """ This function try to retrieve the WEVT_TEMPLETE resource This resource start with the magic CRIM :ivar start: start address :ivar end: end address :ret: Stream use to parse Manifest based provider or raise an exception :raise: ETWBreakerWevtTemplateNotFound """ resource = bv.read(start, end - start) result = resource.find(b"CRIM") if result == -1: raise ETWBreakerWevtTemplateNotFound() return Stream(resource[result:])
def is_gopclntab_section(view: binaryninja.binaryview.BinaryView, section: binaryninja.binaryview.Section) -> bool: if section.name == ".gopclntab": return True # validate magic bytes magic_bytes_found = view.read(section.start, 4) magic_bytes_expected = b'\xfb\xff\xff\xff' if magic_bytes_expected != magic_bytes_found: return False ptr_size = view.address_size first_entry = section.start + 8 + ptr_size first_fun_addr = get_pointer_LE(view, first_entry) first_entry_struct_func_offset = get_pointer_LE(view, first_entry + 8) fun_addr_struct_func = get_pointer_LE( view, section.start + first_entry_struct_func_offset) if first_fun_addr != fun_addr_struct_func: return False return True
def parse_info(debug_info: bn.debuginfo.DebugInfo, bv: bn.binaryview.BinaryView): print("Adding types") types = [] for name, t in bv.parse_types_from_string(""" struct test_type_1 { int a; char b[4]; uint64_t c; bool d; }; struct test_type_2 { struct test_type_1 a; struct test_type_1* b; struct test_type_2* c; };""").types.items(): print( f" Adding type \"{name}\" `{t}` : {debug_info.add_type(str(name), t)}" ) types.append(t) print("Adding data variables") pretty_print_add_data_variable(debug_info, 0x4030, types[0], "test_var_1") pretty_print_add_data_variable(debug_info, 0x4010, bn.types.Type.int(4, True), "test_var_2") # Names are optional pretty_print_add_data_variable(debug_info, 0x4014, bn.types.Type.int(4, True)) t = bn.types.Type.int(4, True) t.const = True pretty_print_add_data_variable(debug_info, 0x2004, t, "test_var_3") print("Adding functions") char_star = bv.parse_type_string("char*")[0] pretty_print_add_function(debug_info, 0x1129, "no_return_type_no_parameters", None, None, bn.types.Type.void(), None) pretty_print_add_function(debug_info, 0x1134, "used_parameter", None, None, bn.types.Type.bool(), [("value", bn.types.Type.bool())]) pretty_print_add_function(debug_info, 0x1155, "unused_parameters", None, None, bn.types.Type.int(4, True), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star)]) pretty_print_add_function(debug_info, 0x1170, "used_and_unused_parameters_1", None, None, bn.types.Type.int(4, True), [("value_1", bn.types.Type.int(4, True)), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star), ("value_4", bn.types.Type.bool())]) pretty_print_add_function(debug_info, 0x1191, "used_and_unused_parameters_2", None, None, bn.types.Type.int(1, False), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(1, False)), ("value_3", char_star), ("value_4", bn.types.Type.int(1, False)), ("value_5", bn.types.Type.char())]) pretty_print_add_function(debug_info, 0x11c0, "local_parameters", None, None, bn.types.Type.void(), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(1, False)), ("value_3", char_star), ("value_4", bn.types.Type.int(1, False)), ("value_5", bn.types.Type.char())])
def get_dword_LE(view: binaryninja.binaryview.BinaryView, addr: int) -> bytes: return struct.unpack("<I", view.read(addr, 4))[0]
def get_pointer_LE(view: binaryninja.binaryview.BinaryView, addr: int) -> bytes: addr_size = view.address_size return struct.unpack("<L" if addr_size == 4 else "<Q", view.read(addr, addr_size))[0]