Beispiel #1
0
    def import_to_structures(self, ask=False):
        """
        Imports virtual tables and returns tid_t of new structure

        :return: idaapi.tid_t
        """
        cdecl_typedef = idaapi.print_tinfo(
            None, 4, 5,
            idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE | idaapi.PRTYPE_SEMI,
            self.create_tinfo(), self.vtable_name, None)
        if ask:
            cdecl_typedef = idaapi.ask_text(
                0x10000, cdecl_typedef,
                "The following new type will be created")
            if not cdecl_typedef:
                return
        previous_ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati,
                                                   self.vtable_name)
        if previous_ordinal:
            idaapi.del_numbered_type(idaapi.cvar.idati, previous_ordinal)
            ordinal = idaapi.idc_set_local_type(previous_ordinal,
                                                cdecl_typedef, idaapi.PT_TYP)
        else:
            ordinal = idaapi.idc_set_local_type(-1, cdecl_typedef,
                                                idaapi.PT_TYP)

        if ordinal:
            print("[Info] Virtual table " + self.vtable_name +
                  " added to Local Types")
            return idaapi.import_type(idaapi.cvar.idati, -1, self.vtable_name)
        else:
            print("[Error] Failed to create virtual table " + self.vtable_name)
            print("*" * 100)
            print(cdecl_typedef)
            print("*" * 100)
Beispiel #2
0
    def pack(self, start=0, stop=None):
        if self.collisions[start:stop].count(True):
            print("[Warning] Collisions detected")
            return

        final_tinfo = idaapi.tinfo_t()
        udt_data = idaapi.udt_type_data_t()
        origin = self.items[start].offset if start else 0
        offset = origin

        for item in [x for x in self.items[start:stop]
                     if x.enabled]:  # Filter disabled members
            gap_size = item.offset - offset
            if gap_size:
                udt_data.push_back(
                    helper.create_padding_udt_member(offset - origin,
                                                     gap_size))
            if item.is_array:
                array_size = self.calculate_array_size(
                    bisect.bisect_left(self.items, item))
                if array_size:
                    udt_data.push_back(
                        item.get_udt_member(array_size, offset=origin))
                    offset = item.offset + item.size * array_size
                    continue
            udt_data.push_back(item.get_udt_member(offset=origin))
            offset = item.offset + item.size

        final_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
        cdecl = idaapi.print_tinfo(
            None, 4, 5,
            idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE | idaapi.PRTYPE_SEMI,
            final_tinfo, self.get_name(), None)
        cdecl = idaapi.ask_text(0x10000, '#pragma pack(push, 1)\n' + cdecl,
                                "The following new type will be created")

        if cdecl:
            structure_name = idaapi.idc_parse_decl(idaapi.cvar.idati, cdecl,
                                                   idaapi.PT_TYP)[0]
            previous_ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati,
                                                       structure_name)

            if previous_ordinal:
                reply = QtWidgets.QMessageBox.question(
                    None, "HexRaysPyTools",
                    "Structure already exist. Do you want to overwrite it?",
                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    idaapi.del_numbered_type(idaapi.cvar.idati,
                                             previous_ordinal)
                    ordinal = idaapi.idc_set_local_type(
                        previous_ordinal, cdecl, idaapi.PT_TYP)
                else:
                    return
            else:
                ordinal = idaapi.idc_set_local_type(-1, cdecl, idaapi.PT_TYP)
            if ordinal:
                print("[Info] New type {0} was added to Local Types".format(
                    structure_name))
                tid = idaapi.import_type(idaapi.cvar.idati, -1, structure_name)
                if tid:
                    tinfo = idaapi.create_typedef(structure_name)
                    ptr_tinfo = idaapi.tinfo_t()
                    ptr_tinfo.create_ptr(tinfo)
                    for scanned_var in self.get_unique_scanned_variables(
                            origin):
                        scanned_var.apply_type(ptr_tinfo)
                    return tinfo
            else:
                print("[ERROR] Structure {0} probably already exist".format(
                    structure_name))
Beispiel #3
0
    def activate(self, ctx):
        hx_view = idaapi.get_widget_vdui(ctx.widget)
        if not self.check(hx_view):
            return

        item = hx_view.item.it.to_specific_type
        parent = hx_view.cfunc.body.find_parent_of(item).to_specific_type
        if parent.op != idaapi.cot_idx or parent.y.op != idaapi.cot_num:
            idx = 0
        else:
            idx = parent.y.numval()

        struct_tinfo = item.x.type
        struct_tinfo.remove_ptr_or_array()

        offset = item.m
        ordinal = struct_tinfo.get_ordinal()
        struct_name = struct_tinfo.dstr()

        if (offset + idx) % 2:
            default_field_type = "_BYTE"
        elif (offset + idx) % 4:
            default_field_type = "_WORD"
        elif (offset + idx) % 8:
            default_field_type = "_DWORD"
        else:
            default_field_type = "_QWORD" if const.EA64 else "_DWORD"

        declaration = idaapi.ask_text(
            0x10000, "{0} field_{1:X}".format(default_field_type, offset + idx), "Enter new structure member:"
        )
        if declaration is None:
            return

        result = self.parse_declaration(declaration)
        if result is None:
            logger.warn("Bad member declaration")
            return

        field_tinfo, field_name = result
        field_size = field_tinfo.get_size()
        udt_data = idaapi.udt_type_data_t()
        udt_member = idaapi.udt_member_t()

        struct_tinfo.get_udt_details(udt_data)
        udt_member.offset = offset * 8
        struct_tinfo.find_udt_member(udt_member, idaapi.STRMEM_OFFSET)
        gap_size = udt_member.size // 8

        gap_leftover = gap_size - idx - field_size

        if gap_leftover < 0:
            logger.error("Too big size for the field. Type with maximum {0} bytes can be used".format(gap_size - idx))
            return

        iterator = udt_data.find(udt_member)
        iterator = udt_data.erase(iterator)

        if gap_leftover > 0:
            udt_data.insert(iterator, helper.create_padding_udt_member(offset + idx + field_size, gap_leftover))

        udt_member = idaapi.udt_member_t()
        udt_member.offset = offset * 8 + idx
        udt_member.name = field_name
        udt_member.type = field_tinfo
        udt_member.size = field_size

        iterator = udt_data.insert(iterator, udt_member)

        if idx > 0:
            udt_data.insert(iterator, helper.create_padding_udt_member(offset, idx))

        struct_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
        struct_tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.BTF_STRUCT, struct_name)
        hx_view.refresh_view(True)