做电影网站配什么公众号,wordpress 一些数据表不可用,网站建设动态页面修改删除,网站怎么防黑客FlowDroid 一、处理流程学习 下载配置源码概况代码逻辑分析analyzeAPKFilerunInfoflowprocessEntryPointcalculateCallbacks(sourcesAndSinks)再次回到processEntryPoint 自己做一些笔记 下载配置
参照我前面的文章可以使用FlowDroid安装初体验 为了看代码了解FlowDroid如何处… FlowDroid 一、处理流程学习 下载配置源码概况代码逻辑分析analyzeAPKFilerunInfoflowprocessEntryPointcalculateCallbacks(sourcesAndSinks)再次回到processEntryPoint 自己做一些笔记 下载配置
参照我前面的文章可以使用FlowDroid安装初体验 为了看代码了解FlowDroid如何处理clone其官方仓库FlowDroid GitHub
源码概况
下载下来的内容还是挺多的主要分了以下几个文件夹
soot-infoflow 核心功能代码soot-infoflowandroid 安卓数据流分析代码soot-infoflow-summaries字面意思函数摘要soot-infoflow-cmd使用cmd的解释运行流程 下面对AliasingTest进行案例分析
代码逻辑分析
analyzeAPKFile 这部分跟进去是一个自定义的测试代码片段跟进去看具体实现可以看到不同的接口
ICC modelGPT4的回答 在FlowDroid中ICCInter-Component Communication组件间通信模型用于表示和处理安卓应用中各个组件例如活动、服务、广播接收器等之间如何相互通信。在Android中组件通常通过Intent机制来相互通信。ICC模型旨在建模这种Intent传递机制以更准确地进行数据流分析。 具体来说FlowDroid的ICC模型可能包括以下几方面的信息
哪个组件发送了Intent。Intent中包含哪些数据。Intent被发送到哪个组件。如何处理接收到的Intent。
通过精确地建模这些交互FlowDroid可以更准确地追踪可能的数据流路径从而更有效地检测潜在的安全问题。该模型对于理解应用如何处理敏感数据以及这些数据可能如何泄露通过组件间的不安全通信等问题非常有用。 再往下跟就是一些配置信息读取环境变量等跟进runInfoflow函数是比较关键的
runInfoflow //这两行代码做了soot的初始化
if (config.getSootIntegrationMode() SootIntegrationMode.CreateNewInstance) {G.reset();initializeSoot();
}//soot初始化关键函数比较常规
private void initializeSoot() {logger.info(Initializing Soot...);final String androidJar config.getAnalysisFileConfig().getAndroidPlatformDir();final String apkFileLocation config.getAnalysisFileConfig().getTargetAPKFile();// Clean up any old Soot instance we may haveG.reset();Options.v().set_no_bodies_for_excluded(true);Options.v().set_allow_phantom_refs(true);if (config.getWriteOutputFiles())Options.v().set_output_format(Options.output_format_jimple);elseOptions.v().set_output_format(Options.output_format_none);Options.v().set_whole_program(true);Options.v().set_process_dir(Collections.singletonList(apkFileLocation));if (forceAndroidJar)Options.v().set_force_android_jar(androidJar);elseOptions.v().set_android_jars(androidJar);Options.v().set_src_prec(Options.src_prec_apk_class_jimple);Options.v().set_keep_offset(false);Options.v().set_keep_line_number(config.getEnableLineNumbers());Options.v().set_throw_analysis(Options.throw_analysis_dalvik);Options.v().set_process_multiple_dex(config.getMergeDexFiles());Options.v().set_ignore_resolution_errors(true);// Set soot phase option if original names should be usedif (config.getEnableOriginalNames())Options.v().setPhaseOption(jb, use-original-names:true);// Set the Soot configuration options. Note that this will needs to be// done before we compute the classpath.if (sootConfig ! null)sootConfig.setSootOptions(Options.v(), config);Options.v().set_soot_classpath(getClasspath());Main.v().autoSetOptions();configureCallgraph();// Load whatever we needlogger.info(Loading dex files...);Scene.v().loadNecessaryClasses();// Make sure that we have valid Jimple bodiesPackManager.v().getPack(wjpp).apply();// Patch the callgraph to support additional edges. We do this now,// because during callback discovery, the context-insensitive callgraph// algorithm would flood us with invalid edges.LibraryClassPatcher patcher getLibraryClassPatcher();patcher.patchLibraries();}接下来对apk资源文件进行解析分析入口点
try {parseAppResources();} catch (IOException | XmlPullParserException e) {logger.error(Parse app resource failed, e);throw new RuntimeException(Parse app resource failed, e);}protected void parseAppResources() throws IOException, XmlPullParserException {final File targetAPK new File(config.getAnalysisFileConfig().getTargetAPKFile());if (!targetAPK.exists())throw new RuntimeException(String.format(Target APK file %s does not exist, targetAPK.getCanonicalPath()));// Parse the resource filelong beforeARSC System.nanoTime();this.resources new ARSCFileParser();this.resources.parse(targetAPK.getAbsolutePath());logger.info(ARSC file parsing took (System.nanoTime() - beforeARSC) / 1E9 seconds);// To look for callbacks, we need to start somewhere. We use the Android// lifecycle methods for this purpose.this.manifest createManifestParser(targetAPK);SystemClassHandler.v().setExcludeSystemComponents(config.getIgnoreFlowsInSystemPackages());SetString entryPoints manifest.getEntryPointClasses();this.entrypoints new HashSet(entryPoints.size());for (String className : entryPoints) {SootClass sc Scene.v().getSootClassUnsafe(className);if (sc ! null)this.entrypoints.add(sc);}}processEntryPoint
Runs the data flow analysis on the given entry point class
if (config.getOneComponentAtATime()) {ListSootClass entrypointWorklist new ArrayList(entrypoints);while (!entrypointWorklist.isEmpty()) {SootClass entrypoint entrypointWorklist.remove(0);processEntryPoint(sourcesAndSinks, resultAggregator, entrypointWorklist.size(), entrypoint);}} elseprocessEntryPoint(sourcesAndSinks, resultAggregator, -1, null);resultAggregator 记录结果的地方 protected void processEntryPoint(ISourceSinkDefinitionProvider sourcesAndSinks,MultiRunResultAggregator resultAggregator, int numEntryPoints, SootClass entrypoint) {long beforeEntryPoint System.nanoTime();// Get rid of leftovers from the last entry pointresultAggregator.clearLastResults();// Perform basic app parsinglong callbackDuration System.nanoTime();try {if (config.getOneComponentAtATime())calculateCallbacks(sourcesAndSinks, entrypoint);elsecalculateCallbacks(sourcesAndSinks);} catch (IOException | XmlPullParserException e) {logger.error(Callgraph construction failed: e.getMessage(), e);throw new RuntimeException(Callgraph construction failed, e);}callbackDuration Math.round((System.nanoTime() - callbackDuration) / 1E9);logger.info(String.format(Collecting callbacks and building a callgraph took %d seconds, (int) callbackDuration));final Collection? extends ISourceSinkDefinition sources getSources();final Collection? extends ISourceSinkDefinition sinks getSinks();final String apkFileLocation config.getAnalysisFileConfig().getTargetAPKFile();if (config.getOneComponentAtATime())logger.info(Running data flow analysis on {} (component {}/{}: {}) with {} sources and {} sinks...,apkFileLocation, (entrypoints.size() - numEntryPoints), entrypoints.size(), entrypoint,sources null ? 0 : sources.size(), sinks null ? 0 : sinks.size());elselogger.info(Running data flow analysis on {} with {} sources and {} sinks..., apkFileLocation,sources null ? 0 : sources.size(), sinks null ? 0 : sinks.size());// Create a new entry point and compute the flows in it. If we// analyze all components together, we do not need a new callgraph,// but can reuse the one from the callback collection phase.if (config.getOneComponentAtATime() config.getSootIntegrationMode().needsToBuildCallgraph()) {createMainMethod(entrypoint);constructCallgraphInternal();}// Create and run the data flow trackerinfoflow createInfoflow();infoflow.addResultsAvailableHandler(resultAggregator);infoflow.runAnalysis(sourceSinkManager, entryPointCreator.getGeneratedMainMethod());// Update the statisticsif (config.getLogSourcesAndSinks() infoflow.getCollectedSources() ! null)this.collectedSources.addAll(infoflow.getCollectedSources());if (config.getLogSourcesAndSinks() infoflow.getCollectedSinks() ! null)this.collectedSinks.addAll(infoflow.getCollectedSinks());// Print out the found results{int resCount resultAggregator.getLastResults() null ? 0 : resultAggregator.getLastResults().size();if (config.getOneComponentAtATime())logger.info(Found {} leaks for component {}, resCount, entrypoint);elselogger.info(Found {} leaks, resCount);}// Update the performance object with the real data{InfoflowResults lastResults resultAggregator.getLastResults();if (lastResults ! null) {InfoflowPerformanceData perfData lastResults.getPerformanceData();if (perfData null)lastResults.setPerformanceData(perfData new InfoflowPerformanceData());perfData.setCallgraphConstructionSeconds((int) callbackDuration);perfData.setTotalRuntimeSeconds((int) Math.round((System.nanoTime() - beforeEntryPoint) / 1E9));}}// We dont need the computed callbacks anymorethis.callbackMethods.clear();this.fragmentClasses.clear();// Notify our result handlersfor (ResultsAvailableHandler handler : resultsAvailableHandlers)handler.onResultsAvailable(resultAggregator.getLastICFG(), resultAggregator.getLastResults());}calculateCallbacks(sourcesAndSinks)
传进来的参数即为读取的sources和sinks Calculates the sets of sources, sinks, entry points, and callbacks methods for the entry point in the given APK file.
private void calculateCallbacks(ISourceSinkDefinitionProvider sourcesAndSinks, SootClass entryPoint)throws IOException, XmlPullParserException {// Add the callback methodsLayoutFileParser lfp null;final CallbackConfiguration callbackConfig config.getCallbackConfig();if (callbackConfig.getEnableCallbacks()) {// If we have a callback file, we use itString callbackFile callbackConfig.getCallbacksFile();if (callbackFile ! null !callbackFile.isEmpty()) {File cbFile new File(callbackFile);if (cbFile.exists()) {CollectedCallbacks callbacks CollectedCallbacksSerializer.deserialize(callbackConfig);if (callbacks ! null) {// Get our callback data from the fileentrypoints callbacks.getEntryPoints();fragmentClasses callbacks.getFragmentClasses();callbackMethods callbacks.getCallbackMethods();// Create the callgraphcreateMainMethod(entryPoint);constructCallgraphInternal();createSourceSinkProvider(entryPoint, lfp);return;}}}if (callbackClasses ! null callbackClasses.isEmpty()) {logger.warn(Callback definition file is empty, disabling callbacks);} else {lfp createLayoutFileParser();switch (callbackConfig.getCallbackAnalyzer()) {case Fast:calculateCallbackMethodsFast(lfp, entryPoint);break;case Default:calculateCallbackMethods(lfp, entryPoint);break;default:throw new RuntimeException(Unknown callback analyzer);}}} else if (config.getSootIntegrationMode().needsToBuildCallgraph()) {// Create the new iteration of the main methodcreateMainMethod(entryPoint);constructCallgraphInternal();}logger.info(Entry point calculation done.);createSourceSinkProvider(entryPoint, lfp);}在此过程中给对Layout进行了解析LayoutFileParser(this.manifest.getPackageName(), this.resources);
lfp createLayoutFileParser(); calculateCallbackMethods(lfp, entryPoint); 下面这是真正的计算了
private void calculateCallbackMethods(LayoutFileParser lfp, SootClass component) throws IOException {final CallbackConfiguration callbackConfig config.getCallbackConfig();// Load the APK fileif (config.getSootIntegrationMode().needsToBuildCallgraph())releaseCallgraph();// Make sure that we dont have any leftovers from previous runsPackManager.v().getPack(wjtp).remove(wjtp.lfp);PackManager.v().getPack(wjtp).remove(wjtp.ajc);// Get the classes for which to find callbacksSetSootClass entryPointClasses getComponentsToAnalyze(component);// Collect the callback interfaces implemented in the apps// source code. Note that the filters should know all components to// filter out callbacks even if the respective component is only// analyzed later.AbstractCallbackAnalyzer jimpleClass callbackClasses null? new DefaultCallbackAnalyzer(config, entryPointClasses, callbackMethods, callbackFile): new DefaultCallbackAnalyzer(config, entryPointClasses, callbackMethods, callbackClasses);if (valueProvider ! null)jimpleClass.setValueProvider(valueProvider);jimpleClass.addCallbackFilter(new AlienHostComponentFilter(entrypoints));jimpleClass.addCallbackFilter(new ApplicationCallbackFilter(entrypoints));jimpleClass.addCallbackFilter(new UnreachableConstructorFilter());jimpleClass.collectCallbackMethods();// Find the user-defined sources in the layout XML files. This// only needs to be done once, but is a Soot phase.lfp.parseLayoutFile(config.getAnalysisFileConfig().getTargetAPKFile());// Watch the callback collection algorithms memory consumptionFlowDroidMemoryWatcher memoryWatcher null;FlowDroidTimeoutWatcher timeoutWatcher null;if (jimpleClass instanceof IMemoryBoundedSolver) {// Make sure that we dont spend too much time and memory in the callback// analysismemoryWatcher createCallbackMemoryWatcher(jimpleClass);timeoutWatcher createCallbackTimeoutWatcher(callbackConfig, jimpleClass);}try {int depthIdx 0;boolean hasChanged true;boolean isInitial true;while (hasChanged) {hasChanged false;// Check whether the solver has been aborted in the meantimeif (jimpleClass instanceof IMemoryBoundedSolver) {if (((IMemoryBoundedSolver) jimpleClass).isKilled())break;}// Create the new iteration of the main methodcreateMainMethod(component);int numPrevEdges 0;if (Scene.v().hasCallGraph()) {numPrevEdges Scene.v().getCallGraph().size();}// Since the generation of the main method can take some time,// we check again whether we need to stop.if (jimpleClass instanceof IMemoryBoundedSolver) {if (((IMemoryBoundedSolver) jimpleClass).isKilled()) {logger.warn(Callback calculation aborted due to timeout);break;}}if (!isInitial) {// Reset the callgraphreleaseCallgraph();// We only want to parse the layout files oncePackManager.v().getPack(wjtp).remove(wjtp.lfp);}isInitial false;// Run the soot-based operationsconstructCallgraphInternal();if (!Scene.v().hasCallGraph())throw new RuntimeException(No callgraph in Scene even after creating one. Thats very sad and should never happen.);lfp.parseLayoutFileDirect(config.getAnalysisFileConfig().getTargetAPKFile());PackManager.v().getPack(wjtp).apply();// Creating all callgraph takes time and memory. Check whether// the solver has been aborted in the meantimeif (jimpleClass instanceof IMemoryBoundedSolver) {if (((IMemoryBoundedSolver) jimpleClass).isKilled()) {logger.warn(Aborted callback collection because of low memory);break;}}if (numPrevEdges Scene.v().getCallGraph().size())hasChanged true;// Collect the results of the soot-based phasesif (this.callbackMethods.putAll(jimpleClass.getCallbackMethods()))hasChanged true;if (entrypoints.addAll(jimpleClass.getDynamicManifestComponents()))hasChanged true;// Collect the XML-based callback methodsif (collectXmlBasedCallbackMethods(lfp, jimpleClass))hasChanged true;// Avoid callback overruns. If we are beyond the callback limit// for one entry point, we may not collect any further callbacks// for that entry point.if (callbackConfig.getMaxCallbacksPerComponent() 0) {for (IteratorSootClass componentIt this.callbackMethods.keySet().iterator(); componentIt.hasNext();) {SootClass callbackComponent componentIt.next();if (this.callbackMethods.get(callbackComponent).size() callbackConfig.getMaxCallbacksPerComponent()) {componentIt.remove();jimpleClass.excludeEntryPoint(callbackComponent);}}}// Check depth limitingdepthIdx;if (callbackConfig.getMaxAnalysisCallbackDepth() 0 depthIdx callbackConfig.getMaxAnalysisCallbackDepth())break;// If we work with an existing callgraph, the callgraph never// changes and thus it doesnt make any sense to go multiple// roundsif (config.getSootIntegrationMode() SootIntegrationMode.UseExistingCallgraph)break;}} catch (Exception ex) {logger.error(Could not calculate callback methods, ex);throw ex;} finally {// Shut down the watchersif (timeoutWatcher ! null)timeoutWatcher.stop();if (memoryWatcher ! null)memoryWatcher.close();}// Filter out callbacks that belong to fragments that are not used by// the host activityAlienFragmentFilter fragmentFilter new AlienFragmentFilter(invertMap(fragmentClasses));fragmentFilter.reset();for (IteratorPairSootClass, AndroidCallbackDefinition cbIt this.callbackMethods.iterator(); cbIt.hasNext();) {PairSootClass, AndroidCallbackDefinition pair cbIt.next();// Check whether the filter accepts the given mappingif (!fragmentFilter.accepts(pair.getO1(), pair.getO2().getTargetMethod()))cbIt.remove();else if (!fragmentFilter.accepts(pair.getO1(), pair.getO2().getTargetMethod().getDeclaringClass())) {cbIt.remove();}}// Avoid callback overrunsif (callbackConfig.getMaxCallbacksPerComponent() 0) {for (IteratorSootClass componentIt this.callbackMethods.keySet().iterator(); componentIt.hasNext();) {SootClass callbackComponent componentIt.next();if (this.callbackMethods.get(callbackComponent).size() callbackConfig.getMaxCallbacksPerComponent())componentIt.remove();}}// Make sure that we dont retain any weird Soot phasesPackManager.v().getPack(wjtp).remove(wjtp.lfp);PackManager.v().getPack(wjtp).remove(wjtp.ajc);// Warn the user if we had to abort the callback analysis earlyboolean abortedEarly false;if (jimpleClass instanceof IMemoryBoundedSolver) {if (((IMemoryBoundedSolver) jimpleClass).isKilled()) {logger.warn(Callback analysis aborted early due to time or memory exhaustion);abortedEarly true;}}if (!abortedEarly)logger.info(Callback analysis terminated normally);// Serialize the callbacksif (callbackConfig.isSerializeCallbacks()) {CollectedCallbacks callbacks new CollectedCallbacks(entryPointClasses, callbackMethods, fragmentClasses);CollectedCallbacksSerializer.serialize(callbacks, callbackConfig);}}这段代码首先对调用图进行重置 protected void releaseCallgraph() {// If we are configured to use an existing callgraph, we may not release// itif (config.getSootIntegrationMode() SootIntegrationMode.UseExistingCallgraph)return;Scene.v().releaseCallGraph();Scene.v().releasePointsToAnalysis();Scene.v().releaseReachableMethods();G.v().resetSpark();}接下来两行代码不懂问了GPT // Make sure that we dont have any leftovers from previous runsPackManager.v().getPack(wjtp).remove(wjtp.lfp);PackManager.v().getPack(wjtp).remove(wjtp.ajc);
PackManager.v().getPack(wjtp)这部分获取名为 “wjtp” 的分析阶段组pack。Soot框架将各种分析和转换任务组织在不同的阶段组如 “wjtp”, “jtp”, “cg” 等中。
remove(“wjtp.lfp”) 和 remove(“wjtp.ajc”)这两行代码从 “wjtp” 阶段组中移除特定的分析或转换阶段。具体来说它们移除名为 “wjtp.lfp” 和 “wjtp.ajc” 的阶段。
这两行代码确保在新一轮的Soot分析或转换开始之前清除先前可能添加到 “wjtp” 阶段组的 “wjtp.lfp” 和 “wjtp.ajc” 分析阶段。这样做主要是为了避免先前运行的残留影响到当前的运行。这是一种清理机制确保每次运行都是在干净、一致的环境中进行。
再次回到processEntryPoint Instantiates and configures the data flow engine private IInPlaceInfoflow createInfoflow() {// Some sanity checksif (config.getSootIntegrationMode().needsToBuildCallgraph()) {if (entryPointCreator null)throw new RuntimeException(No entry point available);if (entryPointCreator.getComponentToEntryPointInfo() null)throw new RuntimeException(No information about component entry points available);}// Get the component lifecycle methodsCollectionSootMethod lifecycleMethods Collections.emptySet();if (entryPointCreator ! null) {ComponentEntryPointCollection entryPoints entryPointCreator.getComponentToEntryPointInfo();if (entryPoints ! null)lifecycleMethods entryPoints.getLifecycleMethods();}// Initialize and configure the data flow trackerIInPlaceInfoflow info createInfoflowInternal(lifecycleMethods);if (ipcManager ! null)info.setIPCManager(ipcManager);info.setConfig(config);info.setSootConfig(sootConfig);info.setTaintWrapper(taintWrapper);info.setTaintPropagationHandler(taintPropagationHandler);info.setAliasPropagationHandler(aliasPropagationHandler);// We use a specialized memory manager that knows about Androidinfo.setMemoryManagerFactory(new IMemoryManagerFactory() {Overridepublic IMemoryManagerAbstraction, Unit getMemoryManager(boolean tracingEnabled,PathDataErasureMode erasePathData) {return new AndroidMemoryManager(tracingEnabled, erasePathData, entrypoints);}});info.setMemoryManagerFactory(null);// Inject additional post-processorsinfo.setPostProcessors(Collections.singleton(new PostAnalysisHandler() {Overridepublic InfoflowResults onResultsAvailable(InfoflowResults results, IInfoflowCFG cfg) {// Purify the ICC results if requestedfinal IccConfiguration iccConfig config.getIccConfig();if (iccConfig.isIccResultsPurifyEnabled()) {// no-op at the moment. We used to have a purifier here, but it didnt make// any sense. Removed it for the better.}return results;}}));return info;}接下来进入到runAnalysis函数内部这个函数似乎比较关键 Conducts a taint analysis on an already initialized callgraph protected void runAnalysis(final ISourceSinkManager sourcesSinks, final SetString additionalSeeds) {final InfoflowPerformanceData performanceData createPerformanceDataClass();try {// Clear the data from previous runsresults createResultsObject();results.setPerformanceData(performanceData);// Print and check our configurationcheckAndFixConfiguration();config.printSummary();// Register a memory watcherif (memoryWatcher ! null) {memoryWatcher.clearSolvers();memoryWatcher null;}memoryWatcher new FlowDroidMemoryWatcher(results, config.getMemoryThreshold());// Initialize the abstraction configurationAbstraction.initialize(config);// Build the callgraphlong beforeCallgraph System.nanoTime();constructCallgraph();performanceData.setCallgraphConstructionSeconds((int) Math.round((System.nanoTime() - beforeCallgraph) / 1E9));logger.info(String.format(Locale.getDefault(), Callgraph construction took %d seconds,performanceData.getCallgraphConstructionSeconds()));// Initialize the source sink managerif (sourcesSinks ! null)sourcesSinks.initialize();// Perform constant propagation and remove dead codeif (config.getCodeEliminationMode() ! CodeEliminationMode.NoCodeElimination) {long currentMillis System.nanoTime();eliminateDeadCode(sourcesSinks);logger.info(Dead code elimination took (System.nanoTime() - currentMillis) / 1E9 seconds);}// After constant value propagation, we might find more call edges// for reflective method callsif (config.getEnableReflection()) {releaseCallgraph();constructCallgraph();}if (config.getCallgraphAlgorithm() ! CallgraphAlgorithm.OnDemand)logger.info(Callgraph has {} edges, Scene.v().getCallGraph().size());IInfoflowCFG iCfg icfgFactory.buildBiDirICFG(config.getCallgraphAlgorithm(),config.getEnableExceptionTracking());if (config.isTaintAnalysisEnabled())runTaintAnalysis(sourcesSinks, additionalSeeds, iCfg, performanceData);// Gather performance dataperformanceData.setTotalRuntimeSeconds((int) Math.round((System.nanoTime() - beforeCallgraph) / 1E9));performanceData.updateMaxMemoryConsumption(getUsedMemory());logger.info(String.format(Data flow solver took %d seconds. Maximum memory consumption: %d MB,performanceData.getTotalRuntimeSeconds(), performanceData.getMaxMemoryConsumption()));// Provide the handler with the final resultsfor (ResultsAvailableHandler handler : onResultsAvailable)handler.onResultsAvailable(iCfg, results);// Write the Jimple files to disk if requestedif (config.getWriteOutputFiles())PackManager.v().writeOutput();} catch (Exception ex) {StringWriter stacktrace new StringWriter();PrintWriter pw new PrintWriter(stacktrace);ex.printStackTrace(pw);if (results ! null)results.addException(ex.getClass().getName() : ex.getMessage() \n stacktrace.toString());logger.error(Exception during data flow analysis, ex);if (throwExceptions)throw ex;}}constructCallgraph(); 构造调用图 protected void constructCallgraph() {if (config.getSootIntegrationMode().needsToBuildCallgraph()) {// Allow the ICC manager to change the Soot Scene before we continueif (ipcManager ! null)ipcManager.updateJimpleForICC();// Run the preprocessorsfor (PreAnalysisHandler tr : preProcessors)tr.onBeforeCallgraphConstruction();// Patch the system libraries we need for callgraph constructionLibraryClassPatcher patcher getLibraryClassPatcher();patcher.patchLibraries();// To cope with broken APK files, we convert all classes that are still// dangling after resolution into phantomsfor (SootClass sc : Scene.v().getClasses())if (sc.resolvingLevel() SootClass.DANGLING) {sc.setResolvingLevel(SootClass.BODIES);sc.setPhantomClass();}// We explicitly select the packs we want to run for performance// reasons. Do not re-run the callgraph algorithm if the host// application already provides us with a CG.if (config.getCallgraphAlgorithm() ! CallgraphAlgorithm.OnDemand !Scene.v().hasCallGraph()) {PackManager.v().getPack(wjpp).apply();PackManager.v().getPack(cg).apply();}}// If we dont have a FastHierarchy, we need to create it - even if we use an// existing callgraphhierarchy Scene.v().getOrMakeFastHierarchy();if (config.getSootIntegrationMode().needsToBuildCallgraph()) {// Run the preprocessorsfor (PreAnalysisHandler tr : preProcessors)tr.onAfterCallgraphConstruction();}}runAnalysis分析结束后回到了processEntryPoint