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 _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 = idc.GetStrucSize(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.GetMemberOffset(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 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 fields(self, reload=False): if reload or not self._fields: self._fields = {} m = 0 while True: if m >= idc.GetStrucSize(self.id): break n = idc.GetMemberName(self.id, m) if n == idc.BADADDR: break sz = idc.GetMemberSize(self.id, m) mid = idc.GetMemberId(self.id, m) tp = idc.GetType(mid) fld = { 'offset': m, 'id': mid, 'name': n, 'size': sz, 'type': [tp, None] } if n != '': fld['type'][1] = idc.GetMemberFlag(self.id, m) self._fields[m] = fld m = idc.GetStrucNextOff(self.id, m) if m == idc.BADADDR: break return self._fields
def _read_struct_member(struct, sid, union, ea, offset, name, size, asobject): """Read a member into a struct for read_struct.""" flags = idc.GetMemberFlag(sid, offset) assert flags != -1 # Extra information for parsing a struct. member_sid, member_ssize = None, None if idc.isStruct(flags): member_sid = idc.GetMemberStrId(sid, offset) member_ssize = idc.GetStrucSize(member_sid) # Get the address of the start of the member. member = ea if not union: member += offset # Now parse out the value. array = [] processed = 0 while processed < size: value, read = _read_struct_member_once(member + processed, flags, size, member_sid, member_ssize, asobject) assert size % read == 0 array.append(value) processed += read if len(array) == 1: value = array[0] else: value = array struct[name] = value
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 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 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 struct_add_struct(sid, name, offset, msid, count=1): """Add a structure member to a structure. If sid is a union, offset must be -1. """ size = idc.GetStrucSize(msid) return idc.AddStrucMember(sid, name, offset, idc.FF_DATA | idc.FF_STRU, msid, size * count)
def find_WdfDriverCreate(): function_offset = OFFSET_WdfDriverCreate # If the XREF to wdfFunctions + function_offset exists.. then we're in case 1! try: call_pfnWdfDriverCreate = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset).next().frm except StopIteration: # this is case 2! call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("mov", 1,function_offset) if call_pfnWdfDriverCreate != None: idc.OpStroffEx(call_pfnWdfDriverCreate,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) else: call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("call", 0, function_offset) idc.OpStroffEx(call_pfnWdfDriverCreate,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) if call_pfnWdfDriverCreate != None: # First identify the RealDriverEntry :) current_func = idaapi.get_func(call_pfnWdfDriverCreate) idc.MakeName(current_func.startEA, "_DriverEntry_") argument_DriverConfig_addr = find_function_arg_with_operand_value(call_pfnWdfDriverCreate, "mov", "rsp", 0x20, 0) register_DriverConfig = idc.GetOpnd(argument_DriverConfig_addr, 1) lea_DriverConfig_addr = find_function_arg(argument_DriverConfig_addr, "lea", register_DriverConfig, 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_DriverConfig_addr) stack_id = idc.GetFrame(current_func) opnd = idc.GetOpnd(lea_DriverConfig_addr, 1) if "rsp" in opnd: stack_member_offset = idc.GetOperandValue(lea_DriverConfig_addr, 1) elif "rbp" in opnd: var_x = opnd.split("+")[-1][:-1] # [rbp+57h+var_80] -> var_80 members, _ = retrieve_stack_members(current_func) inverted_members = {v:k for k, v in members.items()} try: stack_member_offset = inverted_members[var_x] except KeyError as msg: print msg return else: print("+] WdfDriverCreate() Unidentified register stack layout") return #idc.SetMemberName(stack_id, stack_member_offset, "_DriverConfig") struct_id = idaapi.get_struc_id("_WDF_DRIVER_CONFIG") struct_size = idc.GetStrucSize(struct_id) # First check if we have already touch this function stack before #if function_stack_erased(current_func): # need to take care of the already defined structs # pass #else: delete_all_function_stack_members(current_func, force=True) idc.AddStrucMember(stack_id, "driver_config", stack_member_offset, idc.FF_BYTE|idc.FF_DATA, -1, struct_size) idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU|idc.FF_DATA, struct_id, 1)
def create_complex(self, sida, sidb): for offset, name, ftype, strid, count in complex_struc2: self.create_field(sidb, offset, name, ftype, strid, count) size = idc.GetStrucSize(sidb) for offset, name, ftype, strid, count in complex_struc1: if strid != -1: count *= size strid = sidb self.create_field(sida, offset, name, ftype, strid, count)
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 apply_struct(ea, sid, size): if size == -1: size = idc.GetStrucSize(sid) idc.MakeUnknown(ea, size, idc.DOUNK_DELNAMES) idaapi.doStruct(ea, size, sid) return size
def get_structs(): """Get structures from IDA database """ structs = {} for idx, sid, name in idautils.Structs(): struct = ida_struct.get_struc(sid) structs[name] = {} structs[name]["size"] = idc.GetStrucSize(sid) structs[name]["members"] = get_struct_members(struct, sid) return structs
def struc_expanded(self, struct): sid = struct.id sname = idc.GetStrucName(sid) size = idc.GetStrucSize(sid) idx = idc.GetStrucIdx(sid) self.ctrl._handle_action({ 'action': 'struct_expanded', 'struct': idx, 'sname': sname, 'size': size }) return 0
def find_WdfIoQueueCreate(): function_offset = OFFSET_WdfIoQueueCreate calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfnWdfIoQueueCreate = xref.frm calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "call", 0, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "mov", 1, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) for pfn_call in calls_to_pfn_list: lea_argument_addr = find_function_arg(pfn_call, "lea", "r8", 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_argument_addr) stack_id = idc.GetFrame(current_func) stack_member_offset = idc.get_operand_value(lea_argument_addr, 1) struct_id = idaapi.get_struc_id("_WDF_IO_QUEUE_CONFIG") struct_size = idc.GetStrucSize(struct_id) # First check if we have already touch this function stack before if function_stack_erased(current_func): # need to take care of the already defined structs # If the arguments collide then this will fail pass else: delete_all_function_stack_members(current_func) print("Erased the stack members") idc.AddStrucMember(stack_id, "queue_config", stack_member_offset, idc.FF_BYTE | idc.FF_DATA, -1, struct_size) idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU | idc.FF_DATA, struct_id, 1) print("IOQueue Creation at: " + hex(pfn_call))
def __get_local_types(self): for id_ida in range(1, idc.GetMaxLocalType()): name = idc.GetLocalTypeName(id_ida) sizeType = 0 sid = idc.GetStrucIdByName(name) if sid != -1: sizeType = idc.GetStrucSize(sid) one_line = idc.GetLocalType(id_ida, idc.PRTYPE_1LINE) multi_line = idc.GetLocalType( id_ida, idc.PRTYPE_MULTI | idc.PRTYPE_TYPE | idc.PRTYPE_PRAGMA) yield models_ida.IdaRawLocalType(id_ida=id_ida, sizeType=sizeType, name=name, one_line=one_line, multi_line=multi_line)
def build_struct(self): ''' Creates an IDA structure for this Type. ''' if self.struct is not None: return for p in self.parents: p.build_struct() self.struct = idc.AddStrucEx(-1, self.name, 0) if as_signed(self.struct, TARGET_ADDRESS_SIZE) == -1: raise RuntimeError("Unable to make struct `{}`".format(self.name)) else: #TODO: either come up with another way of showing this, or # sync it with the actual function names cmt = "constructors: " for c in self.constructors(): cmt += "{}(0x{:02x}), ".format(idc.Name(c), c) cmt = cmt.strip(", ") idaapi.set_struc_cmt(self.struct, cmt, False) if TARGET_ADDRESS_SIZE == 8: mask = idc.FF_QWRD else: mask = idc.FF_DWRD # Only bases get the magic _vptr member if len(self.parents) == 0: idc.AddStrucMember(self.struct, "_vptr", 0, idc.FF_DATA | mask, -1, TARGET_ADDRESS_SIZE) idc.SetType(idc.GetMemberId(self.struct, 0), "_vfunc**") for i, parent in enumerate(self.parents): try: #TODO: for non-itanium ABI, this may not be available # when RTTI is disabled offset = self.tablegroup.tables[i].offset_to_top except: break idc.AddStrucMember(self.struct, "parent_{}".format(i), -offset, idc.FF_DATA, -1, idc.GetStrucSize(parent.struct)) idc.SetType(idc.GetMemberId(self.struct, -offset), parent.name)
def read_struct(ea, struct=None, sid=None, members=None, asobject=False): """Read a structure from the given address. This function reads the structure at the given address and converts it into a dictionary or accessor object. Arguments: ea: The linear address of the start of the structure. Options: sid: The structure ID of the structure type to read. struct: The name of the structure type to read. members: A list of the names of the member fields to read. If members is None, then all members are read. Default is None. asobject: If True, then the struct is returned as a Python object rather than a dict. One of sid and struct must be specified. """ # Handle sid/struct. if struct is not None: sid2 = idc.GetStrucIdByName(struct) if sid2 == idc.BADADDR: raise ValueError('Invalid struc name {}'.format(struct)) if sid is not None and sid2 != sid: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) sid = sid2 else: if sid is None: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) if idc.GetStrucName(sid) is None: raise ValueError('Invalid struc id {}'.format(sid)) # Iterate through the members and add them to the struct. union = idc.IsUnion(sid) struct = {} for offset, name, size in idautils.StructMembers(sid): if members is not None and name not in members: continue _read_struct_member(struct, sid, union, ea, offset, name, size, asobject) if asobject: struct = objectview(struct, ea, idc.GetStrucSize(sid)) return struct
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 sizeof(typ): if not typ: raise_error("empty struct name") typ = str(typ) if typ.endswith("*"): return pointer_size builtin = { 'int': 4, 'unsigned int': 4, 'short': 2, 'unsigned short': 2, 'char': 1, 'unsigned char': 1, '__int64': 8, 'pvoid': pointer_size, 'pdword': pointer_size, "_DWORD": 4, "_BYTE": 1, "_WORD": 2, 'PDWORD': pointer_size, 'PVOID': pointer_size, "_QWORD": 8, "WCHAR": 2, "PWORD": pointer_size, "float": 4, "double": 8, } if typ in builtin.keys(): return builtin[typ] sid = idc.GetStrucIdByName(typ) if (sid is None) or (sid == 0) or (sid == idc.BADADDR): raise_error('Failed to get tid_t for %s' % typ) return idc.GetStrucSize(sid)
def make_struc_member(self, object_version, address, member_type=ya.OBJECT_TYPE_STRUCT_MEMBER): struc_object_id = object_version.get_parent_object_id() struc_id = 0 try: struc_id = self.struc_ids[struc_object_id] except: return is_union = struc_id in self.union_ids offset = address if is_union: last_offset = idc.GetLastMember(struc_id) if last_offset == idc.BADADDR: last_offset = -1 if last_offset < offset: for i in xrange(last_offset + 1, offset + 1): idc.AddStrucMember(struc_id, "yaco_filler_%d" % i, 0, idc.FF_BYTE | idc.FF_DATA, -1, 1) # ensure that 'offset' fields are present member_size = object_version.get_size() member_name = object_version.get_name() flags = object_version.get_object_flags() if idc.isStruct(flags): # if the sub field is a struct, it must have a single Xref field with the struct object id try: sub_struc_object_id = object_version.getXRefIdsAt(0, 0)[0] sub_struc_id = self.struc_ids[sub_struc_object_id] # logger.debug("%20s: adding sub member at offset 0x%08X, # size=0x%08X (sub=0x%.016X, size=0x%08X) with name %s" % # ( # idc.GetStrucName(struc_id), offset, member_size, sub_struc_id, # idc.GetStrucSize(sub_struc_id), object_version.get_name() # )) sub_struc_size = idc.GetStrucSize(sub_struc_id) if sub_struc_size == 0: logger.error( "%20s: adding sub member at offset 0x%08X, size=0x%08X " "(sub=0x%.016X, size=0x%08X) with name %s : sub struc size is ZERO" % (idc.GetStrucName(struc_id), offset, member_size, sub_struc_id, idc.GetStrucSize(sub_struc_id), object_version.get_name())) else: nitems = member_size / sub_struc_size YaToolIDATools.SetStrucmember(struc_id, member_name, offset, flags, sub_struc_id, nitems) except KeyError: logger.error( "Error while looking for sub struc in struc %s, offset 0x%08X (field name='%s')" % (self.hash_provider.hash_to_string(struc_object_id), offset, object_version.get_name())) traceback.print_exc() elif idc.isEnum0(flags): # an enum is applied here try: sub_enum_object_id = object_version.getXRefIdsAt(0, 0)[0] sub_enum_id = self.enum_ids[sub_enum_object_id] name_ok = idc.SetMemberName(struc_id, offset, member_name) if name_ok is not True: logger.debug( "Error while setting member name (enum) : " "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X" % (name_ok, idc.GetStrucName(struc_id), member_name, offset, flags, member_size, sub_struc_id)) else: sub_enum_size = idc.GetEnumWidth(sub_enum_id) if sub_enum_size == 0: sub_enum_size = member_size nitems = member_size / sub_enum_size ret = idc.SetMemberType(struc_id, offset, flags, sub_enum_id, nitems) if ret == 0: logger.debug( "Error while setting member type (enum) : " "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X" % (ret, idc.GetStrucName(struc_id), member_name, offset, flags, member_size, sub_struc_id)) except KeyError: logger.error( "Error while looking for sub enum in struc %s, offset 0x%08X (field name='%s')" % (struc_object_id, offset, member_name)) traceback.print_exc() else: # logger.debug("%20s: adding member at offset 0x%08X, size=0x%08X with name %s" % # ( # idc.GetStrucName(struc_id), offset, member_size, object_version.get_name() # )) tid = -1 if idc.isASCII(flags): logger.debug( "object: %s : %s" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) try: tid = object_version.get_string_type() except KeyError: tid = idc.ASCSTR_C name_ok = idc.SetMemberName(struc_id, offset, member_name) if name_ok is not True: logger.debug( "Error while setting member name :" + " (struc_id=0x%08X, struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)" % (struc_id, idc.GetStrucName(struc_id), member_name, offset, flags, member_size)) else: item_size = YaToolIDATools.get_field_size(flags, tid) nitems = member_size / item_size # IDA BUG : 4-byte chars are stored as 2 double words, thus me must # multiply nitem by 2! ret = idc.SetMemberType(struc_id, offset, flags, tid, nitems) if ret == 0: logger.debug( "Error while setting member type :" + " (struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)" % (idc.GetStrucName(struc_id), member_name, offset, flags, member_size)) try: repeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(True)) idc.SetMemberComment(struc_id, offset, repeatable_headercomment, 1) except KeyError: pass try: nonrepeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(False)) idc.SetMemberComment(struc_id, offset, nonrepeatable_headercomment, 0) except KeyError: pass member_id = idc.GetMemberId(struc_id, offset) self.set_struct_member_type(object_version, member_id) if object_version.get_type() == ya.OBJECT_TYPE_STRUCT_MEMBER: self.strucmember_ids[object_version.get_id()] = member_id
def make_data(self, object_version, address): size = 0 try: size = object_version.get_size() except KeyError: pass flags = None try: flags = object_version.get_object_flags() except KeyError: pass if size == 0: idc.MakeUnkn(address, idc.DOUNK_EXPAND) else: if flags is not None: if idc.isASCII(flags): try: str_type = object_version.get_string_type() YaToolIDATools.check_and_set_str_type(str_type) except KeyError: pass idc.MakeStr(address, address + size) idc.SetFlags(address, flags) if idc.isStruct(flags): found = False for xref_offset_operand, xref_id_attr in object_version.get_xrefed_id_map( ).iteritems(): (xref_offset, xref_operand) = xref_offset_operand for xref_hash, xref_attrs in xref_id_attr: if xref_hash in self.struc_ids: struc_id = self.struc_ids[xref_hash] if DEBUG_EXPORTER: logger.debug( "making unknown from 0x%08X to 0x%08X" % (address, address + size)) idaapi.do_unknown_range( address, size, idc.DOUNK_DELNAMES) # idc.MakeUnkn(address, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # for i in xrange(1, size): # MakeName(address + i, "") # idc.MakeUnkn(address + i, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # idc.MakeStructEx uses idaapi.doStruct (but asks for name while # we already have the struc id) if DEBUG_EXPORTER: logger.debug( "Making struc at %s : %s (sizeof(%s)=0x%08X, size=0x%08X, flags=0x%08X" % (self.yatools.address_to_hex_string( address), self.yatools.address_to_hex_string( struc_id), idaapi.get_struc_name(struc_id), idc.GetStrucSize(struc_id), size, flags)) idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() if idaapi.doStruct(address, size, struc_id) == 0: if DEBUG_EXPORTER: logger.warning("Making struc failed") idc.SetCharPrm(idc.INF_AUTO, False) # idc.SetFlags(address, flags) found = True else: logger.error( "bad struc flags : idc.isStruct is true but no xref available for object %s" % self.hash_provider.hash_to_string( object_version.get_id())) if not found: logger.error( "bad struc flags : idc.isStruct is true " "but no struc available for object %s (%s)" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) else: idc.MakeData(address, flags & (idc.DT_TYPE | idc.MS_0TYPE), size, 0) else: idc.MakeData(address, idc.FF_BYTE, size, 0) self.make_name(object_version, address, False) self.set_type(object_version, address)
def size(self): return idc.GetStrucSize(self.sid)
def size(id): return idc.GetStrucSize(id)
max_len = idaapi.get_max_ascii_length(ea, ASCSTR_C, 0) idaapi.make_ascii_string(ea, max_len, ASCSTR_C) return idc.GetString(ea, max_len, ASCSTR_C) def dump(self): print " %20s - base 0x%08x - size 0x%08x - access : 0x%x" % ( self.to_str(self.name_addr), self.base, self.size, self.access) def name(self): return "%s" % self.to_str(self.name_addr) print "> parsing .secinfo entries:\n" sid = GetStrucIdByName('MAP_ENTRY') ssize = idc.GetStrucSize(sid) # for v 2.44.7 19-Jul-2016 SEC_INFO_LINKED_LIST = 0x200B6A3C ea = SEC_INFO_LINKED_LIST entries = [] while True: idc.MakeUnknown(ea, ssize, idc.DOUNK_DELNAMES) idaapi.doStruct(ea, ssize, sid) buf = idc.GetManyBytes(ea, ssize) entry = MapEntry.from_buffer_copy(buf) entries.append(entry) entry.dump()
def create_complex2(self, sida, complex_struc): for offset, name, ftype, strid, count in complex_struc: self.create_field(sida, offset, name, ftype, strid, count) return idc.GetStrucSize(sida)
def parse_structures(): # Searching structures, and if not exists - creating them # RSA KEY structure rsa_key = idc.GetStrucIdByName("rsa_key") rsa_key_str = """ struct rsa_key { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; }; """ if rsa_key == -1: rsa_key = idc.AddStrucEx(-1, "rsa_key", 0) idc.AddStrucMember(rsa_key, "key_id", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_key, "key_type", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_key, "key_rights", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_key, "modul_length", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_key, "e_value", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_key, "modul", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 256) # RSA ASN1 DIGEST structure rsa_asn1_digest = idc.GetStrucIdByName("rsa_asn1_digest") rsa_asn1_digest_str = """ struct rsa_asn1_digest { char signer_info[16]; long signature_info; long key_id; char digest[256]; }; """ if rsa_asn1_digest == -1: rsa_asn1_digest = idc.AddStrucEx(-1, "rsa_asn1_digest", 0) idc.AddStrucMember(rsa_asn1_digest, "signer_info", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 16) idc.AddStrucMember(rsa_asn1_digest, "signature_info", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_asn1_digest, "key_id", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(rsa_asn1_digest, "digest", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 256) # Cert PK - Public Keys structure certpk_struct = idc.GetStrucIdByName("Cert_Public") certpk_str = """ struct certpk { char cert_mark[8]; long cert_version; long cert_type; long minver_pk; long minver_ppa; long minver_rd1; long minver_rd2; long minver_isw; long minver_ki; long minver_pau; long minver_pas; long unkn1; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } root_key; long keys_active; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_02; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_03; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_04; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_05; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_06; struct { long key_id; long key_type; long key_rights; long modul_length; long e_value; char modul[256]; } key_07; long rights; long msv_mask; char zero_hole_2[120]; struct { char signer_info[16]; long signature_info; long key_id; char digest[256]; } digest; };""" if certpk_struct == -1: certpk_struct = idc.AddStrucEx(-1, "Cert_Public", 0) idc.AddStrucMember(certpk_struct, "cert_mark", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 8) idc.AddStrucMember(certpk_struct, "cert_version", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "cert_type", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_pk", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_ppa", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_rd1", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_rd2", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_isw", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_ki", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_pau", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "minver_pas", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "unkn1", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "root_key", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "keys_active", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "key_02", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "key_03", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "key_04", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "key_05", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "key_06", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "key_07", -1, 0x60000400, rsa_key, idc.GetStrucSize(rsa_key)) idc.AddStrucMember(certpk_struct, "rights", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "msv_mask", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certpk_struct, "zero_hole_2", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 120) idc.AddStrucMember(certpk_struct, "digest", -1, 0x60000400, rsa_asn1_digest, idc.GetStrucSize(rsa_asn1_digest)) # CertPPA - Primary Protected Application Certificate structure certppa_struct = idc.GetStrucIdByName("Cert_Primary") certppa_str = """ struct certppa { char cert_mark[8]; long cert_version; long cert_type; long minver_src; long minver_pk; long minver_ppa; long minver_rd1; long minver_rd2; long minver_isw; struct { int image_offset; int image_size; int data_byte[5]; } images[4]; char zero_hole[128]; struct { char signer_info[16]; long signature_info; long key_id; char digest[256]; } digest; };""" if certppa_struct == -1: certppa_struct = idc.AddStrucEx(-1, "Cert_Primary", 0) idc.AddStrucMember(certppa_struct, "cert_mark", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 8) idc.AddStrucMember(certppa_struct, "cert_version", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "cert_type", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_src", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_pk", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_ppa", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_rd1", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_rd2", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "minver_isw", -1, (FF_DWRD | FF_DATA) & 0xFFFFFFFF, -1, 4) idc.AddStrucMember(certppa_struct, "images", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 21) idc.AddStrucMember(certppa_struct, "zero_hole", -1, (FF_BYTE | FF_DATA) & 0xFFFFFFFF, -1, 128) idc.AddStrucMember(certppa_struct, "digest", -1, 0x60000400, rsa_asn1_digest, idc.GetStrucSize(rsa_asn1_digest)) # CertISW - Initial Software Certificate structure certisw_struct = idc.GetStrucIdByName("Cert_ISW") certisw_str = """struct certisw { char cert_mark[8]; int cert_version; int cert_type; int minver_src; int minver_pk; int minver_ppa; int minver_rd1; int minver_rd2; int minver_isw; int watchdog_param; int use_DMA; int active_images; struct { int image_offset; int image_size; int data_byte[5]; } images[4]; int magic_1; int reg_bitfield; struct { int reg_address; int reg_value; } reg_table[32]; int reg_type_01; int reg_type_02; int entry_point_offset; int zero_hole[32]; struct { char signer_info[16]; long signature_info; long key_id; char digest[256]; } digest; };""" mbmloader_hdr_str = """struct mbmloader_head { void *entry_point; int anonymous_0; void *anonymous_1; void *anonymous_2; void *anonymous_3; void *anonymous_4; int anonymous_5; int field_1C; void *anonymous_7; int field_24; void *anonymous_8; int anonymous_9; int ruler[4]; char srk_part_1[128]; int srk_1; void *srk_1_pointer; int field_C8; int field_CC; char srk_part_2[128]; int srk_2; void *srk_2_pointer; int field_158; int field_15C; char sha_160_hash[20]; };""" # Searching main structures marks start = idc.MinEA() stop = idc.MaxEA() certpk_addr = idaapi.find_binary(start, stop, "43 65 72 74 50 4B 5F 00", 0, 0) # "CertPK_" string print "Found CertPK at 0x%x" % certpk_addr certppa_addr = idaapi.find_binary(start, stop, "43 65 72 74 50 50 41 00", 0, 0) # "CertPPA" string print "Found CertPPA at 0x%x" % certppa_addr certisw_addr = idaapi.find_binary(start, stop, "43 65 72 74 49 53 57 00", 0, 0) # "CertISW" string print "Found CertISW at 0x%x" % certisw_addr # Apply structure types on Cert* addresses # Read Structures from such data # If type is not parsed already, then... if idc.ParseTypes("certpk;", idc.PT_SILENT) != 0: # ...define the type idc.ParseTypes(certpk_str, idc.PT_SILENT) if idc.ParseTypes("certppa;", idc.PT_SILENT) != 0: idc.ParseTypes(certppa_str, idc.PT_SILENT) if idc.ParseTypes("certisw;", idc.PT_SILENT) != 0: idc.ParseTypes(certisw_str, idc.PT_SILENT) certpk_ = idaapi.Appcall.typedobj("certpk;") certpk_read, certpk = certpk_.retrieve( idaapi.get_many_bytes(certpk_addr, certpk_.size)) certppa_ = idaapi.Appcall.typedobj("certppa;") certppa_read, certppa = certppa_.retrieve( idaapi.get_many_bytes(certppa_addr, certppa_.size)) certisw_ = idaapi.Appcall.typedobj("certisw;") certisw_read, certisw = certisw_.retrieve( idaapi.get_many_bytes(certisw_addr, certisw_.size)) # Make PEM keys if certpk_read == 1: root_key = construct_public_key( certpk.root_key.e_value, int( certpk.root_key.modul[0:certpk.root_key.modul_length].encode( "hex"), 16), certpk.root_key.modul_length * 8) root_key.save_key("root_key.pem") # TODO: add automatic export of all ACTIVE keys from certpk.active_keys pk_02 = construct_public_key( certpk.key_02.e_value, int( certpk.key_02.modul[0:certpk.key_02.modul_length].encode( "hex"), 16), certpk.key_02.modul_length * 8) pk_02.save_key("pk_02.pem") pk_03 = construct_public_key( certpk.key_03.e_value, int( certpk.key_03.modul[0:certpk.key_03.modul_length].encode( "hex"), 16), certpk.key_03.modul_length * 8) pk_03.save_key("pk_03.pem") pk_04 = construct_public_key( certpk.key_04.e_value, int( certpk.key_04.modul[0:certpk.key_04.modul_length].encode( "hex"), 16), certpk.key_04.modul_length * 8) pk_04.save_key("pk_04.pem") else: print "CertPK read fail!" # Verify digests if (certpk_read == 1) & (certppa_read == 1) & (certisw_read == 1): certpk_digest = certpk.digest.digest.encode("hex") certppa_digest = certppa.digest.digest.encode("hex") certisw_digest = certisw.digest.digest.encode("hex") # pk_03.public_decrypt(certisw_digest, 1) # pk_03.verify(idaapi.get_many_bytes(certisw_addr, certisw_.size), certisw_digest, "sha1") # decoder.decode(certpk.digest.signer_info, ) print "CertPK signer info: %s " % certpk.digest.signer_info.encode( "hex") print "CertPK digest: %s " % certpk.digest.digest.encode("hex") print "CertPPA signer info: %s " % certppa.digest.signer_info.encode( "hex") print "CertPPA digest: %s " % certppa.digest.digest.encode("hex") print "CertISW signer info: %s " % certisw.digest.signer_info.encode( "hex") print "CertISW digest: %s " % certisw.digest.digest.encode("hex") else: print "Certs processing fail!" # TODO: Parse rights of the keys # TODO: Parse ASN1 from digests # Processing Images i = 0 while i < 4: print "images type %s " % type(certppa.images) if certppa.images[i].image_offset != 0: print "Found PPA image at %x offset " % certppa.images[ i].image_offset if certisw.images[i].image_offset != 0: print "Found ISW image at %x offset " % certisw.images[ i].image_offset i += 1