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 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 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 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]