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 refs(self): """Return the (address, opnum, type) of all the references (code & data) to this structure within the database. If `opnum` is None, then the `address` has the structure applied to it. If `opnum` is defined, then the instruction at `address` references a field that is the specified structure. """ x, sid = idaapi.xrefblk_t(), self.id # grab first reference to structure ok = x.first_to(sid, 0) if not ok: return [] # collect rest of it's references refs = [(x.frm, x.iscode, x.type)] while x.next_to(): refs.append((x.frm, x.iscode, x.type)) # calculate the high-byte which is used to differentiate an address from a structure bits = math.trunc(math.ceil(math.log(idaapi.BADADDR) / math.log(2.0))) highbyte = 0xff << (bits - 8) # iterate through figuring out if sid is applied to an address or another structure res = [] for ref, _, _ in refs: # structure (probably a frame member) if ref & highbyte == highbyte: # get sptr, mptr name = idaapi.get_member_fullname(ref) mptr, _ = idaapi.get_member_by_fullname(name) if not isinstance(mptr, idaapi.member_t): cls = self.__class__ raise TypeError( "{:s} : Unexpected type {!r} for netnode '{:s}'". format('.'.join((__name__, cls.__name__)), mptr.__class__, name)) sptr = idaapi.get_sptr(mptr) # get frame, func_t frname, _ = name.split('.', 2) frid = internal.netnode.get(frname) ea = idaapi.get_func_by_frame(frid) f = idaapi.get_func(ea) # now find all xrefs to member within function xl = idaapi.xreflist_t() idaapi.build_stkvar_xrefs(xl, f, mptr) # now we can add it for xr in xl: ea, opnum, state = xr.ea, int( xr.opnum), instruction.op_state(ea, opnum) res.append( interface.OREF(ea, opnum, interface.ref_t.of_state(state))) continue # address res.append(interface.OREF(ref, None, interface.ref_t.of_state( '*'))) # using '*' to describe being applied to the an address return res
def refs(self): '''Return the (address, opnum, type) of all the references to this member within the database.''' mid = self.id # calculate the high-byte which is used to determine an address from a structure bits = int(math.ceil(math.log(idaapi.BADADDR) / math.log(2.0))) highbyte = 0xff << (bits - 8) # if structure is a frame.. if internal.netnode.name.get(self.__owner.id).startswith('$ '): name, mptr = self.fullname, self.ptr sptr = idaapi.get_sptr(mptr) # get frame, func_t frname, _ = name.split('.', 2) frid = internal.netnode.get(frname) ea = idaapi.get_func_by_frame(frid) f = idaapi.get_func(ea) # now find all xrefs to member within function xl = idaapi.xreflist_t() idaapi.build_stkvar_xrefs(xl, f, mptr) # now we can add it res = [] for xr in xl: ea, opnum = xr.ea, int(xr.opnum) res.append( interface.OREF( ea, opnum, interface.ref_t(xr.type, instruction.op_state(ea, opnum)))) # FIXME return res # otherwise, it's a structure..which means we need to specify the member to get refs for x = idaapi.xrefblk_t() ok = x.first_to(mid, 0) if not ok: return [] # collect all references available refs = [(x.frm, x.iscode, x.type)] while x.next_to(): refs.append((x.frm, x.iscode, x.type)) # now figure out which operand has the structure member applied to it res = [] for ea, _, t in refs: ops = ((idx, internal.netnode.sup.get(ea, 0xf + idx)) for idx in range(idaapi.UA_MAXOP) if internal.netnode.sup.get(ea, 0xf + idx) is not None) ops = ((idx, interface.node.sup_opstruct( val, idaapi.get_inf_structure().is_64bit())) for idx, val in ops) ops = (idx for idx, ids in ops if self.__owner.id in ids) # sanity res.extend( interface.OREF(ea, int(op), interface.ref_t.of(t)) for op in ops) return res