def arguments(key=None): '''Returns the arguments as (offset,name,size)''' try: if key is None: fn = ui.current.function() if fn is None: raise LookupError, "function.arguments(%r):Not currently positioned within a function"% key else: fn = by(key) except Exception: target = ui.current.address() if key is None else key database.imports.get(target) # grab from declaration o = 0 for arg in internal.declaration.arguments(target): sz = internal.declaration.size(arg) yield o,arg,sz o += sz return # grab from structure fr = idaapi.get_frame(fn) if fr is None: # unable to figure out arguments raise LookupError, "function.arguments(%r):Unable to determine function frame"%key if database.config.bits() != 32: raise RuntimeError, "function.arguments(%r):Unable to determine arguments for %x due to %d-bit calling convention."%(key, fn.startEA, database.config.bits()) base = getLvarSize(fn)+getRvarSize(fn) for (off,size),(name,cmt) in structure.fragment(fr.id, base, getAvarSize(fn)): yield off-base,name,size return
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 __init__(self, func): self.src = func ea = func.startEA self.ea = ea self.name = idaapi.get_func_name(ea) self.elts = [] if idaapi.is_func_tail(func): self.name += "_tail_"+str(ea) fr = idaapi.get_frame(func) struc_vars = [] if fr == None: self.frame = None else: self.frame = struct.frame_node(fr, func) struc_vars = self.frame.struct_vars while ea < func.endEA: if idaapi.isData(idaapi.getFlags(ea)): self.elts.append(data.data_node(ea, idaapi.next_not_tail(ea))) else: if ea == func.startEA and not (idaapi.is_func_tail(func)): self.elts.append(insn.insn_node(ea, struc_vars)) else: self.elts.append(names.name_wrap_insn(ea, insn.insn_node(ea, struc_vars))) ea = idaapi.next_head(ea, func.endEA)
def __init__(self, func): self.src = func ea = func.startEA self.ea = ea self.name = idaapi.get_func_name(ea) self.elts = [] if idaapi.is_func_tail(func): self.name += "_tail_" + str(ea) fr = idaapi.get_frame(func) struc_vars = [] if fr == None: self.frame = None else: self.frame = struct.frame_node(fr, func) struc_vars = self.frame.struct_vars while ea < func.endEA: if idaapi.isData(idaapi.getFlags(ea)): self.elts.append(data.data_node(ea, idaapi.next_not_tail(ea))) else: if ea == func.startEA and not (idaapi.is_func_tail(func)): self.elts.append(insn.insn_node(ea, struc_vars)) else: self.elts.append( names.name_wrap_insn(ea, insn.insn_node(ea, struc_vars))) ea = idaapi.next_head(ea, func.endEA)
def get_function_sid_without_del(self, in_stack, local_size=1, count_from_first_var=False): if not in_stack: return 'create_struct_complex', idc.AddStrucEx(0, 'create_struct_complex', 0) ea = yaunit.get_next_function(lambda ea : yaunit.has_locals(ea, local_size, count_from_first_var)) frame = idaapi.get_frame(ea) self.assertNotEqual(frame, None) offset = idc.GetFirstMember(frame.id) return ea, frame.id
def yacheck_function_local_vars(self): addr = yaunit.load('function_with_local_vars') frame = idaapi.get_frame(addr) frame_size = idaapi.get_struc_size(frame.id) offset = 0 last_name = None while offset < frame_size and last_name is None: last_name = idc.GetMemberName(frame.id, offset) offset += 1 self.assertEqual(last_name, 'local_var')
def ida_to_angr_stack_offset(func_addr, ida_stack_off): frame = idaapi.get_frame(func_addr) if not frame: return ida_stack_off frame_size = idc.get_struc_size(frame) last_member_size = idaapi.get_member_size( frame.get_member(frame.memqty - 1)) angr_stack_off = ida_stack_off - frame_size + last_member_size return angr_stack_off
def yatest_function_local_vars(self): addr = yaunit.get_next_function(yaunit.has_locals) frame = idaapi.get_frame(addr) offset = 0 frame_size = idaapi.get_struc_size(frame.id) while offset < frame_size: if idc.SetMemberName(frame.id, offset, 'local_var'): break offset += 1 yaunit.save('function_with_local_vars', addr)
def get_stack_variable_name(func_start, offset): func = idaapi.get_func(func_start) frame = idaapi.get_frame(func) if frame is None: raise ValueError("couldn't get frame for function @ 0x%x" % func_start) offset += func.frsize member = idaapi.get_member(frame, offset) return idaapi.get_member_name(member.id)
def get_function_sid(self, in_stack, local_size=1): if not in_stack: return 'create_struct_complex', idc.AddStrucEx(0, 'create_struct_complex', 0) ea = yaunit.get_next_function(lambda ea : yaunit.has_locals(ea, local_size)) frame = idaapi.get_frame(ea) self.assertNotEqual(frame, None) offset = idc.GetFirstMember(frame.id) while offset != idaapi.BADADDR: idc.DelStrucMember(frame.id, offset) offset = idc.GetFirstMember(frame.id) return ea, frame.id
def get_stkvar_map(ea): '''ea_t -> {int : (str, tinfo_t)}''' # NOTE mutates d frame = idaapi.get_frame(ea) def make_map(d, (off, name, _)): mem = idaapi.get_member(frame, off) ti = idaapi.tinfo_t() idaapi.get_or_guess_member_tinfo2(mem, ti) d[off] = (name, ti) return d
def has_locals(ea, lvar_size=1, count_from_first_var=False): frame = idaapi.get_frame(ea) if frame is None or frame.memqty <= 1: return False if count_from_first_var: sida = frame.id offset = idc.GetFirstMember(sida) return idc.GetFrameLvarSize(ea) > lvar_size+offset else: return idc.GetFrameLvarSize(ea) > lvar_size
def run(self): try: self.logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtGui.QDialog.DialogCode.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) self.logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for stack frame at 0x%x' % ea) #need the actual pointer value, not the swig wrapped struc_t struc= long(struc.this) else: structName = dlg.getActiveStruct() self.logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers funcstart = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): idc.AnalyzeArea(funcstart, funcend) elif res == QtGui.QDialog.DialogCode.Rejected: self.logger.info('Dialog result: canceled by user') else: self.logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: self.logger.exception("Exception caught: %s", str(err))
def frame(key=None): if key is None: fn = ui.current.function() if fn is None: raise LookupError, "function.frame(%r):Not currently positioned within a function"% key else: fn = by(key) res = idaapi.get_frame(fn.startEA) if res is not None: return structure.instance(res.id, offset=-fn.frsize) #logging.fatal('%s.frame : function does not have a frame : %x %s', __name__, fn.startEA, name(fn.startEA)) logging.info('%s.frame : function does not have a frame : %x %s', __name__, fn.startEA, name(fn.startEA)) return structure.instance(-1)
def renaming_struc_member(self, sptr, mptr, newname): """ Handles renaming of two things: 1. Global Structs 2. Stack Variables :param sptr: Struct Pointer :param mptr: Member Pointer :param newname: New Member Name :return: """ sname = ida_struct.get_struc_name(sptr.id) s_type = compat.parse_struct_type(sname) # stack offset variable if isinstance(s_type, int): func_addr = s_type # compute stack frame for offset frame = idaapi.get_frame(func_addr) frame_size = idc.get_struc_size(frame) last_member_size = idaapi.get_member_size( frame.get_member(frame.memqty - 1)) # stack offset stack_offset = mptr.soff - frame_size + last_member_size size = idaapi.get_member_size(mptr) type_str = self.controller._get_type_str(mptr.flag) # do the change on a new thread self.controller.make_controller_cmd( self.controller.push_stack_variable, func_addr, stack_offset, newname, type_str, size) # actual struct elif isinstance(s_type, str): print("Not implemented") else: print("Error: bad parsing") return 0
def xrefs_to(self): """ Retrieves the xrefs to the stack variable. NOTE: This code is very SWIGGY because IDA did not properly expose this functionality. :raises ValueError: if frame_id, stack_offset, or string_reference was not provided. This is needed to determine what function to use. """ if self._xrefs_to is None: if not self.string_reference: raise ValueError('Unable to get xrefs without string_reference.') if not (self.frame_id and self.stack_offset): raise ValueError('Unable to get xrefs without frame_id and stack_offset') xrefs = idaapi.xreflist_t() frame = idaapi.get_frame(self.frame_id) func = idaapi.get_func(self.string_reference) member = idaapi.get_member(frame, self.stack_offset) idaapi.build_stkvar_xrefs(xrefs, func, member) self._xrefs_to = [ref.ea for ref in xrefs] return self._xrefs_to
def getArguments(ea): '''Returns the arguments as (offset,name,size)''' try: # grab from declaration first o = 0 for arg in _declaration.arguments(ea): sz = _declaration.size(arg) yield o,arg,sz o += sz return except ValueError: pass # grab from structure ea = top(ea) fr = idaapi.get_frame(ea) if fr is None: # unable to figure out arguments return base = getLvarSize(ea)+getRvarSize(ea) for (off,size),(name,cmt) in structure.fragment(fr.id, base, getAvarSize(ea)): yield off-base,name,size
def get_frame(self): if not self.__frame: self.__frame = idaapi.get_frame(self.address) return self.__frame
def fill_function(self, ida_func, user=None, state=None): """ Grab all relevant information from the specified user and fill the @ida_func. """ # == function name === # _func = self.pull_function(ida_func, user=user, state=state) if _func is None: return if compat.get_func_name(ida_func.start_ea) != _func.name: compat.set_ida_func_name(ida_func.start_ea, _func.name) # === comments === # # set the func comment func_comment = self.pull_comment(_func.addr, user=user, state=state) if func_comment is None: func_comment = "" #idc.set_func_cmt(_func.addr, func_comment, 1) #compat.set_ida_comment(_func.addr, func_comment, 1, func_cmt=True) # set the disassembly comments func_cmt_end = "\n" for start_ea, end_ea in idautils.Chunks(ida_func.start_ea): for head in idautils.Heads(start_ea, end_ea): if head == _func.addr: continue comment = self.pull_comment(head, user=user, state=state) if comment is not None: func_cmt_end += f"\n{hex(head)}: {comment}" #compat.set_decomp_comments(_func.addr, {head: comment}) #compat.set_ida_comment(head, comment, 0, func_cmt=False) func_comment += func_cmt_end compat.set_ida_comment(_func.addr, func_comment, 1, func_cmt=True) # === stack variables === # existing_stack_vars = {} frame = idaapi.get_frame(ida_func.start_ea) if frame is None or frame.memqty <= 0: _l.debug( "Function %#x does not have an associated function frame. Skip variable name sync-up.", ida_func.start_ea) return frame_size = idc.get_struc_size(frame) last_member_size = idaapi.get_member_size( frame.get_member(frame.memqty - 1)) for i in range(frame.memqty): member = frame.get_member(i) stack_offset = member.soff - frame_size + last_member_size existing_stack_vars[stack_offset] = member for offset, stack_var in self.pull_stack_variables( ida_func, user=user, state=state).items(): ida_offset = stack_var.get_offset(StackOffsetType.IDA) # skip if this variable already exists if ida_offset in existing_stack_vars: type_str = self._get_type_str( existing_stack_vars[ida_offset].flag) else: type_str = None if ida_offset in existing_stack_vars: if idc.get_member_name(frame.id, existing_stack_vars[ida_offset].soff) == stack_var.name \ and type_str is not None \ and stack_var.type == type_str: continue # rename the existing variable idaapi.set_member_name(frame, existing_stack_vars[ida_offset].soff, stack_var.name) # TODO: retype the existing variable # ===== update the psuedocode ==== # compat.refresh_pseudocode_view(_func.addr)
def make_stackframe(self, object_version, address): object_id = object_version.get_id() parent_object_id = object_version.get_parent_object_id() # associate stack frame id to function id self.stackframes_functions[object_id] = parent_object_id # association stackframe id to internal struc id eaFunc = object_version.get_object_address() logger.debug("stackframe[%s] : address of function is 0x%08X" % (self.hash_provider.hash_to_string(object_id), eaFunc)) attributes = object_version.get_attributes() stack_lvars = None stack_regvars = None stack_args = None try: stack_lvars = self.yatools.hex_string_to_address( attributes["stack_lvars"]) stack_regvars = self.yatools.hex_string_to_address( attributes["stack_regvars"]) stack_args = self.yatools.hex_string_to_address( attributes["stack_args"]) except KeyError: logger.warning("Stackframe at %s has missing attribute" % self.yatools.address_to_hex_string(eaFunc)) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X" % (self.hash_provider.hash_to_string(object_id), eaFunc)) self.analyze_function(eaFunc) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after reanalysis" % (self.hash_provider.hash_to_string(object_id), eaFunc)) idc.SetCharPrm(idc.INF_AUTO, 1) idc.Wait() idc.SetCharPrm(idc.INF_AUTO, 0) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after full reanalysis" % (self.hash_provider.hash_to_string(object_id), eaFunc)) idc.MakeFrame(eaFunc, stack_lvars, stack_regvars, stack_args) stack_frame = idaapi.get_frame(eaFunc) if stack_frame is None: logger.error( "No function found for stackframe[%s] at 0x%08X after idc.MakeFrame" % (self.hash_provider.hash_to_string(object_id), eaFunc)) else: self.struc_ids[object_id] = stack_frame.id _yatools_ida_exporter.set_struct_id(object_id, stack_frame.id) stack_lvars = None try: stack_lvars = self.yatools.hex_string_to_address( object_version.get_attributes()["stack_lvars"]) except KeyError: logger.warning( "Stackframe at %s has no stack_lvars attribute" % self.yatools.address_to_hex_string(eaFunc)) if stack_lvars is not None: logger.debug( "Clearing everything for stackframe at 0x%08X, with stack_lvars=0x%04X", eaFunc, stack_lvars) self.clear_struc_fields( stack_frame.id, object_version.get_size(), object_version.get_xrefed_id_map().iterkeys(), member_type=ya.OBJECT_TYPE_STACKFRAME_MEMBER, name_offset=stack_lvars)
def frame(fn): return idaapi.get_frame(by(fn).startEA)
def run(self): try: logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtWidgets.QDialog.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() if using_ida7api: sid = idc.get_frame_id(ea) else: sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError( 'Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError( 'Failed to get struc_t for stack frame at 0x%x' % ea) if using_ida7api: pass else: #need the actual pointer value, not the swig wrapped struc_t struc = long(struc.this) else: structName = dlg.getActiveStruct() if structName is None: print("No struct selected. Bailing out") return logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) if using_ida7api: sid = idc.get_struc_id(structName) else: sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) if using_ida7api: struc = idaapi.get_struc(tid) else: struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers if using_ida7api: funcstart = idc.get_func_attr(idc.here(), idc.FUNCATTR_START) funcend = idc.get_func_attr(idc.here(), idc.FUNCATTR_END) else: funcstart = idc.GetFunctionAttr( idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): if using_ida7api: idc.plan_and_wait(funcstart, funcend) else: idc.AnalyzeArea(funcstart, funcend) elif res == QtWidgets.QDialog.Rejected: logger.info('Dialog result: canceled by user') else: logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: logger.exception("Exception caught: %s", str(err))
def ida_get_frame(func_addr): return idaapi.get_frame(func_addr)