Пример #1
0
    def processNewInstance(self, cls, method, prototype, stack):
        logger.debug("Processing new instance. DST: [%s%s%s]..." % (cls, method, prototype))
        #test code
#         print "\n"
#         for stackEntry in stack:
#             print stackEntry
#         print "\n"
        #end of test code
        newInstanceDstFromClient = (cls, method, prototype)
        newInstancePosInStack = self._findFirstNewInstancePos(stack)
        throughMethod = stack[newInstancePosInStack]
        newInstanceSrcFromStack = stack[newInstancePosInStack + 1]
        if newInstancePosInStack == -1:
            self._addSuspiciousNewInstance(throughMethod, newInstanceDstFromClient, stack)
            return

        for newInstancePathFromSources in self._sources_newInstance:
            newInstanceSrcFromSources = newInstancePathFromSources[0]
            if newInstanceSrcFromSources != newInstanceSrcFromStack:
                continue

            self._addNewInstancePathToMCG(newInstanceSrcFromSources, throughMethod, newInstanceDstFromClient)

            if newInstancePathFromSources in self._uncovered_newInstance:
                self._uncovered_newInstance.remove(newInstancePathFromSources)
            return

        self._addSuspiciousNewInstance(throughMethod, newInstanceDstFromClient, stack)
Пример #2
0
    def printMoiLists(self, toLogger=True):
        printStr = None

        if self._uncovered_invoke or self._uncovered_newInstance or self._uncovered_dexload:
            printStr = "Printing still uncovered methods of interest:\n\n"
            if self._uncovered_invoke:
                printStr +="REFLECTION INVOKE:\n"
                for (src, dst) in self._uncovered_invoke:
                    printStr += "SRC: [%s %s %s]\n" % src
                    printStr += "DST: [%s %s %s]\n" % dst

            if self._uncovered_newInstance:
                printStr += "REFLECTION NEW_INSTANCE:\n"
                for (src, dst) in self._uncovered_newInstance:
                    printStr += "SRC: [%s %s %s]\n" % src
                    printStr += "DST: [%s %s %s]\n" % dst

            if self._uncovered_dexload:
                printStr += "DYNAMIC LOAD:\n"
                for (src, dst) in self._uncovered_dexload:
                    printStr += "SRC: [%s %s %s]\n" % src
                    printStr += "DST: [%s %s %s]\n" % dst
        else:
            printStr = "All methods of interest are covered at least one time!!!\n"

        if toLogger:
            logger.debug("%s" % printStr)
        else:
            print printStr
Пример #3
0
    def processInvoke(self, cls, method, prototype, stack):
        logger.debug("Processing method invoke: [%s %s %s]..."% (cls, method, prototype))
        #test code
#         print "\n"
#         for stackEntry in stack:
#             print stackEntry
#         print "\n"
        #end of test code

        invokeDstFromClient = (cls, method, prototype)
        invokePosInStack = self._findFirstInvokePos(stack)
        throughMethod = stack[invokePosInStack]
        invokeSrcFromStack = stack[invokePosInStack + 1]
        if invokePosInStack == -1:
            logger.info("Cannot find the first occurrence of invoke method in the stack! Adding method to suspicious list!")
            self._addSuspiciousInvoke(throughMethod, invokeDstFromClient, stack)
            return


        for invokePathFromSources in self._sources_invoke:
            invokeSrcFromSources = invokePathFromSources[0]
            if invokeSrcFromSources != invokeSrcFromStack:
                continue

            self._addInvokePathToMCG(invokeSrcFromSources, throughMethod, invokeDstFromClient)

            if invokePathFromSources in self._uncovered_invoke:
                self._uncovered_invoke.remove(invokePathFromSources)
            return

        self._addSuspiciousInvoke(throughMethod, invokeDstFromClient, stack)
Пример #4
0
    def processDexLoad(self, fileName, source, output, stack):
        logger.debug("Processing dex load message...")

        file_hash = getSha256(fileName)
        file_load_count = self._loaded_files_count.setdefault(file_hash, 0) + 1
        newFilePath = self._rename_source_file(fileName, file_hash, str(file_load_count))

        self._loaded_files_count[file_hash] = file_load_count
        self._codeFiles[newFilePath] = file_hash

        dexloadPathFromStack = self._getDexLoadPathFromStack(stack)

        if dexloadPathFromStack:
            srcFromStack = dexloadPathFromStack[0]
            throughMethod = dexloadPathFromStack[1]
            if dexloadPathFromStack in self._uncovered_dexload:
                self._uncovered_dexload.remove(dexloadPathFromStack)

            self._addDexloadPathToMCG(srcFromStack, throughMethod, newFilePath)
            #we do analyse files if appropriate dex load calls have found in sources of application
            #and if we have not analysed file yet
            if file_load_count > 1:
                logger.info("File [%s] with hash [%s] is loaded for the [%d]th time! Skipping its analysis!" % (newFilePath, file_hash, file_load_count))
            else:
                self.makeFileAnalysis(newFilePath)
            return

        #if the stack does not contain a dexload method detected in the sources
        self._addSuspiciousDexload(newFilePath, stack)
        logger.debug("Dex load message processed!")
Пример #5
0
 def _addNewInstancePathToMCG(self, src, through, dst):
     logger.debug("Adding newInstance method path to our graph...")
     tupl = (src, through, dst)
     if tupl not in self._covered_newInstance:
         self._covered_newInstance.append(tupl)
         self._stadynaMcg.addNewInstancePath(src, through, dst)
         logger.info("The path [%s] -- [%s] through [%s] for newInstance method is added to our graph!" % (str(src), str(dst), str(through)))
     else:
         logger.info("The path [%s] -- [%s] through [%s] for newInstance method is already in our graph!" % (str(src), str(dst), str(through)))
Пример #6
0
 def _addDexloadPathToMCG(self, src, through, filename):
     logger.debug("Adding dexload method path to our graph...")
     tupl = (src, through, filename)
     if tupl not in self._covered_dexload:
         self._covered_dexload.append(tupl)
         self._stadynaMcg.addDexloadPath(src, through, filename)
         logger.info("The path [%s] -- [%s] through [%s] for dexload is added to our graph!" % (str(src), str(filename), str(through)))
     else:
         logger.info("The path [%s] -- [%s] through [%s] for dexload is already in our graph!" % (str(src), str(filename), str(through)))
Пример #7
0
    def makeFileAnalysis(self, file_path):
        logger.debug("Performing analysis of file [%s]..." % file_path)

        a = None
        d = None
        dx = None

        ret_type = androconf.is_android(file_path)
        if ret_type == "APK":
            a = apk.APK(file_path)
            d = dvm.DalvikVMFormat(a.get_dex())

        elif ret_type == "DEX" :
            try :
                d = dvm.DalvikVMFormat(open(file_path, "rb").read())
            except Exception as e :
                logger.error("[%s] is not valid dex file!" % file_path, e)
                return


        dx = analysis.VMAnalysis(d)

        invokeMethodPaths = analysis.seccon_get_invoke_method_paths(dx)
        newInstanceMethodPaths = analysis.seccon_get_newInstance_method_paths(dx)
        dynamicMethodPaths = analysis.seccon_get_dyncode_loading_paths(dx)

        if invokeMethodPaths:
            t = None
            for path in invokeMethodPaths:
                src = path.get_src(d.get_class_manager())
                dst = path.get_dst(d.get_class_manager())
                t = (src, dst)
                self._sources_invoke.append(t)
                self._uncovered_invoke.append(t)

        if newInstanceMethodPaths:
            t = None
            for path in newInstanceMethodPaths:
                src = path.get_src(d.get_class_manager())
                dst = path.get_dst(d.get_class_manager())
                t = (src, dst)
                self._sources_newInstance.append(t)
                self._uncovered_newInstance.append(t)

        if dynamicMethodPaths:
            t = None
            for path in dynamicMethodPaths:
                src = path.get_src(d.get_class_manager())
                dst = path.get_dst(d.get_class_manager())
                t = (src, dst)
                self._sources_dexload.append(t)
                self._uncovered_dexload.append(t)

        #building MFG for the file
        self._stadynaMcg.analyseFile(dx, a)
Пример #8
0
    def performFinalInfoSave(self, where, resultsFileName, executionTime = -1):
        logger.debug("Saving information...")
        self.calculateFinalNumbers()
        #saving gexf
        finalGexfFileName = "%s%s" % (resultsFileName, "_final")
        self.saveGexf(where, finalGexfFileName)


        #saving log file
        logFileName = '%s%s' % (resultsFileName, '_log.txt')
        logSavePath = os.path.join(where, logFileName)
        self._save_log_file(logSavePath, executionTime)

        logger.debug("Final results are saved!")
Пример #9
0
def log_result_path_information(res, res_prefix, res_type) :
    """
        @param res : a result from the detector's result list
        @param res_prefix : result's category name
        @param res_type : result's type

        @rtype : void - it only logs extra information about the analysis result
    """
    res_info = res.get_info()
    if len(res_info) > 0:
        paths = res.get_paths()

        for path in res.get_paths() :
            access, idx = path[0]
            m_idx = path[1]
            logger.info("'%s' %s found '%s'" % (res_prefix, res_type, res_info ) )
            logger.debug("\t=> access_flag %s, index %s, method_index %s" % (access, idx, m_idx))
Пример #10
0
    def _getDexLoadPathFromStack(self, stack):
        logger.debug("Processing dex load stack...")
        #test code
#         print "\n"
#         for stackEntry in stack:
#             print stackEntry
#         print "\n"
        #end of test code

        #we iterate over stack (not over entries in sources)
        #because it is possible that there are several dexload entries
        #in the stack. Thus, we look for the most recent one.
        for stackEntryPos in xrange(1, len(stack)):
            stackEntry = stack[stackEntryPos]
            for dexloadPathFromSources in self._sources_dexload:
                dexloadSrcFromSources = dexloadPathFromSources[0]
                dexloadDstFromSources = dexloadPathFromSources[1]
                if stackEntry != dexloadSrcFromSources:
                    continue

                prevStackEntry = stack[stackEntryPos - 1]
                if prevStackEntry == dexloadDstFromSources:
                    logger.debug("The method, which calls dexload, is found [%s%s%s]!" % dexloadSrcFromSources)
                    return dexloadPathFromSources

        logger.debug("The called dexload method was not detected in sources!")
        return None
Пример #11
0
    def _findFirstInvokePos(self, tmpList):
        logger.debug("Finding the first occurrence of invoke method in the stack...")
        position = -1
        for entry in tmpList:
            position += 1
            if entry[0] == "Ljava/lang/reflect/Method;" and entry[1] == "invoke" and entry[2] == "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;":
                logger.debug("The position of the first occurrence of invoke method is [%d]!" % position)
                return position

        logger.debug("We have not found invoke method in the stack!")
        return position
Пример #12
0
    def _findFirstNewInstancePos(self, tmpList):
        logger.debug("Finding the first occurrence of new instance method in the stack...")
        position = -1
        for entry in tmpList:
            position += 1
            #print entry
            cls = entry[0]
            if cls != "Ljava/lang/Class;" and cls != "Ljava/lang/reflect/Constructor;":
                continue
            method = entry[1]
            if method != "newInstance":
                continue
            logger.debug("The position of the first occurrence of new instance method is [%d]!" % position)
            return position

        logger.debug("We have not found new instance method in the stack!")
        return position
Пример #13
0
    def set_attribute(self, name, value):
        if name not in self.attributes.keys():
            logger.debug("There is no [%name] key in the Node attributes!"
                         % name)

        self.attributes[name] = value
Пример #14
0
 def init(self):
     # step 1:Extract
     logger.debug("Unzipping the APK")
     self.unzip()
     self.decompile()
     return {}
Пример #15
0
def backtrace_registers_before_call(x, method, index_to_find) :
    """
        @param x : a VMAnalysis instance
        @param method : a regexp for the method (the package)
        @param index_to_find : index of the matching method

        @rtype : an ordered list of dictionaries of each register content [{ 'register #': 'value' }, { 'register #': 'value' } ...]
    """
    registers = {}

    code = method.get_code()
    #code.show()

    bc = code.get_bc()
    instruction_list = [ i for i in bc.get_instructions() ]


    found_index = find_call_index_in_code_list(index_to_find, instruction_list)

    if (found_index < 0) :
        logger.error("The call index in the code list can not be found")
        return 0

    else :
        # Initialize the returned list of dictionaries
        registers_final = []

        # Initialize the harvesting dictionary
        registers_found = {}

        # List the register indexes related to the method call
        relevant_registers = relevant_registers_for_the_method(instruction_list[found_index])

        #print relevant_registers

        i = int(found_index) - 1 # start index


        while ((all_relevant_registers_filled(registers_found,relevant_registers) != True) and (i >= 0)) :
            #current_instruction = instruction_list[i].show_buff(0)
            #print current_instruction
            current_instruction = instruction_list[i]

            instruction_name, local_register_number, local_register_value, registers_found =  match_current_instruction(current_instruction, registers_found)

            if cmp(instruction_name, APUT) == 0:
                try :
                    list_index_to_be_changed = relevant_registers.index(str(local_register_value))
                    #print "index_to_be_changed %s" % list_index_to_be_changed
                    del(relevant_registers[int(local_register_value)])
                    relevant_registers.insert(list_index_to_be_changed, local_register_number)
                    logger.debug("New relevant_registers %s" % relevant_registers)
                except :
                    logger.debug("'%s' does not exist anymore in the relevant_registers list" % local_register_value)

            if (cmp(instruction_name, MOVE_RESULT) == 0) and (local_register_number in relevant_registers):
                try:
                    #past_instruction = instruction_list[i-1].show_buff(0)
                    #print past_instruction
                    past_instruction = instruction_list[i-1]
                    p_instruction_name, p_local_register_number, p_local_register_value, registers_found =  match_current_instruction(past_instruction, registers_found)


                    if cmp(p_instruction_name, INVOKE_NO_REGISTER) == 0 :
                        registers_found[local_register_number] = p_local_register_value

                    else:
                        list_index_to_be_changed = relevant_registers.index(str(local_register_number))
                        del(relevant_registers[int(list_index_to_be_changed)])
                        relevant_registers.insert(list_index_to_be_changed, p_local_register_number)

                    logger.debug("New relevant_registers %s" % relevant_registers)

                except:
                    logger.debug("'%s' does not exist anymore in the relevant_registers list" % local_register_value)

            i = i - 1

        #log.info('Registers found during the analysis %s' % registers_found)



        final_answer = all_relevant_registers_filled(registers_found,relevant_registers)
        logger.debug("Are all relevant registers filled ? %s" % str(final_answer))

        for i in relevant_registers :
            try:
                register_number = i
                #print register_number

                register_value  = registers_found[i]
                #print register_value

                temp_dict = { register_number : register_value }
                registers_final.append(temp_dict)

            except KeyError:
                registers_final = []
                logger.debug("KeyError exception : The value of the register # %s could not be found for the relevant registers %s" % (register_number, relevant_registers))
                break



        return registers_final