secure-software-engineering / FlowDroid

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

Missing Nodes in the Calllgraph #167

Open shengliangd opened 5 years ago

shengliangd commented 5 years ago

Hello, I'm trying to get callgraph using FlowDroid. It's really a great tool. But I find that it is missing function calls in the generated callgraph for some cases.

For example, for this following app: sample.zip, I'm sure it calls android.media.AudioRecord.startRecording(), because I can find the call in smali code by decompiling using apktool, and by using this app I know there must be calls to the recording api. But it's not contained in the callgraph.

My code calling FlowDroid goes below:

        // Initialize analyzer
        SetupApplication analyzer = new SetupApplication(sdkPath, apk);
        SootConfigForAndroid sootConf = new SootConfigForAndroid() {
            @Override
            public void setSootOptions(Options options, InfoflowConfiguration config) {
                super.setSootOptions(options, config);
                Options.v().set_process_multiple_dex(true);
                Options.v().set_allow_phantom_refs(true);
                Options.v().set_whole_program(true);
            }
        };
        analyzer.setSootConfig(sootConf);

        // Get call graph
        analyzer.constructCallgraph();
        CallGraph cg = Scene.v().getCallGraph();

I haven't find the simplest cases to reproduce this problem, but this also happens in some other apps. I can provide them if needed. So, is it some problem related to my config, or is it about bugs of FlowDroid? Or is it just an expected behavior? How can I solve it?

Thanks in advance!

StevenArzt commented 5 years ago

I have started to analyze your sample app and I'm not sure that this code is actually reachable. I was able to trace it back to a class called CommonRecordSoundPanel, which has an onClick() handler. This method (across some intermediates) instantiates a class called QQRecorder and calls method a() on it. In that method, a thread is started, which in turn (across some further intermediates) calls startRecording(). However, I was unable to find any place where the original CommonRecordSoundPanel is instantiated. The constructor doesn't seem to get called, and it's not referenced in the layout XML files either. Can you double-check this analysis? I'm wondering whether this is actually dead code.

shengliangd commented 5 years ago

In this app there is a recording panel. If the user press on the panel, it will start recording. To check if it is dead code, I hooked on the method android.media.AudioRecord.startRecording() to get the call stack when it is called. When I press on that panel, I get following call stack:

de.robv.android.xposed.DexposedBridge.handleHookedArtMethod(Unknown Source:123)
me.weishu.epic.art.entry.Entry.onHookVoid(Unknown Source:0)
me.weishu.epic.art.entry.Entry.referenceBridge(Unknown Source:111)
me.weishu.epic.art.entry.Entry.voidBridge(Unknown Source:0)
com.tencent.mobileqq.utils.QQRecorder.b(ProGuard:245)
com.tencent.mobileqq.utils.QQRecorder.a(ProGuard:38)
exy.run(ProGuard:341)

The top 4 lines are from VirtualXposed, which can be ignored in this problem. From the bottom 3 lines we can see that it is definitly called, starting from exy.run()(but we can't track further because it's in a new thread). So I'm sure it's not dead code.

I tried manually analyzing the smali code, and ended at the same thing CommonRecordSoundPanel as you dit. Found no instantiation of it either. It's really strange.

shengliangd commented 5 years ago

Just now found that com.tencent.mobileqq.activity.BaseChatPie also instantiates QQRecorder, and ChatActivity instantiates BaseChatPie, and ChatActivity is an activity registered in the app manifest. Also, BaseChatPie is subclassed by FriendChatPie, TroopChatPie, etc. Maybe this corresponds to the true usage of QQRecorder in this app. But I know little about the implementation of FlowDroid, so no idea of why its methods are not in the CG yet.

shengliangd commented 5 years ago

I performed some kind of grep-tracking(well, tracking call paths using grep), and find following call paths(a graphviz file, changed suffix because github doesn't allow uploading that format): paths.txt

Hope you don't mind that the edges are reversed. Among those end points(nodes without out edge), smali_classes2/com/tencent/mobileqq/activity/aio/audiopanel/CommonRecordSoundPanel.smali:onClick(Landroid/view/View;)V should be what you've found before. I didn't find any instantiation of CommonRecordSoundPanel either. As for Lcom/tencent/mobileqq/activity/aio/audiopanel/RecordSoundPanel;->onClick(Landroid/view/View;)V, and smali_classes2/btw.smali:329: invoke-virtual {v0, v2, v3, v1}, Lcom/tencent/mobileqq/activity/BaseChatPie;->a(Lcom/tencent/mobileqq/utils/QQRecorder$OnQQRecorderListener;ZLcom/tencent/mobileqq/utils/QQRecorder$RecorderParam;)V , I didn't track further.

Things we should pay attention is about smali_classes2/bul.smali:341: invoke-virtual {v0, v3, v1, v2}, Lcom/tencent/mobileqq/activity/BaseChatPie;->a(Lcom/tencent/mobileqq/utils/QQRecorder$OnQQRecorderListener;ZLcom/tencent/mobileqq/utils/QQRecorder$RecorderParam;)V , also one of the end points. The class bul is instantiated in smali_classes2/com/tencent/mobileqq/activity/aio/audiopanel/PressToSpeakPanel.smali: onTouch. So I took a look at the reachable methods(well, Scene.v().getReachableMethods), and there isn't any member method of class PressToSpeakPanel. But PressToSpeakPanel is in res/layout/0_APKTOOL_DUPLICATENAME_0x7f0301af.xml!

So...could this be related to layout parsing?