Exemplo n.º 1
0
def base64_decode(std):
    addr = idc.BADADDR
    ea = idc.get_screen_ea()
    flags = idaapi.get_flags(ea)

    if idc.is_strlit(flags):
        addr = ea   #  cursor is on the string
    elif idc.is_code(flags):
        addr = idc.get_first_dref_from(ea)  # get data reference from the instruction

    if addr == idc.BADADDR:
        plg_print("No string or reference to the string found\n")
        return

    b64str_enc = None
    try:
        b64str_enc = idc.get_strlit_contents(addr, -1, idc.get_str_type(addr))
    except:
        pass

    if not b64str_enc:
        plg_print("Could not get string at address 0x%X" % addr)
        return

    try:
        b64str_dec = base64.standard_b64decode(b64str_enc) if std else base64.urlsafe_b64decode(b64str_enc)
    except Exception as e:
        plg_print("Could not decode. %s" % str(e))
        return

    if b64str_dec:
        plg_print("Base64 decode of string '%s':" % b64str_enc)
        process_data_result(ea, bytearray(b64str_dec))
Exemplo n.º 2
0
    def execute_rename(name):
        """
            This is a wrapper to execute the renaming synchronously
        """
        def get_name():
            return idc.get_name(name["address"])

        def make_name(force=False):
            """
                Thread safe renaming wrapper
            """
            def sync_ask_rename():
                """
                    Dialog asking renaming confirmation to the user
                """
                rename_flag = 0
                if force or idc.ask_yn(
                        rename_flag, "Replace %s by %s" %
                    (get_name(), name["data"])) == 1:
                    logger.debug("[x] renaming %s @ 0x%x as %s", get_name(),
                                 name["address"], name["data"])
                    ida_name.set_name(name["address"],
                                      name["data"].encode('ascii', 'ignore'),
                                      ida_name.SN_AUTO)

            return idaapi.execute_sync(sync_ask_rename, idaapi.MFF_FAST)

        old_name = get_name()
        if not name["data"]:
            return
        elif idaapi.has_dummy_name(idaapi.get_flags(
                name["address"])) or not old_name:
            make_name(force=True)
        elif get_name() != name["data"]:
            make_name()
Exemplo n.º 3
0
def dump_type(ea):
    flags = idaapi.get_flags(ea)
    if idc.is_code(flags):
        return "block" if idaapi.get_func(ea) else "code"
    if idc.is_data(flags):
        return "data"
    return "unexplored"
Exemplo n.º 4
0
 def send_names(self):
     """
         Used to send all the names to the server.
         Usecase: Previously analyzed IDB
     """
     for head in idautils.Names():
         if not idaapi.has_dummy_name(idaapi.get_flags(head[0])):
             self.skel_conn.push_name(head[0], head[1])
Exemplo n.º 5
0
def iterate_vtable(vtable_addr):
    ea = vtable_addr
    while True:
        fn_ea = struct.unpack('<Q', idaapi.get_bytes(ea, 8))[0]
        if idaapi.get_name(fn_ea) != "__cxa_pure_virtual" and not idaapi.is_func(idaapi.get_flags(fn_ea)):
            return
        yield fn_ea
        ea += 8
Exemplo n.º 6
0
 def send_names(self):
     """
         Used to send all the names to the server.
         Usecase: Previously analyzed IDB
     """
     for head in idautils.Names():
         if not idaapi.has_dummy_name(idaapi.get_flags(head[0])):
             self.skel_conn.push_name(head[0], head[1])
Exemplo n.º 7
0
    def renamed(self, *args):
        logger.debug("[IDB Hook] Something is renamed")
        ea, new_name, is_local_name = args
        min_ea = idc.get_inf_attr(idc.INF_MIN_EA)
        max_ea = idc.get_inf_attr(idc.INF_MAX_EA)
        if ea >= min_ea and ea <= max_ea:
            if is_local_name:
                logger.warning("Local names are unimplemented")
            else:
                auto = idaapi.has_auto_name(idaapi.get_flags(ea))
                dummy = idaapi.has_dummy_name(idaapi.get_flags(ea))
                if not dummy and not auto:
                    self.skel_conn.push_name(ea, new_name)
        else:
            logger.warning("ea outside program...")

        return ida_idp.IDB_Hooks.renamed(self, *args)
Exemplo n.º 8
0
    def __init__(self, ea, info, cs):
        """Initialization function."""
        # Init the node structure
        node_t.__init__(self)

        # Check if it's a code instruction
        try:
            is_c = is_code(get_flags(ea))
        except:
            is_c = isCode(GetFlags(ea))
        if not is_c:
            raise CodeException

        #
        # fill node_t struct
        #

        # NodeInfo
        self.info = NodeInfo()
        inst_elements = []

        try:
            size = create_insn(ea)
            bytes = get_bytes(ea, size)
        except:
            size = MakeCode(ea)
            bytes = GetManyBytes(ea, size)

        (address, size, mnemonic, op_str) = cs.disasm_lite(bytes, ea, count=1).next()
        self.info.opcode = mnemonic.encode("ascii", "ignore")

        op_str_ascci = op_str.encode("ascii", "ignore")
        self.info.inst_str = self.info.opcode + " " + op_str_ascci

        splitted = op_str_ascci.split(", ")
        self.info.nargs = 0

        if len(splitted) >= 1:
            self.info.arg1 = splitted[0]
            self.info.nargs += 1
            if len(splitted) >= 2:
                self.info.arg2 = splitted[1]
                self.info.nargs += 1
                if len(splitted) >= 3:
                    self.info.arg3 = splitted[2]
                    self.info.nargs += 1

        # No node will be root but this is acceptable for CFGs
        self.info.is_root = False

        self.info.address = ea
        self.info.has_address = True

        # node_t
        self.node_id = self._genid()
Exemplo n.º 9
0
def Pablo(address, end):

    while address < end:
        offset = idaapi.find_binary(address, end, '?? FF FF FF FF', 0x10,
                                    SEARCH_DOWN)
        offset -= 0x3

        if idaapi.is_unknown(idaapi.get_flags(offset)):
            if text.start_ea <= idaapi.get_qword(offset) <= abs.end_ea:
                idaapi.create_data(offset, FF_QWORD, 0x8, BADNODE)

        address = offset + 0x4
Exemplo n.º 10
0
        def has_if(c, p): # type: (...) -> bool
            if c.op != hr.cit_if:
                return False
            lhs = c.cif.expr.x
            rhs = c.cif.expr.y
            if not rhs or rhs.op != hr.cot_obj:
                return False
            if not idaapi.is_strlit(idaapi.get_flags(rhs.obj_ea)):
                return False
            ctx.if_statement = c.cif
            ctx.this_string_item = my_cexpr_t(lhs)
            ctx.constant_item = my_cexpr_t(rhs)

            # Match the if body (in an extremely approximate way)
            def has_counter(c, p): # type: (...) -> bool
                if c.op != hr.cot_asg:
                    return False
                if c.x.op != hr.cot_var or not is_number(c.y, 0):
                    return False
                ctx.items_to_delete.append(vu.cfunc.body.find_parent_of(c).to_specific_type)
                return True

            def has_do_while(c, p): # type: (...) -> bool
                if c.op != hr.cit_do:
                    return False
                # don't bother matching the loop body -- just match the condition expression
                if c.cdo.expr.x.op != hr.cot_var:
                    return False
                if c.cdo.expr.op == hr.cot_sle or c.cdo.expr.op == hr.cot_ule:
                    if not is_number(c.cdo.expr.y, 0x80000):
                        return False
                elif c.cdo.expr.op == hr.cot_slt or c.cdo.expr.op == hr.cot_ult:
                    if not is_number(c.cdo.expr.y, 0x80001):
                        return False
                else:
                    return False
                ctx.items_to_delete.append(c)
                return True

            last_item_in_then = c.cif.ithen.cblock.back()
            if last_item_in_then.op != hr.cit_goto:
                ctx.is_equal_variant = False
                return ConstraintVisitor([
                    ConstraintChecker(has_counter),
                    ConstraintChecker(has_do_while),
                ], "equals.inner").check(c.cif.ithen, c)
            # Otherwise, look after the if.
            ctx.is_equal_variant = True
            p.add_temp_constraints([
                ConstraintChecker(has_counter),
                ConstraintChecker(has_do_while),
            ])
            return True
Exemplo n.º 11
0
 def has_string(c, p): # type: (...) -> bool
     if c.op != hr.cot_ref:
         return False
     ref = c.x
     if ref.op == hr.cot_idx:
         ref = ref.x
     if ref.op != hr.cot_obj:
         return False
     if not idaapi.is_strlit(idaapi.get_flags(ref.obj_ea)):
         return False
     string = get_string(ref.obj_ea)
     ctx.other_string_item = my_cexpr_t(ref)
     return string[0] == ctx.first_chr
Exemplo n.º 12
0
        def has_part_2(c, p): # type: (...) -> bool
            if c.op != hr.cit_if:
                return False

            if c.cif.ielse or c.cif.expr.op != hr.cot_ne:
                return False

            lhs = c.cif.expr.x
            rhs = c.cif.expr.y
            if rhs.op != hr.cot_obj:
                return False

            if not idaapi.is_strlit(idaapi.get_flags(rhs.obj_ea)):
                return False
            ctx.constant_item = my_cexpr_t(rhs)

            if_cv = ConstraintVisitor(self._get_part_2_checks(ctx, vu), "assign_const.part2")
            return if_cv.check(c.cif.ithen, c)
Exemplo n.º 13
0
    def _sig_instruction(self, addr: int) -> Optional[str]:
        """
        Get the bytes for a single instruction with wildcards
        :param addr: Instruction address
        :return: A signature chunk
        """
        # I'm not sure if either of these checks will ever happen
        # So let it explode until it does by trying to join None
        if not idaapi.is_code(idaapi.get_flags(addr)):
            return None

        if not idaapi.can_decode(addr):
            return None

        insn = idaapi.insn_t()
        insn.size = 0

        idaapi.decode_insn(insn, addr)
        if insn.size == 0:
            return None

        if insn.size < 5:
            return self._sig_bytes(insn.ea, insn.size)

        op_size = self._get_current_opcode_size(insn)
        if op_size == 0:
            return self._sig_bytes(insn.ea, insn.size)

        operand_size = insn.size - op_size
        sig = self._sig_bytes(insn.ea, op_size)

        if self._match_operands(insn.ea):
            sig += ' ' + self._sig_bytes(insn.ea + op_size, operand_size)
        else:
            sig += ' ' + self._sig_wildcards(operand_size)

        return sig
Exemplo n.º 14
0
def dump_flags(ea):
    flags = idaapi.get_flags(ea)
    reply = []
    for k in type_flags:
        if (flags & ida_bytes.MS_CLS) == (k & 0xFFFFFFFF):
            reply.append(type_flags[k])
    if ida_bytes.is_code(flags):
        for k in code_flags:
            if (flags & ida_bytes.MS_CODE) & k:
                reply.append(code_flags[k])
    if ida_bytes.is_data(flags):
        for k in data_flags:
            if (flags & ida_bytes.DT_TYPE) == (k & 0xFFFFFFFF):
                reply.append(data_flags[k])
    for k in comm_flags:
        if (flags & ida_bytes.MS_COMM) & k:
            reply.append(comm_flags[k])
    for k in op0_flags:
        if (flags & ida_bytes.MS_0TYPE) == (k & 0xFFFFFFFF):
            reply.append(op0_flags[k])
    for k in op1_flags:
        if (flags & ida_bytes.MS_1TYPE) == (k & 0xFFFFFFFF):
            reply.append(op1_flags[k])
    return " ".join(reply)
Exemplo n.º 15
0
    def execute_rename(name):
        """
            This is a wrapper to execute the renaming synchronously
        """
        def get_name():
            return idc.get_name(name["address"])

        def make_name(force=False):
            """
                Thread safe renaming wrapper
            """
            def sync_ask_rename():
                """
                    Dialog asking renaming confirmation to the user
                """
                rename_flag = 0
                if force or idc.ask_yn(rename_flag, "Replace %s by %s" %
                                       (get_name(), name["data"])) == 1:
                    logger.debug("[x] renaming %s @ 0x%x as %s",
                                 get_name(),
                                 name["address"],
                                 name["data"])
                    ida_name.set_name(
                        name["address"], name["data"].encode(
                            'ascii', 'ignore'),
                        ida_name.SN_AUTO)
            return idaapi.execute_sync(
                sync_ask_rename,
                idaapi.MFF_FAST)
        old_name = get_name()
        if not name["data"]:
            return
        elif idaapi.has_dummy_name(idaapi.get_flags(name["address"])) or not old_name:
            make_name(force=True)
        elif get_name() != name["data"]:
            make_name()
Exemplo n.º 16
0
def is_op_stack_var(ea, index):
    """ check if operand is a stack variable """
    return idaapi.is_stkvar(idaapi.get_flags(ea), index)
Exemplo n.º 17
0
def is_op_offset(insn, op):
    """ Check is an operand has been marked as an offset (by auto-analysis or manually) """
    flags = idaapi.get_flags(insn.ea)
    return ida_bytes.is_off(flags, op.n)
Exemplo n.º 18
0
def load_file(f, neflags, format):

    print('# PS4 Module Loader')
    ps = Binary(f)

    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL,
                         'gnulnx_x64')

    # Load Aerolib...
    nids = load_nids(idc.idadir() + '/loaders/aerolib.csv')

    # Segment Loading...
    for segm in ps.E_SEGMENTS:

        # Process Loadable Segments...
        if segm.name() in [
                'CODE', 'DATA', 'SCE_RELRO', 'DYNAMIC', 'GNU_EH_FRAME',
                'SCE_DYNLIBDATA'
        ]:

            address = segm.MEM_ADDR if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.OFFSET + 0x1000000
            size = segm.MEM_SIZE if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.FILE_SIZE

            print('# Processing %s Segment...' % segm.name())
            f.file2base(segm.OFFSET, address, address + segm.FILE_SIZE,
                        FILEREG_PATCHABLE)

            if segm.name() not in ['DYNAMIC', 'GNU_EH_FRAME']:

                idaapi.add_segm(0, address, address + size, segm.name(),
                                segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)

                # Processor Specific Segment Details
                idc.set_segm_addressing(address, bitness)
                idc.set_segm_alignment(address, segm.alignment())
                idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())

            # Process Dynamic Segment....
            elif segm.name() == 'DYNAMIC':

                stubs = {}
                modules = {}
                libraries = {}
                f.seek(segm.OFFSET)

                offset = segm.OFFSET
                dynamic = address
                dynamicsize = size

                for entry in xrange(size / 0x10):
                    idc.set_cmt(address + (entry * 0x10),
                                Dynamic(f).process(stubs, modules, libraries),
                                False)
            '''
            # Process Exception Handling Segment...
            elif segm.name() == 'GNU_EH_FRAME':
                
                # Exception Handling Frame Header Structure
                members = [('version', 'Version', 0x1),
                           ('eh_frame_ptr_enc', 'Encoding of Exception Handling Frame Pointer', 0x1),
                           ('fde_count_enc', 'Encoding of Frame Description Entry Count', 0x1),
                           ('table_enc', 'Encoding of Table Entries', 0x1)]
                struct = segm.struct('EHFrame', members)
                
                idaapi.create_struct(address, 0x4, struct)
                
                # Exception Handling Structure
                members = [('exception', 'value', 0x8)]
                struct = segm.struct('Exception', members)
                
                for entry in xrange(size / 0x8):
                    idaapi.create_struct(address + (entry * 0x8), 0x8, struct)
            '''

        # Process SCE 'Special' Shared Object Segment...
        if segm.name() == 'SCE_DYNLIBDATA':

            # SCE Fingerprint
            idc.make_array(address, 0x14)
            idc.set_name(address, 'SCE_FINGERPRINT',
                         SN_NOCHECK | SN_NOWARN | SN_FORCE)
            idc.set_cmt(
                address, ' '.join(
                    x.encode('hex')
                    for x in idc.get_bytes(address, 0x14)).upper(), False)

            # Dynamic Symbol Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('value', 'Value', 0x8), ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)

                # Dynamic Symbol Table
                location = address + Dynamic.SYMTAB
                f.seek(segm.OFFSET + Dynamic.SYMTAB)
                symbols = {}

                for entry in xrange(Dynamic.SYMTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Symbol(f).process(symbols), False)

            except:
                pass

            # Dynamic String Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = address + Dynamic.STRTAB
                f.seek(segm.OFFSET + Dynamic.STRTAB)

                # Stubs
                for key in stubs:
                    idc.create_strlit(location + key, BADADDR)
                    stubs[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Stub', False)

                #print('Stubs: %s' % stubs)

                # Modules
                for key in modules:
                    idc.create_strlit(location + key, BADADDR)
                    modules[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Module', False)

                #print('Modules: %s' % modules)

                # Libraries and LIDs
                lids = {}
                for key, value in libraries.iteritems():
                    idc.create_strlit(location + key, BADADDR)
                    lids[value] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    libraries[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Library', False)

                #print('LIDs: %s' % lids)

                # Symbols
                for key in symbols:
                    idc.create_strlit(location + key, BADADDR)
                    symbols[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Symbol', False)

                #print('Symbols: %s' % symbols)

            except:
                pass

            # Resolve Export Symbols
            try:
                symbols = sorted(symbols.iteritems())
                location = address + Dynamic.SYMTAB + 0x30
                f.seek(segm.OFFSET + Dynamic.SYMTAB + 0x30)

                for entry in xrange((Dynamic.SYMTABSZ - 0x30) / 0x18):
                    Symbol(f).resolve(location + (entry * 0x18), nids,
                                      symbols[entry][1])

            except:
                pass

            # Jump Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Jump Entry Structure
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Jump', members)

                # PS4 Base64 Alphabet
                base64 = list(
                    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-'
                )
                alphabet = {
                    character: index
                    for index, character in enumerate(base64)
                }
                #print('Base64 Table: %s' % alphabet)

                # Jump Table
                location = address + Dynamic.JMPTAB
                f.seek(segm.OFFSET + Dynamic.JMPTAB)

                for entry in xrange(Dynamic.JMPTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(
                        location + (entry * 0x18),
                        Relocation(f).resolve(alphabet, nids, symbols, lids),
                        False)

            except:
                pass

            # Relocation Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)

                # Relocation Table (with specific addends)
                location = address + Dynamic.RELATAB
                f.seek(segm.OFFSET + Dynamic.RELATAB)

                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Relocation(f).process(nids, symbols), False)

            except:
                pass

            # Hash Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Hash Entry Structure
                members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2),
                           ('buckets', 'Buckets', 0x2),
                           ('chains', 'Chains', 0x2)]
                struct = segm.struct('Hash', members)

                # Hash Table
                location = address + Dynamic.HASHTAB
                f.seek(segm.OFFSET + Dynamic.HASHTAB)

                for entry in xrange(Dynamic.HASHTABSZ / 0x8):
                    idaapi.create_struct(location + (entry * 0x8), 0x8, struct)

            except:
                pass

            # Dynamic Tag Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Tag Entry Structure
                members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)]
                struct = segm.struct('Tag', members)

                f.seek(offset)

                for entry in xrange(dynamicsize / 0x10):
                    idaapi.create_struct(dynamic + (entry * 0x10), 0x10,
                                         struct)
                    idc.set_cmt(
                        dynamic + (entry * 0x10),
                        Dynamic(f).comment(address, stubs, modules, libraries),
                        False)

            except:
                pass

    # Start Function
    idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)

    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()

    # Set No Return for __stack_chk_fail...
    try:
        function = idc.get_name_ea_simple('__stack_chk_fail')
        function = idaapi.get_func(function)
        function.flags |= FUNC_NORET
        idaapi.update_func(function)

    except:
        pass

    # Missed Function Creation...
    try:
        code = idaapi.get_segm_by_name('CODE')

        address = code.start_ea
        end = code.end_ea

        # Final Pass
        print('# Performing Final Pass...')
        while address < end:
            address = idaapi.find_not_func(address, SEARCH_DOWN)

            if idaapi.is_unknown(idaapi.get_flags(address)):
                idaapi.create_insn(address)
            else:
                idc.add_func(address)

            address += 4

    except:
        pass

    print('# Done!')
    return 1
Exemplo n.º 19
0
def load_file(f, neflags, format):

    print('# PS4 Kernel Loader')
    ps = Binary(f)

    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL,
                         'gnulnx_x64')

    # Segment Loading...
    for segm in ps.E_SEGMENTS:
        if segm.name() == 'PHDR':
            kASLR = False if segm.FILE_SIZE == 0x118 else True

        # Process Loadable Segments...
        if segm.name() in ['CODE', 'DATA', 'SCE_RELRO']:
            address = segm.MEM_ADDR
            size = segm.MEM_SIZE

            # Dumped Kernel Fix-ups
            if segm.name() in ['DATA', 'SCE_RELRO'
                               ] and (idaapi.get_segm_by_name('CODE').start_ea
                                      != 0xFFFFFFFF82200000 or not kASLR):
                offset = address - idaapi.get_segm_by_name('CODE').start_ea
                dumped = segm.MEM_SIZE
            else:
                offset = segm.OFFSET
                dumped = segm.FILE_SIZE

            print('# Creating %s Segment...' % segm.name())
            f.file2base(offset, address, address + dumped, FILEREG_PATCHABLE)

            idaapi.add_segm(0, address, address + size, segm.name(),
                            segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)

            # Processor Specific Segment Details
            idc.set_segm_addressing(address, bitness)
            idc.set_segm_alignment(address, segm.alignment())
            idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())

        # Process Dynamic Segment...
        elif segm.name() == 'DYNAMIC':
            code = idaapi.get_segm_by_name('CODE')
            data = idaapi.get_segm_by_name('DATA')
            relro = idaapi.get_segm_by_name('SCE_RELRO')

            # ------------------------------------------------------------------------------------------------------------
            # Dynamic Tag Entry Structure
            members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)]
            struct = segm.struct('Tag', members)

            # Dynamic Tag Table
            stubs = {}
            modules = {}
            location = segm.MEM_ADDR

            # Dumps are offset by a small amount
            if code.start_ea != 0xFFFFFFFF82200000:
                dumped = code.start_ea - 0xFFFFFFFF82200000
            else:
                dumped = 0

            f.seek(location - code.start_ea)
            for entry in xrange(segm.MEM_SIZE / 0x10):
                idaapi.create_struct(location + (entry * 0x10), 0x10, struct)
                idc.set_cmt(location + (entry * 0x10),
                            Dynamic(f).process(dumped, stubs, modules), False)

            # ------------------------------------------------------------------------------------------------------------
            # Hash Entry Structure
            members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2),
                       ('buckets', 'Buckets', 0x2), ('chains', 'Chains', 0x2)]
            struct = segm.struct('Hash', members)

            # Hash Table
            try:
                location = Dynamic.HASHTAB
                size = Dynamic.HASHTABSZ

            except:
                location = Dynamic.HASH
                size = Dynamic.SYMTAB - location

            f.seek(location - code.start_ea)
            for entry in xrange(size / 0x8):
                idaapi.create_struct(location + (entry * 0x8), 0x8, struct)

            if kASLR:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)

                # Relocation Table (with specific addends)
                location = Dynamic.RELATAB

                f.seek(location - code.start_ea)
                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Relocation(f).process(dumped, code.end_ea),
                                False)

                # Initialization Function
                idc.add_entry(Dynamic.INIT, Dynamic.INIT, '.init', True)

            else:
                # --------------------------------------------------------------------------------------------------------
                # Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('offset', 'Value', 0x8), ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)

                # Symbol Table
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea)
                functions = {}

                # .symtab
                idc.add_entry(location, location, '.symtab', False)

                for entry in xrange((Dynamic.STRTAB - location) / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Symbol(f).process(functions), False)

                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = Dynamic.STRTAB

                # .strtab
                idc.add_entry(location, location, '.strtab', False)

                # Functions
                for key in functions:
                    idc.create_strlit(location + key, BADADDR)
                    functions[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Function', False)

                functions = sorted(functions.iteritems(),
                                   key=operator.itemgetter(0))
                #print('Functions: %s' % functions)

                # Resolve Functions
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea + 0x18)

                for entry in xrange((Dynamic.STRTAB - location - 0x18) / 0x18):
                    Symbol(f).resolve(functions[entry][1])

    # Fix-up
    if kASLR:
        address = relro.start_ea
        del_items(address, DELIT_SIMPLE, relro.end_ea - address)

        while address < relro.end_ea:
            create_data(address, FF_QWORD, 0x8, BADNODE)
            address += 0x8

    address = code.start_ea

    # ELF Header Structure
    members = [('File format', 0x4), ('File class', 0x1),
               ('Data encoding', 0x1), ('File version', 0x1), ('OS/ABI', 0x1),
               ('ABI version', 0x1), ('Padding', 0x7), ('File type', 0x2),
               ('Machine', 0x2), ('File version', 0x4), ('Entry point', 0x8),
               ('PHT file offset', 0x8), ('SHT file offset', 0x8),
               ('Processor-specific flags', 0x4), ('ELF header size', 0x2),
               ('PHT entry size', 0x2), ('Number of entries in PHT', 0x2),
               ('SHT entry size', 0x2), ('Number of entries in SHT', 0x2),
               ('SHT entry index for string table\n', 0x2)]

    for (comment, size) in members:
        flags = idaapi.get_flags_by_size(size)
        idc.create_data(address, flags if flags != 0 else FF_STRLIT, size,
                        BADNODE)
        idc.set_cmt(address, comment, False)
        address += size

    for index, entry in enumerate(ps.E_SEGMENTS):
        # ELF Program Header Structure
        members = [('Type: %s' % entry.name(), 0x4), ('Flags', 0x4),
                   ('File offset', 0x8), ('Virtual address', 0x8),
                   ('Physical address', 0x8), ('Size in file image', 0x8),
                   ('Size in memory image', 0x8), ('Alignment\n', 0x8)]

        for (comment, size) in members:
            flags = idaapi.get_flags_by_size(size)

            idc.create_data(address, flags if flags != 0 else FF_STRLIT, size,
                            BADNODE)
            idc.set_cmt(address, comment, False)
            address += size

    # Wait for the AutoAnalyzer to Complete...
    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()

    if kASLR:
        # Start Function
        idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)

        # Xfast_syscall
        address = idaapi.find_binary(
            code.start_ea, code.end_ea,
            '0F 01 F8 65 48 89 24 25 A8 02 00 00 65 48 8B 24', 0x10,
            SEARCH_DOWN)
        idaapi.do_unknown(address, 0)
        idaapi.create_insn(address)
        idaapi.add_func(address, BADADDR)
        idaapi.set_name(address, 'Xfast_syscall', SN_NOCHECK | SN_NOWARN)

        # --------------------------------------------------------------------------------------------------------
        # Znullptr's syscalls
        print('# Processing Znullptr\'s Syscalls...')

        # Syscall Entry Structure
        members = [('narg', 'Number of Arguments', 0x4),
                   ('_pad', 'Padding', 0x4), ('function', 'Function', 0x8),
                   ('auevent', 'Augmented Event?', 0x2),
                   ('_pad1', 'Padding', 0x2), ('_pad2', 'Padding', 0x4),
                   ('trace_args_func', 'Trace Arguments Function', 0x8),
                   ('entry', 'Entry', 0x4), ('return', 'Return', 0x4),
                   ('flags', 'Flags', 0x4), ('thrcnt', 'Thread Count?', 0x4)]
        struct = segm.struct('Syscall', members)

        znullptr(code.start_ea, code.end_ea,
                 '4F 52 42 49 53 20 6B 65 72 6E 65 6C 20 53 45 4C 46', struct)

        # --------------------------------------------------------------------------------------------------------
        # Chendo's cdevsw con-struct-or
        print('# Processing Chendo\'s cdevsw structs...')

        # cdevsw Entry Structure
        members = [('d_version', 'Version', 0x4), ('d_flags', 'Flags', 0x4),
                   ('d_name', 'Name', 0x8), ('d_open', 'Open', 0x8),
                   ('d_fdopen', 'File Descriptor Open', 0x8),
                   ('d_close', 'Close', 0x8), ('d_read', 'Read', 0x8),
                   ('d_write', 'Write', 0x8),
                   ('d_ioctl', 'Input/Ouput Control', 0x8),
                   ('d_poll', 'Poll', 0x8), ('d_mmap', 'Memory Mapping', 0x8),
                   ('d_strategy', 'Strategy', 0x8), ('d_dump', 'Dump', 0x8),
                   ('d_kqfilter', 'KQFilter', 0x8), ('d_purge', 'Purge', 0x8),
                   ('d_mmap_single', 'Single Memory Mapping', 0x8),
                   ('d_spare0', 'Spare0', 0x8), ('d_spare1', 'Spare1', 0x8),
                   ('d_spare2', 'Spare2', 0x8), ('d_spare3', 'Spare3', 0x8),
                   ('d_spare4', 'Spare4', 0x8), ('d_spare5', 'Spare5', 0x8),
                   ('d_spare6', 'Spare6', 0x4), ('d_spare7', 'Spare7', 0x4)]
        struct = segm.struct('cdevsw', members)

        chendo(data.start_ea, data.end_ea, '09 20 12 17', struct)

    # --------------------------------------------------------------------------------------------------------
    # Pablo's IDC
    try:
        print('# Processing Pablo\'s Push IDC...')

        # Script 1) Push it real good...
        pablo(code.start_ea, code.end_ea,
              'C5 FA 5A C0 C5 F2 5A C9 C5 EA 5A D2 C5 FB 59 C1')
        pablo(code.start_ea, code.end_ea, 'C5 F9 7E C0 31 C9')
        pablo(code.start_ea, code.end_ea, '48 89 E0 55 53')
        pablo(code.start_ea, code.end_ea, 'B8 2D 00 00 00 C3')
        pablo(code.start_ea, code.end_ea, '31 C0 C3')
        pablo(code.start_ea, code.end_ea, '55 48 89')
        pablo(code.start_ea, code.end_ea, '48 81 EC A0 00 00 00 C7')
        pablo(code.start_ea, code.end_ea, '48 81 EC A8 00 00 00')

        # Script 2) Fix-up Dumped Data Pointers...
        if dumped or not kASLR:
            print('# Processing Pablo\'s Dumped Data Pointers IDC...')
            pablo(data.start_ea, data.end_ea, '?? FF FF FF FF')

    except:
        pass

    # --------------------------------------------------------------------------------------------------------
    # Kiwidog's __stack_chk_fail
    if kASLR:
        print('# Processing Kiwidog\'s Stack Functions...')

        kiwidog(
            code.start_ea, code.end_ea,
            '73 74 61 63 6B 20 6F 76 65 72 66 6C 6F 77 20 64 65 74 65 63 74 65 64 3B'
        )

    # --------------------------------------------------------------------------------------------------------
    # Final Pass
    print('# Performing Final Pass...')
    address = code.start_ea
    while address < code.end_ea:
        address = idaapi.find_not_func(address, SEARCH_DOWN)

        if idaapi.is_unknown(idaapi.get_flags(address)):
            idaapi.create_insn(address)
        else:
            idc.add_func(address)

        address += 4

    print('# Done!')
    return 1
Exemplo n.º 20
0
def rename_vtable_functions(names, vtable_ea, class_name): # type: (typing.Dict[int, str], int, str) -> None
    ea = vtable_ea
    i = 0
    while True:
        function_ea = struct.unpack('<Q', idaapi.get_many_bytes(ea, 8))[0]
        if '__cxa_pure_virtual' not in idc.GetDisasm(function_ea) and not idaapi.is_func(idaapi.get_flags(function_ea)):
            break

        member_fn_name = names.get(i, "m%d" % i)
        function_name = "%s::%s" % (class_name, member_fn_name)
        current_name = idc.GetFunctionName(function_ea)
        if current_name.startswith('nullsub_') or current_name.startswith('j_nullsub_'):
            idc.MakeNameEx(function_ea, function_name + '_null', idaapi.SN_NOWARN)
        elif current_name.startswith('sub_') or \
            current_name.startswith("%s::m%d" % (class_name, i)) or \
            "runtimetypeinfo" in current_name.lower():
            idc.MakeNameEx(function_ea, function_name, idaapi.SN_NOWARN)
        i += 1
        ea += 8
Exemplo n.º 21
0
def has_all_vtable_functions_named(vtable_ea): # type: (int) -> bool
    ea = vtable_ea
    while True:
        function_ea = struct.unpack('<Q', idaapi.get_many_bytes(ea, 8))[0]
        if '__cxa_pure_virtual' not in idc.GetDisasm(function_ea) and not idaapi.is_func(idaapi.get_flags(function_ea)):
            break
        current_name = idc.GetFunctionName(function_ea)
        if current_name.startswith('sub_') or current_name.startswith('j_sub_'):
            return False
        ea += 8
    return True
Exemplo n.º 22
0
Arquivo: Node.py Projeto: yaps8/grap
    def __init__(self, ea, cs, IDA_inst, IDA_inst_size, IDA_inst_string):
        """Initialization function, to disassemble with Capstone"""
        # Init the node structure
        node_t.__init__(self)

        # Check if it's a code instruction
        try:
            is_c = is_code(get_flags(ea))
        except:
            is_c = isCode(GetFlags(ea))
        if not is_c:
            raise CodeException

        #
        # fill node_t struct
        #

        # NodeInfo
        self.info = NodeInfo()
        inst_elements = []

        if cs is not None:
            try:
                size = create_insn(ea)
                bytes = get_bytes(ea, size)
            except:
                size = MakeCode(ea)
                bytes = GetManyBytes(ea, size)

            (address, size, mnemonic,
             op_str) = next(cs.disasm_lite(bytes, ea, count=1))
        else:
            address = ea
            size = IDA_inst_size
            splitted = IDA_inst_string.split(" ")
            mnemonic = splitted[0]
            op_str = " ".join(splitted[1:])

        self.info.opcode = mnemonic
        self.info.inst_str = self.info.opcode + " " + op_str

        splitted = op_str.split(", ")
        self.info.nargs = 0

        if len(splitted) >= 1:
            self.info.arg1 = splitted[0]
            self.info.nargs += 1
            if len(splitted) >= 2:
                self.info.arg2 = splitted[1]
                self.info.nargs += 1
                if len(splitted) >= 3:
                    self.info.arg3 = splitted[2]
                    self.info.nargs += 1

        # No node will be root but this is acceptable for CFGs
        self.info.is_root = False

        self.info.address = ea
        self.info.has_address = True

        # node_t
        self.node_id = self._genid()