Beispiel #1
0
def create_load_seg(li,
                    start,
                    end,
                    modificationType,
                    name,
                    segmentType="CODE"):
    # add_segm(0, start, end, name, "")
    seg = idaapi.segment_t()
    seg.start_ea = start
    seg.end_ea = end
    seg.bitness = 1  # 32-bit
    idaapi.add_segm_ex(seg, name, "", 0)
    # AddSeg(start, end, 0, 1, idaapi.saAbs, idaapi.scPub)
    offset = li.tell()
    # li.file2base(offset, start, end, 0)
    data = li.read(end - start)

    # put_dword

    if modificationType == 2:
        byteswapped = bytearray([0]) * len(data)
        byteswapped[0::2] = data[1::2]
        byteswapped[1::2] = data[0::2]
        # idaapi.mem2base(str(byteswapped), start, end)
        for i in range(0, end - start):
            idaapi.put_byte(start + i, byteswapped[i])
    else:
        idaapi.mem2base(data, start, end)
Beispiel #2
0
def load_file(li, neflags, format):
    
    # Select the PC processor module
    idaapi.set_processor_type("BPF", SETPROC_ALL|SETPROC_FATAL)
    
    buf = read_whole_file(li, 8)
    if not buf:
        return 0

    start = 0x0
    seg = idaapi.segment_t()
    size = len(buf)
    end  = start + size
    
    # Create the segment
    seg.startEA = start
    seg.endEA   = end
    seg.bitness = 1 # 32-bit
    idaapi.add_segm_ex(seg, "bpf_c", "CODE", 0)

    # Copy the bytes
    idaapi.mem2base(buf, start, end)

    # add entry point
    idaapi.add_entry(start, start, "start", 1) 

    # add comment to beginning of disassembly
    idaapi.describe(start, True, "BPF bytecode disassembly")

    # Mark for analysis
    AutoMark(start, AU_CODE)

    setup_enums()
    return 1
Beispiel #3
0
def load_file(li, neflags, format):
    if format != "NeoGeo 68k loader":
        return 0

    idaapi.set_processor_type("68000", SETPROC_ALL | SETPROC_FATAL)

    idaapi.add_segm(0, 0x000000, 0x0FFFFF, "ROM", "CODE")
    idaapi.add_segm(0, 0x100000, 0x10F2FF, "WRAM", "DATA")
    idaapi.add_segm(0, 0x10F300, 0x10FFFF, "BIOSRAM", "DATA")
    idaapi.add_segm(0, 0x200000, 0x2FFFFF, "PORT", "DATA")
    idaapi.add_segm(0, 0x300000, 0x3FFFFF, "IO", "DATA")
    idaapi.add_segm(0, 0x400000, 0x401FFF, "PALETTES", "DATA")
    idaapi.add_segm(0, 0x800000, 0xBFFFFF, "MEMCARD", "DATA")
    idaapi.add_segm(0, 0xC00000, 0xC1FFFF, "SYSROM", "DATA")
    idaapi.add_segm(0, 0xD00000, 0xD0FFFF, "BRAM", "DATA")

    li.seek(0, 2)
    size = li.tell()
    li.seek(0)
    file_data = li.read(size)
    idaapi.mem2base(file_data, 0, 0x100000)

    name_long(0x000000, "InitSP")
    name_long(0x000004, "InitPC")

    idaapi.do_unknown(0x3C0000, 1)
    idaapi.doByte(0x3C0000, 1)
    idaapi.set_name(0x3C0000, "REG_VRAMADDR")
    #idaapi.set_cmt(0x3C0000, "Pouet.", 1)

    return 1
def load_file(li, neflags, format):
    idaapi.set_processor_type("n2t-hack", idaapi.SETPROC_ALL|idaapi.SETPROC_FATAL)

    li.seek(0)
    hack_data = li.read(li.size())

    hack_instructions = [int(instruction, 2) for instruction in hack_data.splitlines()]
    hack_instructions_bin = ''.join(struct.pack("!H", instruction) for instruction in hack_instructions)
    print "Found %d hack instructions" % len(hack_instructions)


    seg = idaapi.segment_t()
    seg.startEA= 0
    seg.endEA = len(hack_instructions)

    seg.align = idaapi.saAbs
    seg.comb = idaapi.scPriv
    seg.bitness = 0 # 16-bit

    idaapi.add_segm_ex(seg, "Hack-ROM", "CODE", idaapi.ADDSEG_OR_DIE)

    # This method seems to change in next versions.
    #idaapi.mem2base(hack_instructions_bin, 0, -1)
    idaapi.mem2base(hack_instructions_bin, 0)

    return 1
Beispiel #5
0
def load_file(li, neflags, format):

    # Select the PC processor module
    idaapi.set_processor_type("EVM", SETPROC_ALL | SETPROC_FATAL)

    # TODO: detect and emulate contract creation code
    li.seek(0)
    buf = li.read(li.size())
    if not buf:
        return 0

    if buf[0:2] == '0x':
        print "Detected hex"
        new_buf = buf[2:].strip().rstrip()
        buf_set = set()
        for c in new_buf:
            buf_set.update(c)
        hex_set = set(list('0123456789abcdef'))
        if buf_set <= hex_set:  # subset
            print "Replacing original buffer with hex decoded version"
            buf = new_buf.decode('hex')

    # Load all shellcode into different segments
    start = 0x0
    seg = idaapi.segment_t()
    size = len(buf)
    end = start + size

    # Create the segment
    seg.startEA = start
    seg.endEA = end
    seg.bitness = 1  # 32-bit
    idaapi.add_segm_ex(seg, "evm", "CODE", 0)

    # TODO: make segments for stack, memory, storage

    # Copy the bytes
    idaapi.mem2base(buf, start, end)

    # check for swarm hash and make it data instead of code
    swarm_hash_address = buf.find('ebzzr0')
    if swarm_hash_address != -1:
        print "Swarm hash detected, making it data"
        for i in range(swarm_hash_address - 1, swarm_hash_address + 42):
            MakeByte(i)
        ida_bytes.set_cmt(swarm_hash_address - 1, "swarm hash", True)
    # add entry point
    idaapi.add_entry(start, start, "start", 1)

    # add comment to beginning of disassembly
    idaapi.describe(start, True, "EVM bytecode disassembly")

    # Mark for analysis
    AutoMark(start, AU_CODE)

    #setup_enums()
    return 1
Beispiel #6
0
    def create_segments(self, li):
        li.seek(0x800)

        code = li.read(self.rom_size)

        idaapi.add_segm(0, 0x80000000, self.rom_addr, 'RAM', 'DATA')
        idc.set_default_sreg_value(0x80000000, 'ds', 0)
        seg = idaapi.getseg(0x80000000)
        seg.perm = idaapi.SEGPERM_EXEC | idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE

        idaapi.mem2base(code, self.rom_addr, 0x800)
        idaapi.add_segm(0, self.rom_addr, self.rom_addr + self.rom_size, 'CODE', 'CODE')
        idc.set_default_sreg_value(self.rom_addr, 'ds', 0)
        seg = idaapi.getseg(self.rom_addr)
        seg.perm = idaapi.SEGPERM_EXEC | idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE

        if self.data_addr != 0:
            idaapi.add_segm(0, self.data_addr, self.data_addr + self.data_size, '.data', 'DATA')
            idc.set_default_sreg_value(self.data_addr, 'ds', 0)
            seg = idaapi.getseg(self.data_addr)
            seg.perm = idaapi.SEGPERM_EXEC | idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE

        if self.bss_addr != 0:
            idaapi.add_segm(0, self.bss_addr, self.bss_addr + self.bss_size, '.bss', 'BSS')
            idc.set_default_sreg_value(self.bss_addr, 'ds', 0)
            seg = idaapi.getseg(self.bss_addr)
            seg.perm = idaapi.SEGPERM_EXEC | idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE

        idaapi.add_segm(0, self.rom_addr + self.rom_size, 0x80200000, 'RAM', 'DATA')
        idc.set_default_sreg_value(self.rom_addr + self.rom_size, 'ds', 0)
        seg = idaapi.getseg(self.rom_addr + self.rom_size)
        seg.perm = idaapi.SEGPERM_EXEC | idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE

        idaapi.add_segm(0, 0x1F800000, 0x1F800400, 'CACHE', 'DATA')
        idaapi.add_segm(0, 0x1F800400, 0x1F801000, 'UNK1', 'XTRN')

        self.add_mem_ctrl1()
        self.add_mem_ctrl2()
        self.add_periph_io()
        self.add_int_ctrl()
        self.add_dma()
        self.add_timers()
        self.add_cdrom_regs()
        self.add_gpu_regs()
        self.add_mdec_regs()
        self.add_spu_voices()
        self.add_spu_ctrl_regs()
        self.create_got_fix()

        idaapi.cvar.inf.start_ss = idaapi.cvar.inf.start_cs = 0
        idaapi.cvar.inf.start_ip = idaapi.cvar.inf.start_ea = self.init_pc
        idaapi.cvar.inf.start_sp = self.sp_base + self.sp_offset
Beispiel #7
0
    def _AddSegment(self, name, base_address, data=None):
        """Add a segment to the IDB with some basic options set for convenience."""
        s = idaapi.segment_t()

        s.startEA = base_address
        s.endEA = base_address + len(data)
        s.bitness = 1  # 32-bit
        s.align = idaapi.saRelByte
        s.comb = idaapi.scPub
        s.sel = idaapi.setup_selector(0)

        # We mark the segments as code, as we know these are loops in memory
        idaapi.add_segm_ex(s, name, "CODE",
                           idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
        idaapi.mem2base(data, base_address)
def map(ea, size, newea, **kwds):
    """Map `size` bytes of data from `ea` into a new segment at `newea`.

    The keyword `name` can be used to name the segment.
    """

    # grab the file offset and the data we want
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise E.ReadOrWriteError(
            u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to read {:#x} bytes from {:#x}."
            .format(
                __name__, ea, size, newea,
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '',
                size, ea))

    # rebase the data to the new address
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise E.DisassemblerError(
            u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to remap {:#x}:{:+#x} to {:#x}."
            .format(
                __name__, ea, size, newea,
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '',
                ea, size, newea))

    # now we can create the new segment
    return new(newea, size, kwds.get("name", "map_{:x}".format(ea)))
def AddSegment(name, base_address, data):
    """Add a segment to the IDB with some basic options set for convenience."""
    s = idaapi.segment_t()
    
    s.startEA = base_address
    s.endEA = base_address + len(data)
    
    s.bitness = 1 # 32-bit
    
    s.align = idaapi.saRelByte
    s.comb = idaapi.scPub
    
    s.sel = idaapi.setup_selector(0)
    
    idaapi.add_segm_ex(s, name, None, idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
    idaapi.mem2base(data, base_address)
Beispiel #10
0
def load_file(li, neflags, format):
    """
    Load the file into database

    @param li: a file-like object which can be used to access the input data
    @param neflags: options selected by the user, see loader.hpp
    @return: 0-failure, 1-ok
    """

    # Select the PC processor module
    idaapi.set_processor_type("metapc", ida_idp.SETPROC_LOADER)

    # read MBR into buffer
    li.seek(0, os.SEEK_SET)
    buf = li.read(li.size())

    seg = idaapi.segment_t()
    start = 0x7C00

    size = len(buf)
    end = start + size

    # Create the segment
    seg.start_ea = start
    seg.end_ea = end
    seg.bitness = 0  # 16-bit
    idaapi.add_segm_ex(seg, "seg0", "CODE", 0)

    # Copy the bytes
    idaapi.mem2base(buf, start, end)

    # add entry point
    idaapi.add_entry(start, start, "start", 1)

    strid = add_struct_def()
    idaapi.set_name(start + 0x1BE, "MBR_PARTITION_TABLE", idaapi.SN_CHECK)
    str_size = idaapi.get_struc_size(strid)
    idaapi.create_struct(start + 0x1BE, str_size, strid)

    idaapi.set_name(510, "MBR_SIGN", idaapi.SN_CHECK)

    # Mark for analysis
    AutoMark(start, AU_CODE)

    load_debugger("bochs", 0)

    return 1
def AddSegment(name, base_address, data):
    """Add a segment to the IDB with some basic options set for convenience."""
    s = idaapi.segment_t()

    s.startEA = base_address
    s.endEA = base_address + len(data)

    s.bitness = 1  # 32-bit

    s.align = idaapi.saRelByte
    s.comb = idaapi.scPub

    s.sel = idaapi.setup_selector(0)

    idaapi.add_segm_ex(s, name, None,
                       idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
    idaapi.mem2base(data, base_address)
Beispiel #12
0
def load_file(li, neflags, format):
    
    """
    Load the file into database

    @param li: a file-like object which can be used to access the input data
    @param neflags: options selected by the user, see loader.hpp
    @return: 0-failure, 1-ok
    """

    # Select the PC processor module
    idaapi.set_processor_type("metapc", SETPROC_ALL|SETPROC_FATAL)

    buf = read_whole_file(li)
    r = extract_pdf_shellcode(buf)
    if not r:
        return 0

    # Load all shellcode into different segments
    start = 0x10000
    seg = idaapi.segment_t()
    for id, ver, n, sc in r:
        size = len(sc)
        end  = start + size
        
        # Create the segment
        seg.startEA = start
        seg.endEA   = end
        seg.bitness = 1 # 32-bit
        idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0)

        # Copy the bytes
        idaapi.mem2base(sc, start, end)

        # Mark for analysis
        AutoMark(start, AU_CODE)

        # Compute next loading address
        start = ((end / 0x1000) + 1) * 0x1000

    # Select the bochs debugger
    LoadDebugger("bochs", 0)

    return 1
Beispiel #13
0
def load_file(li, neflags, format):
    """
    Load the file into database

    @param li: a file-like object which can be used to access the input data
    @param neflags: options selected by the user, see loader.hpp
    @return: 0-failure, 1-ok
    """

    # Select the PC processor module
    idaapi.set_processor_type("metapc", SETPROC_LOADER)

    buf = read_whole_file(li)
    r = extract_pdf_shellcode(buf)
    if not r:
        return 0

    # Load all shellcode into different segments
    start = 0x10000
    seg = idaapi.segment_t()
    for id, ver, n, sc in r:
        size = len(sc)
        end = start + size

        # Create the segment
        seg.start_ea = start
        seg.end_ea = end
        seg.bitness = 1  # 32-bit
        idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0)

        # Copy the bytes
        idaapi.mem2base(sc, start, end)

        # Mark for analysis
        AutoMark(start, AU_CODE)

        # Compute next loading address
        start = ((end / 0x1000) + 1) * 0x1000

    # Select the bochs debugger
    load_debugger("bochs", 0)

    return 1
Beispiel #14
0
def load_file(li, neflags, format):
    """Load the file into database
    
    Args:
        li: a file-like object which can be used to access the input data
        neflags: options selected by the user, see loader.hpp
    Returns: 
        0-failure
        1-ok
    """

    idaapi.set_processor_type("sh4", SETPROC_ALL | SETPROC_FATAL)

    li.seek(0, idaapi.SEEK_END)
    size = li.tell()
    li.seek(0)
    rom_data = li.read(size)

    s = idaapi.segment_t()
    s.startEA = 0
    s.endEA = size
    s.bitness = 1  # 32-bit
    s.align = idaapi.saRelByte
    s.comb = idaapi.scPub
    s.sel = idaapi.setup_selector(0)

    idaapi.add_segm_ex(s, "ROM", "DATA",
                       idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_OR_DIE)
    idaapi.mem2base(rom_data, 0)

    headr = JasperThe2kCat()
    headr.AnotateHeader(binary_file=li)
    headr.MakeStrings(binary_file=li)
    gentries = gameEntries()

    gentries.readGameLoops(binary_file=li)
    gentries.CreateSegments(binary_file=li)
    gentries.makeDWordTables()
    gentries.makeDWordTables(start_address=0x2a0, end_address=0x1000)
    gentries.addIDA_entry()

    print("load ok")
    return 1
Beispiel #15
0
def map(ea, size, newea, **kwds):
    """Map ``size`` bytes of data from ``ea`` into a new segment at ``newea``.
    ``name`` can be used to name the segment.
    """
    fpos,data = idaapi.get_fileregion_offset(ea),database.read(ea, size)
    if len(data) != size:
        raise ValueError("{:s}.map({:x}, {:#x}, {:x}) : Unable to read {:#x} bytes from {:#x}".format(__name__, ea, size, newea, size, ea))
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise ValueError("{:s}.map({:x}, {:#x}, {:x}) : Unable to remap {:#x}:{:+#x} to {:#x}".format(__name__, ea, size, newea, ea, size, newea))
    return create(newea, size, kwds.get("name', 'map_{:x}".format(ea)))
Beispiel #16
0
def map(ea, size, newea, **kwds):
    '''Map /size/ bytes of data from /ea/ into a new segment at /newea/

    /name/ can be used to name the segment.
    '''
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise Exception, "Unable to read %x bytes from %x" % (size, ea)
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise Exception, "Unable to remap %x:+%x to %x" % (ea, size, newea)
    return create(newea, size, kwds.get('name', 'map_%x' % ea))
Beispiel #17
0
def map(ea, size, newea, **kwds):
    '''Map /size/ bytes of data from /ea/ into a new segment at /newea/

    /name/ can be used to name the segment.
    '''
    fpos,data = idaapi.get_fileregion_offset(ea),database.read(ea, size)
    if len(data) != size:
        raise Exception, "Unable to read %x bytes from %x"% (size, ea)
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise Exception, "Unable to remap %x:+%x to %x"% (ea, size, newea)
    return create(newea, size, kwds.get('name', 'map_%x'% ea))
Beispiel #18
0
def map(ea, size, newea, **kwds):
    """Map `size` bytes of data from `ea` into a new segment at `newea`.

    The keyword `name` can be used to name the segment.
    """
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise E.ReadOrWriteError(
            "{:s}.map({:#x}, {:+#x}, {:#x}) : Unable to read {:#x} bytes from {:#x}."
            .format(__name__, ea, size, newea, size, ea))
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise E.DisassemblerError(
            "{:s}.map({:#x}, {:+#x}, {:#x}) : Unable to remap {:#x}:{:+#x} to {:#x}."
            .format(__name__, ea, size, newea, ea, size, newea))
    return new(newea, size, kwds.get("name', 'map_{:x}".format(ea)))
Beispiel #19
0
def map(ea, size, newea, **kwds):
    """Map `size` bytes of data from `ea` into a new segment at `newea`.

    The keyword `name` can be used to name the segment.
    """

    # grab the file offset and the data we want
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise E.ReadOrWriteError(u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to read {:#x} bytes from {:#x}.".format(__name__, ea, size, newea, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', size, ea))

    # rebase the data to the new address
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise E.DisassemblerError(u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to remap {:#x}:{:+#x} to {:#x}.".format(__name__, ea, size, newea, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', ea, size, newea))

    # now we can create the new segment
    return new(newea, size, kwds.get("name", "map_{:x}".format(ea)))
Beispiel #20
0
    def load_one_file(li, options, idx, basename=None):
        bypass_plt = OPT_BYPASS_PLT in options

        f = load_nxo(li)

        if idx == 0:
            if f.armv7:
                idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT)
            else:
                idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_64BIT)

            idc.SetCharPrm(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3)
            idaapi.set_compiler_id(idaapi.COMP_GNU)
            idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1)
            # don't create tails
            idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_FTAIL)

        if OPT_LOAD_31_BIT in options:
            loadbase = 0x8000000
            step = 0x1000000
        elif f.armv7:
            loadbase = 0x60000000
            step = 0x10000000
        else:
            loadbase = 0x7100000000
            step = 0x100000000
        loadbase += idx * step

        f.binfile.seek(0)
        as_string = f.binfile.read(f.bssoff)
        idaapi.mem2base(as_string, loadbase)

        seg_prefix = basename if basename is not None else ''
        for start, end, name, kind in f.sections:
            if name.startswith('.got'):
                kind = 'CONST'
            idaapi.add_segm(0, loadbase+start, loadbase+end, seg_prefix+name, kind)
            segm = idaapi.get_segm_by_name(seg_prefix+name)
            if kind == 'CONST':
                segm.perm = idaapi.SEGPERM_READ
            elif kind == 'CODE':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC
            elif kind == 'DATA':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'BSS':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            idaapi.update_segm(segm)
            idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2)

        # do imports
        # TODO: can we make imports show up in "Imports" window?
        undef_count = 0
        for s in f.symbols:
            if not s.shndx and s.name:
                undef_count += 1
        last_ea = max(loadbase + end for start, end, name, kind in f.sections)
        undef_entry_size = 8
        undef_ea = ((last_ea + 0xFFF) & ~0xFFF) + undef_entry_size # plus 8 so we don't end up on the "end" symbol

        undef_seg = basename + '.UNDEF' if basename is not None else 'UNDEF'
        idaapi.add_segm(0, undef_ea, undef_ea+undef_count*undef_entry_size, undef_seg, 'XTRN')
        segm = idaapi.get_segm_by_name(undef_seg)
        segm.type = idaapi.SEG_XTRN
        idaapi.update_segm(segm)
        for i,s in enumerate(f.symbols):
            if not s.shndx and s.name:
                idc.MakeQword(undef_ea)
                idaapi.do_name_anyway(undef_ea, s.name)
                s.resolved = undef_ea
                undef_ea += undef_entry_size
            elif i != 0:
                assert s.shndx
                s.resolved = loadbase + s.value
                if s.name:
                    if s.type == STT_FUNC:
                        idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
                    else:
                        idaapi.do_name_anyway(s.resolved, s.name)

            else:
                # NULL symbol
                s.resolved = 0

        funcs = set()
        for s in f.symbols:
            if s.name and s.shndx and s.value:
                if s.type == STT_FUNC:
                    funcs.add(loadbase+s.value)
                    symend = loadbase+s.value+s.size
                    if Dword(symend) != 0:
                        funcs.add(symend)

        got_name_lookup = {}
        for offset, r_type, sym, addend in f.relocations:
            target = offset + loadbase
            if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32):
                if not sym:
                    print 'error: relocation at %X failed' % target
                else:
                    idaapi.put_long(target, sym.resolved)
            elif r_type == R_ARM_RELATIVE:
                idaapi.put_long(target, idaapi.get_long(target) + loadbase)
            elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64):
                idaapi.put_qword(target, sym.resolved + addend)
                if addend == 0:
                    got_name_lookup[offset] = sym.name
            elif r_type == R_AARCH64_RELATIVE:
                idaapi.put_qword(target, loadbase + addend)
                if addend < f.textsize:
                    funcs.add(loadbase + addend)
            else:
                print 'TODO r_type %d' % (r_type,)
            ida_make_offset(f, target)

        for func, target in f.plt_entries:
            if target in got_name_lookup:
                addr = loadbase + func
                funcs.add(addr)
                idaapi.do_name_anyway(addr, got_name_lookup[target])

        if not f.armv7:
            funcs |= find_bl_targets(loadbase, loadbase+f.textsize)

            if bypass_plt:
                plt_lookup = f.plt_lookup
                for pco in xrange(0, f.textsize, 4):
                    pc = loadbase + pco
                    d = Dword(pc)
                    if (d & 0x7c000000) == (0x94000000 & 0x7c000000):
                        imm = d & 0x3ffffff
                        if imm & 0x2000000:
                            imm |= ~0x1ffffff
                        if 0 <= imm <= 2:
                            continue
                        target = (pc + imm * 4) - loadbase
                        if target in plt_lookup:
                            new_target = plt_lookup[target] + loadbase
                            new_instr = (d & ~0x3ffffff) | (((new_target - pc) / 4) & 0x3ffffff)
                            idaapi.put_long(pc, new_instr)

            for pco in xrange(0, f.textsize, 4):
                pc = loadbase + pco
                d = Dword(pc)
                if d == 0x14000001:
                    funcs.add(pc + 4)

        for pc, _ in f.eh_table:
            funcs.add(loadbase + pc)

        for addr in sorted(funcs, reverse=True):
            idaapi.auto_make_proc(addr)

        return 1
Beispiel #21
0
    def load_file(li, neflags, fmt):
        idaapi.set_processor_type(
            "arm", idaapi.SETPROC_LOADER_NON_FATAL | idaapi.SETPROC_LOADER)
        idc.set_inf_attr(idc.INF_LFLAGS,
                         idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_64BIT)
        idc.set_inf_attr(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3)
        idaapi.set_compiler_id(idaapi.COMP_GNU)
        idaapi.add_til('gnulnx_arm64', 1)

        # Get the meta offset
        meta_ofs = find_kernel_meta(li)
        assert meta_ofs != -1

        # Read important offsets.
        li.seek(meta_ofs + 0x40)
        text_base, init_base, init_base2, kernel_end = struct.unpack(
            '<QQQQ', li.read(0x20))

        # Load the init segment.
        li.seek(0)
        init_data = li.read(KERNEL_INIT_SIZE)

        idaapi.mem2base(init_data, init_base)

        # Emulate the kernel init segment to determine interesting extents
        emu = Emulator()
        emu.run_emulator(init_base, init_data)

        builder = SegmentBuilder()
        builder.add_segment(init_base, KERNEL_INIT_SIZE, '.init', 'RWX')
        text_phys = 0
        text_size = 0
        ro_size = 0
        rw_size = 0
        core_dram_mappings = []
        for (virt_addr, size, phys_addr, attr) in emu.mappings:
            print('%x, %x, %x, %x' % (virt_addr, size, phys_addr, attr))
            assert attr in [
                0x4000000000078B, 0x78B, 0x6000000000078B, 0x6000000000070B,
                0x60000000000607, 0x60000000000709
            ]
            if attr == 0x78B or attr == 0x4000000000078B:
                # .text
                assert virt_addr == text_base
                builder.add_segment(virt_addr, size, '.text', 'CODE')
                li.seek(phys_addr - init_base)
                idaapi.mem2base(li.read(size), virt_addr)
                text_phys = phys_addr
                text_size = size
            elif attr == 0x6000000000078B:
                # .rodata
                assert text_size != 0
                assert virt_addr == text_base + text_size
                builder.add_segment(virt_addr, size, '.rodata', 'CONST')
                li.seek(phys_addr - init_base)
                idaapi.mem2base(li.read(size), virt_addr)
                ro_size = size
            elif attr == 0x6000000000070B and virt_addr == text_base + text_size + ro_size:
                assert text_size != 0
                assert ro_size != 0
                # .rwdata
                builder.add_segment(virt_addr, size, '.rwdata', 'DATA')
                li.seek(phys_addr - init_base)
                idaapi.mem2base(li.read(size), virt_addr)
                rw_size = size
            elif attr == 0x60000000000607:
                # IO
                DEVICES = {
                    (0x40000000, 0x40000): '.iram',
                    (0x50041000, 0x01000): '.gicd',
                    (0x50042000, 0x01000): '.gicc',
                    (0x60001000, 0x01000): '.semaphore',
                    (0x60004000, 0x01000): '.primary_ictlr',
                    (0x60006000, 0x01000): '.clkrst',
                    (0x60007000, 0x01000): '.flow_ctlr',
                    (0x6000F000, 0x01000): '.evp',
                    (0x70006000, 0x01000): '.uart',
                    (0x7000E000, 0x01000): '.rtc_pmc',
                    (0x70016000, 0x02000): '.atomics',
                    (0x70019000, 0x01000): '.mc',
                    (0x7001C000, 0x01000): '.mc0',
                    (0x7001D000, 0x01000): '.mc1',
                }
                assert (phys_addr, size) in DEVICES.keys()
                name = DEVICES[(phys_addr, size)]
                builder.add_segment(virt_addr, size, name, 'IO')
            elif attr == 0x6000000000070B:
                # Kernel DRAM
                if phys_addr == (emu.ttbr & ~0xFFF) and size == 0x1000:
                    builder.add_segment(virt_addr, size, '.ttbr1', 'DATA')
                else:
                    core_dram_mappings.append(
                        (virt_addr, size, phys_addr, attr))
            else:
                # Linear DRAM
                assert attr == 0x60000000000709
                idaapi.add_segm(0, virt_addr, virt_addr + size, '.linear_dram',
                                'DATA', idaapi.ADDSEG_SPARSE)
                segm = idaapi.get_segm_by_name('.linear_dram')
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
                idaapi.update_segm(segm)
                idaapi.set_segm_addressing(segm, 2)

        assert len(core_dram_mappings) % 5 == 0
        if len(core_dram_mappings) // 5 == 3:
            # 1.0.0-style core local mappings
            assert core_dram_mappings[
                0 + 0][2] == core_dram_mappings[0 + 3][2] - 0x2000
            assert core_dram_mappings[
                0 + 3][2] == core_dram_mappings[0 + 6][2] - 0x2000
            assert core_dram_mappings[
                0 + 6][2] == core_dram_mappings[0 + 9][2] - 0x2000
            assert core_dram_mappings[0 + 0][2] == core_dram_mappings[0 +
                                                                      12][2]

            assert core_dram_mappings[
                1 + 0][2] == core_dram_mappings[1 + 3][2] - 0x2000
            assert core_dram_mappings[
                1 + 3][2] == core_dram_mappings[1 + 6][2] - 0x2000
            assert core_dram_mappings[
                1 + 6][2] == core_dram_mappings[1 + 9][2] - 0x2000
            assert core_dram_mappings[1 + 0][2] == core_dram_mappings[1 +
                                                                      12][2]

            assert core_dram_mappings[
                2 + 0][2] == core_dram_mappings[2 + 3][2] - 0x1000
            assert core_dram_mappings[
                2 + 3][2] == core_dram_mappings[2 + 6][2] - 0x1000
            assert core_dram_mappings[
                2 + 6][2] == core_dram_mappings[2 + 9][2] - 0x1000
            assert core_dram_mappings[2 + 0][2] == core_dram_mappings[2 +
                                                                      12][2]

            builder.add_segment(core_dram_mappings[0][0], 0xA000 * 4,
                                '.core_local_regions', 'DATA')
            builder.add_segment(core_dram_mappings[3 * 4 + 0][0],
                                core_dram_mappings[3 * 4 + 0][1],
                                '.current_common_stack', 'DATA')
            builder.add_segment(core_dram_mappings[3 * 4 + 1][0],
                                core_dram_mappings[3 * 4 + 1][1],
                                '.current_main_stack', 'DATA')
            builder.add_segment(core_dram_mappings[3 * 4 + 2][0],
                                core_dram_mappings[3 * 4 + 2][1],
                                '.current_context', 'DATA')
        elif len(core_dram_mappings) // 5 == 4:
            # 3.0.0-style core local mappings
            assert core_dram_mappings[
                0 + 0][2] == core_dram_mappings[0 + 4][2] - 0x2000
            assert core_dram_mappings[
                0 + 4][2] == core_dram_mappings[0 + 8][2] - 0x2000
            assert core_dram_mappings[
                0 + 8][2] == core_dram_mappings[0 + 12][2] - 0x2000
            assert core_dram_mappings[0 + 0][2] == core_dram_mappings[0 +
                                                                      16][2]

            assert core_dram_mappings[
                1 + 0][2] == core_dram_mappings[1 + 4][2] - 0x2000
            assert core_dram_mappings[
                1 + 4][2] == core_dram_mappings[1 + 8][2] - 0x2000
            assert core_dram_mappings[
                1 + 8][2] == core_dram_mappings[1 + 12][2] - 0x2000
            assert core_dram_mappings[1 + 0][2] == core_dram_mappings[1 +
                                                                      16][2]

            assert core_dram_mappings[
                2 + 0][2] == core_dram_mappings[2 + 4][2] - 0x2000
            assert core_dram_mappings[
                2 + 4][2] == core_dram_mappings[2 + 8][2] - 0x2000
            assert core_dram_mappings[
                2 + 8][2] == core_dram_mappings[2 + 12][2] - 0x2000
            assert core_dram_mappings[2 + 0][2] == core_dram_mappings[2 +
                                                                      16][2]

            assert core_dram_mappings[
                3 + 0][2] == core_dram_mappings[3 + 4][2] - 0x1000
            assert core_dram_mappings[
                3 + 4][2] == core_dram_mappings[3 + 8][2] - 0x1000
            assert core_dram_mappings[
                3 + 8][2] == core_dram_mappings[3 + 12][2] - 0x1000
            assert core_dram_mappings[3 + 0][2] == core_dram_mappings[3 +
                                                                      16][2]

            builder.add_segment(core_dram_mappings[0][0], 0xE000 * 4,
                                '.core_local_regions', 'DATA')
            builder.add_segment(core_dram_mappings[4 * 4 + 0][0],
                                core_dram_mappings[4 * 4 + 0][1],
                                '.current_common_stack', 'DATA')
            builder.add_segment(core_dram_mappings[4 * 4 + 1][0],
                                core_dram_mappings[4 * 4 + 1][1],
                                '.current_main_stack', 'DATA')
            builder.add_segment(core_dram_mappings[4 * 4 + 2][0],
                                core_dram_mappings[4 * 4 + 2][1],
                                '.current_idle_stack', 'DATA')
            builder.add_segment(core_dram_mappings[4 * 4 + 3][0],
                                core_dram_mappings[4 * 4 + 3][1],
                                '.current_context', 'DATA')

        seg_prefix = ''
        for start, end, name, kind in builder.flatten():
            idaapi.add_segm(0, start, end, seg_prefix + name, kind)
            segm = idaapi.get_segm_by_name(seg_prefix + name)
            if kind == 'CONST':
                segm.perm = idaapi.SEGPERM_READ
            elif kind == 'CODE':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC
            elif kind == 'DATA':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'BSS':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'RWX':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE | idaapi.SEGPERM_EXEC
            elif kind == 'IO':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            idaapi.update_segm(segm)
            idaapi.set_segm_addressing(segm, 2)

        # Set vector types as code.
        for i, ctx in enumerate(['sp0', 'spx', 'a64', 'a32']):
            for j, kind in enumerate(['synch', 'irq', 'fiq', 'serror']):
                addr = emu.vbar + 0x200 * i + 0x80 * j
                name = '%s_%s_exception' % (kind, ctx)
                idc.create_insn(addr)
                idc.set_name(addr, name)

        # Set .init as code.
        idc.create_insn(init_base)
        idc.set_name(init_base, 'crt0')

        # Set text start as code.
        idc.create_insn(text_base)
        idc.set_name(text_base, 'HorizonKernelMain')

        # Patch movk instructions to be better understandable by ida.
        li.seek(text_phys - init_base)
        text = li.read(text_size)
        ro_rw = li.read(ro_size + rw_size)
        patch_movk_to_adrp(text_base, text, ro_rw, emu.mappings)

        return 1
Beispiel #22
0
def readToSegment(li, src, size, target, name):
        li.seek(src)
        data = li.read(size)
        idaapi.mem2base(data, target)
        AddSeg(target,target + size,0,1,idaapi.saRelWord, idaapi.scPub)
        RenameSeg(target, name)
Beispiel #23
0
def load_file(li, neflags, format):
    if format != "NeoGeo 68k loader":
        return 0

    idaapi.set_processor_type("68000", SETPROC_ALL | SETPROC_FATAL)

    idaapi.add_segm(0, 0x000000, 0x0FFFFF, "ROM", "CODE")
    idaapi.add_segm(0, 0x100000, 0x10F2FF, "WRAM", "DATA")
    idaapi.add_segm(0, 0x10F300, 0x10FFFF, "BIOSRAM", "DATA")
    idaapi.add_segm(0, 0x200000, 0x2FFFFF, "PORT", "DATA")
    idaapi.add_segm(0, 0x300000, 0x3FFFFF, "IO", "DATA")
    idaapi.add_segm(0, 0x400000, 0x401FFF, "PALETTES", "DATA")
    idaapi.add_segm(0, 0x800000, 0xBFFFFF, "MEMCARD", "DATA")
    idaapi.add_segm(0, 0xC00000, 0xC1FFFF, "SYSROM", "DATA")
    idaapi.add_segm(0, 0xD00000, 0xD0FFFF, "BRAM", "DATA")

    map_io_registers()

    li.seek(0, 2)
    file_size = li.tell()
    li.seek(0)

    # read p1 rom
    file_data = li.read(0x100000)
    file_remain = file_size - 0x100000

    idaapi.mem2base(file_data, 0, 0x100000)

    # read p2 rom
    bank2_seg_offset = 0x01000000
    bank2_seg_index = 0

    while file_remain > 0:
        bank2_seg_start = bank2_seg_offset + 0x200000
        bank2_seg_end = bank2_seg_start + 0x2FFFFF

        idaapi.add_segm(0, bank2_seg_start, bank2_seg_end,
                        "BANK2_%d" % bank2_seg_index, "DATA")

        bytes_to_read = file_remain
        if bytes_to_read > 0x100000:
            bytes_to_read = 0x100000

        file_data = li.read(bytes_to_read)
        idaapi.mem2base(file_data, bank2_seg_start,
                        bank2_seg_start + len(file_data))

        bank2_seg_offset += 0x01000000
        bank2_seg_index += 1
        file_remain -= bytes_to_read

    # http://ajworld.net/neogeodev/beginner/
    name_long(0x000000, "InitSP")
    name_long(0x000004, "InitPC")
    name_long(0x000008, "BusError")
    name_long(0x00000C, "AddressError")
    name_long(0x000010, "IllegalInstruction")
    name_long(0x000014, "DivByZero")
    name_long(0x000018, "CHK")
    name_long(0x00001C, "TRAPV")
    name_long(0x000020, "PrivilegeViolation")
    name_long(0x000024, "Trace")
    name_long(0x000028, "Line1010Emu")
    name_long(0x00002C, "Line1111Emu")
    name_array(0x000030, "Reserved0", 0xC)
    name_long(0x000003C, "UnintializedInterruptVec")
    name_array(0x000040, "Reserved1", 0x20)
    name_long(0x000060, "VirtualInterrupt")
    name_long(0x000064, "Interrupt1")
    name_long(0x000068, "Interrupt2")
    name_long(0x00006C, "Interrupt3")
    name_long(0x000070, "Interrupt4")
    name_long(0x000074, "Interrupt5")
    name_long(0x000078, "Interrupt6")
    name_long(0x00007C, "Interrupt7")
    name_dword_array(0x000080, "Traps", 0x10)
    name_array(0x0000C0, "Reserved2", 0x40)

    # Neo-Geo header
    # https://wiki.neogeodev.org/index.php?title=68k_program_header
    idc.create_strlit(0x000100, 0x000107)
    idaapi.set_name(0x000100, "Magic")
    name_byte(0x000107, "SysVersion")
    name_word(0x000108, "GameID")
    name_long(0x00010A, "ProgramSize")
    name_long(0x00010E, "BackupRAMPtr")
    name_word(0x000112, "BackupRAMSize")
    name_byte(0x000114, "EyecatchFlag")
    name_byte(0x000115, "EyecatchSpriteBank")
    name_long(0x000116, "MenuJP")
    name_long(0x00011A, "MenuUS")
    name_long(0x00011E, "MenuEU")
    name_code(0x000122, "Routine_USER", 6)
    name_code(0x000128, "Routine_PLAYER_START", 6)
    name_code(0x00012E, "Routine_DEMO_END", 6)
    name_code(0x000134, "Routine_COIN_SOUND", 6)
    name_array(0x00013A, "Unknown0", 0x48)
    name_long(0x000182, "CartridgeRecognitionCodePtr")
    name_long(0x000186, "Unknown1")
    name_long(0x00018A, "Unknown2")
    name_long(0x00018E, "MenuES")  # Spanish

    # BIOS RAM
    set_name_with_comment(0x10FD80, "BIOS_SYSTEM_MODE", "0x00 : System"
                          "0x80 : Game")

    set_name_with_comment(0x10FD82, "BIOS_MVS_FLAG", "0 : HOME/AES\n"
                          "1 : MVS")

    set_name_with_comment(
        0x10FDAE, "BIOS_USER_REQUEST", "0 : Startup initialization\n"
        "1 : Eye-catcher\n"
        "2 : Demo Game / Game\n"
        "3 : Title Display")

    set_name_with_comment(
        0x10FDAF, "BIOS_USER_MODE", "Current game status.\n"
        "0 : init/boot\n"
        "1 : title/demo\n"
        "2 : game")

    set_name_with_comment(
        0x10FEC5, "BIOS_TITLE_MODE",
        "Newer games set this to 1 in their command 3 USER subroutine.\n"
        "It prevents the system ROM from calling command 3 twice after game over if credits are already in the system.\n"
    )

    #idaapi.del_items(0x3C0000)
    # VRAM

    set_name_with_comment(
        0x3C0000, "REG_VRAMADDR",
        "sets the VRAM address for the next read/write operation.")
    set_name_with_comment(0x3C0002, "REG_VRAMRW", "the data read or to write.")
    set_name_with_comment(
        0x3C0004, "REG_VRAMMOD",
        "the signed value automatically added to the VRAM address after a write."
    )

    set_name_with_comment(
        0x3C000C, "LSPC_IRQ_ACK",
        "IRQ acknowledgement register.\nbit2 : Ack.VBlank | bit 1 : Ack.HBlank | bit 0 : IRQ3"
    )

    idaapi.set_name(0xC00444, "SYSTEM_RETURN")
    idaapi.set_name(0xC0044A, "SYSTEM_IO")

    idaapi.set_name(0xD00100, "BOARD_CORRUPTED")

    #idaapi.set_cmt(0x3C0000, "Pouet.", 1)
    return 1
Beispiel #24
0
 def _AddData(self, name, base_address, data=None):
     idaapi.mem2base(data, base_address)
Beispiel #25
0
def load_file(li, neflags, format):
    # Check the format we've been asked to load
    if format != FORMAT_NAME:
        return 0

    # Datatrak 68K - set processor type
    idaapi.set_processor_type("68000", SETPROC_ALL | SETPROC_FATAL)

    # Add segments
    idaapi.add_segm(0, 0x000000, 0x03FFFF, "ROM",
                    "CODE")  # TODO validate ROM area
    idaapi.add_segm(0, 0x200000, 0x21FFFF, "RAM",
                    "DATA")  # TODO validate RAM area
    idaapi.add_segm(0, 0x220000, 0x23FFFF, "RAM2",
                    "DATA")  # TODO validate this, it's here just to fill space
    idaapi.add_segm(0, 0x240000, 0x2400FF, "IO_ADC", "DATA")  # A/D converter
    idaapi.add_segm(0, 0x240100, 0x2401FF, "IO_UNK_01", "DATA")  #
    idaapi.add_segm(0, 0x240200, 0x2402FF, "IO_RFPHA",
                    "DATA")  # RF phase detector
    idaapi.add_segm(0, 0x240300, 0x2403FF, "IO_UART", "DATA")  # Dual UART
    idaapi.add_segm(0, 0x240400, 0x2404FF, "IO_UNK_04", "DATA")  #
    idaapi.add_segm(0, 0x240500, 0x2405FF, "IO_UNK_05", "DATA")  #
    idaapi.add_segm(0, 0x240600, 0x2406FF, "IO_UNK_06", "DATA")  #
    idaapi.add_segm(0, 0x240700, 0x2407FF, "IO_UNK_07", "DATA")  #
    idaapi.add_segm(0, 0x240800, 0x2408FF, "IO_UNK_08", "DATA")  #
    idaapi.add_segm(0, 0x240900, 0x24FFFF, "IO_UNKNOWN", "DATA")  #

    # Seek to EOF and get filesize
    li.seek(0, 2)
    size = li.tell()

    # Seek back to start of file, read the file into memory
    li.seek(0)
    file_data = li.read(size)
    idaapi.mem2base(file_data, 0, size)  # data,start,end

    do_68k_vectors()

    # Get the initial program counter
    initPC = struct.unpack('>L', bytearray(file_data[4:8]))[0]

    # Hunt down the DATA segment initialiser, starting at the reset vector
    pattern = [
        0x41,
        0xF9,
        0x00,
        0x20,
        0x00,
        0x00,  # LEA    (0x200000).L, A0     ; start of dseg in RAM
        0x20,
        0x3C,
        0x00,
        None,
        None,
        None,  # MOVE.L #EndOfDataSeg, D0    ; end of dseg in RAM
        0x90,
        0x88,  # SUB.L  A0, D0               ; D0 = D0 - A0
        0x43,
        0xF9,
        0x00,
        None,
        None,
        None,  # LEA    (StartOfData), A1    ; start of dseg initialisation data
        0x53,
        0x80,  # SUBQ.L #1, D0               ; D0 --
        0x10,
        0xD9,  # MOVE.B (A1)+, (A0)+         ; *a0++ = *a1++
        0x51,
        0xC8,
        0xFF,
        0xFC  # DBF    D0, $-2              ; decrement d0, branch if >= 0
    ]
    sh_reg = [0x00] * len(pattern)

    # TODO: Refactor this to use IDA's internal buffer instead of the file_data array?

    for addr in range(initPC, initPC + 0x100):
        # shift in next byte
        sh_reg = sh_reg[1:]
        sh_reg.append(ord(file_data[addr]))

        # check if we've found a match
        match = True
        for i in range(len(pattern)):
            if pattern[i] is not None and pattern[i] != sh_reg[i]:
                match = False
                break

        # exit the search loop if we found a match
        if match:
            break

    if match:
        # If we've exited the loop and have a match, fish the DSEG addresses
        # out of the instruction parameters.
        dsegRamStart = struct.unpack(">L", bytearray(sh_reg[2:6]))[0]
        dsegRamEnd = struct.unpack(">L", bytearray(sh_reg[8:12]))[0]
        dsegRomStart = struct.unpack(">L", bytearray(sh_reg[16:20]))[0]

        print("DSEG RAM Start %08X" % dsegRamStart)
        print("DSEG RAM End   %08X" % dsegRamEnd)
        print("DSEG ROM Start %08X" % dsegRomStart)

        # Calculate initialised data segment end and end of the idata in ROM
        dsegLen = dsegRamEnd - dsegRamStart
        dsegRomEnd = dsegRomStart + dsegLen

        # Load the idata into RAM from the appropriate part of the ROM file
        idaapi.mem2base(file_data[dsegRomStart:dsegRomEnd], dsegRamStart,
                        dsegRamEnd)

        # TODO: Designate the source idata as ROM DATA
        idaapi.add_segm(0, dsegRomStart, dsegRomEnd, "DATAINIT", "DATA")
    else:
        print("No Match")

    # TODO: Try to identify the boundary between CODE and ROMDATA and move that into a segment

    # Wait for autoanalysis to finish
    autoWait()

    # Convert all MOVEA source parameters into address references
    doMoveaAddrRefs()

    # TODO: Search for switch-case jump tables
    oper_re = re.compile(r'\(pc,([ad][0-9]).([bwl])\)')
    insnStack = []
    for ea in Heads(0x33B0, 0x33D0):
        # Decode the instruction and operands
        insn = {
            'ea': ea,
            'disasm': GetDisasm(ea),
            'mnem': GetMnem(ea),
        }
        opnds = []
        for i in range(3):
            opnd = {
                'type': get_operand_type(ea, i),
                'opnd': GetOpnd(ea, i),
                'value': GetOperandValue(ea, i)
            }
            # store non-empty operands only
            if opnd['type'] != 0:  # FIXME use operand type constants
                opnds.append(opnd)
        insn['operands'] = opnds

        # push the instruction onto the stack, limiting the stack size
        insnStack.append(insn)
        insnStack = insnStack[-10:]

        # Look for this sequence at the end of the stack:
        #   ADD.W    d0,d0
        #   MOVE.W   <table>(pc,d0.w)
        #   JMP      <table>(pc,d0.w)
        #
        if insnStack[-1]['mnem'] == 'jmp' and insnStack[-2]['mnem'].startswith(
                'move.') and insnStack[-3]['mnem'].startswith('add.'):
            print("*** Potential jumptable sequence found at EOS")
            pprint(insnStack[-3])
            pprint(insnStack[-2])
            pprint(insnStack[-1])

            # Check the argtypes
            # Jump and move should have identical first argument types
            if insnStack[-1]['operands'][0]['type'] != 4 or insnStack[-2][
                    'operands'][0]['type'] != 4:
                continue

            # Add should be rigged to double the value of a register
            if insnStack[-3]['operands'][0]['type'] != 1 or insnStack[-3][
                    'operands'][1]['type'] != 1:
                continue
            if insnStack[-3]['operands'][0]['opnd'] != insnStack[-3][
                    'operands'][1]['opnd']:
                continue

            # Jumptable address is the offset in the jump instruction's first operand
            jumptableAddr = insnStack[-1]['operands'][0]['value']
            # Jump instruction EA
            jumpinstrAddr = insnStack[-1]['ea']
            # Jump register
            jumpReg = insnStack[-3]['operands'][0]['opnd']

            # Is there a subtract instruction above the 'add R,R'?
            if insnStack[-4]['mnem'].startswith('subi.'):
                jumpOffset = insnStack[-4]['operands'][0]['value']
            else:
                jumpOffset = 0

            print(
                "Jumptable Debug: TADDR %08X, JADDR %08X, OFFSET %d, REGISTER '%s'"
                % (jumptableAddr, jumpinstrAddr, jumpOffset, jumpReg))

            jtLowerBound = None
            jtUpperBound = None

            # Hunt backwards for the compare operations (to get the JT bounds)
            for i in reversed(range(3, 8)):  # 10 - 2
                curi = insnStack[-i]
                previ = insnStack[-(i + 1)]
                if previ['mnem'].startswith('cmpi.'):
                    print("COMPARE value %d" % previ['operands'][0]['value'])
                    if curi['mnem'].startswith('blt.'):
                        jtLowerBound = previ['operands'][0]['value']
                    elif curi['mnem'].startswith('bgt.'):
                        jtUpperBound = previ['operands'][0]['value']

            print("Jumptable Debug: upperbound %s lowerbound %s" %
                  (jtUpperBound, jtLowerBound))

            # TODO: figure out the register size

            # Set jumptable data
            swInf = switch_info_t()
            swInf.set_jtable_element_size

    # TODO: use AddCodeXref(?) to link calls where a function address has been copied into an address register

    # TODO: Search for the task table?
    """
	# ???
	idaapi.do_unknown(0x3C0000, 1)
	idaapi.doByte(0x3C0000, 1)
	idaapi.set_name(0x3C0000, "REG_VRAMADDR")
	#idaapi.set_cmt(0x3C0000, "Pouet.", 1)
	"""

    return 1
Beispiel #26
0
def load_mapping(emu, mapping):
    vaddr, _, size, _ = mapping
    idaapi.mem2base(emu.read_mem(vaddr, size), vaddr)
Beispiel #27
0
    def load_file(li, neflags, format):
        idaapi.set_processor_type("arm",
                                  idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL)
        f = load_nxo(li)
        if f.armv7:
            SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_PC_FLAT)
        else:
            SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_64BIT)

        SetCharPrm(INF_DEMNAMES, idaapi.DEMNAM_GCC3)
        idaapi.set_compiler_id(idaapi.COMP_GNU)
        idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1)

        loadbase = 0x60000000 if f.armv7 else 0x7100000000

        f.binfile.seek(0)
        as_string = f.binfile.read(f.bssoff)
        idaapi.mem2base(as_string, loadbase)
        if f.text[1] != None:
            li.file2base(f.text[1], loadbase + f.text[2],
                         loadbase + f.text[2] + f.text[3], True)
        if f.ro[1] != None:
            li.file2base(f.ro[1], loadbase + f.ro[2],
                         loadbase + f.ro[2] + f.ro[3], True)
        if f.data[1] != None:
            li.file2base(f.data[1], loadbase + f.data[2],
                         loadbase + f.data[2] + f.data[3], True)

        for start, end, name, kind in f.sections:
            if name.startswith('.got'):
                kind = 'CONST'
            idaapi.add_segm(0, loadbase + start, loadbase + end, name, kind)
            segm = idaapi.get_segm_by_name(name)
            if kind == 'CONST':
                segm.perm = idaapi.SEGPERM_READ
            elif kind == 'CODE':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC
            elif kind == 'DATA':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'BSS':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            idaapi.update_segm(segm)
            idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2)

        # do imports
        # TODO: can we make imports show up in "Imports" window?
        undef_count = 0
        for s in f.symbols:
            if not s.shndx and s.name:
                undef_count += 1
        last_ea = max(loadbase + end for start, end, name, kind in f.sections)
        undef_entry_size = 8
        undef_ea = (
            (last_ea + 0xFFF) & ~0xFFF
        ) + undef_entry_size  # plus 8 so we don't end up on the "end" symbol
        idaapi.add_segm(0, undef_ea, undef_ea + undef_count * undef_entry_size,
                        "UNDEF", "XTRN")
        segm = idaapi.get_segm_by_name("UNDEF")
        segm.type = idaapi.SEG_XTRN
        idaapi.update_segm(segm)
        for i, s in enumerate(f.symbols):
            if not s.shndx and s.name:
                MakeQword(undef_ea)
                idaapi.do_name_anyway(undef_ea, s.name)
                s.resolved = undef_ea
                undef_ea += undef_entry_size
            elif i != 0:
                assert s.shndx
                s.resolved = loadbase + s.value
                if s.name:
                    if s.type == STT_FUNC:
                        print hex(s.resolved), s.name
                        idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
                    else:
                        idaapi.do_name_anyway(s.resolved, s.name)

            else:
                # NULL symbol
                s.resolved = 0

        funcs = set()
        for s in f.symbols:
            if s.name and s.shndx and s.value:
                if s.type == STT_FUNC:
                    funcs.add(loadbase + s.value)

        got_name_lookup = {}
        for offset, r_type, sym, addend in f.relocations:
            target = offset + loadbase
            if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32):
                if not sym:
                    print 'error: relocation at %X failed' % target
                else:
                    idaapi.put_long(target, sym.resolved)
            elif r_type == R_ARM_RELATIVE:
                idaapi.put_long(target, idaapi.get_long(target) + loadbase)
            elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT,
                            R_AARCH64_ABS64):
                idaapi.put_qword(target, sym.resolved + addend)
                if addend == 0:
                    got_name_lookup[offset] = sym.name
            elif r_type == R_AARCH64_RELATIVE:
                idaapi.put_qword(target, loadbase + addend)
                if addend < f.textsize:
                    funcs.add(loadbase + addend)
            else:
                print 'TODO r_type %d' % (r_type, )
            ida_make_offset(f, target)

        for func, target in f.plt_entries:
            if target in got_name_lookup:
                addr = loadbase + func
                funcs.add(addr)
                idaapi.do_name_anyway(addr, got_name_lookup[target])

        funcs |= find_bl_targets(loadbase, loadbase + f.textsize)

        for addr in sorted(funcs, reverse=True):
            AutoMark(addr, AU_CODE)
            AutoMark(addr, AU_PROC)

        return 1
Beispiel #28
0
def load_file(li, neflags, format):
    # Set flags
    idaapi.set_processor_type(
        "arm", idaapi.SETPROC_LOADER_NON_FATAL | idaapi.SETPROC_LOADER)
    idc.set_inf_attr(idc.INF_LFLAGS,
                     idc.get_inf_attr(idc.INF_LFLAGS) | idc.LFLG_64BIT)
    idc.set_inf_attr(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3)
    idaapi.set_compiler_id(idaapi.COMP_GNU)
    idaapi.add_til('gnulnx_arm64', 1)

    # Load IRAM memory
    li.seek(0)
    pk11 = li.read(PK1L_SIZE)
    idaapi.mem2base(pk11, PK1L_ADDRESS)

    # Add identity mappings
    add_segment(PK1L_ADDRESS, PK1L_SIZE, '.pk1_identity', 'RWX')
    add_segment(TZRAM_BASE, TZRAM_SIZE, '.tz_identity', 'RWX')

    # Emulate package1 to determine interesting extents
    emu = Emulator()
    emu.run_emulator(pk11)

    # Refresh IRAM contents to reflect any decompression that may have occurred.
    idaapi.mem2base(emu.read_mem(PK1L_ADDRESS, PK1L_SIZE), PK1L_ADDRESS)

    if not emu.found_smc_evp:
        # Set coldboot crt0
        idc.create_insn(emu.entrypoint)
        idc.set_name(emu.entrypoint, 'coldboot_crt0')
        return 1

    iram_mappings = []
    dram_mappings = []
    tzram_mappings = []
    mmio_mappings = []

    for m in emu.mappings:
        if is_tzram(m):
            tzram_mappings.append(m)
        elif is_dram(m):
            dram_mappings.append(m)
        elif is_iram(m):
            iram_mappings.append(m)
        else:
            assert is_mmio(m)
            mmio_mappings.append(m)

    for m in mmio_mappings:
        add_mmio_mapping(m)

    # Process IRAM mappings
    if len(iram_mappings) == 3:
        sorted_irams = sorted(iram_mappings, key=lambda m: m[2])
        if [m[2] for m in sorted_irams] == [0x1000, 0x1000, 0x10000]:
            assert len(set([m[3] for m in sorted_irams])) == 2
            if sorted_irams[1][3] == sorted_irams[2][3]:
                add_segment(sorted_irams[0][0], sorted_irams[0][2], '.bl_sync',
                            'IO')
                add_segment(sorted_irams[1][0], sorted_irams[1][2], '.sc7_fw',
                            'DATA')
                add_segment(sorted_irams[2][0], sorted_irams[2][2],
                            '.sc7_tmp_save', 'DATA')
            else:
                assert sorted_irams[0][3] == sorted_irams[2][3]
                add_segment(sorted_irams[1][0], sorted_irams[1][2], '.bl_sync',
                            'IO')
                add_segment(sorted_irams[0][0], sorted_irams[0][2], '.sc7_fw',
                            'DATA')
                add_segment(sorted_irams[2][0], sorted_irams[2][2],
                            '.sc7_tmp_save', 'DATA')
        else:
            print iram_mappings
            raise ValueError('Unknown IRAM mapping set')
    elif len(iram_mappings) == 2:
        sorted_irams = sorted(iram_mappings, key=lambda m: m[2])
        if [m[2] for m in sorted_irams] == [0x1000, 0x10000]:
            assert len(set([m[3] for m in sorted_irams])) == 2
            add_segment(sorted_irams[0][0], sorted_irams[0][2], '.bl_sync',
                        'IO')
            add_segment(sorted_irams[1][0], sorted_irams[1][2],
                        '.sc7_tmp_save', 'DATA')
        else:
            print iram_mappings
            raise ValueError('Unknown IRAM mapping set')
    else:
        print iram_mappings
        raise ValueError('Unknown IRAM mapping set')

    # Process DRAM mappings
    if len(dram_mappings) == 2:
        sorted_drams = sorted(dram_mappings, key=lambda m: m[2])
        if [m[2] for m in sorted_drams] == [0x1000, 0x10000]:
            add_segment(sorted_drams[0][0], sorted_drams[0][2], '.sc7_se_ctx',
                        'DATA')
            add_segment(sorted_drams[1][0], sorted_drams[1][2], '.sc7_sm_ctz',
                        'DATA')
        else:
            print dram_mappings
            raise ValueError('Unknown DRAM mapping set')
    else:
        print dram_mappings
        raise ValueError('Unknown DRAM mapping set')

    # Process TZRAM segments
    tzram_groups = []
    for (vaddr, paddr, size, attr) in sorted(tzram_mappings,
                                             key=lambda m: m[0]):
        inserted = False
        for i in xrange(len(tzram_groups)):
            if vaddr == tzram_groups[i][-1][0] + tzram_groups[i][-1][
                    2] and tzram_groups[i][-1][2] != 0x40000:
                tzram_groups[i].append((vaddr, paddr, size, attr))
                inserted = True
                break
        if not inserted:
            tzram_groups.append([(vaddr, paddr, size, attr)])

    for group in tzram_groups:
        print 'Group'
        for m in group:
            print '    %x %x %x %x' % m

    # Process groups
    for group in tzram_groups:
        if len(group) > 1:
            if is_executable(group[0]):
                # .text/.rodata/.rwdata :)
                if len(group) == 2:
                    add_segment(group[0][0], group[0][2], '.text_rodata',
                                'CODE')
                    add_segment(group[1][0], group[1][2], '.rwdata', 'DATA')
                    load_mapping(emu, group[0])
                    load_mapping(emu, group[1])
                else:
                    assert len(group) == 3
                    add_segment(group[0][0], group[0][2], '.text', 'CODE')
                    add_segment(group[1][0], group[1][2], '.rodata', 'CONST')
                    add_segment(group[2][0], group[2][2], '.rwdata', 'DATA')
                    load_mapping(emu, group[0])
                    load_mapping(emu, group[1])
                    load_mapping(emu, group[2])
        elif is_executable(group[0]):
            assert len(group) == 1
            vaddr, paddr, size, attr = group[0]
            if size > 0x8000:
                assert len(
                    filter(lambda g: is_executable(g[0]) and g[0][2] > 0x8000,
                           tzram_groups)) == 1
                assert is_writable(group[0])
                add_segment(vaddr, size, '.code', 'RWX')
                load_mapping(emu, group[0])
            elif size == 0x2000:
                assert len(
                    filter(lambda g: is_executable(g[0]) and g[0][2] == 0x2000,
                           tzram_groups)) == 1
                add_segment(vaddr, size, '.pk2ldr', 'RWX')
                load_mapping(emu, group[0])
            else:
                assert size == 0x1000
                assert len(
                    filter(lambda g: is_executable(g[0]) and g[0][2] == 0x1000,
                           tzram_groups)) == 1
                add_segment(vaddr, size, '.vectors', 'CODE')
                load_mapping(emu, group[0])
        elif len(group) == 1 and (group[0][2] == 0x10000
                                  or group[0][2] == 0x40000):
            assert len(
                filter(
                    lambda g: len(g) == 1 and not is_executable(g[0]) and
                    (g[0][2] == 0x10000 or g[0][2] == 0x40000),
                    tzram_groups)) == 1
            assert not is_writable(group[0])
            vaddr, paddr, size, attr = group[0]
            add_segment(vaddr, size, '.tzram_ro_view', 'CONST')
        elif len(group) == 1 and group[0][2] == 0x1000:
            vaddr, paddr, size, attr = group[0]
            pk2ldr_group = filter(
                lambda g: is_executable(g[0]) and g[0][2] == 0x2000,
                tzram_groups)
            assert len(pk2ldr_group) == 1
            pk2ldr_group = pk2ldr_group[0][0]
            if paddr == emu.l3_table:
                add_segment(vaddr, size, '.l3_table', 'DATA')
            elif paddr == (emu.l3_table - 0x1000):
                add_segment(vaddr, size, '.l2_table', 'DATA')
            elif paddr == pk2ldr_group[1]:
                add_segment(vaddr, size, '.reused_stack0', 'DATA')
            elif paddr == (pk2ldr_group[1] + 0x1000):
                add_segment(vaddr, size, '.reused_stack1', 'DATA')
            elif vaddr == emu.phys_to_virt[
                    emu.ttbr & ~0xFFF][0] or vaddr == emu.core0_stack_page:
                add_segment(vaddr, size, '.shared_data', 'DATA')
            else:
                print 'Unknown Group'
                for m in group:
                    print '    %x %x %x %x' % m
                assert False
        else:
            print 'Unknown Group'
            for m in group:
                print '    %x %x %x %x' % m
            assert False

    # Set vector types as code.
    for i, ctx in enumerate(['sp0', 'spx', 'a64', 'a32']):
        for j, kind in enumerate(['synch', 'irq', 'fiq', 'serror']):
            addr = emu.vbar + 0x200 * i + 0x80 * j
            name = '%s_%s_exception' % (ctx, kind)
            idc.create_insn(addr)
            idc.set_name(addr, name)

    # Set coldboot crt0
    idc.create_insn(emu.entrypoint)
    idc.set_name(emu.entrypoint, 'coldboot_crt0')

    # Add SMC list entries
    assert len(emu.smc_lists) == 2
    idc.set_name(emu.smc_lists_addr, 'g_smc_lists')
    for i, name in enumerate(['user', 'priv']):
        addr, num_entries, pad = emu.smc_lists[i]
        idc.set_name(addr, 'g_smc_list_%s' % name)
        for n in xrange(num_entries):
            id, access, func = up('<IIQ', emu.read_mem(addr + 0x10 * n, 0x10))
            if func == 0:
                continue
            smc_name = get_smc_name(name == 'user', id)
            process_smc(func, smc_name)

    # We're done
    return 1
Beispiel #29
0
def load_file(li, neflags, format):
    '''
    Load the file into database

    @param li: a file-like object which can be used to access the input data
    @param neflags: options selected by the user, see loader.hpp
    @return: 0-failure, 1-ok
    '''
    idaapi.set_processor_type('cLEMENCy',
                              idaapi.SETPROC_USER | idaapi.SETPROC_FATAL)
    li.seek(0)
    data = convert(li.read(li.size()))
    if len(data) > 0x4000000:
        # program too large
        return 0

    idaapi.mem2base(data, 0, len(data))
    seg = idaapi.segment_t()
    seg.startEA = 0
    seg.endEA = 0x4000000
    # seg.bitness = 1
    idaapi.add_segm_ex(seg, "PROGRAM", "CODE", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x4000000
    seg.endEA = 0x400001e
    idaapi.add_segm_ex(seg, "CLOCKIO", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x4010000
    seg.endEA = 0x4011000
    idaapi.add_segm_ex(seg, "FLAGIO", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x5000000
    seg.endEA = 0x5002000
    idaapi.add_segm_ex(seg, "RDATA", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x5002000
    seg.endEA = 0x5002003
    idaapi.add_segm_ex(seg, "RDATASZ", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x5010000
    seg.endEA = 0x5012000
    idaapi.add_segm_ex(seg, "SDATA", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x5012000
    seg.endEA = 0x5012003
    idaapi.add_segm_ex(seg, "SDATASZ", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x6000000
    seg.endEA = 0x6800000
    idaapi.add_segm_ex(seg, "SHMEM", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x6800000
    seg.endEA = 0x7000000
    idaapi.add_segm_ex(seg, "NVRAM", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x7FFFF00
    seg.endEA = 0x7FFFF1C
    idaapi.add_segm_ex(seg, "IVEC", "RAM", idaapi.ADDSEG_SPARSE)
    seg = idaapi.segment_t()
    seg.startEA = 0x7FFFF80
    seg.endEA = 0x8000000
    idaapi.add_segm_ex(seg, "PROCID", "RAM", idaapi.ADDSEG_SPARSE)
    idaapi.add_entry(0, 0, "_start", True)
    # idc.AutoMark( 0, AU_CODE )

    return 1
Beispiel #30
0
def load_file(li, netflags, format):
    nsis = nsisfile.NSIS.from_path(idaapi.get_input_file_path())

    # Create NSIS netnode.
    nsis_netnode = idaapi.netnode("$ NSIS", 0, True)
    nsis_netnode.hashset("VERSION_MAJOR", nsis.version_major)
    nsis_netnode.hashset("VERSION_MINOR", nsis.version_minor)

    # Create blocks segments.
    for name, n, sclass in BLOCKS:
        offset = nsis.header.blocks[n].offset
        if offset == 0:
            continue
        content = nsis.block(n)
        # Create block segment
        seg = idaapi.segment_t()
        seg.startEA = offset
        seg.endEA = offset + len(content)
        idaapi.add_segm_ex(seg, name, sclass, 0)
        idaapi.mem2base(content, offset)

    # Add one virtual segment to hold variables.
    var_seg = idaapi.segment_t()
    var_start = align(nsis.size())
    var_seg.startEA = var_start
    var_seg.endEA = var_start + 0x1000  # Size chosen arbitrarily, should be enough.
    idaapi.add_segm_ex(var_seg, "VARS", "BSS", 0)
    # Create standard vars.
    for i, v in enumerate(nrs.strings.SYSVAR_NAMES.values()):
        idaapi.do_name_anyway(var_seg.startEA + i + 20, "$" + v)

    code_base = nsis.header.blocks[fileform.NB_ENTRIES].offset
    # Create sections functions.
    for i, section in enumerate(nsis.sections):
        if section.code == PTR_NONE:
            continue
        name = nsis.get_string(section.name_ptr)
        if not name:
            name = "_section" + str(i)
        ea = code_base + nrs.entry_to_offset(section.code)
        cname = canonize_name(name)
        AddEntryPoint(ea, ea, cname, 1)

    # Mark pages handlers.
    for i, page in enumerate(nsis.pages):
        for fn in ["prefunc", "showfunc", "leavefunc"]:
            addr = getattr(page, fn)
            if addr != PTR_NONE:
                name = "_page_{}_{}".format(i, fn)
                ea = code_base + nrs.entry_to_offset(addr)
                AddEntryPoint(ea, ea, name, 1)

    # Mark installer handlers.
    for event in [
        "Init",
        "InstSuccess",
        "InstFailed",
        "UserAbort",
        "GUIInit",
        "GUIEnd",
        "MouseOverSection",
        "VerifyInstDir",
        "SelChange",
        "RebootFailed",
    ]:
        addr = getattr(nsis.header, "code_on" + event)
        if addr != PTR_NONE:
            name = "_on" + event
            ea = code_base + nrs.entry_to_offset(addr)
            AddEntryPoint(ea, ea, name, 1)

    # Create strings.
    """
    strings_data = nsis.block(fileform.NB_STRINGS)
    strings_off = nsis.header.blocks[fileform.NB_STRINGS].offset
    i = 0
    while i < len(strings_data):
        decoded_string, length = \
            nrs.strings.decode(strings_data, i, nsis.version_major)
        decoded_string = str(decoded_string)
        string_name = canonize_name(decoded_string)
        idaapi.make_ascii_string(strings_off + i, length, ASCSTR_C)
        idaapi.set_cmt(strings_off + i, decoded_string, True)
        idaapi.do_name_anyway(strings_off + i, string_name)
        i += length
    #"""

    # Set processor to nsis script.
    SetProcessorType("nsis", SETPROC_ALL | SETPROC_FATAL)
    return 1