secure-software-engineering / FlowDroid

FlowDroid Static Data Flow Tracker
GNU Lesser General Public License v2.1
1.05k stars 298 forks source link

How to construct call graph without executing Local Packer? #447

Open xwlin-roy opened 2 years ago

xwlin-roy commented 2 years ago

Hi,

I'm trying to make DroidRA(https://github.com/MobileSE/DroidRA) work correctly. DroidRA is based on Coal to perform composite constant propagation analysis( Composite Constant Propagation: Application to Android Inter-Component Communication Analysis). Coal doesn't call SetupApplication.constructCallGraph to build call graph. It just sets up the entry point of the android app and set the cg.spark phase on to construct call graph, the call graph of which is incomplete that lead to the following analysis incorrectly.

Workflow of DroidRA

In my understanding, it first generated the dummy main of android app and then set the main class and entry points before the coal analysis. Then it set the cg.spark phase on to construct call graph. I have several questions here.

    protected void initializeAnalysis(A commandLineArguments) {
        addSceneTransformer();

        // Debug Patch
        // explicitly include packages for shorter runtime:
        List<String> excludeList = new LinkedList<String>();
        excludeList.add("java.*");
        excludeList.add("sun.*");

        // exclude classes of android.* will cause layout class cannot be
        // loaded for layout file based callback analysis.

        // 2020-07-26 (SA): added back the exclusion, because removing it breaks
        // calls to Android SDK stubs. We need a proper test case for the layout
        // file issue and then see how to deal with it.
        excludeList.add("android.*");

        excludeList.add("org.apache.*");
        excludeList.add("org.eclipse.*");
        excludeList.add("soot.*");
        excludeList.add("javax.*");
        Options.v().set_exclude(excludeList);

        Options.v().set_no_bodies_for_excluded(true);
        Options.v().set_allow_phantom_refs(true);
        Options.v().set_output_format(Options.output_format_none);
        Options.v().set_whole_program(true);
        Options.v().set_soot_classpath(
                commandLineArguments.getInput() + File.pathSeparator + commandLineArguments.getClasspath());

        Options.v().setPhaseOption("cg.spark", "on");
//        Options.v().setPhaseOption("cg", "off");

        // do not merge variables (causes problems with PointsToSets)
        Options.v().setPhaseOption("jb.ulp", "off");

        // Options.v().setPhaseOption("jb.ne", "off");
        Options.v().setPhaseOption("jb.uce", "remove-unreachable-traps:true");

        Options.v().setPhaseOption("cg", "trim-clinit:false");
        Options.v().set_prepend_classpath(true);

        Options.v().set_src_prec(Options.src_prec_java);

        for (String analysisClass : AnalysisParameters.v().getAnalysisClasses()) {
            try {
                SootClass sootClass = Scene.v().loadClassAndSupport(analysisClass);
                Scene.v().forceResolve(analysisClass, SootClass.BODIES);
                sootClass.setApplicationClass();
            } catch (Exception ex) {
                //TODO: need more investigation
            }
        }

        Scene.v().loadNecessaryClasses();

        //Scene.v().setMainClassFromOptions();
        Scene.v().setMainClass(Scene.v().getSootClass("dummyMainClass"));
        Scene.v().setEntryPoints(EntryPoints.v().application());
    }

In this way, coal could still generate call graph. But the call graph is incomplete when compared to the SetupApplication.constructCallGraph way.

  1. Why in this way, coal could still generate android app call graph by just setting up the entry points and without the android lifecycle modeling?
  2. In coal code, it will disable jb.ulp phase in the jimple body creation phase. To fix the android app call graph of coal incomplete issue, I firstly build call graph with SetupApplication.constructCallGraph and provide this call graph to coal instead of using coal's call graph. However, when FlowDroid build call graph in constructCallGraph API, it will call LocalPacker even though I also set the jb.ulp phase off. The activeBody in SootMethod from call graph built by FlowDroid cannot be handled by coal.(In this way it will leads to some bugs in changeBody function of coal code, which I haven't dig into.)

Therefore, in order to make DroidRA work correctly in the complete call graph, How can I fix this issue? I have several directions:

  1. Try to build the call graph with the help of FlowDroid, in this way, I need disable jb.ulp phase. But I cannot figure out how to do this.
  2. Let the coal build a complete call graph without the help of FlowDroid, so I can disable jb.ulp phase which won't leads to the bugs in changeBody. In this direction, How can I construct a complete call graph in the code base of coal?
  3. If the above two ways cannot work out, what I can do is to fix the bugs in coal code(changeBody) when it handle the jimple body that has been transformed by LocalPacker phase.

Any suggestion in this issue? Thanks in advance.