Exemple #1
0
    def import_c_header(path,
                        pack=0,
                        raw_args=True,
                        silent=False,
                        autoimport=True):
        """
            Import a C header file.

            :param str path: The path to the C header file to import.
            :param int pack: The packing for the structure in the header. 0
                means default (from compiler/configuration), other values are
                power of 2 up to 16. No verification is made on that value.
            :param bool raw_args: Should leave the name of the argument
                unchanged: do not remove the _ in the name. True by default.
            :param bool silent: Should silently fails on error and mask
                warnings.
            :param bool autoimport: If True (the default), this function will
                import all new types in the IDB ("Structures", "Enums", ...
                Views), instead of only keeping them in the type
                library (til, the "Local Types" view).
            :return: The number of error which occur during parsing.
        """
        # This use the idc.parse_decls function, which is different of the
        #   ida_typeinf.parse_decls function, this one should be implemented
        #   using the type library
        flags = ida_typeinf.PT_FILE | ida_typeinf.PT_REPLACE
        if raw_args:
            flags |= ida_typeinf.PT_RAWARGS
        if silent:
            flags |= ida_typeinf.PT_SIL

        # handle pack conversion, hugly but should be ok
        if pack <= 2:
            flags |= (pack << 4) & ida_typeinf.PT_PACKMASK
        else:
            if pack == 4:
                flags |= (3 << 4) & ida_typeinf.PT_PACKMASK
            elif pack == 8:
                flags |= (4 << 4) & ida_typeinf.PT_PACKMASK
            elif pack == 16:
                flags |= (5 << 4) & ida_typeinf.PT_PACKMASK

        if autoimport:
            tidft = ida_typeinf.get_idati()  # default type lib of the idb
            # we get the nb of ordinal type, before parsing
            nb_typ = ida_typeinf.get_ordinal_qty(tidft)
            # now we make the parsing
            nb_error = idc.parse_decls(path, flags)
            # get the new number of types after it has been parsed
            nb_typ_after = ida_typeinf.get_ordinal_qty(tidft)
            # now we can import all of them
            for i in range(nb_typ, nb_typ_after):
                # get the name of the type
                na = ida_typeinf.get_numbered_type_name(tidft, i)
                # import the type, put it at the end
                ida_typeinf.import_type(tidft, -1, na)
            return nb_error
        else:
            return idc.parse_decls(path, flags)
Exemple #2
0
    def __call__(self):
        from .core import Core

        dll = Core.get_ida_dll()

        get_idati = dll.get_idati
        get_idati.argtypes = []
        get_idati.restype = ctypes.c_void_p

        set_numbered_type = dll.set_numbered_type
        set_numbered_type.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.c_int,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_int,
        ]
        set_numbered_type.restype = ctypes.c_int

        py_ti = ida_typeinf.get_idati()
        ordinal_qty = ida_typeinf.get_ordinal_qty(py_ti) - 1
        last_ordinal = self.local_types[-1][0]
        if ordinal_qty < last_ordinal:
            ida_typeinf.alloc_type_ordinals(py_ti, last_ordinal - ordinal_qty)
        else:
            for py_ordinal in range(last_ordinal + 1, ordinal_qty + 1):
                ida_typeinf.del_numbered_type(py_ti, py_ordinal)

        local_types = self.local_types
        for py_ord, name, type, fields, cmt, fieldcmts, sclass in local_types:
            if type:
                ti = get_idati()
                ordinal = ctypes.c_uint32(py_ord)
                ntf_flags = ctypes.c_int(ida_typeinf.NTF_REPLACE)
                name = ctypes.c_char_p(name)
                type = ctypes.c_char_p(type)
                fields = ctypes.c_char_p(fields)
                cmt = ctypes.c_char_p(cmt)
                fieldcmts = ctypes.c_char_p(fieldcmts)
                sclass = ctypes.c_int(sclass)
                set_numbered_type(
                    ti,
                    ordinal,
                    ntf_flags,
                    name,
                    type,
                    fields,
                    cmt,
                    fieldcmts,
                    sclass,
                )
            else:
                ida_typeinf.del_numbered_type(py_ti, py_ord)

        ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
Exemple #3
0
    def local_types_changed(self):
        from .core import Core

        dll = Core.get_ida_dll()

        get_idati = dll.get_idati
        get_idati.argtypes = []
        get_idati.restype = ctypes.c_void_p

        get_numbered_type = dll.get_numbered_type
        get_numbered_type.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_int),
        ]
        get_numbered_type.restype = ctypes.c_bool

        local_types = []
        py_ti = ida_typeinf.get_idati()
        for py_ord in range(1, ida_typeinf.get_ordinal_qty(py_ti)):
            name = ida_typeinf.get_numbered_type_name(py_ti, py_ord)

            ti = get_idati()
            ordinal = ctypes.c_uint32(py_ord)
            type = ctypes.c_char_p()
            fields = ctypes.c_char_p()
            cmt = ctypes.c_char_p()
            fieldcmts = ctypes.c_char_p()
            sclass = ctypes.c_int()
            get_numbered_type(
                ti,
                ordinal,
                ctypes.pointer(type),
                ctypes.pointer(fields),
                ctypes.pointer(cmt),
                ctypes.pointer(fieldcmts),
                ctypes.pointer(sclass),
            )
            local_types.append(
                (
                    py_ord,
                    name,
                    type.value,
                    fields.value,
                    cmt.value,
                    fieldcmts.value,
                    sclass.value,
                )
            )
        self._send_packet(evt.LocalTypesChangedEvent(local_types))
        return 0
Exemple #4
0
 def local_types_changed(self):
     local_types = []
     ti = ida_typeinf.get_idati()
     for ordinal in range(1, ida_typeinf.get_ordinal_qty(ti)):
         name = ida_typeinf.get_numbered_type_name(ti, ordinal)
         type_info = ida_typeinf.tinfo_t()
         type_info.get_numbered_type(ti, ordinal)
         ret = type_info.serialize()
         local_types.append((ordinal, name, ret))
     self._send_packet(evt.LocalTypesChangedEvent(local_types))
     return 0
Exemple #5
0
    def local_types_changed(self):
        local_types = []
        for ordinal in range(1, ida_typeinf.get_ordinal_qty(None)):
            ret = ida_typeinf.idc_get_local_type_raw(ordinal)
            if ret is not None:
                type_str, fields_str = ret
                type_name = ida_typeinf.get_numbered_type_name(
                    ida_typeinf.cvar.idati, ordinal
                )
                cur_ti = ida_typeinf.tinfo_t()
                cur_ti.deserialize(
                    ida_typeinf.cvar.idati, type_str, fields_str
                )
                type_serialized = cur_ti.serialize()
                local_types.append(
                    (
                        ordinal,
                        type_serialized[0],
                        type_serialized[1],
                        type_name,
                    )
                )
            else:
                local_types.append(None)

        if self.last_local_type is None:
            self.last_local_type = local_types
            sent_types = local_types
        else:

            def differ_local_types(types1, types2):
                # [(i, types1, types2), ...]
                ret_types = []
                for i in range(max([len(types1), len(types2)])):
                    if i >= len(types1):
                        ret_types.append((i, None, types2[i]))
                    elif i >= len(types2):
                        ret_types.append((i, types1[i], None))
                    else:
                        if types1[i] != types2[i]:
                            ret_types.append((i, types1[i], types2[i]))
                return ret_types

            diff = differ_local_types(self.last_local_type, local_types)
            self.last_local_type = local_types
            if len(diff) == 1 and diff[0][2] is None:
                return 0
            elif len(diff) == 0:
                return 0
            sent_types = [t[2] for t in diff]

        self._send_packet(evt.LocalTypesChangedEvent(sent_types))
        return 0
Exemple #6
0
    def local_types_changed(self):
        print("local type changed")
        return

        changed_types = []
        # self._plugin.logger.trace(self._plugin.core.local_type_map)
        for i in range(1,
                       ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())):
            t = ImportLocalType(i)
            if t and t.name and ida_struct.get_struc_id(
                    t.name) == ida_idaapi.BADADDR and ida_enum.get_enum(
                        t.name) == ida_idaapi.BADADDR:
                if i in self._plugin.core.local_type_map:
                    t_old = self._plugin.core.local_type_map[i]
                    if t_old and not t.isEqual(t_old):
                        changed_types.append((t_old.to_tuple(), t.to_tuple()))
                    elif t_old is None and i in self._plugin.core.delete_candidates:
                        if not self._plugin.core.delete_candidates[i].isEqual(
                                t):
                            changed_types.append(
                                (self._plugin.core.delete_candidates[i].
                                 to_tuple(), t.to_tuple()))
                        del self._plugin.core.delete_candidates[i]

                else:
                    changed_types.append((None, t.to_tuple()))
            if t is None:
                assert i in self._plugin.core.local_type_map
                if i in self._plugin.core.local_type_map:
                    t_old = self._plugin.core.local_type_map[i]
                    if t_old != t:
                        self._plugin.core.delete_candidates[i] = t_old
                    elif i in self._plugin.core.delete_candidates:
                        # changed_types.append((self._plugin.core.delete_candidates[i],None))
                        del self._plugin.core.delete_candidates[i]

                    # t_old = self._plugin.core.local_type_map[i]
                    # changed_types.append((t_old,None))
        # self._plugin.logger.trace(changed_types)
        if fDebug:
            pydevd_pycharm.settrace('localhost',
                                    port=2233,
                                    stdoutToServer=True,
                                    stderrToServer=True,
                                    suspend=False)
        self._plugin.logger.trace("Changed_types: %s" % list(
            map(
                lambda x: (x[0][0] if x[0] else None, x[1][0]
                           if x[1] else None), changed_types)))
        if len(changed_types) > 0:
            self._send_packet(evt.LocalTypesChangedEvent(changed_types))
        self._plugin.core.update_local_types_map()
        return 0
Exemple #7
0
    def __process_types(self):
        localtypes = []

        ti_lib_obj = ida_typeinf.get_idati()
        ti_lib_count = ida_typeinf.get_ordinal_qty(ti_lib_obj)

        for ti_ordinal in range(1, ti_lib_count + 1):
            ti_info = ida_typeinf.tinfo_t()
            if ti_info.get_numbered_type(ti_lib_obj, ti_ordinal):
                localtypes.append(self.__process_types_tinfo(ti_info))

        return localtypes
Exemple #8
0
 def local_types_changed(self):
     local_types = []
     for ordinal in range(1, ida_typeinf.get_ordinal_qty(None)):
         ret = ida_typeinf.idc_get_local_type_raw(ordinal)
         if ret is not None:
             type_str, fields_str = ret
             type_name = ida_typeinf.get_numbered_type_name(
                 ida_typeinf.cvar.idati, ordinal)
             cur_ti = ida_typeinf.tinfo_t()
             cur_ti.deserialize(ida_typeinf.cvar.idati, type_str,
                                fields_str)
             type_serialized = cur_ti.serialize()
             local_types.append(
                 (type_serialized[0], type_serialized[1], type_name))
         else:
             local_types.append(None)
     self._send_event(LocalTypesChangedEvent(local_types))
     return 0
Exemple #9
0
    def __call__(self):
        ti = ida_typeinf.get_idati()

        ordinal_qty = ida_typeinf.get_ordinal_qty(ti)
        last_ordinal = self.local_types[-1][0]
        if ordinal_qty < last_ordinal:
            ida_typeinf.alloc_type_ordinals(ti, last_ordinal - ordinal_qty)
        else:
            for ordinal in range(last_ordinal + 1, ordinal_qty + 1):
                ida_typeinf.del_numbered_type(ti, ordinal)

        for ordinal, name, ret in self.local_types:
            name = Event.encode_bytes(name)
            type, fields, fieldcmts = ret
            type = Event.encode_bytes(type)
            fields = Event.encode_bytes(fields)
            fieldcmts = Event.encode_bytes(fieldcmts)

            type_info = ida_typeinf.tinfo_t()
            type_info.deserialize(ti, type, fields, fieldcmts)
            type_info.set_numbered_type(ti, ordinal, 0, name)

        ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
Exemple #10
0
    def __call__(self):
        local_type = []
        for t in self.local_type:
            if t is not None:
                local_type.append((
                    Event.encode_bytes(t[0]),
                    Event.encode_bytes(t[1]),
                    Event.encode_bytes(t[2]),
                ))
            else:
                local_type.append(None)

        missing_ord = len(local_type) - ida_typeinf.get_ordinal_qty(None) + 1
        if missing_ord > 0:
            ida_typeinf.alloc_type_ordinals(None, missing_ord)

        for i, t in enumerate(local_type):
            if t is not None:
                cur_tinfo = ida_typeinf.tinfo_t()
                cur_tinfo.deserialize(None, t[0], t[1])
                cur_tinfo.set_numbered_type(None, i + 1, 0, t[2])
            else:
                ida_typeinf.del_numbered_type(None, i + 1)
        ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
Exemple #11
0
 def alloc_oridinal(target_ordinal):
     # Get_ordinal_qty() will return (current max ordinal + 1)
     missing_ord = (target_ordinal - ida_typeinf.get_ordinal_qty(None) +
                    1)
     if missing_ord > 0:
         ida_typeinf.alloc_type_ordinals(None, missing_ord)
Exemple #12
0
    def export(self):
        """
        Show an export dialog to export symbols and header file for given
        IDB.
        :return: None
        """
        class ExportForm(Form):
            def __init__(self):
                description = '''
                <h2>Export</h2>

                Select a directory to export IDB data into.
                '''

                Form.__init__(self,
                              r"""BUTTON YES* Save
                              Export
                              {StringLabel}
                              <#Symbols#Symbols filename:{iSymbolsFilename}>
                              <#C Header#C Header filename:{iHeaderFilename}>
                              <#ifdef_macro#ifdef'ed:{iIfdef}>
                              <#Select dir#Browse for dir:{iDir}>
                              """, {
                                  'iDir': Form.DirInput(),
                                  'StringLabel':
                                      Form.StringLabel(description,
                                                       tp=Form.FT_HTML_LABEL),
                                  'iSymbolsFilename': Form.StringInput(
                                      value='symbols.txt'),
                                  'iHeaderFilename': Form.StringInput(
                                      value='fa_structs.h'),
                                  'iIfdef': Form.StringInput(
                                      value='FA_STRUCTS_H'),
                              })
                self.__n = 0

            def OnFormChange(self, fid):
                return 1

        form = ExportForm()
        form, args = form.Compile()
        ok = form.Execute()
        if ok == 1:
            # save symbols
            symbols_filename = os.path.join(form.iDir.value,
                                            form.iSymbolsFilename.value)
            with open(symbols_filename, 'w') as f:
                results = IdaLoader.extract_all_user_names(None)
                for k, v in sorted(results.items()):
                    f.write('{} = 0x{:08x};\n'.format(k, v))

            # save c header
            idati = ida_typeinf.get_idati()
            c_header_filename = os.path.join(form.iDir.value,
                                             form.iHeaderFilename.value)

            consts_ordinal = None
            ordinals = []
            for ordinal in range(1, ida_typeinf.get_ordinal_qty(idati) + 1):
                ti = ida_typeinf.tinfo_t()
                if ti.get_numbered_type(idati, ordinal):
                    if ti.get_type_name() == 'FA_CONSTS':
                        # convert into macro definitions
                        consts_ordinal = ordinal
                    elif ti.get_type_name() in ('__va_list_tag',
                                                'va_list'):
                        continue
                    elif '$' in ti.get_type_name():
                        # skip deleted types
                        continue
                    else:
                        ordinals.append(str(ordinal))

            with open(c_header_filename, 'w') as f:
                ifdef_name = form.iIfdef.value.strip()

                if len(ifdef_name) > 0:
                    f.write('#ifndef {ifdef_name}\n'
                            '#define {ifdef_name}\n\n'
                            .format(ifdef_name=ifdef_name))

                if consts_ordinal is not None:
                    consts = re.findall('\s*(.+?) = (.+?),',
                                        idc.print_decls(
                                            str(consts_ordinal), 0))
                    for k, v in consts:
                        f.write('#define {} ({})\n'.format(k, v))

                    # ida exports using this type
                    f.write('#define _BYTE char\n')
                    f.write('\n')

                structs_buf = idc.print_decls(','.join(ordinals),
                                              idc.PDF_DEF_BASE)

                for struct_type, struct_name in re.findall(
                        r'(struct|enum) .*?([a-zA-Z0-9_\-]+?)\s+\{',
                        structs_buf):
                    f.write(
                        'typedef {struct_type} {struct_name} {struct_name};\n'
                        .format(struct_type=struct_type,
                                struct_name=struct_name))

                structs_buf = structs_buf.replace('__fastcall', '')
                f.write('\n')
                f.write(structs_buf)
                f.write('\n')

                if len(ifdef_name) > 0:
                    f.write('#endif // {ifdef_name}\n'
                            .format(ifdef_name=ifdef_name))

        form.Free()
Exemple #13
0
 def update_local_types_map(self):
     for i in range(1,
                    ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())):
         t = ImportLocalType(i)
         self.local_type_map[i] = t