secure-software-engineering / FlowDroid

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

Cannot generate runnable applications simply unpack and repack an app using FlowDroid #550

Open limerick1718 opened 1 year ago

limerick1718 commented 1 year ago

Hi @StevenArzt, sorry to bother you but I find that simply unpacking and repacking an app using FlowDroid cannot generate a valid runnable app.

This is the example app: org.wikipedia.apk.zip

Here is the code to unpack and repack the app:

public static void RepackAfterUnpack(String androidJar, String apkPath, String outputPath) {
        G.reset();
        InfoflowAndroidConfiguration config = new InfoflowAndroidConfiguration();
        config.getAnalysisFileConfig().setTargetAPKFile(apkPath);
        config.getAnalysisFileConfig().setAndroidPlatformDir(androidJar);
        config.setCodeEliminationMode(InfoflowConfiguration.CodeEliminationMode.NoCodeElimination);
        config.setCallgraphAlgorithm(InfoflowConfiguration.CallgraphAlgorithm.CHA); 
        SetupApplication setupApplication = new SetupApplication(config);
        setupApplication.getConfig().setEnableReflection(true);
        setupApplication.getConfig().setMergeDexFiles(true);
        setupApplication.constructCallgraph();
        Scene.v().loadNecessaryClasses();
        setupApplication.removeSimulatedCodeElements();
        Options.v().set_output_format(Options.output_format_dex);
        Options.v().set_output_dir(outputPath);
        Options.v().set_validate(true);
        PackManager.v().writeOutput();
}

The code runs fine and can generate an app. After that, I also re-align and re-sign the generated app. The generated app also can be successfully installed on an Android emulator. However, the installed app cannot be opened and crashed.

I also tried to unpack and repack the app without FlowDroid (using soot):

 public static void RepackAfterUnpack(String androidJar, String apkPath, String outputPath) {
        G.reset();
        Options.v().set_allow_phantom_refs(true);
        Options.v().set_whole_program(true);
        Options.v().set_prepend_classpath(true);
        Options.v().set_android_jars(androidJar);
        Options.v().set_src_prec(Options.src_prec_apk); 
        Options.v().set_process_dir(Collections.singletonList(apkPath)); 
        Options.v().set_process_multiple_dex(true); 
        Options.v().set_include_all(true);
        Options.v().set_output_dir(outputPath);
        Options.v().set_output_format(Options.output_format_dex);
        Options.v().set_validate(true); 
        Scene.v().loadNecessaryClasses();
        CallGraphBuilder callGraphBuilder = new CallGraphBuilder();
        callGraphBuilder.build();
        CallGraph callGraph = callGraphBuilder.getCallGraph();
        // PackManager.v().runPacks();
        PackManager.v().writeOutput();
    }

Following the steps I mentioned before (e.g., resigning the app using the same instructions), the app can be successfully installed on an Android emulator. I also check the app, it works fine. So, the problem should not be related to other phases of app building but should be related to the FlowDroid. Would you please kindly help me and let me know what's wrong with my code? Or is it a bug of FlowDroid?

Please kindly let me know if I missed anything.

Thank you very much and have a great day!

StevenArzt commented 1 year ago

What are you trying to achieve? Your code is a wild mixture of Soot and FlowDroid operations and will likely fail. What is the purpose of having FlowDroid in that code? You're not actually using any dataflow capabilities.

limerick1718 commented 1 year ago

Thank you very much for your quick reply!

My goal is (1) to analyze the APK (e.g., generate the Call Graph with ICC links, therefore I need FlowDroid), then (2) to modify the APK by removing/adding methods, and finally (3) to generate an APK (therefore I need to repack the revised APK). I tried it with Soot solely. Of course, it can work but it cannot get the call graph with ICC. So, I need to use FlowDroid. I failed. To figure out why I failed, I tried to simply unpack and repack using FlowDroid, which is shown in the example. Of course, I failed again. So the problem is in the unpacking and repacking process I think. This is the goal I want to achieve, and what I did to achieve that goal. (Note the second code block is another approach, which successfully generate the runnable APK.)

Would you please kindly help me?

Thank you very much!

limerick1718 commented 1 year ago

Thank you very much for your help!

According to your comment in another issue, I (1) delete the call loadNecessaryClasses when running FlowDroid and (2) test the code again. The code fails again (Cannot generate valid runnable application). We may need a step further investigation.

Thanks again and have a great day!

StevenArzt commented 1 year ago

You should use FlowDroid as the main driver of the analysis. You can try to start with the following code. I haven't had the time to test it, so no guarantees.

SetupApplication app = new SetupApplication(platformsDir, apkFile);
app.constructCallgraph();

// instrument your app

Options.v().set_output_format(Options.output_format_dex);
PackManager.v().writeOutput();

The FlowDroid run should already initialize Soot, so no need to configure the basic Soot options on your own. Further, FlowDroid already loads the necessary classes and parses the APK file.

If you want to have ICC support, you also need to set the respective FlowDroid options for ICC.

limerick1718 commented 1 year ago

Thank you very much for your help!

I follow your advice and simply use the following statement to unpack and repack the APK file:

SetupApplication setupApplication = new SetupApplication(androidJar, apkPath);

setupApplication.constructCallgraph();
setupApplication.removeSimulatedCodeElements();

Options.v().set_output_format(Options.output_format_dex);
Options.v().set_output_dir(outputPath);
PackManager.v().writeOutput();

I test it with and without setupApplication.removeSimulatedCodeElements();. This statement is included because you mentioned in another issue thread: https://github.com/secure-software-engineering/FlowDroid/issues/119

However, it still failed.

It would be okay if you just propose some idea and I test it :) (By the may, I might attend your talk in FSE last month in Singapore. Thanks for sharing the paper, but sorry that I didn’t recognize you at that time.

StevenArzt commented 1 year ago

Please be more specific. What do you mean with "it still failed"? I copy&pasted my code into a small test application. It compiles, it generates a callgraph, and it writes out an APK file.

limerick1718 commented 1 year ago

Please be more specific. What do you mean with "it still failed"? I copy&pasted my code into a small test application. It compiles, it generates a callgraph, and it writes out an APK file.

Sorry for the ambiguity.

In this thread, the failure is "the installed app cannot be opened and crashed.".

From my end, FlowDroid can output an APK file as well. However, as I indicated here, "The generated app also can be successfully installed on an Android emulator. However, the installed app cannot be opened and crashed." While in contrast, the APK file generated by the Soot can be operated (i.e., installed and running) on the emulator successfully.

Thank you very much and have a great day!