예제 #1
0
    def __extract_member_from_pointer(self, cexpr, obj):
        parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op),
                           list(self.parents)[:0:-1])
        parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1])

        logger.debug("Parsing expression {}. Parents - {}".format(
            obj.name, parents_type))

        # Extracting offset and removing expression parents making this offset
        if parents_type[0] in ('idx', 'add'):
            # `obj[idx]' or `(TYPE *) + x'
            if parents[0].y.op != idaapi.cot_num:
                # There's no way to handle with dynamic offset
                return
            offset = parents[0].y.numval() * cexpr.type.get_ptrarr_objsize()
            cexpr = self.parent_expr()
            if parents_type[0] == 'add':
                del parents_type[0]
                del parents[0]
        elif parents_type[0:2] == ['cast', 'add']:
            # (TYPE *)obj + offset or (TYPE)obj + offset
            if parents[1].y.op != idaapi.cot_num:
                return
            if parents[0].type.is_ptr():
                size = parents[0].type.get_ptrarr_objsize()
            else:
                size = 1
            offset = parents[1].theother(parents[0]).numval() * size
            cexpr = parents[1]
            del parents_type[0:2]
            del parents[0:2]
        else:
            offset = 0

        return self.__extract_member(cexpr, obj, offset, parents, parents_type)
예제 #2
0
    def __extract_member_from_xword(self, cexpr, obj):
        parents_type = [idaapi.get_ctype_name(x.cexpr.op) for x in list(self.parents)[:0:-1]]
        parents = [x.cexpr for x in list(self.parents)[:0:-1]]

        logger.debug("Parsing expression {}. Parents - {}".format(obj.name, parents_type))

        if parents_type[0] == 'add':
            if parents[0].theother(cexpr).op != idaapi.cot_num:
                return
            offset = parents[0].theother(cexpr).numval()
            cexpr = self.parent_expr()
            del parents_type[0]
            del parents[0]
        else:
            offset = 0

        return self.__extract_member(cexpr, obj, offset, parents, parents_type)
예제 #3
0
    def __extract_member_from_xword(self, cexpr, obj):
        parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op),
                           list(self.parents)[:0:-1])  #0为null,所以需跳过
        parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1])
        logger.debug("Parsing expression {}. Parents - {}".format(
            obj.name, parents_type))
        if parents_type[0] == 'add':
            ocexptr = parents[0].theother(cexpr)
            if ocexptr.op != idaapi.cot_num:
                return
            offset = ocexptr.numval()
            cexpr = self.parent_expr()
            del parents_type[0]
            del parents[0]
        else:
            offset = 0

        return self.__extract_member(cexpr, obj, offset, parents, parents_type)
예제 #4
0
    def check_member_assignment(self, expression, index):
        """
        We are now in cexpr_t == idaapi.cot_var. This function checks if expression is part of member assignment
        statement. Returns None if not.

        :param expression: idaapi.cexpr_t
        :param index: int
        :return: Structures.AbstractField
        """
        parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op),
                           list(self.parents)[:0:-1])
        parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1])

        for parent in parents:
            if parent.ea != idaapi.BADADDR:
                self.expression_address = parent.ea
                break
        else:
            self.expression_address = idaapi.BADADDR

        offset = 0

        if parents_type[0:2] == ['asg', 'expr']:
            if parents[0].y == expression:
                # Assignment like (v1 = v2) where v2 is scanned variable
                if parents[0].x.op == idaapi.cot_var:
                    self.add_variable(parents[0].x.v.idx)
                    return
            else:
                # if expression is (var = something), we have to explore whether continue to scan this variable or not
                if parents[0].y.op != idaapi.cot_num:
                    if parents[0].y.op == idaapi.cot_call:
                        # Check if expression: var = function((TYPE) var, ...) or var = function(var, ...)
                        args = parents[0].y.a
                        if args and ((args[0].op == idaapi.cot_cast
                                      and args[0].x.op == idaapi.cot_var
                                      and args[0].x.v.idx == index) or
                                     (args[0].op == idaapi.cot_var
                                      and args[0].v.idx == index)):
                            return
                    try:
                        self.protected_variables.remove(index)
                    except KeyError:
                        print "[Info] Remove variable {0} from scan list, address: 0x{1:08X}".format(
                            index, self.expression_address)
                        self.variables.pop(index)
                    return

        # Assignment like v1 = (TYPE) v2 where TYPE is one the supported types
        elif parents_type[0:3] == ['cast', 'asg', 'expr']:
            if parents[1].x.op == idaapi.cot_var:
                if filter(lambda x: x.equals_to(parents[0].type),
                          Const.LEGAL_TYPES):
                    self.add_variable(parents[1].x.v.idx)
                    return

        # Universal call with no cast conversion and offsets: call(..., this, ...)
        if parents_type[0] == 'call':
            arg_index, _ = Helper.get_func_argument_info(
                parents[0], expression)
            if SCAN_ALL_ARGUMENTS or not arg_index:
                self.scan_function(parents[0].x.obj_ea, 0, arg_index)
            return

        # --------------------------------------------------------------------------------------------
        # When variable is DWORD, int, __int64 etc
        # --------------------------------------------------------------------------------------------
        elif self.variables[index].equals_to(Const.X_WORD_TINFO):

            if parents_type[0:2] == ['add', 'cast']:
                if parents[0].theother(expression).op != idaapi.cot_num:
                    return
                offset = parents[0].theother(expression).numval()

                if parents_type[2] == 'ptr':
                    if parents_type[3] == 'asg':
                        if parents[3].x == parents[2]:
                            # *(TYPE *)(var + x) = ???
                            return self.get_member(
                                offset,
                                index,
                                object=parents[3].y,
                                default=parents[1].type.get_pointed_object())
                        if parents[3].x.op == idaapi.cot_var:
                            # other_var = *(TYPE *)(var + x)
                            return self.create_member(offset, index,
                                                      parents[3].x.type)
                    return self.create_member(
                        offset, index, parents[1].type.get_pointed_object())

                elif parents_type[2] == 'call':
                    # call(..., (TYPE)(var + x), ...)
                    if parents[0].theother(expression).op != idaapi.cot_num:
                        return
                    offset = parents[0].theother(expression).numval()
                    return self.get_member(offset,
                                           index,
                                           call=parents[2],
                                           arg=parents[1])

                elif parents_type[2] == 'asg':
                    # other_var = (LEGAL TYPE) (var + offset)
                    if parents[2].y == parents[1] and parents[
                            2].x.op == idaapi.cot_var:
                        if filter(lambda x: x.equals_to(parents[1].type),
                                  Const.LEGAL_TYPES):
                            self.scan_function(self.function.entry_ea, offset,
                                               parents[2].x.v.idx)
                            return

                cast_type = parents[1].type
                if cast_type.is_ptr():
                    return self.create_member(offset, index,
                                              cast_type.get_pointed_object())

            elif parents_type[0:2] == ['cast', 'ptr']:

                if parents_type[2] == 'asg' and parents[2].x == parents[1]:
                    # *(TYPE *)var = ???
                    return self.get_member(
                        0,
                        index,
                        object=parents[2].y,
                        default=parents[0].type.get_pointed_object())
                return self.create_member(0, index,
                                          parents[0].type.get_pointed_object())

            elif parents_type[0:2] == ['cast', 'call']:
                # call(..., (TYPE)(var + x), ...)
                return self.get_member(0,
                                       index,
                                       call=parents[1],
                                       arg=parents[0])

            elif parents_type[0] == 'add':
                # call(..., var + x, ...)
                if parents[0].theother(expression).op != idaapi.cot_num:
                    return
                offset = parents[0].theother(expression).numval()

                if parents_type[1] == 'call':
                    return self.get_member(offset,
                                           index,
                                           call=parents[1],
                                           arg=parents[0])

                elif parents_type[1] == 'asg':
                    if parents[1].y == parents[0] and parents[
                            1].x.op == idaapi.cot_var:
                        self.scan_function(self.function.entry_ea, offset,
                                           parents[1].x.v.idx)
                        return

            elif parents_type[0] == 'asg':
                # var = (int)&Some_object
                if parents[0].y.op == idaapi.cot_cast and parents[
                        0].y.x.op == idaapi.cot_ref:
                    return self.create_member(
                        0, index, parents[0].y.x.type.get_pointed_object())

        # --------------------------------------------------------------------------------------------
        # When variable is void *, PVOID, DWORD *, QWORD * etc
        # --------------------------------------------------------------------------------------------
        else:
            # print "[DEBUG] D* Parents:", parents_type
            offset = 0

            if parents_type[0] == 'idx':
                if parents[0].y.op != idaapi.cot_num:
                    # There's no way to handle with dynamic offset
                    return None
                offset = parents[0].y.numval(
                ) * self.variables[index].get_ptrarr_objsize()
                if parents_type[1] == 'asg' and parents[1].x == parents[0]:
                    # var[idx] = ???
                    return self.get_member(
                        offset,
                        index,
                        object=parents[1].y,
                        default=self.variables[index].get_pointed_object())
                elif parents_type[1] == 'cast':
                    # (TYPE) var[idx]
                    return self.create_member(offset, index, parents[1].type)
                return self.create_member(offset, index, Const.X_WORD_TINFO)
            elif parents_type[0:2] == ['ptr', 'asg']:
                # *var = ???
                return self.get_member(
                    0,
                    index,
                    object=parents[1].y,
                    default=self.variables[index].get_pointed_object())
            else:
                if parents_type[0:2] == ['cast', 'ptr']:

                    if parents_type[2] == 'call':
                        # call(..., *(TYPE *) var, ...)
                        return self.get_member(0,
                                               index,
                                               call=parents[2],
                                               arg=parents[1])
                    elif parents_type[2] == 'asg' and parents[2].x == parents[
                            1]:
                        # *(TYPE *) var = ???
                        return self.get_member(
                            0,
                            index,
                            object=parents[2].y,
                            default=parents[0].type.get_pointed_object())

                elif parents_type[0:2] == ['cast', 'add']:
                    if parents[1].theother(parents[0]).op != idaapi.cot_num:
                        return None
                    offset = parents[1].theother(parents[0]).numval()
                    offset *= parents[0].type.get_ptrarr_objsize(
                    ) if parents[0].type.is_ptr() else 1

                    if parents_type[2] == 'ptr':
                        if parents_type[3] == 'asg' and parents[
                                3].x == parents[2]:
                            # *((TYPE *)var + x) = ???
                            return self.get_member(
                                offset,
                                index,
                                object=parents[3].y,
                                default=parents[0].type.get_pointed_object())
                        return self.create_member(
                            offset, index,
                            parents[0].type.get_pointed_object())
                    elif parents_type[2] == 'call':
                        # call(..., (TYPE)var + offset, ...)
                        return self.get_member(offset,
                                               index,
                                               call=parents[2],
                                               arg=parents[1])
                    elif parents_type[2] == 'cast' and parents[2].type.is_ptr(
                    ):
                        if parents_type[3] == 'call':
                            # call(..., (TYPE *) ((TYPE *)var + x), ...)
                            # Where argument type is not the same as cast type. Ida has a bug here choosing sometimes
                            # wrong pointer type
                            idx, tinfo = Helper.get_func_argument_info(
                                parents[3], parents[2])
                            return self.create_member(
                                offset, index, tinfo.get_pointed_object())

                        # (TYPE *) ((TYPE *)var + x)
                        return self.create_member(
                            offset, index,
                            parents[2].type.get_pointed_object())

                elif parents_type[0:2] == ['add', 'cast']:
                    if parents[0].theother(expression).op != idaapi.cot_num:
                        return None
                    offset = parents[0].theother(expression).numval(
                    ) * self.variables[index].get_ptrarr_objsize()

                    if parents_type[2] == 'call':
                        # call(..., (TYPE)(var + x), ...)
                        return self.get_member(offset,
                                               index,
                                               call=parents[2],
                                               arg=parents[1])
                    elif parents_type[2] == 'asg':
                        if parents[2].y == parents[1] and parents[
                                2].x.op == idaapi.cot_var:
                            if filter(lambda x: x.equals_to(parents[1].type),
                                      Const.LEGAL_TYPES):
                                self.scan_function(self.function.entry_ea,
                                                   offset, parents[2].x.v.idx)
                                return
                    else:
                        return self.create_member(
                            offset, index,
                            parents[1].type.get_pointed_object())

                elif parents_type[0] == 'add':

                    # call(..., var + offset, ...)
                    if parents[0].theother(expression).op != idaapi.cot_num:
                        return None
                    offset = parents[0].theother(expression).numval(
                    ) * self.variables[index].get_ptrarr_objsize()

                    if parents_type[1] == 'call':
                        return self.get_member(offset,
                                               index,
                                               call=parents[1],
                                               arg=parents[0])

                    if parents_type[1] == 'asg':
                        # other_var = var + offset
                        if parents[1].y == parents[0] and parents[
                                1].x.op == idaapi.cot_var:
                            self.scan_function(self.function.entry_ea, offset,
                                               parents[1].x.v.idx)
                            return

                elif parents_type[0:2] == ['cast', 'call']:
                    # call(..., (TYPE) var, ...)
                    return self.get_member(0,
                                           index,
                                           call=parents[1],
                                           arg=parents[0])

                elif parents_type[0] == 'ptr':
                    if parents_type[1] == 'cast':
                        # (TYPE) *var
                        return self.create_member(0, index, parents[0].type)
                    # *var
                    return self.create_member(
                        0, index, self.variables[index].get_pointed_object())

                elif parents_type[0] == 'asg':
                    return

        if 'return' not in parents_type[0:2] and parents_type[0] not in (
                'if', 'band', 'eq', 'ne', 'cast'):
            print "[DEBUG] Unhandled type", self.variables[index].dstr(), \
                "Index:", index, \
                "Offset:", offset, \
                "Function:", idaapi.get_ea_name(self.function.entry_ea), \
                "Address: 0x{0:08X}".format(expression.ea), \
                "Parents:", parents_type