def createUserTypeStruct(self, addr, name, size, self_size): fields = [] sid = idc.GetStrucIdByName("structField") sz = idc.GetStrucSize(sid) sid_type = idc.GetStrucIdByName("type") fields = [] curr_offset = 0 idc.MakeComm(addr, name) for i in xrange(size): fieldname = self.nameFromOffset( self.getPtr(sid, addr + i * sz, "Name")) type_addr = self.getPtr(sid, addr + i * sz, "typ") typename = self.getType(type_addr) size = self.getPtr(sid_type, type_addr, "size") if fieldname == "" or fieldname is None: fieldname = "unused_" + Utils.id_generator() offset = self.getStructFieldOffset(sid, addr + i * sz) if offset != curr_offset: print "Offset missmatch.Got %d expected %d. Adding padding..." % ( curr_offset, offset) if offset < curr_offset: raise ("Too many bytes already") while offset != curr_offset: fields.append(("padding", "char")) curr_offset += 1 curr_offset += size if size != 0: offset_kind = idc.GetMemberOffset(sid_type, "kind") kind_of_type = self.getKindEnumName(type_addr) print kind_of_type if kind_of_type == "STRUCT_": #Disabled for now name_type = self.getName(type_addr) while name_type[0] == "*": name_type = name_type[1:] name_type = Utils.relaxName(name_type) name_type = "ut_" + name_type #print "setting type %s" % name_type fields.append((fieldname, name_type)) elif kind_of_type == "STRING": fields.append((fieldname, "string")) elif kind_of_type == "SLICE": fields.append((fieldname, "slice")) elif kind_of_type == "INTERFACE": fields.append((fieldname, "__iface")) else: fields.append((fieldname, "char [%d]" % size)) if curr_offset != self_size: print "%x: Structure size mismatch: %x" % (addr, curr_offset) if self_size < curr_offset: raise ("Too many bytes already") while self_size != curr_offset: fields.append(("padding", "char")) curr_offset += 1 new_type = [(name, fields)] self.settings.structCreator.createTypes(new_type) new_type_sid = idc.GetStrucIdByName(name) sz = idc.GetStrucSize(new_type_sid) if sz != self_size: print "%x" % addr raise ("Error at creating structure")
def check_create_struct_complex(self, in_stack): ident = yaunit.load('create_struct_complex_%d' % in_stack) # get first struct id sida = None if ident == 'create_struct_complex': self.assertFalse(in_stack) sida = idc.GetStrucIdByName('create_struct_complex') else: self.assertTrue(in_stack) frame = idaapi.get_frame(ident) self.assertIsNotNone(frame) sida = frame.id self.assertNotEqual(sida, idaapi.BADADDR) # get second struct id sidb = idc.GetStrucIdByName('create_struct_complex_sub_%d' % in_stack) self.assertNotEqual(sidb, idaapi.BADADDR) # check second struct for offset, name, ftype, strid, count in complex_struc2: size = get_size(ftype, strid) if ftype is not None else 1 name = 'field_%.04X_%s' % (offset, name) self.check_field(sidb, ftype, strid, offset, count * size, name) # check first struct sizeb = idc.GetStrucSize(sidb) for offset, name, ftype, strid, count in complex_struc1: size = get_size(ftype, strid) if ftype is not None else 1 if strid == 1: size *= sizeb strid = sidb name = 'field_%.04X_%s' % (offset, name) self.check_field(sida, ftype, strid, offset, count * size, name)
def makeInterface(self, offset): idc.SetType(offset, "interfaceType") ifaceid = idc.GetStrucIdByName("interfaceType") meth_offs = idc.GetMemberOffset(ifaceid, "methods") slice_id = idc.GetStrucIdByName("slice") size_off = idc.GetMemberOffset(slice_id, "len") size = self.stepper.ptr(offset + meth_offs + size_off) if size != 0: addr = self.getPtr(slice_id, offset + meth_offs, "data") idc.SetType(addr, "imethod") sz = idc.GetStrucSize(idc.GetStrucIdByName("imethod")) self.make_arr(addr, size, sz, "imethod") names = self.processIMethods(addr, size) # For now only for go1.7 if names is None: return name = self.getName(offset) while name[0] == "*": name = name[1:] name = Utils.relaxName(name) name = "user_interface_" + name # TODO: this is for go1.7 need additional check for other versions fields = [("inter", "void *"), ("type", "void *"), ("link", "void *"), ("bad", "__int32"), ("unused", "__int32")] for i in names: fields.append((i, "void *")) itype = [(name, fields)] self.settings.structCreator.createTypes(itype)
def currentType(self, check=CHECK_NONE, **kwargs): tnm = None if self.typeid: tnm = self.typeid else: nm = idc.Name(idaapi.get_screen_ea()) if nm and nm.startswith('vtbl_'): tnm = nm[5:] if not tnm: obj = MODS.explore.Explore(self.typeid).getVar() if obj: tnm = obj[-1].get('type') if not tnm: raise self.TypeNotExistsError("Type not found") tnm = tnm.replace('*', '').strip() tpdescr = {'name': tnm} sid = idc.GetStrucIdByName(tnm) if sid != idc.BADADDR: tpdescr['id'] = sid svid = idc.GetStrucIdByName(tnm + 'Vtbl') if svid != idc.BADADDR: tpdescr['vtblid'] = svid tpdescr['vtblnm'] = tnm + 'Vtbl' else: tpdescr = self.getTypeVtbl(tpdescr) ea = idc.LocByName('vtbl_' + tnm) if ea != idc.BADADDR: tpdescr['vtblea'] = ea if check == self.CHECK_VTBL and not tpdescr.get('vtblea'): raise self.TypeNotExistsError("vtbl not found", tnm) return tpdescr
def yacheck_apply_struct(self): addrs = yaunit.load('apply_struct') for k in range(-1, 4): # retrieve struct id addr = addrs[k + 1] sid = idc.GetStrucIdByName('apply_struct_%x' % (k + 1)) self.assertNotEqual(sid, idaapi.BADADDR) # begin to check if something is applied flags = idaapi.get_flags_novalue(addr) self.assertTrue(idaapi.isStroff(flags, 1)) ti = idaapi.opinfo_t() flags = idc.GetFlags(addr) self.assertTrue(idaapi.get_opinfo(addr, 1, flags, ti)) # apply struct only if k == -1: # check struct is applied self.assertEqual(ti.path.ids[0], sid) continue # check union is selected & applied at target address uid = idc.GetStrucIdByName('apply_union_%x' % (k + 1)) self.assertNotEqual(uid, idaapi.BADADDR) fid = idc.GetMemberId(uid, k) self.assertNotEqual(fid, -1) # check union is applied self.assertEqual([x for x in ti.path.ids if x], [sid, fid])
def yacheck_create_sub(self): for offset, count in create_sub: name = 'substruct_' + hhex(offset) + '_' + hhex(count) sida = idc.GetStrucIdByName(name + '_sub1') self.assertNotEqual(sida, idaapi.BADADDR) sidb = idc.GetStrucIdByName(name + '_sub2') self.assertNotEqual(sidb, idaapi.BADADDR) self.check_field(sida, idaapi.FF_STRU, sidb, offset, count * idc.GetStrucSize(sidb), 'sub_struc')
def _find_or_create_struct(): name = "sce_module_info_t" sid = idc.GetStrucIdByName(name) if sid != idc.BADADDR: return sid # already exists sid = idc.AddStrucEx(-1, name, 0) idc.AddStrucMember(sid, "modattribute", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "modversion", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "modname", -1, idc.FF_ASCI, -1, 27) idc.AddStrucMember(sid, "type", -1, idc.FF_BYTE, -1, 1) idc.AddStrucMember(sid, "gp_value", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "ent_top", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "ent_end", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "stub_top", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "stub_end", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "module_nid", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "field_38", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "field_3C", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "field_40", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "mod_start", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "mod_stop", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "exidx_start", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "exidx_end", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "extab_start", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "extab_end", -1, idc.FF_DWRD, -1, 4) idc.Til2Idb(-1, name) return sid
def _find_or_create_struct(): name = "sce_module_imports_t" sid = idc.GetStrucIdByName(name) if sid != idc.BADADDR: return sid # already exists sid = idc.AddStrucEx(-1, name, 0) idc.AddStrucMember(sid, "size", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "version", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "flags", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "num_functions", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "num_vars", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "num_tls_vars", -1, idc.FF_WORD, -1, 2) idc.AddStrucMember(sid, "reserved1", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "lib_nid", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "lib_name", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "reserved2", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "func_nid_table", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "func_entry_table", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "var_nid_table", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "var_entry_table", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "tls_nid_table", -1, idc.FF_DWRD, -1, 4) idc.AddStrucMember(sid, "tls_entry_table", -1, idc.FF_DWRD, -1, 4) idc.Til2Idb(-1, name) return sid
def rename(self, nuname=None, **kwargs): tp = self.currentType(**kwargs) cnm = tp['name'] if not nuname: nuname = idc.AskStr(cnm, "Set new type name for " + cnm + ":") if not nuname or nuname == cnm: Logger.debug("Rename cancelled") return sid = idc.GetStrucIdByName(nuname) if sid and sid != idc.BADADDR: raise self.WrongTypeError("Type already exists", nuname) Logger.debug("Renaming class %s to %s", str(tp), nuname) if tp.get('vtblea'): idc.MakeName(tp['vtblea'], 'vtbl_' + nuname) if tp.get('id'): idc.SetStrucName(tp['id'], nuname) if tp.get('vtblid'): tp['vtblnm'] = nuname + 'Vtbl' idc.SetStrucName(tp['vtblid'], tp['vtblnm']) for nm in idautils.Names(): if nm[1].startswith(cnm): fn = nm[1].replace(cnm, nuname) Logger.debug("Renaming function " + nm[1] + " to " + fn) idc.MakeName(nm[0], fn) self.typeid = nuname self.update()
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 update_prototype_with_hashes(self, proto, hash_provider, obj_name): try: parsed_elements = self.get_proto_valid_names(proto, obj_name) new_prototype = "" dependencies = list() for (el, is_valid) in parsed_elements: if is_valid: hashed = hash_provider.get_struc_enum_id_for_name(el) if hashed is not None: h = hash_provider.hash_to_string(hashed) new_prototype += el + " /*%" + el + "#" + h + "%*/" dependencies.append((h, idc.GetStrucIdByName(el))) else: new_prototype += el else: new_prototype += el logger.debug("prototype updated from '%s' to '%s'" % (proto, new_prototype)) return (new_prototype, dependencies) except: traceback.print_exc() logger.error( "Error while parsing prototype : '%s' (object_name=%s" % (proto, obj_name)) return (proto, list())
def create_struc_from_skeleton(name, skeleton, default_type=idaapi.FF_DWRD): sorted_data_types = sorted(data_types.items(), key=lambda x: x[1], reverse=True) sid = idc.GetStrucIdByName(name) if sid != idaapi.BADADDR: idc.DelStruc(sid) idx = idc.AddStrucEx(idaapi.BADADDR, name, False) i = 0 size = skeleton[-1][SKELETON_OFFSET] + data_types[skeleton[-1] [SKELETON_TYPE]] while i < size: if i < skeleton[0][SKELETON_OFFSET]: if i + data_types[default_type] <= skeleton[0][SKELETON_OFFSET]: idc.AddStrucMember(idx, 'field_{0}'.format(hex(i)), i, default_type | idaapi.FF_DATA, -1, data_types[default_type]) i += data_types[default_type] else: for data_type in sorted_data_types: if skeleton[0][SKELETON_OFFSET] - i >= data_type[1]: idc.AddStrucMember(idx, 'field_{0}'.format(hex(i)), i, data_type[0] | idaapi.FF_DATA, -1, data_type[1]) i += data_type[1] break elif i == skeleton[0][SKELETON_OFFSET]: idc.AddStrucMember(idx, skeleton[0][SKELETON_NAME], skeleton[0][SKELETON_OFFSET], skeleton[0][SKELETON_TYPE] | idaapi.FF_DATA, -1, data_types[skeleton[0][SKELETON_TYPE]]) i += data_types[skeleton[0][SKELETON_TYPE]] skeleton.pop(0) else: skeleton.pop(0)
def processIMethods(self, offst, size): sz = idc.GetStrucSize(idc.GetStrucIdByName("imethod")) comm = [] for i in xrange(size): comm.append(self.processIMethod(offst + i * sz)) idc.MakeComm(offst, "\n".join(comm)) return comm
def handle_offset(self, offset): #Check if we already parse this if offset in self.type_addr: return print "Processing: %x" % offset self.type_addr.append(offset) #Set type and get name idc.SetType(offset, "type") name = self.getName(offset) idc.MakeComm(offset, name) #get kind name kind_name = self.getKindEnumName(offset) print kind_name if name[0] == "*" and kind_name != "PTR": name = name[1:] name = Utils.relaxName(name) Utils.rename(offset, name) self.betterTypePlease(offset) sid = idc.GetStrucIdByName("type") addr = self.getPtrToThis(sid, offset) if addr != 0: addr = self.getOffset(addr) self.handle_offset(addr) return if kind_name != "FUNC": self.processUncommon(sid, offset)
def makeArrType(self, offset): idc.SetType(offset, "arrayType") sid = idc.GetStrucIdByName("arrayType") addr = self.getPtr(sid, offset, "elem") self.handle_offset(addr) addr = self.getPtr(sid, offset, "slice") self.handle_offset(addr)
def getName(self, offset): #print "GetName: %x" % offset sid = idc.GetStrucIdByName("type") name_off = self.getDword(sid, offset, "string") string_addr = self.getOffset(name_off) + 3 ln = idc.Byte(string_addr - 1) return self.get_str(string_addr, ln)
def createStruct(self, name): sid = idc.GetStrucIdByName(name) if sid != -1: idc.DelStruc(sid) sid = idc.AddStrucEx(-1, name, 0) self.types_id['name'] = sid return sid
def yacheck_reference_loop(self): for k in range(0, 2): sid = idc.GetStrucIdByName('refloop' + str(k)) self.assertNotEqual(sid, idaapi.BADADDR) self.assertEqual(idc.GetMemberName(sid, 0), 'refloop_field' + str(k)) mid = idc.GetMemberId(sid, 0) self.assertNotEqual(mid, -1) self.assertEqual(idc.GetType(mid), 'refloop' + str(1 - k) + ' *')
def find_or_create_struct(name): sid = idc.GetStrucIdByName(name) if (sid == idc.BADADDR): sid = idc.AddStrucEx(-1, name, 0) add_struct_to_idb(name) return sid
def get_struc_enum_id_for_name(self, name): item_id = idc.GetStrucIdByName(name) if item_id == idc.BADADDR: item_id = idc.GetEnum(name) if item_id == idc.BADADDR: logger.error("no struc or enum id for name : %s", name) return None return self.get_struc_enum_object_id(item_id, name)
def getType(self, addr): print "%x" % addr sid = idc.GetStrucIdByName("type") name = self.getName(addr) if self.getKindEnumName(addr) != "PTR": while name[0] == "*": name = name[1:] return name
def yacheck_set_field_prototype(self): for field_type, name, prototype in set_field_prototype: sid = idc.GetStrucIdByName(name) self.assertNotEqual(sid, idaapi.BADADDR) for k in range(0, get_size(field_type, -1) - 1): self.assertEqual(field_type, idc.GetMemberFlag(sid, k) & idaapi.DT_TYPE) mid = idc.GetMemberId(sid, k) self.assertEqual(prototype, idc.GetType(mid))
def parseFuncType(self, offset): return sid = idc.GetStrucIdByName("funcType") in_size = idc.Word(offset + idc.GetMemberOffset(sid, "incount")) out_size = idc.Word(offset + idc.GetMemberOffset(sid, "outcount")) sz = idc.GetStrucSize(sid) for i in xrange(in_size + out_size): idc.SetType(offset + sz + i * self.stepper.size, "type *")
def apply_struct(ea, name, size): sid = idc.GetStrucIdByName(name) if (size == -1): size = idc.GetStrucSize(sid) idc.MakeUnknown(ea, size, idc.DOUNK_DELNAMES) idaapi.doStruct(ea, size, sid) return size
def processStructField(self, addr, index): offset = addr + index sid = idc.GetStrucIdByName("structField") ptr = self.getPtr(sid, offset, "Name") ln = idc.Byte(ptr + 2) fieldName = self.get_str(ptr + 3, ln) Utils.rename(ptr, fieldName) ptr = self.getPtr(sid, offset, "typ") self.handle_offset(ptr)
def makeStructType(self, offset): idc.SetType(offset, "structType") sid = idc.GetStrucIdByName("structType") slice_id = idc.GetStrucIdByName("slice") offset_elem = idc.GetMemberOffset(sid, "fields") inner_offset = idc.GetMemberOffset(slice_id, "data") addr = self.stepper.ptr(offset_elem + offset + inner_offset) inner_offset = idc.GetMemberOffset(slice_id, "len") size = self.stepper.ptr(offset + offset_elem + inner_offset) if size == 0: return idc.SetType(addr, "structField") sz = idc.GetStrucSize(idc.GetStrucIdByName("structField")) self.make_arr(addr, size, sz, "structField") sid_type = idc.GetStrucIdByName("type") size_new_struct = self.getPtr(sid_type, offset, "size") for i in xrange(size): self.processStructField(addr, i * sz)
def processStructField(self, addr, index): offset = addr + index sid = idc.GetStrucIdByName("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 yacheck_create_struct_field(self): for offset, count, field_type, string_type, comment, repeatable in create_field: size = count * get_size(field_type, string_type) name = get_name(field_type, string_type, offset, size) sid = idc.GetStrucIdByName('struct_' + name) self.assertNotEqual(sid, idaapi.BADADDR) fname = 'field_' + name self.check_field(sid, field_type, string_type, offset, size, fname) if comment is not None: for k in range(offset, offset + size - 1): self.assertEqual(idc.GetMemberComment(sid, k, repeatable), comment)
def create_struc(name, size, default_type=idaapi.FF_DWRD): sid = idc.GetStrucIdByName(name) if sid != idaapi.BADADDR: idc.DelStruc(sid) idx = idc.AddStrucEx(idaapi.BADADDR, name, False) i = 0 while i < size: idc.AddStrucMember(idx, 'field_{0}'.format(hex(i)), i, default_type | idaapi.FF_DATA, -1, data_types[default_type]) i += data_types[default_type]
def makeMap(self, offset): idc.SetType(offset, "mapType") sid = idc.GetStrucIdByName("mapType") addr = self.getPtr(sid, offset, "key") self.handle_offset(addr) addr = self.getPtr(sid, offset, "elem") self.handle_offset(addr) addr = self.getPtr(sid, offset, "bucket") self.handle_offset(addr) addr = self.getPtr(sid, offset, "hmap") self.handle_offset(addr)