Example #1
0
    def struc_member_changed(self, sptr, mptr):
        #print(f"struc member changed: {sptr.id}, {mptr.id}")

        # struct pointer is actually a stack frame
        if sptr.is_frame():
            stack_frame = sptr
            func_addr = idaapi.get_func_by_frame(stack_frame.id)
            try:
                all_var_info = compat.get_func_stack_var_info(func_addr)
                stack_var_info = all_var_info[compat.ida_to_angr_stack_offset(
                    func_addr, mptr.soff)]
            except KeyError:
                l.debug(
                    f"Failed to track an internal changing stack var: {mptr.id}."
                )
                return 0

            # find the properties of the changed stack var
            angr_offset = compat.ida_to_angr_stack_offset(
                func_addr, stack_var_info.stack_offset)
            size = stack_var_info.size
            type_str = stack_var_info.type

            new_name = stack_var_info.name  #ida_struct.get_member_name(mptr.id)

            # do the change on a new thread
            sv = StackVariable(angr_offset, StackOffsetType.IDA, new_name,
                               type_str, size, func_addr)
            self.binsync_state_change(self.controller.push_artifact, sv)
        else:
            self.ida_struct_changed(sptr.id)

        return 0
Example #2
0
    def struc_member_renamed(self, sptr, mptr):
        #print(f"struc member renamed: {sptr.id}: {mptr.id}")
        """
        Handles renaming of two things:
        1. Global Structs
        2. Stack Variables

        :param sptr:    Struct Pointer
        :param mptr:    Member Pointer
        :return:
        """
        # struct pointer is actually a stack frame
        if sptr.is_frame():
            stack_frame = sptr
            func_addr = idaapi.get_func_by_frame(stack_frame.id)
            try:
                stack_var_info = compat.get_func_stack_var_info(func_addr)[
                    compat.ida_to_angr_stack_offset(func_addr, mptr.soff)]
            except KeyError:
                l.debug(
                    f"Failed to track an internal changing stack var: {mptr.id}."
                )
                return 0

            # find the properties of the changed stack var
            angr_offset = compat.ida_to_angr_stack_offset(
                func_addr, stack_var_info.stack_offset)
            size = stack_var_info.size
            type_str = stack_var_info.type

            # TODO: correct this fix in the get_func_stack_var_info
            new_name = ida_struct.get_member_name(mptr.id)

            # do the change on a new thread
            sv = StackVariable(angr_offset, StackOffsetType.IDA, new_name,
                               type_str, size, func_addr)
            self.binsync_state_change(self.controller.push_artifact, sv)

        # an actual struct
        else:
            self.ida_struct_changed(sptr.id)

        return 0
Example #3
0
 def add_auto_comment(self, ea, text):
     if ea is not None:
         prefix = ""
         if idaapi.get_struc(ea) is not None:
             if idc.GetStrucIdx(ea) == idc.BADADDR:
                 prefix = "stackframe '%s'" % idc.GetFunctionName(
                     idaapi.get_func_by_frame(ea))
             else:
                 prefix = "structure '%s'" % idc.GetStrucName(ea)
         elif idc.GetEnumIdx(ea) != idc.BADADDR:
             prefix = "enum '%s'" % idc.GetEnumName(ea)
         else:
             foffset = idc.GetFuncOffset(ea)
             if foffset is None:
                 prefix = yatools.ea_to_hex(ea)
             else:
                 prefix = "%s,%s" % (yatools.ea_to_hex(ea), foffset)
         self.auto_comments.add((prefix, text))
     else:
         self.auto_comments.add(("", text))
Example #4
0
    def save_strucs(self, ida_model, memory_exporter):
        """
        Structures : export modified structures and delete those who have been deleted
        """
        for struc_id in self.structures_to_process:
            sidx = idc.GetStrucIdx(struc_id)
            if sidx is None or sidx == idc.BADADDR:
                # it is a deleted structure or a stackframe
                # in this last case we need to export the parent (function)
                eaFunc = idaapi.get_func_by_frame(struc_id)
                if eaFunc != idc.BADADDR:
                    # OK, it is a stackframe
                    ida_model.accept_struct(memory_exporter, eaFunc, struc_id)
                    ida_model.accept_ea(memory_exporter, eaFunc)
                else:
                    # it is a deleted structure
                    ida_model.delete_struct(memory_exporter, struc_id)
            else:

                ida_model.accept_struct(memory_exporter, idc.BADADDR, struc_id)

        logger.debug("Walking members")
        """
        Structure members : update modified ones, and remove deleted ones
        We iterate over members :
            -if the parent struc has been deleted, delete the member
            -otherwise, detect if the member has been updated or removed
                -updated : accept struc_member + accept_struct if not already exported!
                -removed : accept struc_member_deleted
        """
        for (struc_id, member_set) in self.strucmember_to_process.iteritems():
            ida_struc = idaapi.get_struc(struc_id)
            logger.debug("Walking struc 0x%08X" % struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            is_stackframe = False
            struc_deleted = False
            if sidx is None or sidx == idc.BADADDR:
                f = idaapi.get_func_by_frame(struc_id)
                if f is not None and f != idc.BADADDR:
                    is_stackframe = True
                else:
                    struc_deleted = True

            stackframe_func_addr = idc.BADADDR
            if is_stackframe:
                eaFunc = idaapi.get_func_by_frame(struc_id)
                stackframe_func_addr = eaFunc
                ida_model.accept_function(memory_exporter, eaFunc)

            if struc_deleted:
                # The structure has been deleted : we need to delete the members
                # Note: at first sight, it is not a stackframe
                # TODO: handle function->stackframe deletion here
                for (member_id, offset) in member_set:
                    ida_model.delete_struct_member(memory_exporter,
                                                   idc.BADADDR, struc_id,
                                                   offset)
            else:
                # The structure or stackframe has been modified
                for (member_id, offset) in member_set:
                    ida_member = idaapi.get_member(ida_struc, offset)
                    if ida_member is None:
                        new_member_id = -1
                    else:
                        new_member_id = ida_member.id
                    if new_member_id == -1:
                        # the member has been deleted : delete it
                        ida_model.delete_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       struc_id, offset)
                    elif offset > 0 and idc.GetMemberId(
                            struc_id, offset - 1) == new_member_id:
                        # the member was deleted, and replaced by a member starting above it
                        ida_model.delete_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       struc_id, offset)
                    else:
                        # the member has just been modified
                        ida_model.accept_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       ida_member.id)
Example #5
0
    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
Example #6
0
    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
Example #7
0
    def save_strucs(self, memory_exporter):
        """
        Structures : export modified structures and delete those who have been deleted
        """
        for struc_id in self.structures_to_process:
            self.ida_model.clear_exported_struc_enum_id(struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            if sidx is None or sidx == idc.BADADDR:
                # it is a deleted structure or a stackframe
                # in this last case we need to export the parent (function)
                eaFunc = idaapi.get_func_by_frame(struc_id)
                if eaFunc != idc.BADADDR:
                    # OK, it is a stackframe
                    self.ida_model.accept_struc(
                        memory_exporter, 0, struc_id, ya.OBJECT_TYPE_STACKFRAME, ya.OBJECT_TYPE_STACKFRAME_MEMBER,
                        stackframe_func_addr=eaFunc)
                    self.ida_model.accept_ea(memory_exporter, 0, eaFunc)
                else:
                    # it is a deleted structure
                    self.ida_model.accept_deleted_struc(memory_exporter, struc_id)
            else:

                self.ida_model.accept_struc(memory_exporter, 0, struc_id)

        logger.debug("Walking members")
        """
        Structure members : update modified ones, and remove deleted ones
        We iterate over members :
            -if the parent struc has been deleted, delete the member
            -otherwise, detect if the member has been updated or removed
                -updated : accept struc_member + accept_struc if not already exported!
                -removed : accept struc_member_deleted
        """
        for (struc_id, member_set) in self.strucmember_to_process.iteritems():
            ida_struc = idaapi.get_struc(struc_id)
            logger.debug("Walking struc 0x%08X" % struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            is_stackframe = False
            struc_deleted = False
            if sidx is None or sidx == idc.BADADDR:
                f = idaapi.get_func_by_frame(struc_id)
                if f is not None and f != idc.BADADDR:
                    is_stackframe = True
                else:
                    struc_deleted = True

            if is_stackframe:
                strucmember_type = ya.OBJECT_TYPE_STACKFRAME_MEMBER
                struc_name = None
                struc_type = ya.OBJECT_TYPE_STACKFRAME
                eaFunc = idaapi.get_func_by_frame(struc_id)
                stackframe_func_addr = eaFunc
                func = idaapi.get_func(eaFunc)
                self.ida_model.accept_function(memory_exporter, 0, eaFunc, func)
            else:
                strucmember_type = ya.OBJECT_TYPE_STRUCT_MEMBER
                struc_type = ya.OBJECT_TYPE_STRUCT
                stackframe_func_addr = None
                if not struc_deleted:
                    struc_name = idc.GetStrucName(struc_id)

            if struc_deleted:
                # The structure has been deleted : we need to delete the members
                # Note: at first sight, it is not a stackframe
                # TODO: handle function->stackframe deletion here
                for (member_id, offset) in member_set:
                    self.ida_model.accept_deleted_strucmember(memory_exporter, struc_id, None, offset)
            else:
                # The structure or stackframe has been modified
                is_union = ida_struc.is_union()

                for (member_id, offset) in member_set:
                    ida_member = idaapi.get_member(ida_struc, offset)
                    if ida_member is None:
                        new_member_id = -1
                    else:
                        new_member_id = ida_member.id
                    logger.debug("exporting member %s at offset 0x%02X (mid=0x%016X)" %
                                 (strucmember_type, offset, member_id))
                    self.ida_model.clear_exported_struc_member_id(new_member_id)

                    if new_member_id == -1:
                        # the member has been deleted : delete it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif offset > 0 and idc.GetMemberId(struc_id, offset - 1) == new_member_id:
                        # the member was deleted, and replaced by a member starting above it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif new_member_id != member_id:
                        # the member has been deleted and later recreated
                        name = idaapi.get_member_name(new_member_id)
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)
                    else:
                        # the member has just been modified
                        name = idaapi.get_member_name(new_member_id)
                        logger.debug("exporting member %s (%s) at offset 0x%02X (mid=0x%016X)" %
                                     (strucmember_type, name, offset, member_id))
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)