Example #1
0
    def getPackageUid(self, package_name):
        logger.debug("Getting UID of the package [%s]..." % package_name)
        uid = -1
        if not self.is_alive():
            logger.error("The device [%s] is not running!" % self.device_name)
            return uid
        if package_name == "":
            logger.warning("The name of the package is not specified!")
            return uid

        uid_lines = subprocess.check_output([
            'adb', '-s', self.device_name, 'shell', 'cat',
            '/data/system/packages.list'
        ])
        lines = uid_lines.splitlines()
        for i in range(
                0, len(lines)):  #first line just announces the list of devices
            words = lines[i].split(' ')
            if words[0].strip() == package_name:
                uid = int(words[1].strip())
                break

        logger.debug("The UID of the package [%s] is [%d]" %
                     (package_name, uid))
        return uid
    def _convertDex2JarFiles(self,
                             converter,
                             dexFilesRootDir,
                             dexFilesRelativePaths,
                             jarFilesRootDir,
                             proceedOnError=True):
        jarFilesRelativePaths = []
        for dexFileRelativePath in dexFilesRelativePaths:
            dexFilePath = os.path.join(dexFilesRootDir, dexFileRelativePath)
            jarFileRelativePath = os.path.splitext(
                dexFileRelativePath)[0] + ".jar"
            jarFilePath = os.path.join(jarFilesRootDir, jarFileRelativePath)
            try:
                converter.convertDex2Jar(dexFilePath,
                                         jarFilePath,
                                         overwrite=True)
            except Dex2JarConvertionError as e:
                if proceedOnError:
                    logger.warning("Cannot convert [%s] to [%s]. %s" (
                        dexFilePath, jarFilePath, e.msg))
                    continue
                else:
                    raise
            jarFilesRelativePaths.append(jarFileRelativePath)

        return jarFilesRelativePaths
Example #3
0
 def addInvokePath(self, src, through, dst):
     src_class_name, src_method_name, src_descriptor = src
     dst_class_name, dst_method_name, dst_descriptor = dst
     through_class_name, through_method_name, through_descriptor = through
     key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name, src_descriptor, through_class_name, through_method_name, through_descriptor, POSTFIX_REFL_INVOKE)
     n1 = self._get_existed_node(key)
     if n1 == None:
         logger.warning("Something wrong has happened! Could not find invoke Node in Graph with key [%s]" % str(key))
         return
     
     n2 = self._get_node(NODE_METHOD, (dst_class_name, dst_method_name, dst_descriptor))
     n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
     n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
     n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
     
     self.G.add_edge(n1.id, n2.id)
     
     #check if called method calls protected feature
     data = "%s-%s-%s" % (dst_class_name, dst_method_name, dst_descriptor)
     if data in DVM_PERMISSIONS_BY_API_CALLS:
         logger.info("BINGOOOOOOO! The protected method is called through reflection!")
         perm = DVM_PERMISSIONS_BY_API_CALLS[ data ]
         key1 = "%s %s %s %s %s %s %s %s" %  (through_class_name, through_method_name, through_descriptor, dst_class_name, dst_method_name, dst_descriptor, POSTFIX_PERM, perm)
         n3 = self._get_node(NODE_FAKE_PERMISSION, key1, perm, False)
         n3.set_attribute(ATTR_CLASS_NAME, dst_class_name)
         n3.set_attribute(ATTR_METHOD_NAME, dst_method_name)
         n3.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
         n3.set_attribute(ATTR_PERM_NAME, perm)
         n3.set_attribute(ATTR_PERM_LEVEL, MANIFEST_PERMISSIONS[ perm ][0])
         self.G.add_edge(n2.id, n3.id)
    def _instrFilesWithEmma(self,
                            instrumenter,
                            jarFilesRootDir,
                            jarFilesRelativePaths,
                            instrJarsRootDir,
                            coverageMetadataFile,
                            proceedOnError=True):

        instrJarFilesRelativePaths = []
        for jarFileRelativePath in jarFilesRelativePaths:
            jarFileAbsPath = os.path.join(jarFilesRootDir, jarFileRelativePath)
            instrJarRelativeDir = jarFileRelativePath[:jarFileRelativePath.
                                                      rfind("/") + 1]
            instrJarFullDir = os.path.join(instrJarsRootDir,
                                           instrJarRelativeDir)

            try:
                instrumenter.instrumentJarWithEmma(
                    jarFile=jarFileAbsPath,
                    outputFolder=instrJarFullDir,
                    emmaMetadataFile=coverageMetadataFile)
            except EmmaCannotInstrumentException as e:
                if proceedOnError:
                    logger.warning("Cannot instrument [%s]. %s" (
                        jarFileAbsPath, e.msg))
                    continue
                else:
                    raise
            instrJarFilesRelativePaths.append(jarFileRelativePath)

        return instrJarFilesRelativePaths
Example #5
0
 def _convertJar2DexWithInstr(self, converter, instrJarsRootDir, 
                              instrJarFilesRelativePaths, 
                              finalDexFilesRootDir, proceedOnError):
     instrDexFilesRelativePaths = []
     for jarFileRelativePath in instrJarFilesRelativePaths:
         jarFileAbsPath = os.path.join(instrJarsRootDir, jarFileRelativePath)
         dexFileRelativePath = os.path.splitext(jarFileRelativePath)[0] + ".dex"
         dexFileAbsPath = os.path.join(finalDexFilesRootDir, dexFileRelativePath)
         
         #we instrument main file with auxiliary classes
         print "jarFileRelativePath: " + jarFileRelativePath
         
         try:
             withFiles = []
             #we compile main file with additional instrumentation files
             #hack: emma copies instrumented jar files into lib folder
             if jarFileRelativePath == "classes.jar":
                 emmaDevicePath = os.path.join(self.config.getEmmaDir(), self.config.getEmmaDeviceJar())
                 withFiles.append(self.config.getAndroidSpecificInstrumentationClassesPath())
                 withFiles.append(emmaDevicePath)
             
             converter.convertJar2Dex(jarFile=jarFileAbsPath, 
                                      dexFile=dexFileAbsPath, 
                                      withFiles=withFiles, 
                                      overwrite=True)
         except Jar2DexConvertionError as e:
             if proceedOnError:
                 logger.warning("Cannot instrument [%s]. %s" % (jarFileAbsPath, e.msg))
                 continue
             else:
                 raise
         instrDexFilesRelativePaths.append(dexFileRelativePath)
     
     return instrDexFilesRelativePaths
Example #6
0
    def start_activity(self, package_name, activity_name):
        #adb shell am start -n com.package.name/com.package.name.ActivityName
        logger.debug("Starting activity [%s] of the package [%s]..." %
                     (package_name, activity_name))
        if not self.is_alive():
            logger.error("The device [%s] is not running!" % self.device_name)
            return

        if not package_name:
            logger.warning("The name of the package is not specified!")
            return

        if not activity_name:
            logger.warning("The name of the activity is not specified!")
            return

        run_string = package_name + '/' + activity_name

        try:
            with open(os.devnull, 'w') as f_null:
                subprocess.check_call([
                    'adb', '-s', self.device_name, 'shell', 'am start', '-n',
                    run_string
                ],
                                      stderr=f_null)
        except subprocess.CalledProcessError:
            logger.error("Could not run activity!")
            return
Example #7
0
def analyseStadynaMsg(device, filesDir, stadynaAnalyser, stadynaMsg):
    logger.debug("Analysing obtained message...")
    operation = int(stadynaMsg.get(consts.JSON_OPERATION))
    if operation == consts.OP_CLASS_NEW_INSTANCE:
        logger.debug("Obtained message is OP_CLASS_NEW_INSTANCE!")
        processNewInstanceMsg(stadynaAnalyser, stadynaMsg)
        return
    if operation == consts.OP_METHOD_INVOKE:
        logger.debug("Obtained message is OP_METHOD_INVOKE!")
        processInvokeMsg(stadynaAnalyser, stadynaMsg)
        return
    if operation == consts.OP_DEX_LOAD:
        logger.debug("Obtained message is OP_DEX_LOAD!")
        processDexLoadMsg(device, filesDir, stadynaAnalyser, stadynaMsg)
        return
    logger.warning("Program does not contain routine to process message: [%d]!" % operation)
Example #8
0
 def _convertDex2JarFiles(self, converter, dexFilesRootDir, dexFilesRelativePaths, jarFilesRootDir, proceedOnError=True):
     jarFilesRelativePaths = []
     for dexFileRelativePath in dexFilesRelativePaths:
         dexFilePath = os.path.join(dexFilesRootDir, dexFileRelativePath)
         jarFileRelativePath = os.path.splitext(dexFileRelativePath)[0] + ".jar"
         jarFilePath = os.path.join(jarFilesRootDir, jarFileRelativePath)
         try:
             converter.convertDex2Jar(dexFilePath, jarFilePath, overwrite=True)
         except Dex2JarConvertionError as e:
             if proceedOnError:
                 logger.warning("Cannot convert [%s] to [%s]. %s" (dexFilePath, jarFilePath, e.msg))
                 continue
             else:
                 raise
         jarFilesRelativePaths.append(jarFileRelativePath) 
         
     return jarFilesRelativePaths
Example #9
0
 def get_file(self, what, to_dir):
     logger.debug("Coping file [%s] from device to directory [%s]..." % (what, to_dir))
     if not self.is_alive():
         logger.error("The device [%s] is not running!" % self.device_name)
         return False
     
     if what == "":
         logger.warning("The name of the file to download is not specified!")
         return False
     
     try:
         with open(os.devnull, 'w') as f_null:
             subprocess.check_call(["adb", "-s", self.device_name, "pull", what, to_dir], stderr=f_null)
     except subprocess.CalledProcessError:
         logger.error("Could not download file [%s] from the device!" % what)
         return False
     
     logger.debug("File [%s] is downloaded!" % what)
     return True
Example #10
0
 def install_package(self, apk_path):
     logger.debug("Installing application [%s]..." % apk_path)
     if not self.is_alive():
         logger.error("The device [%s] is not running!" % str(self.device_name))
         return False
     
     if apk_path == "":
         logger.warning("The path to the application to install is not specified!")
         return False
     
     try:
         with open(os.devnull, 'w') as f_null:
             subprocess.check_call(["adb", "-s", self.device_name, "install", "-r", apk_path], stderr=f_null)
     except subprocess.CalledProcessError:
         logger.error("Could not install application [%s] on the device!" % apk_path)
         return False
     
     logger.debug("Application [%s] is installed!" % apk_path)
     return True
    def _convertJar2DexWithInstr(self, converter, instrJarsRootDir,
                                 instrJarFilesRelativePaths,
                                 finalDexFilesRootDir, proceedOnError):
        instrDexFilesRelativePaths = []
        for jarFileRelativePath in instrJarFilesRelativePaths:
            jarFileAbsPath = os.path.join(instrJarsRootDir,
                                          jarFileRelativePath)
            dexFileRelativePath = os.path.splitext(
                jarFileRelativePath)[0] + ".dex"
            dexFileAbsPath = os.path.join(finalDexFilesRootDir,
                                          dexFileRelativePath)

            #we instrument main file with auxiliary classes
            print "jarFileRelativePath: " + jarFileRelativePath

            try:
                withFiles = []
                #we compile main file with additional instrumentation files
                #hack: emma copies instrumented jar files into lib folder
                if jarFileRelativePath == "classes.jar":
                    emmaDevicePath = os.path.join(
                        self.config.getEmmaDir(),
                        self.config.getEmmaDeviceJar())
                    withFiles.append(
                        self.config.
                        getAndroidSpecificInstrumentationClassesPath())
                    withFiles.append(emmaDevicePath)

                converter.convertJar2Dex(jarFile=jarFileAbsPath,
                                         dexFile=dexFileAbsPath,
                                         withFiles=withFiles,
                                         overwrite=True)
            except Jar2DexConvertionError as e:
                if proceedOnError:
                    logger.warning("Cannot instrument [%s]. %s" %
                                   (jarFileAbsPath, e.msg))
                    continue
                else:
                    raise
            instrDexFilesRelativePaths.append(dexFileRelativePath)

        return instrDexFilesRelativePaths
Example #12
0
 def _instrFilesWithEmma(self, instrumenter, jarFilesRootDir, jarFilesRelativePaths, 
         instrJarsRootDir, coverageMetadataFile, proceedOnError=True):
     
     instrJarFilesRelativePaths = []
     for jarFileRelativePath in jarFilesRelativePaths:
         jarFileAbsPath = os.path.join(jarFilesRootDir, jarFileRelativePath)
         instrJarRelativeDir = jarFileRelativePath[:jarFileRelativePath.rfind("/")+1]
         instrJarFullDir = os.path.join(instrJarsRootDir, instrJarRelativeDir)
         
         try:
             instrumenter.instrumentJarWithEmma(jarFile=jarFileAbsPath, outputFolder=instrJarFullDir, emmaMetadataFile=coverageMetadataFile)
         except EmmaCannotInstrumentException as e:
             if proceedOnError:
                 logger.warning("Cannot instrument [%s]. %s" (jarFileAbsPath, e.msg))
                 continue
             else:
                 raise
         instrJarFilesRelativePaths.append(jarFileRelativePath)
     
     return instrJarFilesRelativePaths
Example #13
0
 def get_package_uid(self, package_name):
     logger.debug("Getting UID of the package [%s]..." % package_name)
     uid = -1
     if not self.is_alive():
         logger.error("The device [%s] is not running!" % self.device_name)
         return uid
     if package_name == "":
         logger.warning("The name of the package is not specified!")
         return uid
     
     uid_lines = subprocess.check_output(['adb', '-s', self.device_name, 'shell', 'cat', '/data/system/packages.list'])
     lines = uid_lines.splitlines()
     for i in range(0,len(lines)): #first line just announces the list of devices
         words = lines[i].split(' ')
         if words[0].strip() == package_name:
             uid = int(words[1].strip())
             break
     
     logger.debug("The UID of the package [%s] is [%d]" % (package_name, uid))
     return uid
Example #14
0
 def initAlreadyInstrApkEnv(self, pathToInstrApk, resultsDir, pathToInstrManifestFile=None):
     if not apk_utils.checkInputApkFile(pathToInstrApk):
         logger.error("Provided file [%s] is not a valid apk file!" % pathToInstrApk)
         return
     
     if not os.path.isdir(resultsDir):
         logger.error("Provided path to results dir [%s] do not point to dir!" % resultsDir)
         return
     
     coverageMetadataFolderPath = os.path.join(resultsDir, self.config.getCoverageMetadataRelativeDir())
     if not os.path.isdir(coverageMetadataFolderPath):
         logger.error("In the results dir [%s] there is no folder with coverage metadata!" % resultsDir)
         return
     self.coverageMetadataFolder = coverageMetadataFolderPath
     
     if self.config.getCoverageMetadataFilename() not in os.listdir(coverageMetadataFolderPath):
         logger.error("Cannot find metadata filename in the coverage metadata folder: %s!" % self.coverageMetadataFolder)
         return 
     
     self.coverageMetadataFile = os.path.join(self.coverageMetadataFolder, self.config.getCoverageMetadataFilename())
     
     #by default trying to look for a file in the 
     if pathToInstrManifestFile:
         androidManifestPath = pathToInstrManifestFile
     else:
         androidManifestPath = os.path.join(resultsDir, "AndroidManifest.xml")
     
     if not os.path.isfile(androidManifestPath):
         logger.warning("Path [%s] is not pointing to a real file! Leaving pointer to AndroidManifest.xml empty!" % androidManifestPath)
         return
     
     self.instrumentedApk = pathToInstrApk
     self.apkResultsDir = resultsDir
     self.runtimeReportsRootDir = self._createDir(resultsDir, self.config.getRuntimeReportsRelativeDir(), False, False)
     self.androidManifestFile = androidManifestPath
     
     self.androidManifest = AndroidManifest(self.androidManifestFile)
     self.packageName = self.androidManifest.getInstrumentationTargetPackage()
     self.runnerName = self.androidManifest.getInstrumentationRunnerName()
     
     self._bboxStateMachine.start(STATE_VALID_SETTINGS_PROVIDED)
Example #15
0
    def addInvokePath(self, src, through, dst):
        src_class_name, src_method_name, src_descriptor = src
        dst_class_name, dst_method_name, dst_descriptor = dst
        through_class_name, through_method_name, through_descriptor = through
        key = "%s %s %s %s %s %s %s" % (
            src_class_name, src_method_name, src_descriptor,
            through_class_name, through_method_name, through_descriptor,
            POSTFIX_REFL_INVOKE)
        n1 = self._get_existed_node(key)
        if n1 == None:
            logger.warning(
                "Something wrong has happened! Could not find invoke Node in Graph with key [%s]"
                % str(key))
            return

        n2 = self._get_node(NODE_METHOD,
                            (dst_class_name, dst_method_name, dst_descriptor))
        n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
        n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
        n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)

        self.G.add_edge(n1.id, n2.id)

        #check if called method calls protected feature
        data = "%s-%s-%s" % (dst_class_name, dst_method_name, dst_descriptor)
        if data in DVM_PERMISSIONS_BY_API_CALLS:
            logger.info(
                "BINGOOOOOOO! The protected method is called through reflection!"
            )
            perm = DVM_PERMISSIONS_BY_API_CALLS[data]
            key1 = "%s %s %s %s %s %s %s %s" % (
                through_class_name, through_method_name, through_descriptor,
                dst_class_name, dst_method_name, dst_descriptor, POSTFIX_PERM,
                perm)
            n3 = self._get_node(NODE_FAKE_PERMISSION, key1, perm, False)
            n3.set_attribute(ATTR_CLASS_NAME, dst_class_name)
            n3.set_attribute(ATTR_METHOD_NAME, dst_method_name)
            n3.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
            n3.set_attribute(ATTR_PERM_NAME, perm)
            n3.set_attribute(ATTR_PERM_LEVEL, MANIFEST_PERMISSIONS[perm][0])
            self.G.add_edge(n2.id, n3.id)
Example #16
0
def check_spell(doc):
    #SpellChecker
    words = [token.text for token in doc]
    misspelled = spell.unknown(words)
    misspelled
    
    errors = []
    
    if misspelled:
        for misspell in misspelled:

            if misspell == ' ' or misspell in words:
                logger.warning(f'word "{misspell}" skipped in spelling correction')
                continue

            correct = spell.correction(misspell)
            tip = spell.candidates(misspell)
            misspell_text = f'Esta palavra... "{misspell}"'
            error = {'match': misspell_text,'correct': correct, 'tip': 'Você quis dizer "{}"?'.format(correct)}
            errors.append(error)
        
    return errors
Example #17
0
 def start_activity(self, package_name, activity_name):
     #adb shell am start -n com.package.name/com.package.name.ActivityName 
     logger.debug("Starting activity [%s] of the package [%s]..." % (package_name, activity_name))
     if not self.is_alive():
         logger.error("The device [%s] is not running!" % self.device_name)
         return
     
     if not package_name:
         logger.warning("The name of the package is not specified!")
         return
     
     if not activity_name:
         logger.warning("The name of the activity is not specified!")
         return
     
     run_string = package_name + '/' + activity_name
     
     try:
         with open(os.devnull, 'w') as f_null:
             subprocess.check_call(['adb', '-s', self.device_name, 'shell', 'am start', '-n', run_string], stderr=f_null)
     except subprocess.CalledProcessError:
         logger.error("Could not run activity!")
         return
Example #18
0
    def get_file(self, what, to_dir):
        logger.debug("Coping file [%s] from device to directory [%s]..." %
                     (what, to_dir))
        if not self.is_alive():
            logger.error("The device [%s] is not running!" % self.device_name)
            return False

        if what == "":
            logger.warning(
                "The name of the file to download is not specified!")
            return False

        try:
            with open(os.devnull, 'w') as f_null:
                subprocess.check_call(
                    ["adb", "-s", self.device_name, "pull", what, to_dir],
                    stderr=f_null)
        except subprocess.CalledProcessError:
            logger.error("Could not download file [%s] from the device!" %
                         what)
            return False

        logger.debug("File [%s] is downloaded!" % what)
        return True
Example #19
0
    def install_package(self, apk_path):
        logger.debug("Installing application [%s]..." % apk_path)
        if not self.is_alive():
            logger.error("The device [%s] is not running!" %
                         str(self.device_name))
            return False

        if apk_path == "":
            logger.warning(
                "The path to the application to install is not specified!")
            return False

        try:
            with open(os.devnull, 'w') as f_null:
                subprocess.check_call(
                    ["adb", "-s", self.device_name, "install", "-r", apk_path],
                    stderr=f_null)
        except subprocess.CalledProcessError:
            logger.error("Could not install application [%s] on the device!" %
                         apk_path)
            return False

        logger.debug("Application [%s] is installed!" % apk_path)
        return True
    def initAlreadyInstrApkEnv(self,
                               pathToInstrApk,
                               resultsDir,
                               pathToInstrManifestFile=None):
        if not apk_utils.checkInputApkFile(pathToInstrApk):
            logger.error("Provided file [%s] is not a valid apk file!" %
                         pathToInstrApk)
            return

        if not os.path.isdir(resultsDir):
            logger.error(
                "Provided path to results dir [%s] do not point to dir!" %
                resultsDir)
            return

        coverageMetadataFolderPath = os.path.join(
            resultsDir, self.config.getCoverageMetadataRelativeDir())
        if not os.path.isdir(coverageMetadataFolderPath):
            logger.error(
                "In the results dir [%s] there is no folder with coverage metadata!"
                % resultsDir)
            return
        self.coverageMetadataFolder = coverageMetadataFolderPath

        if self.config.getCoverageMetadataFilename() not in os.listdir(
                coverageMetadataFolderPath):
            logger.error(
                "Cannot find metadata filename in the coverage metadata folder: %s!"
                % self.coverageMetadataFolder)
            return

        self.coverageMetadataFile = os.path.join(
            self.coverageMetadataFolder,
            self.config.getCoverageMetadataFilename())

        #by default trying to look for a file in the
        if pathToInstrManifestFile:
            androidManifestPath = pathToInstrManifestFile
        else:
            androidManifestPath = os.path.join(resultsDir,
                                               "AndroidManifest.xml")

        if not os.path.isfile(androidManifestPath):
            logger.warning(
                "Path [%s] is not pointing to a real file! Leaving pointer to AndroidManifest.xml empty!"
                % androidManifestPath)
            return

        self.instrumentedApk = pathToInstrApk
        self.apkResultsDir = resultsDir
        self.runtimeReportsRootDir = self._createDir(
            resultsDir, self.config.getRuntimeReportsRelativeDir(), False,
            False)
        self.androidManifestFile = androidManifestPath

        self.androidManifest = AndroidManifest(self.androidManifestFile)
        self.packageName = self.androidManifest.getInstrumentationTargetPackage(
        )
        self.runnerName = self.androidManifest.getInstrumentationRunnerName()

        self._bboxStateMachine.start(STATE_VALID_SETTINGS_PROVIDED)
Example #21
0
    def analyseFile(self, vmx, apk):
        vm = vmx.get_vm()
        self.androGuardObjects.append((apk, vm, vmx))

        #         self.internal_methods.extend(vm.get_methods())

        #creating real internal nodes
        internal_called_methods = vmx.get_tainted_packages(
        ).stadyna_get_internal_called_methods()
        for method in internal_called_methods:
            class_name, method_name, descriptor = method

            nodeType = None
            if method_name == "<clinit>":
                nodeType = NODE_STATIC_INIT
            elif method_name == "<init>":
                nodeType = NODE_CONSTRUCTOR
            else:
                nodeType = NODE_METHOD
            n = self._get_node(nodeType, (class_name, method_name, descriptor))
            n.set_attribute(ATTR_CLASS_NAME, class_name)
            n.set_attribute(ATTR_METHOD_NAME, method_name)
            n.set_attribute(ATTR_DESCRIPTOR, descriptor)
            self.G.add_node(n.id)

        #creating real edges (nodes are already there)
        #currently we are working only with internal packages.
        for j in vmx.get_tainted_packages().get_internal_packages():
            src_class_name, src_method_name, src_descriptor = j.get_src(
                vm.get_class_manager())
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst(
                vm.get_class_manager())

            n1 = self._get_existed_node(
                (src_class_name, src_method_name, src_descriptor))
            #             n1.set_attribute(ATTR_CLASS_NAME, src_class_name)
            #             n1.set_attribute(ATTR_METHOD_NAME, src_method_name)
            #             n1.set_attribute(ATTR_DESCRIPTOR, src_descriptor)

            n2 = self._get_existed_node(
                (dst_class_name, dst_method_name, dst_descriptor))
            #             n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
            #             n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
            #             n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
            self.G.add_edge(n1.id, n2.id)

        #adding fake class nodes
        for method in internal_called_methods:
            src_class_name, src_method_name, src_descriptor = method
            if src_method_name == "<init>" or src_method_name == "<clinit>":
                n1 = self._get_existed_node(
                    (src_class_name, src_method_name, src_descriptor))
                n2 = self._get_node(NODE_FAKE_CLASS, src_class_name, None,
                                    False)
                n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
                if src_method_name == "<clinit>":
                    self.G.add_edge(n1.id, n2.id)
                elif src_method_name == "<init>":
                    self.G.add_edge(n2.id, n1.id)

        #real (external) reflection invoke nodes
        reflection_invoke_paths = analysis.seccon_get_invoke_method_paths(vmx)
        for j in reflection_invoke_paths:
            src_class_name, src_method_name, src_descriptor = j.get_src(
                vm.get_class_manager())
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst(
                vm.get_class_manager())

            n1 = self._get_existed_node(
                (src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning(
                    "Cannot find the node [%s], where reflection invoke is called!"
                    % (src_class_name, src_method_name, src_descriptor))
                continue

            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name,
                                            src_descriptor, dst_class_name,
                                            dst_method_name, dst_descriptor,
                                            POSTFIX_REFL_INVOKE)
            n2 = self._get_node(NODE_REFL_INVOKE, key, LABEL_REFL_INVOKE, True)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)

            self.G.add_edge(n1.id, n2.id)

        #real (external) reflection new instance nodes
        reflection_newInstance_paths = analysis.seccon_get_newInstance_method_paths(
            vmx)
        for j in reflection_newInstance_paths:
            src_class_name, src_method_name, src_descriptor = j.get_src(
                vm.get_class_manager())
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst(
                vm.get_class_manager())

            n1 = self._get_existed_node(
                (src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning(
                    "Cannot find the node [%s], where reflection new instance is called!"
                    % (src_class_name, src_method_name, src_descriptor))
                continue

            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name,
                                            src_descriptor, dst_class_name,
                                            dst_method_name, dst_descriptor,
                                            POSTFIX_REFL_NEWINSTANCE)
            n2 = self._get_node(NODE_REFL_NEWINSTANCE, key,
                                LABEL_REFL_NEWINSTANCE, True)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)

            self.G.add_edge(n1.id, n2.id)

        #adding fake entry points
        if apk != None:
            for i in apk.get_activities():
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node(
                    (j, "onCreate", "(Landroid/os/Bundle;)V"))
                if n1 != None:
                    key = "%s %s %s %s" % (j, "onCreate",
                                           "(Landroid/os/Bundle;)V",
                                           POSTFIX_ACTIVITY)
                    n2 = self._get_node(NODE_FAKE_ACTIVITY, key,
                                        LABEL_ACTIVITY, False)
                    self.G.add_edge(n2.id, n1.id)
                    self.entry_nodes.append(n1.id)

            for i in apk.get_services():
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node((j, "onCreate", "()V"))
                if n1 != None:
                    key = "%s %s %s %s" % (j, "onCreate", "()V",
                                           POSTFIX_SERVICE)
                    n2 = self._get_node(NODE_FAKE_SERVICE, key, LABEL_SERVICE,
                                        False)
                    self.G.add_edge(n2.id, n1.id)
                    self.entry_nodes.append(n1.id)

            for i in apk.get_receivers():
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node(
                    (j, "onReceive",
                     "(Landroid/content/Context;Landroid/content/Intent;)V"))
                if n1 != None:
                    key = "%s %s %s %s" % (
                        j, "onReceive",
                        "(Landroid/content/Context;Landroid/content/Intent;)V",
                        POSTFIX_RECEIVER)
                    n2 = self._get_node(NODE_FAKE_SERVICE, key, LABEL_RECEIVER,
                                        False)
                    self.G.add_edge(n2.id, n1.id)
                    self.entry_nodes.append(n1.id)

        #fake permissions
        list_permissions = vmx.stadyna_get_permissions([])
        for x in list_permissions:
            for j in list_permissions[x]:
                if isinstance(j, PathVar):
                    continue

                src_class_name, src_method_name, src_descriptor = j.get_src(
                    vm.get_class_manager())
                dst_class_name, dst_method_name, dst_descriptor = j.get_dst(
                    vm.get_class_manager())

                n1 = self._get_existed_node(
                    (src_class_name, src_method_name, src_descriptor))
                if n1 == None:
                    logger.warning(
                        "Cannot find node [%s %s %s] for permission [%s]!" %
                        (src_class_name, src_method_name, src_descriptor, x))
                    continue

                #SOURCE, DEST, POSTFIX, PERMISSION_NAME
                key = "%s %s %s %s %s %s %s %s" % (
                    src_class_name, src_method_name, src_descriptor,
                    dst_class_name, dst_method_name, dst_descriptor,
                    POSTFIX_PERM, x)
                n2 = self._get_node(NODE_FAKE_PERMISSION, key, x, False)
                n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
                n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
                n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
                n2.set_attribute(ATTR_PERM_NAME, x)
                n2.set_attribute(ATTR_PERM_LEVEL, MANIFEST_PERMISSIONS[x][0])

                self.G.add_edge(n1.id, n2.id)

        #fake DexClassLoader nodes
        dyn_code_loading = analysis.seccon_get_dyncode_loading_paths(vmx)
        for j in dyn_code_loading:
            src_class_name, src_method_name, src_descriptor = j.get_src(
                vm.get_class_manager())
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst(
                vm.get_class_manager())

            n1 = self._get_existed_node(
                (src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning(
                    "Cannot find dexload node [%s]!" %
                    (src_class_name, src_method_name, src_descriptor))
                continue

            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name,
                                            src_descriptor, dst_class_name,
                                            dst_method_name, dst_descriptor,
                                            POSTFIX_DEXLOAD)
            n2 = self._get_node(NODE_FAKE_DEXLOAD, key, LABEL_DEXLOAD, False)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)

            self.G.add_edge(n1.id, n2.id)

        # Specific Java/Android library
        for c in vm.get_classes():
            #if c.get_superclassname() == "Landroid/app/Service;" :
            #    n1 = self._get_node( c.get_name(), "<init>", "()V" )
            #    n2 = self._get_node( c.get_name(), "onCreate", "()V" )

            #    self.G.add_edge( n1.id, n2.id )
            if c.get_superclassname(
            ) == "Ljava/lang/Thread;" or c.get_superclassname(
            ) == "Ljava/util/TimerTask;":
                for i in vm.get_method("run"):
                    if i.get_class_name() == c.get_name():
                        n1 = self._get_node(NODE_METHOD,
                                            (i.get_class_name(), i.get_name(),
                                             i.get_descriptor()))
                        n2 = self._get_node(
                            NODE_METHOD,
                            (i.get_class_name(), "start", i.get_descriptor()))

                        # link from start to run
                        self.G.add_edge(n2.id, n1.id)
                        #n2.add_edge( n1, {} )

                        # link from init to start
                        for init in vm.get_method("<init>"):
                            if init.get_class_name() == c.get_name():
                                #TODO: Leaving _get_existed_node to check if all the nodes are included
                                #It is possible that internal_packages does not contain this node. Leaving _get_existed_node to check this
                                n3 = self._get_node(
                                    NODE_CONSTRUCTOR,
                                    (init.get_class_name(), "<init>",
                                     init.get_descriptor()))
                                self.G.add_edge(n3.id, n2.id)
Example #22
0
def perform_analysis(inputApkPath, resultsDirPath, sourceFilesDirPath):
    logger.debug("Starting analysis of the application [%s]..." % inputApkPath)
    startTime = time.time()

    if not copyFileToDir(inputApkPath, sourceFilesDirPath):
        logger.error(
            "Could not copy source file to directory! The analysis was not performed!"
        )
        return

    apkFileNameExt = os.path.basename(inputApkPath)
    apkFileName, _ = os.path.splitext(apkFileNameExt)
    apkFilePath = os.path.join(sourceFilesDirPath, apkFileNameExt)

    stadynaAnalyser = StadynaAnalyser()
    stadynaAnalyser.makeInitialAnalysis(apkFilePath)

    initial_name = apkFileName + "_initial"
    stadynaAnalyser.saveGexf(resultsDirPath, initial_name)

    if not stadynaAnalyser.containMethodsToAnalyse():
        logger.info("Input apk file does not contain suspicious methods!")
        stadynaAnalyser.performInfoSave(resultsDirPath, apkFileName)
        logger.info("The analysis is finished!")
        return

    stadynaAnalyser.printMoiLists()

    dev = getDeviceForDynAnalysis()
    if not dev.is_alive():
        logger.warning(
            "The selected device to perform dynamic analysis is not alive! Finishing!"
        )
        stadynaAnalyser.performInfoSave(resultsDirPath, apkFileName)
        logger.info("The analysis is finished!")
        return

    #TODO: Check if it is possible racing conditions here
    #If we at first install application and then run Message analyser
    #everything is fine.
    #If we at first start Message analyser and then start the application
    #the first dex load is actual load when the application is installed.

    androApk = apk.APK(inputApkPath)
    installed = dev.install_package(inputApkPath)
    if not installed:
        logger.error(
            "An error occurred during the installation of the app [%s]! Cannot perform an analysis!"
            % inputApkPath)
        return

    package = androApk.get_package()
    mainActivity = androApk.get_main_activity()
    uid = dev.get_package_uid(package)
    if uid == -1:
        logger.error(
            "Cannot get the uid of the package [%s]! Cannot start an analysis!"
            % package)
        return

    #TODO: test section
    messages = Queue.Queue()
    seccon_producer = SecconMessageProducer(dev, messages)
    seccon_producer.setDaemon(False)
    seccon_producer.start()

    #sleeping 3sec before starting new activity
    time.sleep(3)

    #Add here the invocation of the main activity
    startMainActivity(dev, package, mainActivity)

    while 1:
        while not messages.empty():
            line = messages.get()
            #print 'Received line: ' + repr(line)
            decodedLine = json.loads(line)
            if int(decodedLine.get(consts.JSON_UID)) != uid:
                continue
            analyseStadynaMsg(dev, sourceFilesDirPath, stadynaAnalyser,
                              decodedLine)
            stadynaAnalyser.printMoiLists()

        try:
            time.sleep(2)
            #The same method can be used for different calls. Thus, we comment this line now )
            #checkExit(stadynaAnalyser)
        except KeyboardInterrupt:
            logger.debug("Exiting...")
            break

    seccon_producer.stopThread()
    seccon_producer.join()

    endTime = time.time()

    stadynaAnalyser.performFinalInfoSave(resultsDirPath, apkFileName,
                                         (endTime - startTime))
    logger.info("The analysis is finished!")
Example #23
0
def perform_analysis(inputApkPath, resultsDirPath, sourceFilesDirPath):    
    logger.debug("Starting analysis of the application [%s]..." % inputApkPath)
    startTime = time.time()
    
    if not copyFileToDir(inputApkPath, sourceFilesDirPath):
        logger.error("Could not copy source file to directory! The analysis was not performed!")
        return
    
    apkFileNameExt = os.path.basename(inputApkPath)
    apkFileName, _ = os.path.splitext(apkFileNameExt)
    apkFilePath = os.path.join(sourceFilesDirPath, apkFileNameExt)
    
    stadynaAnalyser = StadynaAnalyser()
    stadynaAnalyser.makeInitialAnalysis(apkFilePath)
    
    initial_name = apkFileName + "_initial"
    stadynaAnalyser.saveGexf(resultsDirPath, initial_name)
    
    if not stadynaAnalyser.containMethodsToAnalyse():
        logger.info("Input apk file does not contain suspicious methods!")
        stadynaAnalyser.performInfoSave(resultsDirPath, apkFileName)
        logger.info("The analysis is finished!")
        return
    
    stadynaAnalyser.printMoiLists()
    
    dev = getDeviceForDynAnalysis()
    if not dev.is_alive():
        logger.warning("The selected device to perform dynamic analysis is not alive! Finishing!")
        stadynaAnalyser.performInfoSave(resultsDirPath, apkFileName)
        logger.info("The analysis is finished!")
        return
    
    #TODO: Check if it is possible racing conditions here
    #If we at first install application and then run Message analyser
    #everything is fine.
    #If we at first start Message analyser and then start the application
    #the first dex load is actual load when the application is installed. 
    
    androApk = apk.APK(inputApkPath)
    installed = dev.install_package(inputApkPath)
    if not installed:
        logger.error("An error occurred during the installation of the app [%s]! Cannot perform an analysis!" % inputApkPath)
        return
    
    package = androApk.get_package()
    mainActivity = androApk.get_main_activity() 
    uid = dev.get_package_uid(package)
    if uid == -1:
        logger.error("Cannot get the uid of the package [%s]! Cannot start an analysis!" % package)
        return
    
    #TODO: test section
    messages = Queue.Queue()
    seccon_producer = SecconMessageProducer(dev, messages)
    seccon_producer.setDaemon(False)
    seccon_producer.start()
    
    #sleeping 3sec before starting new activity 
    time.sleep(3)
    
    #Add here the invocation of the main activity
    startMainActivity(dev, package, mainActivity) 
    
    while 1:
        while not messages.empty():
            line = messages.get()
            #print 'Received line: ' + repr(line)
            decodedLine = json.loads(line)
            if int(decodedLine.get(consts.JSON_UID)) != uid:
                continue
            analyseStadynaMsg(dev, sourceFilesDirPath, stadynaAnalyser, decodedLine)
            stadynaAnalyser.printMoiLists()
        
        try:
            time.sleep(2)
            #The same method can be used for different calls. Thus, we comment this line now )
            #checkExit(stadynaAnalyser)  
        except KeyboardInterrupt:
            logger.debug("Exiting...")  
            break
    
    seccon_producer.stopThread()
    seccon_producer.join()
    
    endTime = time.time()
    
    stadynaAnalyser.performFinalInfoSave(resultsDirPath, apkFileName, (endTime-startTime))
    logger.info("The analysis is finished!")
Example #24
0
    def analyseFile(self, vmx, apk):
        vm = vmx.get_vm()
        self.androGuardObjects.append((apk, vm, vmx))

#         self.internal_methods.extend(vm.get_methods())
        
        #creating real internal nodes
        internal_called_methods = vmx.get_tainted_packages().stadyna_get_internal_called_methods()
        for method in internal_called_methods:
            class_name, method_name, descriptor = method
            
            nodeType = None
            if method_name == "<clinit>":
                nodeType = NODE_STATIC_INIT
            elif method_name == "<init>":
                nodeType = NODE_CONSTRUCTOR
            else:
                nodeType = NODE_METHOD
            n = self._get_node(nodeType, (class_name, method_name, descriptor))
            n.set_attribute(ATTR_CLASS_NAME, class_name)
            n.set_attribute(ATTR_METHOD_NAME, method_name)
            n.set_attribute(ATTR_DESCRIPTOR, descriptor)
            self.G.add_node(n.id)
            
        
        
        
        #creating real edges (nodes are already there)
        #currently we are working only with internal packages.
        for j in vmx.get_tainted_packages().get_internal_packages():
            src_class_name, src_method_name, src_descriptor = j.get_src(vm.get_class_manager())
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst(vm.get_class_manager())
             
            n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
#             n1.set_attribute(ATTR_CLASS_NAME, src_class_name)
#             n1.set_attribute(ATTR_METHOD_NAME, src_method_name)
#             n1.set_attribute(ATTR_DESCRIPTOR, src_descriptor)
             
            n2 = self._get_existed_node((dst_class_name, dst_method_name, dst_descriptor))
#             n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
#             n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
#             n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
            self.G.add_edge(n1.id, n2.id)
        
        
        
        #adding fake class nodes    
        for method in internal_called_methods:
            src_class_name, src_method_name, src_descriptor = method
            if src_method_name == "<init>" or src_method_name == "<clinit>":
                n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
                n2 = self._get_node(NODE_FAKE_CLASS, src_class_name, None, False)
                n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
                if src_method_name == "<clinit>":
                    self.G.add_edge(n1.id, n2.id)
                elif src_method_name == "<init>":
                    self.G.add_edge(n2.id, n1.id)
                
        
        #real (external) reflection invoke nodes    
        reflection_invoke_paths = analysis.seccon_get_invoke_method_paths(vmx)
        for j in reflection_invoke_paths:
            src_class_name, src_method_name, src_descriptor = j.get_src( vm.get_class_manager() )
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst( vm.get_class_manager() )
            
            n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning("Cannot find the node [%s], where reflection invoke is called!" % (src_class_name, src_method_name, src_descriptor))
                continue
            
            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name, src_descriptor, dst_class_name, dst_method_name, dst_descriptor, POSTFIX_REFL_INVOKE)
            n2 = self._get_node(NODE_REFL_INVOKE, key, LABEL_REFL_INVOKE, True)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)
            
            self.G.add_edge( n1.id, n2.id )
            
        
        #real (external) reflection new instance nodes   
        reflection_newInstance_paths = analysis.seccon_get_newInstance_method_paths(vmx)
        for j in reflection_newInstance_paths:
            src_class_name, src_method_name, src_descriptor = j.get_src( vm.get_class_manager() )
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst( vm.get_class_manager() )
            
            n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning("Cannot find the node [%s], where reflection new instance is called!" % (src_class_name, src_method_name, src_descriptor))
                continue
            
            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name, src_descriptor, dst_class_name, dst_method_name, dst_descriptor, POSTFIX_REFL_NEWINSTANCE)
            n2 = self._get_node(NODE_REFL_NEWINSTANCE, key, LABEL_REFL_NEWINSTANCE, True)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)
            
            self.G.add_edge( n1.id, n2.id )
        
        
        #adding fake entry points
        if apk != None:
            for i in apk.get_activities() :
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node((j, "onCreate", "(Landroid/os/Bundle;)V"))
                if n1 != None: 
                    key = "%s %s %s %s" % (j, "onCreate", "(Landroid/os/Bundle;)V", POSTFIX_ACTIVITY)
                    n2 = self._get_node(NODE_FAKE_ACTIVITY, key, LABEL_ACTIVITY, False)
                    self.G.add_edge( n2.id, n1.id )
                    self.entry_nodes.append( n1.id )
                    
            for i in apk.get_services() :
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node( (j, "onCreate", "()V") )
                if n1 != None : 
                    key = "%s %s %s %s" % (j, "onCreate", "()V", POSTFIX_SERVICE)
                    n2 = self._get_node(NODE_FAKE_SERVICE, key, LABEL_SERVICE, False)
                    self.G.add_edge( n2.id, n1.id )
                    self.entry_nodes.append( n1.id )
            
            for i in apk.get_receivers() :
                j = bytecode.FormatClassToJava(i)
                n1 = self._get_existed_node( (j, "onReceive", "(Landroid/content/Context;Landroid/content/Intent;)V") )
                if n1 != None : 
                    key = "%s %s %s %s" % (j, "onReceive", "(Landroid/content/Context;Landroid/content/Intent;)V", POSTFIX_RECEIVER)
                    n2 = self._get_node(NODE_FAKE_SERVICE, key, LABEL_RECEIVER, False)
                    self.G.add_edge( n2.id, n1.id )
                    self.entry_nodes.append( n1.id )

        
        #fake permissions
        list_permissions = vmx.stadyna_get_permissions([])
        for x in list_permissions:
            for j in list_permissions[x]:
                if isinstance(j, PathVar):
                    continue

                src_class_name, src_method_name, src_descriptor = j.get_src( vm.get_class_manager() )
                dst_class_name, dst_method_name, dst_descriptor = j.get_dst( vm.get_class_manager() )
                
                n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
                if n1 == None:
                    logger.warning("Cannot find node [%s %s %s] for permission [%s]!" % (src_class_name, src_method_name, src_descriptor, x))
                    continue
                
                #SOURCE, DEST, POSTFIX, PERMISSION_NAME
                key = "%s %s %s %s %s %s %s %s" %  (src_class_name, src_method_name, src_descriptor, dst_class_name, dst_method_name, dst_descriptor, POSTFIX_PERM, x)
                n2 = self._get_node(NODE_FAKE_PERMISSION, key, x, False)
                n2.set_attribute(ATTR_CLASS_NAME, dst_class_name)
                n2.set_attribute(ATTR_METHOD_NAME, dst_method_name)
                n2.set_attribute(ATTR_DESCRIPTOR, dst_descriptor)
                n2.set_attribute(ATTR_PERM_NAME, x)
                n2.set_attribute(ATTR_PERM_LEVEL, MANIFEST_PERMISSIONS[ x ][0])
                
                self.G.add_edge(n1.id, n2.id)
                                

        #fake DexClassLoader nodes
        dyn_code_loading = analysis.seccon_get_dyncode_loading_paths(vmx)
        for j in dyn_code_loading:
            src_class_name, src_method_name, src_descriptor = j.get_src( vm.get_class_manager() )
            dst_class_name, dst_method_name, dst_descriptor = j.get_dst( vm.get_class_manager() )
            
            n1 = self._get_existed_node((src_class_name, src_method_name, src_descriptor))
            if n1 == None:
                logger.warning("Cannot find dexload node [%s]!" % (src_class_name, src_method_name, src_descriptor))
                continue
            
            key = "%s %s %s %s %s %s %s" % (src_class_name, src_method_name, src_descriptor, dst_class_name, dst_method_name, dst_descriptor, POSTFIX_DEXLOAD)
            n2 = self._get_node(NODE_FAKE_DEXLOAD, key, LABEL_DEXLOAD, False)
            n2.set_attribute(ATTR_CLASS_NAME, src_class_name)
            n2.set_attribute(ATTR_METHOD_NAME, src_method_name)
            n2.set_attribute(ATTR_DESCRIPTOR, src_descriptor)
            
            self.G.add_edge( n1.id, n2.id )
        
        
        
        # Specific Java/Android library
        for c in vm.get_classes():
            #if c.get_superclassname() == "Landroid/app/Service;" :
            #    n1 = self._get_node( c.get_name(), "<init>", "()V" )
            #    n2 = self._get_node( c.get_name(), "onCreate", "()V" )

            #    self.G.add_edge( n1.id, n2.id )
            if c.get_superclassname() == "Ljava/lang/Thread;" or c.get_superclassname() == "Ljava/util/TimerTask;" :
                for i in vm.get_method("run") :
                    if i.get_class_name() == c.get_name() :
                        n1 = self._get_node(NODE_METHOD, (i.get_class_name(), i.get_name(), i.get_descriptor()))
                        n2 = self._get_node(NODE_METHOD, (i.get_class_name(), "start", i.get_descriptor())) 
                       
                        # link from start to run
                        self.G.add_edge( n2.id, n1.id )
                        #n2.add_edge( n1, {} )

                        # link from init to start
                        for init in vm.get_method("<init>") :
                            if init.get_class_name() == c.get_name():
                                #TODO: Leaving _get_existed_node to check if all the nodes are included
                                #It is possible that internal_packages does not contain this node. Leaving _get_existed_node to check this
                                n3 = self._get_node(NODE_CONSTRUCTOR, (init.get_class_name(), "<init>", init.get_descriptor()))
                                self.G.add_edge( n3.id, n2.id )