def MakeBundledAssemblyStruct(self, FileItemStructOffset): if self.Is64Bit == True: addv = 8 mf = MakeQword vf = Qword else: mf = MakeDword addv = 4 vf = Dword offset = FileItemStructOffset mf(offset) FileNameOffset = vf(offset) FileName = idc.GetString(FileNameOffset) offset+=addv mf(offset) FileDataOffset = vf(offset) offset+=addv mf(offset) FileSize = vf(offset) FileSizeOffset = offset offset+=addv mf(offset) FileCompressedSize = vf(offset) FileCompressedSizeOffset = offset offset+=addv IsGZip = "" FileDataCompressed = idc.GetManyBytes(FileDataOffset,3) b1,b2,b3 = struct.unpack('ccc', FileDataCompressed[0:3]) if b1 == '\x1f' and b2 == '\x8b' and b3 == '\x08': IsGZip = "Y" else: IsGZip = "N" ba = BundledAssembly() ba.FileItemStructOffset = FileItemStructOffset ba.FileNameOffset = FileNameOffset ba.FileName = FileName ba.FileDataOffset = FileDataOffset ba.FileSize = FileSize ba.FileSizeOffset = FileSizeOffset ba.FileCompressedSizeOffset = FileCompressedSizeOffset ba.FileCompressedSize = FileCompressedSize ba.IsGZip = IsGZip #ba.FileDataCompressed = FileDataCompressed return ba
def getName(self, offset): sid = idc.GetStrucIdByName("type") string_addr = offset + idc.GetMemberOffset(sid, "string") ptr = self.stepper.ptr(string_addr) idc.SetType(ptr, "string") name = self.stepper.ptr(ptr) return idc.GetString(name)
def parse_function_tables(self): count = 0 for pattern in self.search(): name2func = {} ea = pattern.start while ea < pattern.stop: string_address = idc.Dword(ea + (pattern.name_element * pattern.element_size)) function_address = idc.Dword(ea + (pattern.function_element * pattern.element_size)) new_function_name = idc.GetString(string_address) current_function_name = idc.Name(function_address) if not self.valid_function_name(new_function_name): print "ERROR: '%s' is not a valid function name. This is likely not a function table, or I have parsed it incorrectly!" % new_function_name print " Ignoring all entries in the structures between 0x%X and 0x%X.\n" % ( pattern.start, pattern.stop) name2func = {} break elif current_function_name.startswith("sub_"): name2func[new_function_name] = function_address ea += (pattern.num_elements * pattern.element_size) for (name, address) in name2func.iteritems(): print "0x%.8X => %s" % (address, name) idc.MakeName(address, name) count += 1 print "Renamed %d functions!" % count
def __PltResolver(jmprel, strtab, symtab): idx = 0 while True: r_off = idc.Qword(jmprel + 0x18 * idx) r_info1 = idc.Dword(jmprel + 0x18 * idx + 0x8) r_info2 = idc.Dword(jmprel + 0x18 * idx + 0xc) r_addend = idc.Qword(jmprel + 0x18 * idx + 0x10) if r_off > 0x7fffffff: return if r_info1 == 7: st_name = idc.Dword(symtab + r_info2 * 0x18) name = idc.GetString(strtab + st_name) # rename got idc.set_name(r_off, name + '_ptr') plt_func = idc.Qword(r_off) # rename plt idc.set_name(plt_func, 'j_' + name) SetFuncFlags(plt_func) # rename plt.sec for addr in idautils.DataRefsTo( r_off): # 新版本gcc中got表的ref只在.plt.sec段出现 plt_sec_func = idaapi.get_func(addr).startEA idc.set_name(plt_sec_func, '_' + name) # 其实重点是.plt.sec设置为 _xxx 即可正常解析 ParseTypes(plt_sec_func) SetFuncFlags(plt_sec_func) idx += 1
def _collect_data(self, collect_args): for data_ref in list(idautils.DataRefsFrom(collect_args["func_item"])): if data_ref in self._string_addresses: str_type = idc.GetStringType(data_ref) if idc.GetStringType(data_ref) is not None: string = idc.GetString(data_ref, -1, str_type) self._list_of_strings.append(string)
def parseValue(self, rawValue): """ Parse the string value @return: """ if self.type_params == ASCII_STR: value = idc.GetString(rawValue, strtype=idc.ASCSTR_C) description = "ASCII C-String" if self.type_params == UNICODE_STR: value = idc.GetString(rawValue, strtype=idc.ASCSTR_UNICODE) description = "Unicode String" if value is not None: value, raw_value = self.normalize_raw_value(value) self.addParsedvalue(value, 0, description, raw_value)
def getName(self, offset): sid = ida_struct.get_struc_id("type") string_addr = offset + idc.get_member_offset(sid, "string") ptr = self.stepper.ptr(string_addr) idc.SetType(ptr, "string") name = self.stepper.ptr(ptr) return idc.GetString(name)
def get_goroot(): goroot_path_str = "" ''' Get GOROOT path string ''' func_goroot = find_func_by_name("runtime_GOROOT") if func_goroot is None: _error("Failed to find func contains goroot") return goroot_path_str goroot_flowchart = idaapi.FlowChart(f=func_goroot) ret_cbs = find_ret_cb(goroot_flowchart) ''' runtime.GOROOT() normally has 2 return code blocks: 1. False return mov [rsp+28h+arg_0], rax mov [rsp+28h+arg_8], rcx mov rbp, [rsp+28h+var_8] add rsp, 28h retn 2. True return(Which we needed): mov rax, cs:runtime_internal_sys_DefaultGoroot mov rcx, cs:qword_D9AB58 mov [rsp+28h+arg_0], rax mov [rsp+28h+arg_8], rcx mov rbp, [rsp+28h+var_8] add rsp, 28h retn ''' for cb_idx in ret_cbs: if idc.GetOpType(goroot_flowchart[cb_idx].startEA, 0) == 1: # e.g.: mov rax, cs:runtime_internal_sys_DefaultGoroot ''' Op Types refer: https://www.hex-rays.com/products/ida/support/sdkdoc/ua_8hpp.html#aaf9da6ae7e8b201108fc225adf13b4d9 o_void = 0 # No Operand o_reg = 1 # General Register (al,ax,es,ds...) reg o_mem = 2 # Direct Memory Reference (DATA) addr o_phrase = 3 # Memory Ref [Base Reg + Index Reg] phrase o_displ = 4 # Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr o_imm = 5 # Immediate Value value o_far = 6 # Immediate Far Address (CODE) addr o_near = 7 # Immediate Near Address (CODE) addr ...... ''' goroot_path_str_addr = read_mem( idc.GetOperandValue(goroot_flowchart[cb_idx].startEA, 1)) goroot_path_str = idc.GetString(goroot_path_str_addr) if goroot_path_str is None or len(goroot_path_str) == 0: raise Exception("Invalid GOROOT") idc.MakeStr(goroot_path_str_addr, goroot_path_str_addr + len(goroot_path_str) + 1) idaapi.autoWait() break if len(goroot_path_str) > 0: _info("Go ROOT Path: %s\n" % goroot_path_str) return goroot_path_str.replace("\\", "/")
def __init__(self, addr, deepness=0): super(RTTITypeDescriptor, self).__init__(addr, deepness) nameAddr = addr + RTTITypeDescriptor.Offset.mangledName.value + RTTITypeDescriptor.NameOffset.classPrefix.value self.mangledName = idc.GetString(nameAddr) demangledName = idc.Demangle('??_7' + self.mangledName + '6B@', 8) if demangledName != None: demangledName = demangledName[0:len(demangledName) - 11] self.name = demangledName
def strstr(self, hayptr, needle=''): haystack = idc.GetString(hayptr) offset = haystack.find(needle) if offset == -1: return 0 else: return hayptr + offset
def strcat(self, dst, src=''): ''' Monitors, reports and simulates the strcat function. ''' print 'strcat(0x%X, "%s")' % (dst, src) addr = dst + len(idc.GetString(dst)) idc.DbgWrite(addr, src + "\x00") return dst
def getPropValue(self, tp, v1, v2): if tp == MapiEnum.PT_BINARY: data = idc.GetManyBytes(v2, int(v1 & 0xFFFFFFFF)) data = self.hexFormat(data) + ' (' + self.bin2str(data) + ')' elif tp == MapiEnum.PT_STRING: data = idc.GetString(v1) elif tp == MapiEnum.PT_UNICODE_STRING: data = idc.GetString(v1, -1, idc.ASCSTR_UNICODE) elif tp == MapiEnum.PT_INT: data = hex(v1 & 0xFFFFFFFF) elif tp == MapiEnum.PT_SHORT or tp == MapiEnum.PT_BOOLEAN: data = hex(v1 & 0xFFFF) elif tp == MapiEnum.PT_APPTIME or tp == MapiEnum.PT_SYSTIME: data = hex(v1) else: data = '' return data
def have_string(self, operand): if operand[0] != 'a': return False loc_addr = idc.LocByName(operand) if idc.GetString(loc_addr) != '' and idc.isData(idc.GetFlags(loc_addr)): return True else: return False
def _collect_data(self, collect_args): for data_ref in list(idautils.DataRefsFrom(collect_args["func_item"])): if data_ref in self._string_addresses: str_type = idc.GetStringType(data_ref) if idc.GetStringType(data_ref) is not None: string = idc.GetString(data_ref, -1, str_type) if not (string in self._string_counters): self._string_counters[string] = 0 self._string_counters[string] += 1
def parse_pclntable(module_data): pPcHeader = module_data.pPcHeader pc_header = parse_pc_header(pMem=pPcHeader) ptrSize = pc_header.ptrSize numberOfFuncs = pc_header.nFunc log._info("Number of Functions : %d" % numberOfFuncs) pclntable_start = module_data.pPclnTable cur_addr = pclntable_start for idx in range(numberOfFuncs): cur_addr = pclntable_start + (2 * ptrSize) * idx func_rva = common.mem_read_integer(addr=cur_addr, read_size=ptrSize) _func_structure_offset = common.mem_read_integer(addr=cur_addr + ptrSize, read_size=ptrSize) _func_addr = pclntable_start + _func_structure_offset if not idc.GetFunctionName(func_rva): log._info("Unk Func @0x%x" % func_rva) idc.MakeUnkn(func_rva, idc.DOUNK_EXPAND) idaapi.autoWait() idc.MakeCode(func_rva) idaapi.autoWait() if idc.MakeFunction(func_rva): idaapi.autoWait() log._info("Create Func @0x%x" % func_rva) _func = parse__func(pMem=_func_addr) #args=_func.args #func_id=_func.args func_name_addr = module_data.pFuncNameTable + _func.nameoff func_name = idc.GetString(func_name_addr) if func_name: clean_func_name = utils.clean_function_name(func_name) log._info("@0x%x Name : [%s]" % (func_rva, func_name)) idc.MakeComm(func_rva, "@0x" + str(hex(func_rva)) + " entry") idaapi.autoWait() if idc.MakeStr(func_name_addr, func_name_addr + len(func_name) + 1): idaapi.autoWait() else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name)) _func_addr = idaapi.get_func(func_rva) if _func_addr is not None: if idc.MakeNameEx(_func_addr.startEA, func_name, flags=idaapi.SN_FORCE): idaapi.autoWait() log._info("@0x%x Name : [%s]" % (func_rva, func_name)) else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name))
def read_string(ea): s = idc.GetString(ea, -1, idc.ASCSTR_C) if s: slen = len(s) + 1 idc.MakeUnknown(ea, slen, idc.DOUNK_SIMPLE) idaapi.make_ascii_string(ea, slen, idc.ASCSTR_C) return s, ea + slen else: return s, ea
def on_BL(addr, reg): X0, X1, X3 = reg['X0'], reg['X1'], reg['X3'] if not (X0 and X1 and X3): return _log(5, 'Have call to {:#x}({:#x}, {:#x}, ?, {:#x})', addr, X0, X1, X3) # OSMetaClass::OSMetaClass(this, className, superclass, classSize) if not idc.SegName(X1).endswith("__TEXT.__cstring") or not idc.SegName(X0): return found_metaclass(X0, idc.GetString(X1), X3, reg['X2'] or None)
def __init__(self, ea): self.method_list = list() # print '%08x: Parsing methods' % ea entry_size = idc.Dword(ea) num_entries = idc.Dword(ea + 4) ea = ea + 8 for i in range(num_entries): method_name = idc.GetString(idc.Dword(ea), -1, idc.ASCSTR_C) method_type = idc.GetString(idc.Dword(ea + 4), -1, idc.ASCSTR_C) method_ea = idc.Dword(ea + 8) self.method_list.append({ 'name': method_name, 'type': method_type, 'addr': method_ea }) ea = ea + entry_size return
def __init__(self, ea): self.ivar_list = list() # print '%08x: Parsing ivars' % ea entry_size = idc.Dword(ea) num_entries = idc.Dword(ea + 4) ea = ea + 8 for i in range(num_entries): ivar_offset = idc.Dword(idc.Dword(ea)) ivar_name = idc.GetString(idc.Dword(ea + 4), -1, idc.ASCSTR_C) ivar_type = idc.GetString(idc.Dword(ea + 8), -1, idc.ASCSTR_C) self.ivar_list.append({ 'name': ivar_name, 'type': ivar_type, 'offset': ivar_offset }) ea = ea + entry_size return
def get_type_info(ea): tis = read_pointer(ea + get_address_size_in_bytes()) if is_invalid_ea(tis): return idc.BADADDR name = idc.GetString(tis) if name == None or len(name) == 0: return idc.BADADDR, name ea2 = ea + 2*get_address_size_in_bytes() return ea2, name
def processStructField(self, addr, index): offset = addr + index sid = ida_struct.get_struc_id("structField") ptr = self.getPtr(sid, offset, "Name") if ptr != 0: idc.SetType(ptr, "string") fieldName = idc.GetString(self.stepper.ptr(ptr)) Utils.rename(ptr, fieldName) ptr = self.getPtr(sid, offset, "typ") self.handle_offset(ptr)
def get_string(ea): """ Returns a string from the given location. :param ea: starting address of string :return: A string """ stype = idc.GetStringType(ea) return idc.GetString(ea, strtype=stype)
def getAsciiString(self, ea): """Fetch the best ascii string that starts at the given address, according to IDA. Args: ea (int): effective address of the wanted string Return Value: IDA's best ascii string that starts at the given address """ return idc.GetString(ea, -1, -1)
def parse_prelink_info(): """Find and parse the kernel __PRELINK_INFO dictionary.""" segments = _find_prelink_info_segments() for segment in segments: prelink_info_string = idc.GetString(segment) prelink_info = kplist.kplist_parse(prelink_info_string) if prelink_info: return prelink_info _log(0, 'Could not find __PRELINK_INFO') return None
def analyze_invoke2(funcaddr): #print('funcaddr : %08X - %s' % (funcaddr, GetFunctionName(funcaddr))) func_st = idc.GetFunctionAttr(funcaddr, idc.FUNCATTR_START) func_en = idc.GetFunctionAttr(funcaddr, idc.FUNCATTR_END) funcname = idc.GetFunctionName(func_st) addr = func_st state = 0 if not funcname.startswith('sub_'): return while addr < func_en: mnem = idc.GetMnem(addr) #print(' %08X: %s' % (addr, mnem)) if mnem == 'lea': oprand1 = idc.GetOpnd(addr, 1) match = name_re.match(oprand1) #print(' %s' % (oprand1)) if match is not None: #print(' %s' % (match.group(1))) strname = match.group(1) nameaddr = idc.LocByName(strname) if strname.startswith('off'): idc.MakeStr(nameaddr, idc.BADADDR) name = idc.GetString(nameaddr, -1, idc.ASCSTR_C) #print(' opaddr: %X' % addr) #print(' strname: %s' % strname) #print(' nameaddr: %X' % nameaddr) #print(' name: %s' % name) if state == 0: libname = name state = 1 else: name = method_re.match(name).group(0) #print(' %X: %s @%s' % (func_st, name, libname)) idc.MakeNameEx(func_st, name, idc.SN_NOWARN | idc.SN_AUTO) break addr = idc.NextHead(addr, func_en) if addr == idc.BADADDR: break
def make_hkclass( offset, enums_by_id): # type: (int, typing.Dict[int, dict]) -> HkClass rclass = make_hkclass_raw(memdump[offset:offset + 0x50]) # type: HkClassRaw declared_enums = [] # type: typing.List[dict] for i in range(rclass.m_numDeclaredEnums): o = (rclass.m_declaredEnums - memdump_pointer_base) + i * HkClassEnumRawStruct.size v = parse_enum(o)._asdict() enums_by_id[o] = v declared_enums.append(v) members = [] # type: typing.List[dict] for i in range(rclass.m_numDeclaredMembers): o = (rclass.m_declaredMembers - memdump_pointer_base) + i * HkClassMemberRawStruct.size rmember = make_hkclassmember_raw( memdump[o:o + HkClassMemberRawStruct.size]) # type: HkClassMemberRaw mname = idc.GetString(memdump_addr_to_ida_addr(rmember.m_name)) mcl = rmember.m_class - memdump_pointer_base if rmember.m_class else 0 menum = rmember.m_enum - memdump_pointer_base if rmember.m_enum else 0 mtype = HkClassMemberType(rmember.m_type).name msubtype = HkClassMemberType(rmember.m_subtype).name marray_size = rmember.m_cArraySize mflags = rmember.m_flags moffset = rmember.m_offset members.append( HkClassMember(mname, mcl, menum, mtype, msubtype, marray_size, mflags, moffset)._asdict()) name = idc.GetString(memdump_addr_to_ida_addr(rclass.m_name)) parent = rclass.m_parent - memdump_pointer_base if rclass.m_parent else 0 obj_size = rclass.m_objectSize flags = rclass.m_flags version = rclass.m_describedVersion return HkClass(name, parent, obj_size, declared_enums, members, flags, version)
def getMatches(self, addr): results = [] try: string = idc.GetString(addr) if string is not None and len(string) > 3 and idc.get_str_type( addr) is not None: results.append(string) except Exception as e: if pdbg: traceback.print_exc() return results
def get_string(ea): string_type = idc.GetStringType(ea) if string_type is None: raise NoString("No string at 0x{:08X}".format(ea)) string = idc.GetString(ea, strtype=string_type) if not string: raise NoString("No string at 0x{:08X}".format(ea)) return string
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 "_cgo_" in srcfile_path or "go/src/git" in srcfile_path): # 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 nextProcName(startAddr, endAddr): addr = startAddr while addr < endAddr: mnem = idc.GetMnem(addr) if mnem == 'push': optype = idc.GetOpType(addr, 0) if optype == 5: procaddr = idc.GetOperandValue(addr, 0) procname = idc.GetString(procaddr, -1, idc.ASCSTR_C) return (procname, idc.NextHead(addr)) addr = idc.NextHead(addr) return ('', addr)