def parse_hdr(self): ''' Refer: function [go12Init()] in https://golang.org/src/debug/gosym/pclntab.go ''' magic = idc.Dword(self.start_addr) & 0xFFFFFFFF if magic != Pclntbl.MAGIC: print magic, Pclntbl.MAGIC common._error("Invalid pclntbl header magic number!") idc.Exit(1) #raise Exception("Invalid pclntbl header magic number!") idc.MakeDword(self.start_addr) idc.MakeComm(self.start_addr, "Magic Number") idc.MakeNameEx(self.start_addr, "runtime_symtab", flags=idaapi.SN_FORCE) idaapi.autoWait() if idc.Word(self.start_addr + 4) & 0xFFFF != 0: raise Exception("Invalid pclntbl header") idc.MakeWord(self.start_addr + 4) self.min_lc = idc.Byte(self.start_addr + 6) & 0xFF if (self.min_lc != 1) and (self.min_lc != 2) and (self.min_lc != 4): raise Exception("Invalid pclntbl minimum LC!") idc.MakeComm(self.start_addr + 6, "instruction size quantum") idaapi.autoWait() self.ptr_sz = idc.Byte(self.start_addr + 7) & 0xFF if (self.ptr_sz != 4) and (self.ptr_sz != 8): raise Exception("Invalid pclntbl pointer size!") idc.MakeComm(self.start_addr + 7, "ptr size") idaapi.autoWait()
def parse_func_pointer(): renamed = 0 text_seg = common.get_text_seg() if text_seg is None: debug('Failed to get text segment') return for addr in idautils.Functions(text_seg.startEA, text_seg.endEA): name = idc.GetFunctionName(addr) # Look at data xrefs to the function - find the pointer that is located in .rodata data_ref = idaapi.get_first_dref_to(addr) while data_ref != idc.BADADDR: if 'rodata' in idc.get_segm_name(data_ref): # Only rename things that are currently listed as an offset; eg. off_9120B0 if 'off_' in idc.GetTrueName(data_ref): if idc.MakeNameEx(data_ref, ('%s_ptr' % name), flags=idaapi.SN_FORCE): idaapi.autoWait() renamed += 1 else: common._error( 'Failed to name pointer @ 0x%02x for %s' % (data_ref, name)) data_ref = idaapi.get_next_dref_to(addr, data_ref) common._info("Rename %d function pointers.\n" % renamed)
def parse_strings(): strings_added = 0 retry = [] text_seg = common.get_text_seg() if text_seg is None: common._debug('Failed to get text segment') return strings_added # This may be inherently flawed as it will only search for defined functions # and as of IDA Pro 6.95 it fails to autoanalyze many GO functions, currently # this works well since we redefine/find (almost) all the functions prior to # this being used. Could be worth a strategy rethink later one or on diff archs for addr in idautils.Functions(text_seg.startEA, text_seg.endEA): name = idc.GetFunctionName(addr) end_addr = idautils.Chunks(addr).next()[1] if (end_addr < addr): common._error('Unable to find good end for the function %s' % name) pass common._debug('Found function %s starting/ending @ 0x%x 0x%x' % (name, addr, end_addr)) while addr <= end_addr: if parse_str_ptr(addr): strings_added += 1 addr = idc.FindCode(addr, idaapi.SEARCH_DOWN) elif is_string_patt(addr): if 'rodata' not in idc.get_segm_name( addr) and 'text' not in idc.get_segm_name(addr): common._debug('Should a string be in the %s section?' % idc.get_segm_name(addr)) string_addr = idc.GetOperandValue(addr, 1) addr_3 = idc.FindCode(idc.FindCode(addr, idaapi.SEARCH_DOWN), idaapi.SEARCH_DOWN) string_len = idc.GetOperandValue(addr_3, 1) if string_len > 1: if create_string(string_addr, string_len): if create_offset(addr): strings_added += 1 else: # There appears to be something odd that goes on with IDA making some strings, always works # the second time, so lets just force a retry... retry.append((addr, string_addr, string_len)) # Skip the extra mov lines since we know it won't be a load on any of them addr = idc.FindCode(addr_3, idaapi.SEARCH_DOWN) else: addr = idc.FindCode(addr, idaapi.SEARCH_DOWN) for instr_addr, string_addr, string_len in retry: if create_string(string_addr, string_len): if create_offset(instr_addr): strings_added += 1 else: common._error( 'Unable to make a string @ 0x%x with length of %d for usage in function @ 0x%x' % (string_addr, string_len, instr_addr)) return strings_added
def parse_srcfile(self): ''' Parse and extract source all file names ''' srcfile_tbl_off = common.read_mem( self.func_tbl_addr + self.func_tbl_sz + self.ptr_sz, forced_addr_sz=4) & 0xFFFFFFFF self.srcfile_tbl_addr = self.start_addr + srcfile_tbl_off idc.MakeComm(self.func_tbl_addr + self.func_tbl_sz + self.ptr_sz, \ "Source file table addr: 0x%x" % self.srcfile_tbl_addr) idc.MakeNameEx(self.srcfile_tbl_addr, "runtime_filetab", flags=idaapi.SN_FORCE) idaapi.autoWait() self.srcfile_num = (common.read_mem(self.srcfile_tbl_addr, forced_addr_sz=4) & 0xFFFFFFFF) - 1 common._info( "--------------------------------------------------------------------------------------" ) common._info( "Source File paths(Total number: %d, default print results are user-defind files):\n" % self.srcfile_num) for idx in xrange(self.srcfile_num): srcfile_off = common.read_mem( (idx + 1) * 4 + self.srcfile_tbl_addr, forced_addr_sz=4) & 0xFFFFFFFF srcfile_addr = self.start_addr + srcfile_off srcfile_path = idc.GetString(srcfile_addr) if srcfile_path is None or len(srcfile_path) == 0: common._error("Failed to parse the [%d] src file(off: 0x%x, addr: @ 0x%x)" %\ (idx+1, srcfile_off, srcfile_addr)) continue if len(self.goroot) > 0 and (srcfile_path.startswith(self.goroot) or "/pkg/" in srcfile_path or\ srcfile_path == "<autogenerated>" or srcfile_path.startswith("_cgo_")): # ignore golang std libs and 3rd pkgs common._debug(srcfile_path) else: # User defined function self.srcfiles.append(srcfile_path) common._info(srcfile_path) idc.MakeStr(srcfile_addr, srcfile_addr + len(srcfile_path) + 1) idaapi.autoWait() idc.MakeComm((idx + 1) * 4 + self.srcfile_tbl_addr, "") idaapi.add_dref((idx + 1) * 4 + self.srcfile_tbl_addr, srcfile_addr, idaapi.dr_O) idaapi.autoWait() common._info( "--------------------------------------------------------------------------------------" )
def parse_hdr(self): ''' Refer: function [go12Init()] in https://golang.org/src/debug/gosym/pclntab.go ''' magic = idc.Dword(self.start_addr) & 0xFFFFFFFF if magic != Pclntbl.MAGIC: print magic, Pclntbl.MAGIC common._error("Invalid pclntbl header magic number!") idc.Exit(1) #raise Exception("Invalid pclntbl header magic number!") if idc.Word(self.start_addr + 4) & 0xFFFF != 0: raise Exception("Invalid pclntbl header") self.min_lc = idc.Byte(self.start_addr + 6) & 0xFF if (self.min_lc != 1) and (self.min_lc != 2) and (self.min_lc != 4): raise Exception("Invalid pclntbl minimum LC!") self.ptr_sz = idc.Byte(self.start_addr + 7) & 0xFF if (self.ptr_sz != 4) and (self.ptr_sz != 8): raise Exception("Invalid pclntbl pointer size!")
def parse(self, is_test=False): func_addr = common.read_mem(self.addr, forced_addr_sz=self.pclntbl.ptr_sz, read_only=is_test) name_addr = common.read_mem(self.addr + self.pclntbl.ptr_sz, forced_addr_sz=4, read_only=is_test) \ + self.pclntbl.start_addr raw_name_str = idc.GetString(name_addr) if raw_name_str and len(raw_name_str) > 0: self.name = common.clean_function_name(raw_name_str) if not is_test: idc.MakeComm(self.addr, "Func Entry") idaapi.autoWait() # make comment for func name offset idc.MakeComm( self.addr + self.pclntbl.ptr_sz, "Func name offset(Addr @ 0x%x), name string: %s" % (name_addr, raw_name_str)) idaapi.autoWait() # Make name string if len(self.name) > 0: if idc.MakeStr(name_addr, name_addr + len(raw_name_str) + 1): idaapi.autoWait() common._debug("Match func_name: %s" % self.name) else: common._error("Make func_name_str [%s] failed @0x%x" % (self.name, name_addr)) # Rename function real_func_addr = idaapi.get_func(func_addr) if len(self.name) > 0 and real_func_addr is not None: if idc.MakeNameEx(real_func_addr.startEA, self.name, flags=idaapi.SN_FORCE): idaapi.autoWait() common._debug("Rename function 0x%x: %s" % (real_func_addr.startEA, self.name)) else: common._error('Failed to rename function @ 0x%x' % real_func_addr.startEA) self.args = common.read_mem(self.addr + self.pclntbl.ptr_sz + 4, forced_addr_sz=4, read_only=is_test) self.frame = common.read_mem(self.addr + self.pclntbl.ptr_sz + 2 * 4, forced_addr_sz=4, read_only=is_test) self.pcsp = common.read_mem(self.addr + self.pclntbl.ptr_sz + 3 * 4, forced_addr_sz=4, read_only=is_test) self.pcfile = common.read_mem(self.addr + self.pclntbl.ptr_sz + 4 * 4, forced_addr_sz=4, read_only=is_test) self.pcln = common.read_mem(self.addr + self.pclntbl.ptr_sz + 5 * 4, forced_addr_sz=4, read_only=is_test) self.nfuncdata = common.read_mem(self.addr + self.pclntbl.ptr_sz + 6 * 4, forced_addr_sz=4, read_only=is_test) self.npcdata = common.read_mem(self.addr + self.pclntbl.ptr_sz + 7 * 4, forced_addr_sz=4, read_only=is_test) if not is_test: idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 4, "args") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 2 * 4, "frame") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 3 * 4, "pcsp") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 4 * 4, "pcfile") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 5 * 4, "pcln") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 6 * 4, "nfuncdata") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 7 * 4, "npcdata") idaapi.autoWait()