Ejemplo n.º 1
0
Archivo: ESigs.py Proyecto: newmsk/ESig
    def handle_dll_calls(self):
        dll_call_count = ida_bytes.get_dword(self.E_info_entry_ea +
                                             self.dll_call_count_offset)
        dll_call_lib_names_ea = ida_bytes.get_dword(
            self.E_info_entry_ea + self.dll_call_lib_names_offset)
        dll_call_func_names_ea = ida_bytes.get_dword(
            self.E_info_entry_ea + self.dll_call_func_names_offset)
        self.dll_calls = Dll_calls(dll_call_lib_names_ea,
                                   dll_call_func_names_ea, dll_call_count)

        ida_auto.auto_wait()

        ea = ida_name.get_name_ea(idaapi.BADADDR, "j__krnl_MCallDllCmd")
        code_fref_eas = []
        fref_ea = ida_xref.get_first_fcref_to(ea)

        while fref_ea != idaapi.BADADDR:
            code_fref_eas.append(fref_ea)
            fref_ea = ida_xref.get_next_cref_to(ea, fref_ea)

        for ref_ea in code_fref_eas:
            #get prev mov instruction
            prev_ins_ea = idaapi.get_item_head(ref_ea - 1)
            ins = ida_lines.generate_disasm_line(prev_ins_ea,
                                                 ida_lines.GENDSM_REMOVE_TAGS)
            if (ins.startswith("mov     eax,")):
                index = ida_bytes.get_dword(prev_ins_ea + 1)
                cmt = self.dll_calls[index]
                ida_bytes.set_cmt(ref_ea, cmt, False)
Ejemplo n.º 2
0
def set_repeated_comment(address, repeated_comment):
    assert type(repeated_comment) == str
    if is_function_start(address):
        pfn = ida_funcs.get_func(address)
        ida_funcs.set_func_cmt(pfn, repeated_comment, 1)
    else:
        ida_bytes.set_cmt(address, repeated_comment, 1)
Ejemplo n.º 3
0
 def run(self, arg=0):
     print("running")
     ea = idc.get_screen_ea()
     if idc.GetOpType(ea, 1) != 5:   # Immediate
         return
     value = idc.GetOperandValue(ea, 1) & 0xffffffff
     ida_bytes.set_cmt(ea, windows_ioctl_decode(value), 1)
     return
Ejemplo n.º 4
0
def restore_x(unique_name=None, start=None):
    ea = ida_kernwin.get_screen_ea()

    # signature
    if not unique_name:
        if not start:
            seg = ida_segment.getseg(ea)
            start = seg.start_ea
        sig_bytes = ida_bytes.get_bytes(start, SIGNATURE_SIZE)
        sig_hash = hashlib.md5(sig_bytes).hexdigest()
        unique_name = sig_hash

    if not start:
        seg = ida_segment.getseg(ea)
        start = seg.start_ea

    if MD5_hash_data_file and os.path.isfile(MD5_hash_data_file):
        with open(MD5_hash_data_file, "rb") as ifile:
            received_data = pickle.loads(ifile.read())
            saved_data = received_data

            print("dumpDyn::restore\n\
            Name: {}\n\
            Restore address: {}\n".format(unique_name, hex(start)))

            # (start_addr, end_addr, names, comms, bpts, funcs)
            if unique_name in saved_data:
                current_data = saved_data[unique_name]

                # restore names
                names = current_data[2]

                for name in names:
                    # names: (rel_addr, name, is_code)
                    ida_name.set_name(start + name[0], name[1])
                    flags = ida_bytes.get_flags(start + name[0])
                    if name[2] and not ida_bytes.is_code(flags):
                        ida_auto.auto_make_code(start + name[0])

                # restore comments
                # comms: (rel_addr, TYPE, comment)
                comms = current_data[3]
                for comm in comms:
                    # 0:MakeComm and 1:MakeRptCmt
                    ida_bytes.set_cmt(start + comm[0], comm[2], comm[1])

                # restore breakpoints
                # bpts: (rel_addr, size, type)
                bpts = current_data[4]
                for bpt in bpts:
                    ida_dbg.add_bpt(start + bpt[0], bpt[1], bpt[2])

                # restore functions
                funcs_addr = current_data[5]
                for addr in funcs_addr:
                    ida_auto.auto_make_proc(start + addr)  # make code & func
Ejemplo n.º 5
0
 def make_rpt():
     """
         Inserting a comment
     """
     ida_bytes.set_cmt(
         comment["address"],
         comment["data"].encode(
             'ascii',
             'replace'),
         1)
Ejemplo n.º 6
0
    def rcomment(self, value):
        """
            Setter which allow to set the value of the repeatable comment.

            :param value: The comment to set.
            :type value: :class:`str`
        """
        if value is None:
            value = ""
        ida_bytes.set_cmt(self.ea, value, 1)
Ejemplo n.º 7
0
def load_struc(struc: StructureData, p: int, path: str) -> int:
    """
    Load the given structure into the current IDA Pro at the given offset.

    Example::

        load_struc(sections[0].data, 0x0, 'foo-section')

    Args:
      struc (wasm.Structure): the structure to load.
      p (int): the effective address at which to load.
      path (str): the namespaced name of the given structure.

    Returns:
      int: the next offset following the loaded structure.
    """
    for field in get_fields(struc):
        # build names like: `sections:2:payload:entries:0:module_str`
        name = path + ':' + field.name

        # recurse into nested structures
        if is_struc(field.value):
            p = load_struc(cast(StructureData, field.value), p, name)

        # recurse into lists of structures
        elif (isinstance(field.value, list) and len(field.value) > 0
              and is_struc(field.value[0])):

            for i, v in enumerate(field.value):
                p = load_struc(v, p, name + ':' + str(i))

        # emit primitive types
        else:
            # add annotations like follows:
            #
            #     imports:002D sections:2:payload:entries:0:module_len         <--- Add line prior to element.
            #     imports:002D                 db 3                    ;; 0x3  <--- Render element for human.
            #     imports:002E sections:2:payload:entries:0:module_str
            #     imports:002E                 db 0x65 ;; e            ;; env  <--- Pull out strings and lists nicely.
            #     imports:002F                 db 0x6E ;; n
            #     imports:0030                 db 0x76 ;; v

            # add line prior to element
            ida_lines.update_extra_cmt(p, ida_lines.E_PREV + 0, name)

            # if primitive integer element, set it as such
            if isinstance(field.value, int):
                MakeN(p, field.size)

            # add comment containing human-readable representation
            ida_bytes.set_cmt(p, format_value(name, field.value), 0)

            p += field.size

    return p
Ejemplo n.º 8
0
def import_line_comments(comments, sections):
    """
    Import line comments

    :param comments: Dict containing line comments
    :param sections: Dict containing section info
    """

    for addr, comment in comments.items():
        addr = adjust_addr(sections, int(addr))
        ida_bytes.set_cmt(addr, comment, 0)
Ejemplo n.º 9
0
def main():
    for segstart, segend, segname in enum_segments():
        for head in idautils.Heads(segstart, segend):
            if not is_code(head):
                continue

            # pattern:
            #
            #   lea     rax, unk_6BDF88
            #   mov     [rsp+0], rax
            #   mov     qword ptr [rsp+8], 40h
            if ida_ua.ua_mnem(head) != "lea":
                continue

            next_head = ida_bytes.next_head(head, idc.BADADDR)
            if ida_ua.ua_mnem(next_head) != "mov":
                continue

            next_head2 = ida_bytes.next_head(next_head, idc.BADADDR)
            if ida_ua.ua_mnem(next_head2) != "mov":
                continue

            dst = idc.get_operand_value(head, 1)
            if idc.get_segm_name(dst) not in (".rdata", "UPX1"):
                continue

            size = idc.get_operand_value(next_head2, 1)

            if size > 0x100:
                continue
            if size <= 2:
                continue

            buf = ida_bytes.get_bytes(dst, size)
            if not buf:
                continue

            if b"\x00" in buf:
                continue

            try:
                s = buf.decode("ascii")
            except UnicodeDecodeError:
                continue

            print("string pointer: 0x%x -> 0x%x: %s" % (head, dst, s))
            ida_bytes.del_items(dst, 1)
            ida_bytes.create_data(dst, idc.FF_BYTE, 1, idc.BADADDR)
            ida_bytes.set_cmt(dst, s, True)
            ida_name.set_name(dst, "s_%x" % (dst))
Ejemplo n.º 10
0
def add_comments(info_for_pcs, selections):
    for pc, info in info_for_pcs.items():
        comment = ida_bytes.get_cmt(pc, 0)
        if (not comment):
            comment = ""
        if (selections['add_tids'] and selections['add_seqs']):
            label_portion = "(seq #, thread ID) = {}".format(sorted(list(info)))
        elif (selections['add_tids']):
            label_portion = "thread ID = {}".format(sorted(list(info)))
        else:
            label_portion = "seq # = {}".format(sorted(list(info)))
        if (comment == ""):
            comment = label_portion
        else:
            comment = comment + ", " + label_portion
        ida_bytes.set_cmt(pc, comment, 0)
def main():
    for segstart, segend, segname in enum_segments():
        if segname not in ('.rdata', 'UPX1' ):
            continue

        for src, dst, psize in find_pointers(segstart, segend):
            if idc.get_segm_name(dst) not in (".rdata", "UPX0"):
                continue
                
            if psize == 8:
                size = ida_bytes.get_qword(src + 0x8)
            else:
                size = ida_bytes.get_dword(src + 0x4)
                
            if size > 0x100:
                continue
            if size <= 2:
                continue

            buf = ida_bytes.get_bytes(dst, size)
            if not buf:
                continue

            if b"\x00" in buf:
                continue

            try:
                s = buf.decode("ascii")
            except UnicodeDecodeError:
                continue

            print("string pointer: 0x%x -> 0x%x: %s" % (src, dst, s))

            ida_bytes.del_items(src, 1)
            ida_bytes.set_cmt(dst, s, True)

            # pointer
            ida_bytes.del_items(src, psize)
            ida_bytes.create_data(src, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR)
            # this doesn't seem to always work :-(
            idc.op_plain_offset(src, -1, 0)
            ida_name.set_name(src, "s_%x" % (src))
            ida_bytes.set_cmt(src, s, True)

            # size
            ida_bytes.del_items(src + psize, psize)
            ida_bytes.create_data(src + psize, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR)
Ejemplo n.º 12
0
def set_ida_comment(addr, cmt, decompiled=False):
    func = ida_funcs.get_func(addr)
    if not func:
        l.info(f"No function found at {addr}")
        return False

    rpt = 1

    # function comment
    if addr == func.start_ea:
        idc.set_func_cmt(addr, cmt, rpt)
        return True

    # a comment in decompilation
    elif decompiled:
        try:
            cfunc = idaapi.decompile(addr)
        except Exception:
            ida_bytes.set_cmt(addr, cmt, rpt)
            return True

        eamap = cfunc.get_eamap()
        decomp_obj_addr = eamap[addr][0].ea
        tl = idaapi.treeloc_t()

        # try to set a comment using the cfunc obj and normal address
        for a in [addr, decomp_obj_addr]:
            tl.ea = a
            for itp in range(idaapi.ITP_SEMI, idaapi.ITP_COLON):
                tl.itp = itp
                cfunc.set_user_cmt(tl, cmt)
                cfunc.save_user_cmts()
                cfunc.refresh_func_ctext()

                # attempt to set until it does not fail (orphan itself)
                if not cfunc.has_orphan_cmts():
                    cfunc.save_user_cmts()
                    return True
                cfunc.del_orphan_cmts()

        return False

    # a comment in disassembly
    else:
        ida_bytes.set_cmt(addr, cmt, rpt)
        return True
Ejemplo n.º 13
0
def write_reg_info(index: dict):
    """Write register info as line comment at instruction pointed to by the program counter and
    change focus to that location

    :param index: _index.json JSON data
    """

    cmt = ""
    for reg, val in index["regs"].items():
        cmt += f"{reg.ljust(6)} : {hex(val)}\n"

    progctr = get_pc_by_arch(index)
    if progctr is None:
        raise ArchNotSupportedError(
            "Architecture not fully supported, skipping register status comment"
        )
    ida_bytes.set_cmt(progctr, cmt, 0)
    ida_kernwin.jumpto(progctr)
Ejemplo n.º 14
0
def main():
    filename, _ = QFileDialog.getOpenFileName(None, "Open file", ".",
                                              "CSV Files(*.csv)")
    if filename == "":
        return

    processes = set()
    input_file = open(filename, "r")
    reader = csv.reader(input_file)
    next(reader, None)
    for row in reader:
        processes.add((row[0], int(row[1])))
    input_file.close()

    selected_pid = ProcessSelectDialog.selectProcess(processes)
    # N.B.:  0 is a valid process ID
    if (None == selected_pid):
        return

    semantic_labels = read_semantic_labels(filename + ".semantic_labels")

    snapshot = ida_loader.snapshot_t()
    snapshot.desc = "Before ida_taint2.py @ %s" % (datetime.datetime.now())
    ida_kernwin.take_database_snapshot(snapshot)

    input_file = open(filename, "r")
    reader = csv.reader(input_file)
    labels_for_pc = {}
    # skip header
    next(reader, None)
    for row in reader:
        pid = int(row[1])
        pc = int(row[2], 16)
        label = int(row[3])

        try:
            label = semantic_labels[label]
        except KeyError:
            pass

        if pid != selected_pid:
            continue
        fn = ida_funcs.get_func(pc)
        if not fn:
            continue
        fn_start = fn.start_ea
        fn_name = ida_funcs.get_func_name(fn_start)
        if "TAINTED" not in fn_name:
            ida_name.set_name(fn_start, "TAINTED_" + fn_name,
                              ida_name.SN_CHECK)
        fn.color = FUNC_COLOR
        ida_nalt.set_item_color(pc, INST_COLOR)
        if pc not in labels_for_pc:
            labels_for_pc[pc] = set()
        labels_for_pc[pc].add(label)
    input_file.close()

    for pc, labels in labels_for_pc.items():
        comment = ida_bytes.get_cmt(pc, 0)
        if not comment:
            comment = ""
        label_portion = "taint labels = {}".format(list(labels))
        if comment == "":
            comment = label_portion
        else:
            comment += ", " + label_portion
        ida_bytes.set_cmt(pc, comment, 0)
Ejemplo n.º 15
0
 def _on_commentchanged(self, ea, comment, repeatable):
     ida_bytes.set_cmt(ea, Unicoder.encode(comment), repeatable)
Ejemplo n.º 16
0
 def __call__(self):
     ida_bytes.set_cmt(self.ea, Event.encode(self.comment), self.rptble)
Ejemplo n.º 17
0
 def __call__(self):
     ida_bytes.set_cmt(self.ea, self.comment, self.rptble)
Ejemplo n.º 18
0
def set_comment(address, comment):
    assert type(comment) == str

    # Always succeeds
    ida_bytes.set_cmt(address, comment, 0)
Ejemplo n.º 19
0
    def apply_signatures(self, start_addr: int, end_addr: int) -> None:
        total_objs = len(self._signatures)

        idaapi.msg('Applying obj symbols...\n')

        objs_list = dict()

        for sig in self._signatures:
            bytes_data = sig.get_sig()

            low_entropy = (not bytes_data.is_bios_call()) and (sig.get_entropy() < self.min_entropy)

            labels = sig.get_labels()

            search_addr = start_addr

            while search_addr < end_addr:
                addr, _ = masked_search(search_addr, end_addr, bytes_data.get_bytes(), bytes_data.get_masks())

                if addr == idaapi.BADADDR:
                    break

                if not sig.is_applied():
                    objs_list[sig.get_name()] = (addr, sig.get_entropy())

                for lb in labels:
                    lb_name = lb[0]
                    lb_offs = lb[1]

                    if lb_name == '':  # removed label
                        continue

                    lb_addr = addr + lb_offs

                    if ida_bytes.is_unknown(ida_bytes.get_flags(lb_addr) and not low_entropy and not (sig.is_applied() and self.only_first)):
                        ida_auto.auto_make_code(lb_addr)

                    is_func = not lb_name.startswith('loc_')
                    new_name = '%s_' % sig.get_name().replace('.', '_')
                    new_lb_name = lb_name.replace('text_', new_name).replace('loc_', new_name)
                    new_lb_name = ('_%s' % new_lb_name) if ('0' <= new_lb_name[0] <= '9') else new_lb_name

                    if not low_entropy and not (sig.is_applied() and self.only_first) and not self.has_non_default_name(lb_addr, new_lb_name):
                        SigApplier.set_function(lb_addr, new_lb_name, is_func, False)
                        idaapi.msg('Symbol %s at 0x%08X\n' % (new_lb_name, lb_addr))
                    else:
                        prev_comment = ida_bytes.get_cmt(lb_addr, False)

                        prev_comment = ('%s\n' % prev_comment) if prev_comment else ''

                        new_comment = 'Possible %s/%s' % (sig.get_name(), new_lb_name)

                        if prev_comment.find(new_comment) == -1:
                            ida_bytes.set_cmt(lb_addr, '%s%s' % (prev_comment, new_comment), False)
                            idaapi.msg('Possible symbol %s at 0x%08X\n' % (new_lb_name, lb_addr))

                sig.set_applied(True)

                search_addr = addr + 4

        idaapi.msg('Applied OBJs for %s: %d/%d:\n' % (self.short_lib_name, len(objs_list), total_objs))

        for k, v in objs_list.items():
            idaapi.msg('\t0x%08X: %s, %.02f entropy\n' % (v[0], k, v[1]))
Ejemplo n.º 20
0
        if (inst2 != None) and (inst2.get_canon_mnem() == "mov"):
            inst3 = idautils.DecodePreviousInstruction(inst2.ea)
            if (inst3 != None) and (inst3.get_canon_mnem() == "lea"):
                length = inst.Op2.value
                data_addr = inst3.Op2.addr

    return data_addr, length


def decrypt_string(data, key):
    crypt = b64decode(data)
    plain = "".join(chr(ord(c) ^ ord(k)) for c, k in izip(crypt, cycle(key)))
    return b64decode(plain)


arch = 64 if idaapi.get_inf_structure().is_64bit() else 32
ea = ida_name.get_name_ea(idaapi.BADADDR, "main.decodeString")
key_addr = ida_name.get_name_ea(idaapi.BADADDR, "main.encoderKey")
key = ida_bytes.get_bytes(ida_bytes.get_dword(key_addr),
                          ida_bytes.get_dword(key_addr + arch / 8))

for xref in idautils.CodeRefsTo(ea, True):
    inst = idautils.DecodeInstruction(xref)
    if (inst != None) and (inst.get_canon_mnem() == "call"):
        data_addr, length = get_params(xref)
        data = ida_bytes.get_bytes(data_addr, length)
        decrypted_str = decrypt_string(data, key)
        print "0x{:08x} -> 0x{:x}[0x{:x}] = \"{}\"".format(
            xref, data_addr, length, decrypted_str)
        ida_bytes.set_cmt(xref, decrypted_str, False)
Ejemplo n.º 21
0
"""
    This file is part of Polichombr
        (c) ANSSI-FR 2018

    Description:
        Semi automated test that add some data in the IDA database,
        that should be reflected in the second database
"""

import ida_name, ida_bytes, ida_struct
import idc

ida_name.set_name(0x401000, "TESTFUNCTION")
ida_bytes.set_cmt(0x40100A, "TEST COMMENT", 0)
ida_bytes.set_cmt(0x40100F, "TEST RPT COMMENT", 1)

struct_1 = ida_struct.add_struc(0, "TESTSTRUCT1")

struct_pointer = ida_struct.get_struc(struct_1)

ida_struct.add_struc_member(struct_pointer, "TESTMEMBER", 0, 0, None, 0)

idc.SetType(0x401000, "int __cdecl start(char *lpszTestArg);")
Ejemplo n.º 22
0
def define_item(address, size, shortdesc, comment):
    del_items(address, True)
    create_data(address, (word_flag() if size == IOREG_16 else byte_flag()),
                size, ida_netnode.BADNODE)
    set_name(address, shortdesc)
    set_cmt(address, comment, True)
Ejemplo n.º 23
0
def set_ida_comment(addr, cmt, rpt, func_cmt=False):
    if func_cmt:
        print(f"SETTING FUNC COMMENT: '{cmt}'")
        idc.set_func_cmt(addr, cmt, rpt)
    else:
        ida_bytes.set_cmt(addr, cmt, rpt)
Ejemplo n.º 24
0
def do_import():
    db = {}
    module = idaapi.get_root_filename().lower()
    base = idaapi.get_imagebase()

    file = ida_kernwin.ask_file(0,
                                "x64dbg database|{}".format(get_file_mask()),
                                "Import database")
    if not file:
        return
    print("Importing database {}".format(file))

    with open(file) as dbdata:
        db = json.load(dbdata)

    count = 0
    labels = db.get("labels", [])
    for label in labels:
        try:
            if label["module"] != module:
                continue
            ea = int(label["address"], 16) + base
            name = label["text"]
            ida_name.set_name(ea, str(name), 0)
            count += 1
        except:
            pass
    print("{:d}/{:d} label(s) imported".format(count, len(labels)))

    count = 0
    comments = db.get("comments", [])
    for comment in comments:
        try:
            if comment["module"] != module:
                continue
            ea = int(comment["address"], 16) + base
            name = comment["text"]
            ida_bytes.set_cmt(ea, str(name), 1)
            count += 1
        except:
            pass
    print("{:d}/{:d} comment(s) imported".format(count, len(comments)))

    count = 0
    breakpoints = db.get("breakpoints", [])
    for breakpoint in breakpoints:
        try:
            if breakpoint["module"] != module:
                continue
            ea = int(breakpoint["address"], 16) + base
            bptype = breakpoint["type"]
            if bptype == BPNORMAL:
                count += 1
                ida_dbg.add_bpt(ea, 1, BPT_DEFAULT)
            elif bptype == BPHARDWARE:
                titantype = int(breakpoint["titantype"], 16)
                hwtype = (titantype >> 4) & 0xF
                if hwtype == UE_HARDWARE_EXECUTE:
                    hwtype = BPT_EXEC
                elif hwtype == UE_HARDWARE_WRITE:
                    hwtype = BPT_WRITE
                elif hwtype == UE_HARDWARE_READWRITE:
                    hwtype = BPT_RDWR
                else:
                    continue
                hwsize = titantype & 0xF
                if hwsize == UE_HARDWARE_SIZE_1:
                    hwsize = 1
                elif hwsize == UE_HARDWARE_SIZE_2:
                    hwsize = 2
                elif hwsize == UE_HARDWARE_SIZE_4:
                    hwsize = 4
                elif hwsize == UE_HARDWARE_SIZE_8:
                    hwsize = 8
                else:
                    continue
                count += 1
                ida_dbg.add_bpt(ea, hwsize, hwtype)
        except:
            pass
    print("{:d}/{:d} breakpoint(s) imported".format(count, len(breakpoints)))

    print("Done!")
Ejemplo n.º 25
0
 def make_rpt():
     """
         Inserting a comment
     """
     ida_bytes.set_cmt(comment["address"],
                       comment["data"].encode('ascii', 'replace'), 1)
Ejemplo n.º 26
0
def load_file(f, neflags, format):
    f.seek(0)

    ida_idp.set_processor_type("metapc", ida_idp.SETPROC_LOADER)
    MGROUPStart = 0
    magic = f.read(2)

    if magic == MZ_HEADER_MAGIC:
        f.seek(0x22)
        MGROUPStart = DW(f) * 16
        f.seek(MGROUPStart)
        magic = f.read(2)

    headerSize = DW(f)
    segmentDataAlignment = DW(f)
    nextExeOff = DD(f)
    SegDataOff = DD(f)

    f.file2base(MGROUPStart, 0, SegDataOff, True)
    ida_segment.add_segm(0, 0, 0x50, "HEADER", "MODULE")
    f.seek(MGROUPStart + 2)

    headerSize = rnDW(f, "headerSize", MGROUPStart)
    segmentDataAlignment = rnDW(f, "segmentDataAlignment", MGROUPStart)
    nextExeOff = rnDD(f, "nextExeOff", MGROUPStart)
    SegDataOff = rnDD(f, "SegDataOff", MGROUPStart)

    ResDataOff = rnDD(f, "ResDataOff", MGROUPStart)
    flags = rnDW(f, "flags", MGROUPStart)
    version = rnDB(f, "version", MGROUPStart)
    revision = rnDB(f, "revision", MGROUPStart)
    AutoDataSegNo = rnDW(f, "AutoDataSegNo", MGROUPStart)
    HeapSize = rnDW(f, "HeapSize", MGROUPStart)
    StackSize = rnDW(f, "StackSize", MGROUPStart)
    StartProc = rnDD(f, "StartProc", MGROUPStart)
    LoadProc = rnDD(f, "LoadProc", MGROUPStart)
    FreeProc = rnDD(f, "FreeProc", MGROUPStart)
    nSegments = rnDW(f, "nSegments", MGROUPStart)
    pSegTable = rnDW(f, "pSegTable", MGROUPStart)
    cbResTab = rnDW(f, "cbResTab", MGROUPStart)
    pResTab = rnDW(f, "pResTab", MGROUPStart)
    cbEntTab = rnDW(f, "cbEntTab", MGROUPStart)
    pEntTab = rnDW(f, "pEntTab", MGROUPStart)
    cbNamTab = rnDW(f, "cbNamTab", MGROUPStart)
    pNamTab = rnDW(f, "pNamTab", MGROUPStart)
    cbStrTab = rnDW(f, "cbStrTab", MGROUPStart)
    pStrTab = rnDW(f, "pStrTab", MGROUPStart)
    cbNRNamTab = rnDW(f, "cbNRNamTab", MGROUPStart)
    pNRNamTab = rnDW(f, "pNRNamTab", MGROUPStart)

    ida_segment.add_segm(0, pSegTable,
                         pSegTable + (nSegments * SEG_STRUCT_SIZE), "SEGTABLE",
                         "MODULE")
    ida_segment.add_segm(0, pResTab, pResTab + cbResTab, "RESOURCES", "MODULE")
    ida_segment.add_segm(0, pEntTab, pEntTab + cbEntTab, "ENTTABLE", "MODULE")
    ida_segment.add_segm(0, pNamTab, pNamTab + cbNamTab, "ENTNAME", "MODULE")
    ida_segment.add_segm(0, pStrTab, pStrTab + cbStrTab, "IMPORTS", "MODULE")
    ida_segment.add_segm(0, pNRNamTab, pNRNamTab + cbNRNamTab, "NRENTNAME",
                         "MODULE")

    #parse segtable
    segentsid = defSEGENT()
    base = SegDataOff // 16

    importCount = 0
    for i in range(nSegments):
        segEntStart = pSegTable + i * SEG_STRUCT_SIZE
        ida_bytes.create_struct(segEntStart, SEG_STRUCT_SIZE, segentsid)
        segStart = ida_bytes.get_word(segEntStart + 2)
        segLen = ida_bytes.get_word(segEntStart + 4)
        segImports = ida_bytes.get_word(segEntStart + 6)
        importCount += segImports
        f.file2base(MGROUPStart + SegDataOff + segStart * 16,
                    SegDataOff + segStart * 16,
                    SegDataOff + (segStart + segLen) * 16, True)

        segBase = (base + segStart) * 16
        #segmentDef = ida_segment.segment_t()
        #segmentDef.start_ea = segBase
        #segmentDef.end_ea = (base+segStart+segLen)*16
        #ida_segment.set_selector()
        print(base + segStart)
        ida_segment.add_segm(base + segStart, segBase,
                             (base + segStart + segLen) * 16, "", "", 0)
        sel = ida_segment.find_selector(base + segStart)
        seg = ida_segment.getseg(segBase)
        ida_segment.set_segm_addressing(seg, 0)
        segtable[i] = seg
        segimportstable[i] = segImports
        if i + 1 == AutoDataSegNo:
            ida_segment.set_segm_name(seg, "DATA", 0)
            ida_segment.set_segm_class(seg, "DATA", 0)
            dataSel = sel
        else:
            ida_segment.set_segm_name(seg, "TEXT", 0)
            ida_segment.set_segm_class(seg, "CODE", 0)
            if AutoDataSegNo == 0:
                dataSel = sel
    ida_segregs.set_default_dataseg(dataSel)

    #parse enttable
    pENT = pEntTab
    currord = 1
    while pENT < pEntTab + cbEntTab:
        bundleCount = ida_bytes.get_byte(pENT)
        bundleFlags = ida_bytes.get_byte(pENT + 1)
        if bundleCount == 0 and bundleFlags == 0:
            break
        pENT += 2
        for i in range(bundleCount):
            if bundleFlags == 0xFF:
                ordFlags = ida_bytes.get_byte(pENT)
                if ordFlags & 0x80:
                    toexport.append(currord)
                segNo = ida_bytes.get_byte(pENT + 3)
                segOff = ida_bytes.get_word(pENT + 4)

                enttable[currord] = (segtable[segNo - 1].start_ea // 16,
                                     segOff)
                pENT += 6
            else:
                ordFlags = ida_bytes.get_byte(pENT)
                if ordFlags & 0x80:
                    toexport.append(currord)
                segOff = ida_bytes.get_word(pENT + 1)
                enttable[currord] = (segtable[bundleFlags - 1].start_ea // 16,
                                     segOff)
                pENT += 3

            currord += 1

    modulename = readPASSTR(pNamTab)

    make_entry(StartProc, modulename + "_start")
    make_entry(LoadProc, modulename + "_load")
    make_entry(FreeProc, modulename + "_free")

    #export named ordinals
    namedordtable = loadExportsF(f)

    for i in toexport:
        if i in namedordtable:
            name = namedordtable[i]
        else:
            name = "Ordinal" + str(i)
        (base, off) = enttable[i]
        addr = base * 16 + off
        ida_entry.add_entry(i, addr, name, 1)

    #process imports

    ida_segment.add_segm(0xF000, 0xF0000, 0xF0000 + importCount * 2, "IMPORTS",
                         "XTRN", 0)

    import_ea = 0xF0000

    for seg in segtable:
        segend = segtable[seg].end_ea
        f.seek(MGROUPStart + segend)

        for i in range(segimportstable[seg]):
            count = DB(f)
            mode = DB(f)
            relocStart = DW(f)
            module = DW(f)
            proc = DW(f)

            if (module == 0xFFFF):
                (base, off) = enttable[proc]
            else:
                modulestr = readPASSTR(pStrTab + module)
                if (proc & 0x8000) != 0:  # read by ord
                    ordinal = proc & 0x7FFF
                    procname = modulestr + "_Ordinal" + str(ordinal)
                    if not modulestr in importedmodules:
                        if os.path.isfile(modulestr + ".EXE"):
                            importedmodules[modulestr] = loadExports(
                                modulestr + ".EXE")
                        else:
                            filename = ida_kernwin.ask_file(
                                0, modulestr + ".EXE",
                                "Select file to name exports")
                            if filename is not None and os.path.isfile(
                                    filename):
                                importedmodules[modulestr] = loadExports(
                                    filename)
                            else:
                                importedmodules[modulestr] = None
                    if modulestr in importedmodules and (
                            importedmodules[modulestr] is not None
                    ) and ordinal in importedmodules[modulestr]:
                        procname = importedmodules[modulestr][ordinal]
                else:
                    procname = readPASSTR(pStrTab + proc)
                ida_bytes.create_data(import_ea, ida_bytes.FF_WORD, 2,
                                      ida_idaapi.BADADDR)
                ida_name.force_name(import_ea, procname)
                ida_bytes.set_cmt(import_ea, "Imported from " + modulestr, 1)
                base = 0xF000
                off = import_ea - 0xF0000
                import_ea += 2

            for xx in range(count):
                next = ida_bytes.get_word(segtable[seg].start_ea + relocStart)
                if mode == 0x20:
                    ida_bytes.put_word(segtable[seg].start_ea + relocStart + 2,
                                       base)
                    ida_bytes.put_word(segtable[seg].start_ea + relocStart,
                                       off)
                elif mode == 0x10:
                    ida_bytes.put_word(segtable[seg].start_ea + relocStart,
                                       off)
                elif mode == 0x0:
                    ida_bytes.put_word(segtable[seg].start_ea + relocStart,
                                       base)
                relocStart = next

            #print "import %d: seg %d mode %s count %d relocStart %s module %s proc %s" % (i, seg, hex(mode), count, hex(relocStart), modulestr, hex(proc))

    return 1