Exemplo n.º 1
0
def print_section_list():
    for s in idautils.Segments():
        seg = idaapi.getseg(s)
        print("    {name:\"%s\", begin:0x%x, end:0x%x}," % (idc.SegName(s), idc.SegStart(s), idc.SegEnd(s)))
Exemplo n.º 2
0
 def segName(self, selector):
     return idc.SegName(selector)
Exemplo n.º 3
0
def is_tls_segment(ea):
    try:
        seg_name = idc.SegName(ea)
        return seg_name in (".tbss", ".tdata", ".tls")
    except:
        return False
Exemplo n.º 4
0
 def chunk_info(self, chunk_addr, chunk):
     line =  idaapi.COLSTR("Chunk ", idaapi.SCOLOR_NUMBER)
     line += idaapi.COLSTR("0x%x\n\n" % (chunk_addr), idaapi.SCOLOR_INSN)
     line += idaapi.COLSTR("size: 0x%x\nfd: 0x%x - %s" % \
             (chunk.size, chunk.fd, idc.SegName(chunk.fd)), SCOLOR_DEFAULT)
     return line
Exemplo n.º 5
0
def slave_handler(task_id, f_eas_to_export, yatools, hash_provider):
    m = YaToolIDAModel(yatools, hash_provider)
    m.set_slave_skip(True)
    # v = MakeFileXmlExporter("database/database_%08i.xml" % (task_id))
    v = ya.MakeFlatBufferExporter()
    logger.info("Computing port with %s" % os.path.abspath(DATABASE_PATH))
    logger.info("slave connecting to  %r" % (IPC_ADDRESS,))
    client = Client(IPC_ADDRESS)
    client.send("READY")

    v.visit_start()

    try:
        loop_count = 0
        data = client.recv()
        while data != "FINISHED":
            job_name = data
            if job_name == "ACCEPT_SEGMENT":
                (parent_id, seg_ea_start, seg_ea_end) = client.recv()
                logger.info("Received ACCEPT_SEGMENT job : parent:%X 0x%08X->0x%08X:%s" %
                            (parent_id, seg_ea_start, seg_ea_end, idc.SegName(seg_ea_start)))
                m.set_skip_accept_segment(False)
                m.accept_segment(v, parent_id, seg_ea_start, seg_ea_end)
                m.set_skip_accept_segment(True)
            elif job_name == "ACCEPT_SEGMENT_CHUNK":
                (seg_ea_start, seg_ea_end, chunk_start, chunk_end) = client.recv()
                logger.info("Received ACCEPT_SEGMENT_CHUNK job : 0x%08X->0x%08X in seg 0x%08X->0x%08X:%s" %
                            (chunk_start, chunk_end, seg_ea_start, seg_ea_end, idc.SegName(seg_ea_start)))
                m.set_skip_accept_segment(False)
                m.accept_segment_chunk(
                    v, chunk_start, chunk_end, seg_start=seg_ea_start, seg_end=seg_ea_end, export_eas=True)
                m.set_skip_accept_segment(True)
            elif job_name != "NOP":
                logger.error("Received bad job : %r" % job_name)
            loop_count += 1

            mem = get_mem_usage()
            out_of_memory = False
            if mem > MAX_SLAVE_MEMORY_USAGE_MB:
                logger.warning("Using %d Mb : limit reached" % mem)
                out_of_memory = True
            elif mem == 0 and loop_count % 4 == 3:
                objs = muppy.get_objects()
                obj_count = 0
                for o in objs:
                    if isinstance(o, idaapi.member_t):
                        obj_count += 1
                out_of_memory = obj_count > MAX_IDAMEMBER_T_COUNT

            if out_of_memory:
                client.send("OUTOFMEMORY")
            else:
                logger.warning("Memory limit not reached")
                client.send("READY")
            data = client.recv()
    except EOFError:
        logger.warning("Received EOF")
        traceback.print_exc()

    v.visit_end()
    with open(os.path.join(DATABASE_PATH, "database_%08i.yadb" % task_id), 'wb') as fh:
        fh.write(v.GetBuffer())
Exemplo n.º 6
0
import sys
import struct

vftable_section_names = [
    ".rodata", ".data.rel.ro", ".data.rel.ro.local", ".rdata"
]

rtti_list = []

class_list = {}

hasdrr = 0
hasgot = 0
hasplt = 0
for seg in idautils.Segments():
    if idc.SegName(seg) == '.text':
        text_start = idc.SegStart(seg)
        text_end = idc.SegEnd(seg)
    if idc.SegName(seg) == '.pdata':
        pdata_start = idc.SegStart(seg)
        pdata_end = idc.SegEnd(seg)
    if idc.SegName(seg) == '.idata':
        idata_start = idc.SegStart(seg)
        idata_end = idc.SegEnd(seg)
    if idc.SegName(seg) == '.rdata':
        rdata_start = idc.SegStart(seg)
        rdata_end = idc.SegEnd(seg)
    if idc.SegName(seg) == '.data.rel.ro':
        drrdata_start = idc.SegStart(seg)
        drrdata_end = idc.SegEnd(seg)
        hasdrr = 1
Exemplo n.º 7
0
def get_seg_range(seg):
    for s in idautils.Segments():
        if idc.SegName(s) == seg:
            start_ea = idc.SegStart(s)
            end_ea = idc.SegEnd(s)
    return start_ea, end_ea
Exemplo n.º 8
0
def find_and_rename_memcpy_function():

    ea = 0
    pattern = "57 56 8B 74 24 10 8B 4C 24 14 8B 7C 24 0C 8B C1 8B D1 03 C6 3B FE 76 08"

    memcpy_func_addr = None

    # Find memcpy func
    while ea != BADADDR:

        ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                            pattern)

        if ea and segment_name == idc.SegName(ea):

            memcpy_func_addr = ea
            idaapi.set_name(ea, "_memcpy_maze", idaapi.SN_FORCE)
            print "Pattern: {0}".format(pattern)
            print "\tPatched find_and_rename_memcpy_function: {0}".format(
                hex(memcpy_func_addr).split("L")[0])

    # Find all memcpy refs and resolve them.
    # This is possible to be resolved with xref IDA functions
    # But because the code is obfuscated, it will be done this way
    if memcpy_func_addr:
        '''

        .text:1001DEE1 0F 84 69 95 01 00  jz      sub_10037450
        .text:1001DEE7 0F 85 63 95 01 00  jnz     sub_10037450

        '''
        patterns = [
            "68 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 0F 85",
            "68 ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 0F 84"
        ]

        for pattern in patterns:

            count_patched = 0
            count_not_patched = 0
            ea = 0

            while ea != BADADDR:

                ea = idc.FindBinary(ea,
                                    SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                                    pattern)
                ''' Identify the ones that pushes the return
                    .text:1001E0EC 68 01 E1 01 10      push    offset byte_1001E101
                    .text:1001E0F1 0F 84 59 93 01 00   jz      _memcpy_maze
                    .text:1001E0F7 0F 85 53 93 01 00   jnz     _memcpy_maze
                '''

                # relative offset from first jz
                # push_instr_addr + push_instr_size + 2 (0F 84)
                relative_offset_addr = ea + 5 + 2
                # push_inst_addr + push_instr_size + relative offset + jz_instr_size
                absolute_addr = ea + 0x5 + Dword(relative_offset_addr) + 0x6

                # If points to the memcpy func
                if absolute_addr == memcpy_func_addr:

                    # Copy instruction values before patching
                    values = GetManyBytes(ea, 5 + 6 + 6)
                    ''' Original
                    .text:10001574 50                 push    eax
                    .text:10001575 55                 push    ebp
                    .text:10001576 53                 push    ebx
                    .text:10001577 68 94 15 00 10     push    offset dword_10001594
                    .text:1000157C 0F 84 CE 5E 03 00  jz      _memcpy_maze
                    .text:10001582 0F 85 C8 5E 03 00  jnz     _memcpy_maze

                    The idea is to patch in order to create:
                    .text:10021905 52                 push    edx
                    .text:10021906 56                 push    esi
                    .text:10021907 50                 push    eax
                    .text:10021908 FF 15 50 74 03 10  call    dword ptr ds:_memcpy_maze
                    .text:1002190E 68 21 19 02 10     push    offset loc_10021921
                    .text:10021913 C3                 retn
                    .text:10021914 90                 nop
                    .text:10021915 90                 nop
                    .text:10021916 90                 nop
                    .text:10021917 90                 nop
                    .text:10021918 90                 nop
                    '''

                    # Patch push with the call _memcpy_maze
                    idc.PatchByte(ea, 0xFF)
                    idc.PatchByte(ea + 1, 0x15)
                    idc.PatchDword(ea + 2, memcpy_func_addr)

                    # Below patch with the original push
                    # push    offset dword_714522A8
                    idc.PatchByte(ea + 6, ord(values[0]))
                    idc.PatchByte(ea + 7, ord(values[1]))
                    idc.PatchByte(ea + 8, ord(values[2]))
                    idc.PatchByte(ea + 9, ord(values[3]))
                    idc.PatchByte(ea + 10, ord(values[4]))

                    # Add ret
                    idc.PatchByte(ea + 11, 0xC3)  # 8 pos ret

                    # Nop left part of last instruction
                    idc.PatchByte(ea + 12, 0x90)
                    idc.PatchByte(ea + 13, 0x90)
                    idc.PatchByte(ea + 13, 0x90)
                    idc.PatchByte(ea + 14, 0x90)
                    idc.PatchByte(ea + 15, 0x90)
                    idc.PatchByte(ea + 16, 0x90)

                    idc.MakeCode(ea)

                    count_patched += 1

                else:

                    count_not_patched += 1

            print "Pattern: {0}".format(pattern)
            print "\tPatched find_and_rename_memcpy_function: {0}".format(
                count_patched)
            print "\tNot Patched find_and_rename_memcpy_function: {0}".format(
                count_not_patched)
Exemplo n.º 9
0
def delete_fake_calls_before_jz_jnz():
    '''
    .text:714517B9 74 2C                         jz      short loc_714517E7
    .text:714517BB 75 0A                         jnz     short loc_714517C7
    .text:714517BD FF 15 0C 70 48 71             call    ds:LsaClose

    .text:71463763 75 5F                         jnz     short near ptr dword_714637C0+4
    .text:71463765 74 0A                         jz      short near ptr dword_71463770+1
    .text:71463767 FF 15 EC 71 48 71             call    ds:LsaConnectUntrusted

    74 ?? 75 ?? FF 15
    75 ?? 74 ?? FF 15

    '''

    patterns = ["74 ?? 75 ?? FF 15", "75 ?? 74 ?? FF 15"]

    for pattern in patterns:

        count_patched = 0
        count_not_patched = 0
        ea = 0

        while ea != BADADDR:

            ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                                pattern)

            if ea and segment_name == idc.SegName(ea):
                '''
                74 2C                         jz      short loc_714517E7
                75 0A                         jnz     short loc_714517C7
                FF 15 0C 70 48 71             call    ds:LsaClose

                Result:
                74 2C                         jz      short loc_714517E7
                75 0A                         jnz     short loc_714517C7
                90 90 90 90 90 90             nops 
                '''

                # Patch from pos, and delete fake calls
                pos = ea + 0x4

                patch_loop(pos, 6, 0x90)

                idc.MakeCode(ea)

                count_patched += 1

            else:

                count_not_patched += 1

        print "Pattern: {0}".format(pattern)
        print "\tPatched delete_fake_calls_before_jz_jnz: {0}".format(
            count_patched)
        print "\tNot Patched delete_fake_calls_before_jz_jnz: {0}".format(
            count_not_patched)
    '''

    .text:714713E4 0F 84 36 01 FE FF             jz      loc_71451520
    .text:714713EA 75 0A                         jnz     short near ptr loc_714713F5+1

    0F ?? ?? ?? ?? ?? 75 ?? FF 15
    0F ?? ?? ?? ?? ?? 74 ?? FF 15

    '''
    patterns = [
        "0F ?? ?? ?? ?? ?? 75 ?? FF 15", "0F ?? ?? ?? ?? ?? 74 ?? FF 15"
    ]

    for pattern in patterns:

        count_patched = 0
        count_not_patched = 0
        ea = 0

        while ea != BADADDR:

            ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                                pattern)

            if ea and segment_name == idc.SegName(ea):
                '''
                0F 84 36 01 FE FF             jz      loc_71451520
                75 0A                         jnz     short near ptr loc_714713F5+1
                FF 15 00 70 48 71             call    ds:EqualDomainSid

                Result:
                0F 84 36 01 FE FF             jz      loc_71451520
                75 0A                         jnz     short near ptr loc_714713F5+1
                90 90 90 90 90 90             nops
                '''

                # Patch from pos, and delete fake calls
                pos = ea + 0x8
                patch_loop(pos, 6, 0x90)

                idc.MakeCode(ea)

                count_patched += 1

            else:

                count_not_patched += 1

        print "Pattern: {0}".format(pattern)
        print "\tPatched delete_fake_calls_before_jz_jnz: {0}".format(
            count_patched)
        print "\tNot Patched delete_fake_calls_before_jz_jnz: {0}".format(
            count_not_patched)
        '''
        .text:10021C11 0F 84 09 F9 FD FF       jz      loc_10001520
        .text:10021C17 0F 85 03 F9 FD FF       jnz     loc_10001520
        .text:10021C1D FF 15 00 91 03 10       call    ds:CreateFileW
        '''
        patterns = [
            "0F 84 ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? FF 15",
            "0F 85 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? FF 15"
        ]

        for pattern in patterns:

            count_patched = 0
            count_not_patched = 0
            ea = 0

            while ea != BADADDR:

                ea = idc.FindBinary(ea,
                                    SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                                    pattern)

                if ea and segment_name == idc.SegName(ea):
                    '''
                    .text:10021C11 0F 84 09 F9 FD FF       jz      loc_10001520
                    .text:10021C17 0F 85 03 F9 FD FF       jnz     loc_10001520
                    .text:10021C1D FF 15 00 91 03 10       call    ds:CreateFileW

                    Result:
                    .text:10021C11 0F 84 09 F9 FD FF       jz      loc_10001520
                    .text:10021C17 0F 85 03 F9 FD FF       jnz     loc_10001520
                    .text:10021C1D 90                      nop
                    .text:10021C1E 90                      nop
                    .text:10021C1F 90                      nop
                    .text:10021C20 90                      nop
                    .text:10021C21 90                      nop
                    .text:10021C22 90                      nop
                    '''

                    # Patch from pos, and delete fake calls
                    pos = ea + 12

                    patch_loop(pos, 6, 0x90)

                    idc.MakeCode(ea)

                    count_patched += 1

                else:

                    count_not_patched += 1

            print "Pattern: {0}".format(pattern)
            print "\tPatched delete_fake_calls_before_jz_jnz: {0}".format(
                count_patched)
            print "\tNot Patched delete_fake_calls_before_jz_jnz: {0}".format(
                count_not_patched)
Exemplo n.º 10
0
def loadWorkspaceFromIdb():
    '''
    from IDA Pro, load the currently loaded module into a vivisect workspace.
    currently only supports windows PE files.

    Returns:
      vivisect.Workspace: the loaded and analyzed vivisect workspace.
    '''
    vw = vivisect.VivWorkspace()

    if is_x86():
        vw.setMeta('Architecture', 'i386')
    elif is_x64():
        vw.setMeta('Architecture', 'amd64')
    else:
        raise NotImplementedError('unsupported architecture')

    if not is_exe():
        raise NotImplementedError('unsupported file format')

    vw.setMeta('Platform', 'windows')
    vw.setMeta('Format', 'pe')
    vw._snapInAnalysisModules()

    filename = idc.GetInputFile()

    for segstart in idautils.Segments():
        segname = idc.SegName(segstart)
        segbuf = get_segment_data(segstart)

        if segbuf is None:
            raise RuntimeError('failed to read segment data')

        logger.debug('mapping section %s with %x bytes', segname, len(segbuf))
        vw.addMemoryMap(segstart, envi.memory.MM_RWX, segname, segbuf)
        vw.addSegment(segstart, len(segbuf), segname, filename)

    for ea, ordinal, name in get_exports():
        logger.debug('marking export %s at %x', name, ea)
        vw.addEntryPoint(ea)
        vw.addExport(ea, vivisect.const.EXP_FUNCTION, name, filename)

    for ea, dllname, name, ordinal in get_imports():
        logger.debug('marking import %s!%s at %x', dllname, name, ea)
        vw.makeImport(ea, dllname, name)

    logger.debug('running vivisect auto-analysis')
    vw.analyze()

    for fva in get_functions():
        logger.debug('marking function %s at %x', idc.GetFunctionName(fva), fva)
        vw.makeFunction(fva)
        vw.makeName(fva, idc.GetFunctionName(fva))

    # can only set thunk-ness after a function is defined.
    for ea, dllname, name, ordinal in get_imports():
        try:
            thunk = get_import_thunk(ea)
        except ValueError:
            pass
        else:
            logger.debug('found thunk for %s.%s at %x', dllname, name, thunk)
            vw.makeFunction(thunk)
            vw.makeFunctionThunk(thunk, '%s.%s' % (dllname, name))

    return vw
Exemplo n.º 11
0
    def _initialize_page(self, n, new_page):
        if n in self._initialized:
            return False
        self._initialized.add(n)

        new_page_addr = n * self._page_size
        initialized = False

        if self.state is not None:
            self.state.scratch.push_priv(True)

        if self._memory_backer is None:
            pass

        project = load_project()

        #print "LOADING 0x%x" % new_page_addr

        if get_memory_type() == TEXT_SIMPROCS_FROM_LOADER or (
                get_memory_type() == ONLY_SIMPROCS_FROM_LOADER
                and idc.SegName(new_page_addr)
                == project.arch.got_section_name):  #yes this is weird

            if isinstance(self._memory_backer, cle.Clemory):
                # first, find the right clemory backer
                for addr, backer in self._memory_backer.cbackers if self.byte_width == 8 else (
                    (x, y) for x, _, y in self._memory_backer.stride_repr):
                    start_backer = new_page_addr - addr
                    if isinstance(start_backer, BV):
                        continue
                    if start_backer < 0 and abs(
                            start_backer) >= self._page_size:
                        continue
                    if start_backer >= len(backer):
                        continue

                    # find permission backer associated with the address
                    # fall back to read-write if we can't find any...
                    flags = IdaPage.PROT_READ | IdaPage.PROT_WRITE
                    for start, end in self._permission_map:
                        if start <= new_page_addr < end:
                            flags = self._permission_map[(start, end)]
                            break

                    snip_start = max(0, start_backer)
                    write_start = max(new_page_addr, addr + snip_start)
                    write_size = self._page_size - write_start % self._page_size

                    if self.byte_width == 8:
                        snip = _ffi.buffer(backer)[snip_start:snip_start +
                                                   write_size]
                        mo = SimMemoryObject(claripy.BVV(snip),
                                             write_start,
                                             byte_width=self.byte_width)
                        self._apply_object_to_page(n * self._page_size,
                                                   mo,
                                                   page=new_page)
                    else:
                        for i, byte in enumerate(backer):
                            mo = SimMemoryObject(claripy.BVV(
                                byte, self.byte_width),
                                                 write_start + i,
                                                 byte_width=self.byte_width)
                            self._apply_object_to_page(n * self._page_size,
                                                       mo,
                                                       page=new_page)

                    new_page.permissions = claripy.BVV(flags, 3)
                    initialized = True

            elif len(self._memory_backer) <= self._page_size:
                for i in self._memory_backer:
                    if new_page_addr <= i and i <= new_page_addr + self._page_size:
                        if isinstance(self._memory_backer[i],
                                      claripy.ast.Base):
                            backer = self._memory_backer[i]
                        elif isinstance(self._memory_backer[i], bytes):
                            backer = claripy.BVV(self._memory_backer[i])
                        else:
                            backer = claripy.BVV(self._memory_backer[i],
                                                 self.byte_width)
                        mo = SimMemoryObject(backer,
                                             i,
                                             byte_width=self.byte_width)
                        self._apply_object_to_page(n * self._page_size,
                                                   mo,
                                                   page=new_page)
                        initialized = True
            elif len(self._memory_backer) > self._page_size:
                for i in range(self._page_size):
                    try:
                        if isinstance(self._memory_backer[i],
                                      claripy.ast.Base):
                            backer = self._memory_backer[i]
                        elif isinstance(self._memory_backer[i], bytes):
                            backer = claripy.BVV(self._memory_backer[i])
                        else:
                            backer = claripy.BVV(self._memory_backer[i],
                                                 self.byte_width)
                        mo = SimMemoryObject(backer,
                                             new_page_addr + i,
                                             byte_width=self.byte_width)
                        self._apply_object_to_page(n * self._page_size,
                                                   mo,
                                                   page=new_page)
                        initialized = True
                    except KeyError:
                        pass

        # page from debugger
        try:
            seg = idaapi.getseg(
                new_page_addr)  ### CHANGE TO SUPPORT OTHER DEBUGGERS
            if seg is not None:
                perms = 0
                if seg.perm & idaapi.SEGPERM_EXEC:
                    perms += IdaPage.PROT_EXEC
                if seg.perm & idaapi.SEGPERM_WRITE:
                    perms += IdaPage.PROT_WRITE
                if seg.perm & idaapi.SEGPERM_READ:
                    perms += IdaPage.PROT_READ
                new_page.permissions = claripy.BVV(perms, 3)
                #print "permissions setted %x  %d" % (new_page_addr, perms)

                initialized = True
                setattr(new_page, "from_ida_dbg", True)
        except Exception as ee:
            import traceback
            traceback.print_exc()

        if self.state is not None:
            self.state.scratch.pop_priv()
        return initialized
Exemplo n.º 12
0
def getSectionInfo(root_path):

    with open(root_path + 'section.csv', 'w') as f:

        wr = csv.writer(f)
        wr.writerow(['name', 'align', 'combination', 'flags', 'selector', 'type', 'r', 'w', 'x', 'size'])

        # segment objects
        for seg in idautils.Segments():

            # Segment Name
            try:
                name = idc.SegName(seg)
            except:
                name = "error"

            # Segment Align
            try:
                align = idc.GetSegmentAttr(seg, SEGATTR_ALIGN)
            except:
                align = "error"

            # Segment Combination
            try:
                combination = idc.GetSegmentAttr(seg, SEGATTR_COMB)
            except:
                combination = "error"

            # Segment Flags
            try:
                flags = idc.GetSegmentAttr(seg, SEGATTR_FLAGS)
            except:
                flags = "error"

            # Segment Selector
            try:
                selector = idc.GetSegmentAttr(seg, SEGATTR_SEL)
            except:
                selector = "error"

            # Segment Type
            try:
                seg_type = idc.GetSegmentAttr(seg, SEGATTR_TYPE)
            except:
                seg_type = "error"

            # Segment Permission
            try:
                perm_r = 0
                perm_w = 0
                perm_x = 0

                perm = idc.GetSegmentAttr(seg, SEGATTR_PERM)

                if perm == 1:
                    perm_x = 1

                elif perm == 2:
                    perm_w = 1

                elif perm == 4:
                    perm_r = 1

                elif perm == 3:
                    perm_x = 1
                    perm_w = 1

                elif perm == 6:
                    perm_w = 1
                    perm_r = 1

                elif perm == 5:
                    perm_x = 1
                    perm_r = 1

                elif perm == 7:
                    perm_r = 1
                    perm_w = 1
                    perm_x = 1

            except:
                perm_r = "error"
                perm_w = "error"
                perm_x = "error"

            # Segment Size
            try:
                size = idc.GetSegmentAttr(seg, SEGATTR_END) - idc.GetSegmentAttr(seg, SEGATTR_START)
            except:
                size = "error"

            wr.writerow([name, align, combination, flags, selector, seg_type, perm_r, perm_w, perm_x, size])
Exemplo n.º 13
0
print "0x%x %s" % (ea, ea)

#获取当前光标的地址
ea = here()
print "0x%x %s" % (ea, ea)

#获取当前IDB中最小地址
print hex(MinEA())

#获取当前IDB中最大地址
print hex(MaxEA())

ea = here()

#获取指定地址区段名称
print idc.SegName(ea)

#获取指定地址反汇编代码
print idc.GetDisasm(ea)

#获取指定地址助记符
print idc.GetMnem(ea)

#获取指定地址第一个操作数
print idc.GetOpnd(ea, 0)

#获取指定地址第二个操作数
print idc.GetOpnd(ea, 1)

#标识无效地址
print hex(idaapi.BADADDR)
Exemplo n.º 14
0
def main(fileName):
    if fileName is None:
        return
    jsonValue = {}
    jsonValue["names"] = {}
    jsonValue["functions"] = {}
    jsonValue["segments"] = []
    jsonValue["strings"] = {}

    for addr, name in idautils.Names():
        jsonValue["names"][addr] = name

    # Record segment details
    for ea in idautils.Segments():
        cur_seg = {}
        cur_seg["start"] = idc.SegStart(ea)
        cur_seg["end"] = idc.SegEnd(ea)
        cur_seg["name"] = idc.SegName(ea)
        seg = idaapi.getseg(ea)
        cur_seg["r"] = (seg.perm & idaapi.SEGPERM_READ) != 0
        cur_seg["w"] = (seg.perm & idaapi.SEGPERM_WRITE) != 0
        cur_seg["x"] = (seg.perm & idaapi.SEGPERM_EXEC) != 0
        cur_seg["semantics"] = DefaultSectionSemantics
        if seg.type == idaapi.SEG_CODE:
            cur_seg["semantics"] = ReadOnlyCodeSectionSemantics
        elif seg.type == idaapi.SEG_DATA or seg.type == idaapi.SEG_BSS:
            if cur_seg["w"]:
                cur_seg["semantics"] = ReadWriteDataSectionSemantics
            else:
                cur_seg["semantics"] = ReadOnlyDataSectionSemantics

    # Record function details
    for ea in idautils.Functions():
        cur_func = {}
        cur_func["start"] = ea
        cur_func["end"] = idc.GetFunctionAttr(ea, idc.FUNCATTR_END)
        cur_func["comment"] = linearize_comment(ea, True)
        cur_func["comments"] = {}
        for line_ea in idautils.Heads(ea, cur_func["end"]):
            line_comment = linearize_comment(line_ea)
            if line_comment is not None:
                cur_func["comments"][line_comment] = line_ea

        flags = idc.GetFunctionFlags(ea)
        cur_func["can_return"] = (flags & idc.FUNC_NORET) != idc.FUNC_NORET
        cur_func["thunk"] = False
        f = idaapi.get_func(ea)
        blocks = []
        for block in idaapi.FlowChart(f):
            blocks.append([block.startEA, block.endEA])

            # IDA treats thunks as being part of the function they are tunking to
            # Binary Ninja doesn't so only add the first basic block for all thunks
            if flags & idc.FUNC_THUNK != 0:
                cur_func["thunk"] = True
                break
        cur_func["basic_blocks"] = blocks
        jsonValue["functions"][idc.GetFunctionName(ea)] = cur_func

    # Record string details
    for string in idautils.Strings():
        name = ""
        if string.ea in jsonValue["names"]:
            name = jsonValue["names"][string.ea]

        xrefs = list(idautils.DataRefsTo(string.ea))
        if idaapi.IDA_SDK_VERSION < 700:
            jsonValue["strings"][string.ea] = (name, string.length,
                                               string.type, xrefs)
        else:
            jsonValue["strings"][string.ea] = (name, string.length,
                                               string.strtype, xrefs)

    # TODO: global variable names and types
    # TODO: stack local variable names and types
    # TODO: types and enumerations
    # TODO: non-function comments

    with open(fileName, "wb") as f:
        f.write(json.dumps(jsonValue, indent=4))

    print("Exported idb to {}".format(fileName))
Exemplo n.º 15
0
def enum_segments():
    for segstart in idautils.Segments():
        segend = idc.SegEnd(segstart)
        segname = idc.SegName(segstart)
        yield segstart, segend, segname
Exemplo n.º 16
0
def obfuscated_jz_jnz():
    '''
    Resolve opaque predicates, in case that opaque predicate points to FF 25 the call will be patched:
    
    Example:

    .text:10001540 68 71 15 00 10      push    offset byte_10001571
    .text:10001545 0F 84 57 5C 03 00   jz      loc_100371A2
    .text:1000154B 0F 85 51 5C 03 00   jnz     loc_100371A2

    Pattern
    68 ?? ?? ?? ?? ??
    0F 84 ?? ?? ?? ??
    0F 85 ?? ?? ?? ??

    68 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 0F 85 ?? ?? ?? ??

    Operation -> DWORD( 9C 9F 01 00 ) - DWORD( 96 9F 01 00 ) == 6 

    That means that jumps to the same relative address

    0x19f9C - 0x19F96 = 0x6

    If that address points to FF 25 ?? ?? ?? ??

    .text:100371A2 FF 25 9C 90 03 10        jmp     ds:lstrlenA <----------
    .text:100371A8                          -----------------------------
    .text:100371A8 FF 25 A0 90 03 10        jmp     ds:GetModuleHandleA
    .text:100371AE                          -----------------------------
    .text:100371AE FF 25 A4 90 03 10        jmp     ds:LoadLibraryA
    .text:100371B4                          -----------------------------
    .text:100371B4
    .text:100371B4                          
    .text:100371B4                          
    .text:100371B4 FF 25 A8 90 03 10        jmp     ds:GetLastError
    .text:100371BA                          -----------------------------
    .text:100371BA FF 25 AC 90 03 10        jmp     ds:lstrcpyA

    Patch with CALL PUSH RET formula

    .text:10001540 90                       nop    ; Return addr - 0x10001571
    .text:10001541 90                       nop
    .text:10001542 90                       nop
    .text:10001543 90                       nop
    .text:10001544 90                       nop
    .text:10001545 FF 15 9C 90 03 10        call    ds:lstrlenA
    .text:1000154B 68 71 15 00 10           push    10001571h
    .text:10001550 C3                       retn

    '''

    count_patched = 0
    count_not_patched = 0
    ea = 0

    while ea != BADADDR:

        ea = idc.FindBinary(
            ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
            "68 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 0F 85 ?? ?? ?? ??")

        if ea and segment_name == idc.SegName(ea):

            idc.MakeComm(
                ea,
                "Return addr - {0}".format(hex(Dword(ea + 0x1)).split("L")[0]))

            jz_pos = ea + 0x5
            jz_value = Dword(jz_pos + 0x2)

            jnz_pos = jz_pos + 0x6
            jnz_value = Dword(jnz_pos + 0x2)

            # Check same jmp addr
            if jz_value - jnz_value == 0x6:

                pos_jmp = jz_pos + jz_value + 0x6

                # If the jmp points to a FF 25 instruction (absolute jmp)
                if Word(pos_jmp) == 0x25FF:
                    '''
                    .text:1000153F 55                   push    ebp
                    .text:10001540 68 71 15 00 10       push    offset byte_10001571
                    .text:10001545 0F 84 57 5C 03 00    jz      loc_100371A2
                    .text:1000154B 0F 85 51 5C 03 00    jnz     loc_100371A2
                    .text:10001551 56                   push    esi
                    '''

                    # Patch the conditional jmp, copying the absolute jmp into it
                    idc.PatchWord(jz_pos, Word(pos_jmp))
                    idc.PatchDword(jz_pos + 0x2, Dword(pos_jmp + 0x2))

                    # At this point the FF 25 instruction have been copied into the conditional jmp position
                    # Ex: FF 25 3C 70 48 71 jmp     ds:CryptGenRandom
                    # But the absolute jmp will be patched with a call FF 15

                    # FF 15 call
                    idc.PatchByte(jz_pos, 0xFF)
                    idc.PatchByte(jz_pos + 0x1, 0x15)

                    # Copy the push instruction where conditonal jmp was
                    idc.PatchWord(jnz_pos, Word(ea))
                    idc.PatchWord(jnz_pos + 0x1, Word(ea + 0x1))
                    idc.PatchWord(jnz_pos + 0x3, Word(ea + 0x3))
                    idc.PatchByte(jnz_pos + 0x5, 0xC3)

                    # Nop the first 5 bytes.
                    patch_loop(ea, 0x5, 0x90)
                    '''
                    .text:10001540 90                  nop                     ; Return addr - 0x10001571
                    .text:10001541 90                  nop
                    .text:10001542 90                  nop
                    .text:10001543 90                  nop
                    .text:10001544 90                  nop
                    .text:10001545 FF 15 9C 90 03 10   call    ds:lstrlenA
                    .text:1000154B 68 71 15 00 10      push    10001571h
                    .text:10001550 C3                  retn
                    '''

                    idc.MakeCode(ea)

                else:
                    '''
                    .text:10021C0C 68 27 1C 02 10         push    offset loc_10021C27
                    .text:10021C11 0F 84 09 F9 FD FF      jz      loc_10001520
                    .text:10021C17 0F 85 03 F9 FD FF      jnz     loc_10001520

                    .text:10021C0C 90                     nop
                    .text:10021C0D 90                     nop
                    .text:10021C0E 90                     nop
                    .text:10021C0F 90                     nop
                    .text:10021C10 90                     nop
                    .text:10021C11 90                     nop
                    .text:10021C12 90                     nop
                    .text:10021C13 90                     nop
                    .text:10021C14 90                     nop
                    .text:10021C15 90                     nop
                    .text:10021C16 90                     nop
                    .text:10021C17 E9 04 F9 FD FF         jmp     loc_10001520
                    .text:10021C1C 90                     nop   <- last byte of old jnz instr
                    '''

                    # The first 11 bytes to nop

                    for i in range(0, 11):

                        idc.PatchByte(ea + i, 0x90)

                    # Add 1 to the address, because the size of the conditional jmp is 6, and the size of the unconditional jmp is 5
                    addr_to_jmp = Dword(jnz_pos + 0x2) + 0x1

                    # Patch first jz_value with unconditional jmp
                    idc.PatchByte(jnz_pos, 0xE9)

                    # Set the relative address
                    idc.PatchDword(jnz_pos + 0x1, addr_to_jmp)

                    # Last byte of the jnz to NOP (0x90)
                    idc.PatchByte(jnz_pos + 0x5, 0x90)

                    idc.MakeCode(ea)
                    '''
                    .text:10021C0C 90                     nop
                    .text:10021C0D 90                     nop
                    .text:10021C0E 90                     nop
                    .text:10021C0F 90                     nop
                    .text:10021C10 90                     nop
                    .text:10021C11 90                     nop
                    .text:10021C12 90                     nop
                    .text:10021C13 90                     nop
                    .text:10021C14 90                     nop
                    .text:10021C15 90                     nop
                    .text:10021C16 90                     nop
                    .text:10021C17 E9 04 F9 FD FF         jmp     loc_10001520
                    .text:10021C1C 90                     nop   <- last byte of old jnz instr
                    '''

                count_patched += 1

            else:

                count_not_patched += 1

    print "\tPatched obfuscated_jz_jnz: {0}".format(count_patched)
    print "\tNot Patched obfuscated_jz_jnz: {0}".format(count_not_patched)
Exemplo n.º 17
0
 def is_in_got(self, addr):
     """
     Checks whether or not an address is in the GOT section.
     """
     return idc.SegName(addr) == '.got.plt'
Exemplo n.º 18
0
def patch_jmp_eax():
    '''
    
    This type of push + jmp eax can be found in the maze code

    .text:71452297 68 A8 22 45 71 push    offset dword_714522A8
    .text:7145229C FF E0          jmp     eax

    With this patter the script is able to find this type of code:

    68 ?? ?? ?? ?? FF E0

    '''

    count_patched = 0
    count_not_patched = 0
    ea = 0

    while ea != BADADDR:

        ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                            "68 ?? ?? ?? ?? FF E0")

        if ea and segment_name == idc.SegName(ea):
            '''
            68 A8 22 45 71 push    offset dword_714522A8
            FF E0          jmp     eax

            in some cases we found this after the jmp fake api calls
            FF 15 08 90 03 10      call    ds:LsaAddAccountRights
            '''

            # push + jmp = 7 bytes
            # call Fake api call = 6 bytes
            # Store the byte values in "values" list
            values = GetManyBytes(ea, 7 + 6)
            '''
            FF D0          call    eax
            68 A8 22 45 71 push    offset dword_714522A8
            C3             ret
            '''

            # Patch with call eax
            idc.PatchByte(ea, 0xFF)
            idc.PatchByte(ea + 0x1, 0xD0)

            # Patch push
            idc.PatchByte(ea + 0x2, ord(values[0]))
            idc.PatchByte(ea + 0x3, ord(values[1]))
            idc.PatchByte(ea + 0x4, ord(values[2]))
            idc.PatchByte(ea + 0x5, ord(values[3]))
            idc.PatchByte(ea + 0x6, ord(values[4]))

            # Patch ret
            idc.PatchByte(ea + 0x7, 0xC3)
            '''
            If the script found in the position 7 and 8 FF 15 that means that it has found a fake api call
            
            57                   push    edi
            A1 D4 90 03 10       mov     eax, ds:lstrcatW
            89 C6                mov     esi, eax
            68 C9 28 00 10       push    offset loc_100028C9
            FF E0                jmp     eax
            FF 15 08 90 03 10    call    ds:LsaAddAccountRights
            91                   xchg    eax, ecx
            23 00                and     eax, [eax]
            '''

            # NOP the fake call
            if ord(values[7]) == 0xFF and ord(values[8]) == 0x15:

                for i in range(0, 5):

                    idc.PatchByte(ea + 0x8 + i, 0x90)

            idc.MakeCode(ea)
            count_patched += 1

        else:
            count_not_patched += 1

    print "\tPatched patch_jmp_eax: {0}".format(count_patched)
    print "\tNot Patched patch_jmp_eax: {0}".format(count_not_patched)
Exemplo n.º 19
0
def search_vftable_list_gcc():
    for seg in idautils.Segments():
        if idc.SegName(seg) in vftable_section_names:
            find_vftable_gcc(seg)
Exemplo n.º 20
0
def obfuscated_jz_jnz_2():

    patterns = [
        "68 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 75 ??",
        "68 ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 74 ??"
    ]

    for pattern in patterns:

        ea = 0
        count_patched = 0
        count_not_patched = 0
        '''

        It is assumed, after analysis, that the following conditions are met.

        - The first jz  or jnz instruction is the one that contains the final address.
        - The second jz or jnz instruction contains the intermediate address,
        this intermediate address contains another conditional jmp instruction 
        that points to the same final address as the first conditional jmp instruction.    

        .text:1002AFE3 68 1D B0 02 10     push  offset loc_1002B01D
        .text:1002AFE8 0F 84 12 6E 00 00  jz    loc_10031E00        <- jmp to Final Addr
        .text:1002AFEE 75 04              jnz   short loc_1002AFF4  <- jmp to Intermediate Addr
        .text:1002AFF0 E2 1B              loop  loc_1002B00D

        .text:1002AFF2 00                 db    0
        .text:1002AFF3 00                 db    0

        .text:1002AFF4
        .text:1002AFF4                         loc_1002AFF4:
        .text:1002AFF4 0F 85 06 6E 00 00  jnz  loc_10031E00        <- jmp to Final Addr
        .text:1002AFFA 74 04              jz   short loc_1002B000  <- Junk Code
        .text:1002AFFC 13 1A              adc  ebx, [edx]

        '''

        while ea != BADADDR:

            ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE,
                                pattern)

            if ea and segment_name == idc.SegName(ea):

                # First push
                push_addr = ea

                # First conditional jmp (jz or jnz)
                first_j = ea + 0x5

                # Second conditional jmp (jz or jnz)
                second_j = first_j + 0x6

                # pos contains the last position
                pos = 0xFFFFFFFF & first_j + Dword(first_j + 0x2) + 0x6

                # pos_2 contains the intermediate position before jmp to the final pos
                pos_2 = 0xFFFFFFFF & first_j + 0x6 + 0x2 + Byte(first_j + 0x6 +
                                                                0x1)

                # First opcode intermediate instruction
                value_pos_2 = Byte(pos_2)

                # Final address
                pos_3 = pos_2 + Dword(pos_2 + 0x2) + 0x6

                # If the OPCODE value of the intermediate jmp instruction begins with 0x0F must be patched
                if value_pos_2 == 0xF:

                    value_pos_final = Word(pos_3)

                    # If the final address first two bytes values are FF 25 (absolute jmp)
                    # Patch with call push ret formula
                    if value_pos_final == 0x25FF:
                        '''
                        .text:1002D25D 68 9C D2 02 10                          push    offset dword_1002D29C
                        .text:1002D262 0F 84 A6 9F 00 00                       jz      loc_1003720E  <------ jmp     ds:GetTickCount
                        .text:1002D268 75 04                                   jnz     short loc_1002D26E
                        .text:1002D26A 86 01                                   xchg    al, [ecx]
                        .text:1002D26C 00                                      db    0
                        .text:1002D26D 00                                      db    0
                        .text:1002D26E
                        .text:1002D26E                         loc_1002D26E:                          
                        .text:1002D26E 0F 85 9A 9F 00 00                       jnz     loc_1003720E   <------ jmp     ds:GetTickCount
                        .text:1002D274 74 0A                                   jz      short loc_1002D280
                        .text:1002D276 FF 15 10 92 03 10                       call    ds:EnumChildWindows


                        The first conditional jmp and the intermediate points to WinAPI function:
                        .text:1003720E FF 25 E4 90 03 10                       jmp     ds:GetTickCount

                        Patched:

                        .text:1002D25D 90                                      nop
                        .text:1002D25E 90                                      nop
                        .text:1002D25F 90                                      nop
                        .text:1002D260 90                                      nop
                        .text:1002D261 90                                      nop
                        .text:1002D262 FF 15 E4 90 03 10                       call    ds:GetTickCount
                        .text:1002D268 68 9C D2 02 10                          push    1002D29Ch
                        .text:1002D26D C3                                      retn
                        .text:1002D26E 90                                      nop
                        .text:1002D26F 90                                      nop
                        .text:1002D270 90                                      nop
                        .text:1002D271 90                                      nop
                        .text:1002D272 90                                      nop
                        .text:1002D273 90                                      nop
                        .text:1002D274 90                                      nop
                        .text:1002D275 90                                      nop
                        .text:1002D276 90                                      nop
                        .text:1002D277 90                                      nop
                        .text:1002D278 90                                      nop
                        .text:1002D279 90                                      nop
                        .text:1002D27A 90                                      nop
                        .text:1002D27B 90                                      nop

                        '''

                        idc.PatchByte(first_j, 0xFF)
                        idc.PatchByte(first_j + 0x1, 0x15)
                        idc.PatchDword(first_j + 0x2, Dword(pos_3 + 0x2))

                        # patch 0x90
                        patch_loop(first_j + 0x6, 2, 0x90)

                        # Patch from pos_2 8 bytes NOPS
                        patch_loop(pos_2, 8, 0x90)

                        # Copy push addr

                        idc.PatchByte(second_j, Byte(push_addr))
                        idc.PatchByte(second_j + 0x1, Byte(push_addr + 0x1))
                        idc.PatchByte(second_j + 0x2, Byte(push_addr + 0x2))
                        idc.PatchByte(second_j + 0x3, Byte(push_addr + 0x3))
                        idc.PatchByte(second_j + 0x4, Byte(push_addr + 0x4))

                        # Patch with ret
                        idc.PatchByte(second_j + 0x5, 0xC3)

                        # Patch push_addr
                        patch_loop(push_addr, 5, 0x90)

                        idc.MakeCode(ea)
                        count_patched += 1

                    #If the final address first two bytes values are not FF 25 (jmp)
                    else:
                        '''
                        .text:1002C85C 68 99 C8 02 10                          push    offset loc_1002C899
                        .text:1002C861 0F 84 B9 4C FD FF                       jz      loc_10001520
                        .text:1002C867 75 04                                   jnz     short loc_1002C86D
                        .text:1002C869 FD                                      std
                        .text:1002C86A 0A 00                                   or      al, [eax]
                        .text:1002C86C 00                                      db    0
                        .text:1002C86D
                        .text:1002C86D                         loc_1002C86D:                           
                        .text:1002C86D 0F 85 AD 4C FD FF                       jnz     loc_10001520
                        .text:1002C873 74 04                                   jz      short loc_1002C879
                        .text:1002C875 CF                                      iret

                        Patched:

                        .text:1002C85C 68 99 C8 02 10                          push    offset loc_1002C899
                        .text:1002C861 E9 BA 4C FD FF                          jmp     loc_10001520
                        .text:1002C861                         ; ---------------------------------------------------------------------------
                        .text:1002C866 FF                                      db 0FFh ; ÿ
                        .text:1002C867 75 04                                   jnz     short loc_1002C86D
                        .text:1002C869 FD                                      std
                        .text:1002C86A 0A 00                                   or      al, [eax]
                        .text:1002C86A                         ; ---------------------------------------------------------------------------
                        .text:1002C86C 00                                      db    0
                        .text:1002C86D                         ; ---------------------------------------------------------------------------
                        .text:1002C86D
                        .text:1002C86D                         loc_1002C86D:                           ; CODE XREF: .text:1002C867↑j
                        .text:1002C86D 90                                      nop
                        .text:1002C86E 90                                      nop
                        .text:1002C86F 90                                      nop
                        .text:1002C870 90                                      nop
                        .text:1002C871 90                                      nop
                        .text:1002C872 90                                      nop
                        .text:1002C873 90                                      nop
                        .text:1002C874 90                                      nop
                        '''

                        idc.PatchByte(first_j, 0xE9)
                        idc.PatchDword(first_j + 0x1,
                                       Dword(first_j + 0x2) + 0x1)

                        # Patch from pos_2 8 bytes NOPS
                        patch_loop(pos_2, 8, 0x90)
                        idc.MakeCode(ea)
                        count_patched += 1

        print "Pattern: {0}".format(pattern)
        print "\tPatched obfuscated_jz_jnz_2: {0}".format(count_patched)
        print "\tNot Patched obfuscated_jz_jnz_2: {0}".format(
            count_not_patched)
Exemplo n.º 21
0
def main():
    global functions
    program_ver_arch_opt = idc.ARGV[2]
    program = idc.ARGV[3]
    PROGRAM = idc.ARGV[1]
    parent_dir = os.path.join(config.Normalize_INST_DIR, config.Normalize_type,
                              PROGRAM, program_ver_arch_opt)
    print(parent_dir)
    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)
    norm_inst_dir = parent_dir + os.sep + 'function_norm_inst/'
    if not os.path.exists(norm_inst_dir):
        os.makedirs(norm_inst_dir)

    textStartEA = 0
    textEndEA = 0
    res = []
    for seg in idautils.Segments():
        if (idc.SegName(seg)[:5] == ".text"):
            textStartEA = idc.SegStart(seg)
            textEndEA = idc.SegEnd(seg)
            print(str(hex(textStartEA)))
            print(str(hex(textEndEA)))
            print('\n')
        for func in idautils.Functions(textStartEA, textEndEA):
            flags = idc.GetFunctionFlags(func)
            if flags & idc.FUNC_LIB:
                print hex(func), "FUNC_LIB", idc.GetFunctionName(func)
                continue
            func_name = idc.GetFunctionName(func)

            # replace '.' in program to '_'
            program = '_'.join(program.split('.'))
            cur_function_name = program + '_' + func_name
            if len(cur_function_name) > 130:
                cur_function_name = cur_function_name[:130]
            if ':' in cur_function_name:
                cur_function_name = '_'.join(cur_function_name.split(':'))
            if cur_function_name.lower() in functions:
                pass
            else:
                functions.append(cur_function_name.lower())
                norm_inst_file = norm_inst_dir + os.sep + str(
                    cur_function_name) + "_norm.csv"
                norm_fp = open(norm_inst_file, 'w')

                tmp = []
                allblock = idaapi.FlowChart(idaapi.get_func(func))
                for block in allblock:
                    one_block_norms = []
                    curEA = block.startEA
                    while curEA <= block.endEA:
                        #print config.Normalize_type
                        cur_norm_inst = eval(config.Normalize_type)(curEA)
                        tmp.append(cur_norm_inst)
                        one_block_norms.append(cur_norm_inst)
                        curEA = idc.NextHead(curEA, block.endEA)

                    one_block_norm_str = '\t'.join(one_block_norms)
                    one_block_norm_str = str(hex(
                        block.startEA)) + '\t' + one_block_norm_str + '\n'
                    norm_fp.write(one_block_norm_str)
                norm_fp.close()
                res.append(tmp)

    file_name = os.path.join(parent_dir, program + '.csv')
Exemplo n.º 22
0
import idc
import idautils
from idaapi import *

f = open('kernelStrings.pl','w')

#why does this say False?
s = idautils.Strings(False)
s.setup(strtypes=Strings.STR_C)
for i, v in enumerate(s):
    if v is None:
        f.write("Failed to retrieve string index %d" % i)
    else:
        #f.write("%x: len=%d type=%d index=%d-> '%s'\n" % (v.ea, v.length, v.type, i, str(v)))
	seg=idc.SegName(v.ea)
	#I'm probably replacing more things than I should, but prolog is getting confused by random backslashes.
	currentString=str(v).replace("\n","").replace('"',"'").replace("\\","")
	#f.write("%s\n" % str(seg))
	f.write("kernelString(segment(\"%s\"),stringFromProgram(\"%s\")).\n" % (str(seg), currentString))

f.close()

idc.Exit(0)
Exemplo n.º 23
0
'''
	File name: dump_sections.py
'''

import idautils
import idc
import idaapi

SECTION_NAME = '.e1t1_fw'
FOUND_FLAG = False

for sec in idautils.Segments():
	sec_name = idc.SegName(sec)
	
	if sec_name == SECTION_NAME:
		FOUND_FLAG = True
		start = idc.GetSegmentAttr(sec, idc.SEGATTR_START)
		end = idc.GetSegmentAttr(sec, idc.SEGATTR_END)

		with open(SECTION_NAME+".bin", 'wb') as f:
			while start < end:
				if not idc.hasValue(idc.GetFlags(start)):
					continue
					
				data = idc.Byte(start)
				f.write(chr(data))
				start += 1
				
if not FOUND_FLAG:
	print "[+] Could not found %s section " %(SECTION_NAME)
else:
 def getSegName(self, segName):
     for seg in idautils.Segments():
         if idc.SegName(seg) == segName:
             return idc.SegStart(seg), idc.SegEnd(
                 seg), idc.SegEnd(seg) - idc.SegStart(seg)
Exemplo n.º 25
0
def _collect_vtables(metaclass_info):
    """Use OSMetaClass information to search for virtual method tables."""
    # Build a mapping from OSMetaClass instances to virtual method tables.
    metaclass_to_vtable_builder = _OneToOneMapFactory()
    vtable_lengths = {}

    # Define a callback for when we find a vtable.
    def found_vtable(metaclass, vtable, length):
        # Add our vtable length.
        vtable_lengths[vtable] = length
        # If our classname has a defined vtable symbol and that symbol's address isn't this vtable,
        # don't add the link.
        classname = metaclass_info[metaclass].classname
        proper_vtable_symbol = symbol.vtable_symbol_for_class(classname)
        proper_vtable_symbol_ea = idau.get_name_ea(proper_vtable_symbol)
        if proper_vtable_symbol_ea not in (idc.BADADDR, vtable):
            return
        # If our vtable has a symbol and it doesn't match the metaclass, skip adding a link.
        vtable_symbol = idau.get_ea_name(vtable, user=True)
        if vtable_symbol:
            vtable_classname = symbol.vtable_symbol_get_class(vtable_symbol)
            if vtable_classname != classname:
                _log(
                    2,
                    'Declining association between metaclass {:x} ({}) and vtable {:x} ({})',
                    metaclass, classname, vtable, vtable_classname)
                return
        # Add a link if they are in the same kext.
        if segment.kernelcache_kext(metaclass) == segment.kernelcache_kext(
                vtable):
            metaclass_to_vtable_builder.add_link(metaclass, vtable)

    # Process all the segments with found_vtable().
    for ea in idautils.Segments():
        segname = idc.SegName(ea)
        if not segname.endswith('__DATA_CONST.__const'):
            continue
        _log(2, 'Processing segment {}', segname)
        _process_const_section_for_vtables(ea, metaclass_info, found_vtable)
    # If a metaclass has multiple vtables, that's really weird, unless the metaclass is
    # OSMetaClass's metaclass. In that case all OSMetaClass subclasses will have their vtables
    # refer back to OSMetaClass's metaclass.
    def bad_metaclass(metaclass, vtables):
        metaclass_name = metaclass_info[metaclass].classname
        if metaclass_name != 'OSMetaClass':
            vtinfo = ['{:#x}'.format(vt) for vt in vtables]
            _log(0, 'Metaclass {:#x} ({}) has multiple vtables: {}', metaclass,
                 metaclass_name, ', '.join(vtinfo))

    # If a vtable has multiple metaclasses, that's really weird.
    def bad_vtable(vtable, metaclasses):
        mcinfo = [
            '{:#x} ({})'.format(mc, metaclass_info[mc].classname)
            for mc in metaclasses
        ]
        _log(0, 'Vtable {:#x} has multiple metaclasses: {}', vtable,
             ', '.join(mcinfo))

    metaclass_to_vtable = metaclass_to_vtable_builder.build(
        bad_metaclass, bad_vtable)
    # The resulting mapping may have fewer metaclasses than metaclass_info.
    class_info = dict()
    for metaclass, classinfo in metaclass_info.items():
        # Add the vtable and its length, which we didn't have earlier. If the current class doesn't
        # have a vtable, take it from the superclass (recursing if necessary).
        metaclass_with_vtable = metaclass
        while metaclass_with_vtable:
            vtable = metaclass_to_vtable.get(metaclass_with_vtable, None)
            if vtable:
                classinfo.vtable = vtable
                classinfo.vtable_length = vtable_lengths[vtable]
                break
            classinfo_with_vtable = metaclass_info.get(metaclass_with_vtable,
                                                       None)
            if not classinfo_with_vtable:
                break
            metaclass_with_vtable = classinfo_with_vtable.meta_superclass
        # Set the superclass field and add the current classinfo to the superclass's children. This
        # is safe since this is the last filtering operation.
        superclass = metaclass_info.get(classinfo.meta_superclass, None)
        if superclass:
            classinfo.superclass = metaclass_info[classinfo.meta_superclass]
            classinfo.superclass.subclasses.add(classinfo)
        # Add the classinfo to the final dictionary.
        class_info[classinfo.classname] = classinfo
    return class_info, vtable_lengths
Exemplo n.º 26
0
    def objc_msgsend_xref(self,
                          call_ea,
                          objc_self,
                          objc_selector,
                          create_xref=True):
        '''
        This function will create a code xref to an objc method
        
        call_ea : location of call/jmp objc_msgsend (regardless of direct/indirect)
        objc_self: ea where RDI is set to static value (or that we find it's from a previous call or the RDI of the current function)
        objc_selector: ea where RSI is set to static value
        
        This ignores the RDI register, which is the `self` argument to objc_msgsend()
        id objc_msgSend(id self, SEL op, ...);
        So far, this seems to be fine as far as the cross-references are concerned.

        '''

        # get instruction mnemonic at address - I guess to check and make sure
        # it's mov rsi, blah
        instruction = idc.GetDisasm(objc_selector)
        if self.debugflag:
            print ">>> objc_msgsend_xref 0x%08x %s" % (objc_selector,
                                                       instruction)

        # get outbound references in the appropriate segment
        # implicit assumption is there is exacltly one
        target_selref = None
        for _ref in idautils.DataRefsFrom(objc_selector):
            if idc.SegName(_ref) == "__objc_selrefs":
                target_selref = _ref

        if not target_selref:
            return False

        # get outbound references in the appropriate segment
        # implicit assumption is there is exacltly one
        target_methname = None
        for _ref in idautils.DataRefsFrom(target_selref):
            if idc.SegName(_ref) == "__objc_methname":
                target_methname = _ref

        if not target_methname:
            return False

        # get inbound references
        # __objc_const
        # must be a __objc2_meth
        # I hope this method is correct to find __objc2_meth structs
        # BUG: when the binary has mutiple objc methods by the same name, this logic fails
        # Track RDI register. have to figure out what instance/class is referenced
        objc2_meth_struct_id = ida_struct.get_struc_id("__objc2_meth")
        meth_struct_found = False
        target_method = None
        for _ref in idautils.DataRefsTo(target_methname):
            # multiple may match
            # we care about the __obj2_meth struct found in references
            if idc.SegName(_ref) == "__objc_const":
                # check the outbound references
                for _meth_ref in idautils.DataRefsFrom(_ref):
                    if _meth_ref == objc2_meth_struct_id:
                        meth_struct_found = True

                if meth_struct_found:
                    # only do this once
                    # TODO: check against RDI here to make sure it's the proper class
                    # meth_struct_found = False

                    for _meth_ref in idautils.DataRefsFrom(_ref):
                        # assumption made on function always being in text segment
                        if idc.SegName(_meth_ref) == "__text":
                            # save the method implementation -- this is the function ptr
                            if self.debugflag:
                                print "0x%08x checking for the proper method -- %s" % (
                                    _meth_ref,
                                    idc.get_name(
                                        idc.get_func_attr(
                                            _meth_ref, idc.FUNCATTR_START)))
                            target_method = _meth_ref

        if not target_method:
            return False

        # After dereferencing across the IDB file, we finally have a target function.
        # In other words, if there isn't a method **in this binary** no xref is made (IDA only loads one binary?)
        # that is referenced from the mov rsi, <selector> instruction
        if self.debugflag: print "Found target method 0x%08x" % target_method
        if create_xref:
            idc.AddCodeXref(objc_selector, target_method, idc.fl_CF)

        return True
Exemplo n.º 27
0
def FindChildNode2(func, bbl_heads, parent, cur, stack, num_call, write_head):
    '''
    Handle function which was instrumented by ratio.
    Find 1st layer instrumented child.
    Recusion when encounter jump instruction. Stop when found a child node.
    @func       function address
    @bbl_heads  all bbl heads of function.
    @parent     parent node address
    @cur        the address to start the search. This vuale is typically the starting address of BBL.
    @stack      stack of search address, avoid recusion loops
    @num_call   indicates how many call is contained in one edge.
    @write_head list
    '''
    global g_f
    global g_off_set_random
    global g_size_ins_block
    global g_off_random

    # num_call = 0 # don't count call in parent bbl
    num_mem = 0  # don't count call mem function in parent bbl

    # current pos must in func
    end = idc.GetFunctionAttr(func, idc.FUNCATTR_END)
    if cur < func:
        return

    # avoid recusion loops
    if cur in stack:
        return
    stack.append(cur)

    ea = cur
    while ea < end and idaapi.BADADDR != ea:  #idaapi.BADADDR
        #print(hex(ea), idc.GetDisasm(ea))
        flag = idc.GetFlags(ea)
        if idc.isData(flag):
            ea += idc.ItemSize(ea)
            continue

        if not idc.isCode(flag):
            ea += 1
            continue

        # code
        # found a child node, stop
        if ea < end - g_size_ins_block and IsInstrumentIns(ea):
            parent_id = idc.Dword(
                parent +
                g_off_random)  #(int)(idc.GetOpnd(parent, 1).strip('h'), 16)
            child_id = idc.Dword(
                ea + g_off_set_random +
                g_off_random)  #(int)(idc.GetOpnd(ea+0x13, 1).strip('h'), 16)
            #if len(g_dict_func_edge):
            if 1 == write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
                return

            if parent != ea + g_off_set_random:
                #g_f.write(("%d %d %d %d %d %d %d\n") % ( parent, ea+0x13, parent_id, child_id, (parent_id >> 1) ^ child_id, num_call, num_mem ))
                g_f.write(("%d %d %d %d %d ") %
                          (parent, ea + g_off_set_random, parent_id, child_id,
                           (parent_id >> 1) ^ child_id))
                write_head[0] = 1
            #return

        if ea in bbl_heads:
            pass

        mnem = idc.GetMnem(ea)  #asm = idc.GetDisasm(ea)
        if mnem[:3] == 'ret':  #asm[:3] == 'ret':
            if write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
            return

        # jmp jz jnz ja ......
        elif 'j' == mnem[
                0]:  # and 'm' != mnem[1]:   jmp dst addr has been instumented.

            if write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
                return

            for xref in idautils.XrefsFrom(ea):  # idautils.ida_xref.XREF_ALL)
                if xref.type == 18 or xref.type == 19:  # 18 :'Code_Far_Jump', 19 : 'Code_Near_Jump',   please see XrefTypeName
                    FindChildNode2(func, bbl_heads, parent, xref.to, stack,
                                   num_call, write_head)

                elif xref.type == 20:  # 20 : 'Code_User'
                    print('******************************************')
                    print('Code_User', hex(parent), hex(ea), idc.GetDisasm(ea))

                elif xref.type == 21:  # 21 : 'Ordinary_Flow'
                    FindChildNode2(func, bbl_heads, parent, xref.to, stack,
                                   num_call, write_head)

            return

        # call.  count call ins.
        elif mnem == 'call':  #asm.startswith('call'):
            to = 0
            for to in idautils.CodeRefsFrom(ea, False):
                fun_name = idc.GetFunctionName(to).lower()
                if IsSanFunc(fun_name):
                    continue
                if fun_name.find('alloc') >= 0 or fun_name.find('free') >= 0 \
                    or fun_name.find('create') >= 0 or fun_name.find('delete') >= 0 \
                    or fun_name.find('destroy') >= 0:
                    num_mem += 1
                break
            # only count instrumented function
            if idc.SegName(ea) == idc.SegName(to):
                if not IsSanFunc(fun_name) and IsInstrumentIns(to):
                    #if len(g_dict_func_edge):
                    #    num_call += g_dict_func_edge[to]
                    #else:
                    num_call += 1
            ea += idc.ItemSize(ea)
            continue

        else:
            ea += idc.ItemSize(ea)
            #ea += idc.DecodeInstruction(ea)
            #ea = idc.NextNotTail(ea)

    if write_head[0]:
        g_f.write(("%d %d\n") % (num_call, num_mem))
        write_head[0] = 0

    return
Exemplo n.º 28
0
def get_segm_name(seg_ea):
    if idaapi.IDA_SDK_VERSION <= 699:
        retval = idc.SegName(seg_ea)
    else:
        retval = idc.get_segm_name(seg_ea)
    return retval
Exemplo n.º 29
0
def get_destructor_segment():
    """Returns the start address of the global destructor section"""
    for seg_ea in idautils.Segments():
        seg_name = idc.SegName(seg_ea).lower()
        if seg_name in [".fini_array", ".dtor"]:
            return seg_ea
Exemplo n.º 30
0
 def get_name(self):
     return idc.SegName(self.addr)