def makeInterface(self, offset): idc.SetType(offset, "interfaceType") ifaceid = ida_struct.get_struc_id("interfaceType") meth_offs = idc.get_member_offset(ifaceid, "methods") slice_id = ida_struct.get_struc_id("slice") size_off = idc.get_member_offset(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 = ida_struct.get_struc_size(ida_struct.get_struc_id("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 parseFuncType(self, offset): return sid = ida_struct.get_struc_id("funcType") in_size = idc.Word(offset + idc.get_member_offset(sid, "incount")) out_size = idc.Word(offset + idc.get_member_offset(sid, "outcount")) sz = ida_struct.get_struc_size(sid) for i in xrange(in_size + out_size): idc.SetType(offset + sz + i * self.stepper.size, "type *")
def fillStruct(self, sid, data): for i in data: new_type = None # (i1, i2, i3) = self.stepper.parseField(i[1]) name = i[1] if name[0] == "*": name = name[1:] if i[1] != "uintptr": i1, i2, i3 = (idc.FF_BYTE | idc.FF_DATA, -1, 1) else: i1, i2, i3 = self.uintptr if name == i[1]: new_type = i[1] else: new_type = name + " *" res = idc.add_struc_member(sid, i[0], -1, i1, i2, i3) use_name = i[0] if res == -1: # Bad name # print "Bad name %s for struct member" % i[0] use_name = i[0] + "_autogen_" + id_generator() idc.add_struc_member(sid, use_name, -1, i1, i2, i3) if new_type is not None: offset = idc.get_member_offset(sid, use_name) # print "Setting %s as %s" % (i[0], new_type) idc.SetType(idc.get_member_id(sid, offset), new_type)
def _populate_wrapper_struct__slices(sid, classinfo): """Fill in the members of the wrapper struct.""" # First add the vtable pointer. offset = 0 vtable_ptr_type = '{}::vtable *'.format(classinfo.classname) ret = idau.struct_add_ptr(sid, 'vtable', offset, type=vtable_ptr_type) if ret not in (0, idc.STRUC_ERROR_MEMBER_OFFSET): _log(0, 'Could not create {}.vtable: {}', classinfo.classname, ret) return False # Now add all the ::fields structs. offset += idau.WORD_SIZE for ci in classinfo.ancestors(inclusive=True): # Get the sid of the ::fields struct. fields_sid = idau.struct_open(ci.classname + '::fields') if fields_sid is None: _log(0, 'Could not find {}::fields', ci.classname) return False # If this is a 0-length struct (no fields), skip it. size = ida_struct.get_struc_size(fields_sid) if size == 0: continue # If this is already in the wrapper struct, skip it. This avoids weird # STRUC_ERROR_MEMBER_VARLAST errors. if idc.get_member_offset(sid, ci.classname) != -1: continue # Add the ::fields struct to the wrapper. ret = idau.struct_add_struct(sid, ci.classname, offset, fields_sid) if ret != 0: _log(0, 'Could not create {}.{}: {}', classinfo.classname, ci.classname, ret) return False offset += size return True
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 createUserTypeStruct(self, addr, name, size, self_size): fields = [] sid = ida_struct.get_struc_id("structField") sz = ida_struct.get_struc_size(sid) sid_type = ida_struct.get_struc_id("type") fields = [] curr_offset = 0 idc.set_cmt(addr, name, 0) for i in range(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) print(f"Get offset: {offset:x}") 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.get_member_offset(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 = ida_struct.get_struc_id(name) sz = ida_struct.get_struc_size(new_type_sid) if sz != self_size: print("%x" % addr ) raise("Error at creating structure")
def getKindEnumName(self, addr): try: struc_id = ida_struct.get_struc_id("type") offset_kind = idc.get_member_offset(struc_id, "kind") kind = idc.get_wide_byte(addr + offset_kind) & 0x1F return self.settings.typer.standardEnums[0][1][kind] except IndexError as e: pass
def makeStructType(self, offset): idc.SetType(offset, "structType") sid = ida_struct.get_struc_id("structType") slice_id = ida_struct.get_struc_id("slice") offset_elem = idc.get_member_offset(sid, "fields") inner_offset = idc.get_member_offset(slice_id, "data") addr = self.stepper.ptr(offset_elem + offset + inner_offset) inner_offset = idc.get_member_offset(slice_id, "len") size = self.stepper.ptr(offset+offset_elem+inner_offset) if size == 0: return idc.SetType(addr, "structField") sz = ida_struct.get_struc_size(ida_struct.get_struc_id("structField")) self.make_arr(addr, size, sz, "structField") sid_type = ida_struct.get_struc_id("type") size_new_struct = self.getPtr(sid_type, offset, "size") for i in xrange(size): self.processStructField(addr, i*sz) name = self.getName(offset) name = Utils.relaxName(name) name = "ut_" + name self.createUserTypeStruct(addr, name, size, size_new_struct)
def set_struct_offsets(offsets, sid): for offset in offsets: try: add_struct_member(sid, offset_name(offset), offset.offset, offset.size) except exceptions.SarkErrorStructMemberName: # Get the offset of the member with the same name existing_offset = idc.get_member_offset(sid, offset_name(offset)) if offset.offset == existing_offset: pass else: raise except exceptions.SarkErrorStructMemberOffset: # Get the size of the member at the same offset if offset.size == idc.get_member_size(sid, offset.offset): # If they are the same, all is well. pass
def getPtrToThis(self, sid, offset): memb_offs = idc.get_member_offset(sid, "ptrtothis") return idc.get_wide_dword(offset + memb_offs)
def getPtr(self, sid, addr, name): name_off = idc.get_member_offset(sid, name) return self.stepper.ptr(addr+name_off)
def getDword(self, sid, addr, name): name_off = idc.get_member_offset(sid, name) return idc.get_wide_dword(addr+name_off)
def build_stack_variable(func_ea): stack_vars = dict() frame = idc.get_func_attr(func_ea, idc.FUNCATTR_FRAME) if not frame: return stack_vars f_name = get_symbol_name(func_ea) #grab the offset of the stored frame pointer, so that #we can correlate offsets correctly in referent code # e.g., EBP+(-0x4) will match up to the -0x4 offset delta = idc.get_member_offset(frame, " s") if delta == -1: delta = 0 if f_name not in _FUNC_UNSAFE_LIST: offset = idc.get_first_member(frame) while -1 != _signed_from_unsigned(offset): member_name = idc.get_member_name(frame, offset) if member_name is None: offset = idc.get_next_offset(frame, offset) continue if (member_name == " r" or member_name == " s"): offset = idc.get_next_offset(frame, offset) continue member_size = idc.get_member_size(frame, offset) if offset >= delta: offset = idc.get_next_offset(frame, offset) continue member_flag = idc.get_member_flag(frame, offset) flag_str = _get_flags_from_bits(member_flag) member_offset = offset - delta stack_vars[member_offset] = { "name": member_name, "size": member_size, "flags": flag_str, "writes": list(), "referent": list(), "reads": list(), "safe": False } offset = idc.get_next_offset(frame, offset) else: offset = idc.get_first_member(frame) frame_size = idc.get_func_attr(func_ea, idc.FUNCATTR_FRSIZE) flag_str = "" member_offset = _signed_from_unsigned(offset) - delta stack_vars[member_offset] = { "name": f_name, "size": frame_size, "flags": flag_str, "writes": list(), "referent": list(), "reads": list(), "safe": False } return stack_vars
def __getitem__(self, item): if type(item) is str: return StructureMember(get_member_offset(self.__sid, item)) raise NotImplementedError