[Soot-list] Questions on Soot/FlowDroid's constructed callgraph on app that uses threads

Marc-André Laverdière marc-andre.laverdiere-papineau at polymtl.ca
Fri Nov 21 09:40:35 EST 2014


Hi John,

Yours is a very long email, and I read it in diagonals, so my answers
are not going to be great... but here comes anyway.

Regarding the first question, that is related to Soot's architecture. If
you want to do something before the FLowdroid taint analysis runs, I
suggest to add a preprocessor.
Basically, running PackManager.v.runPacks is going to execute the whole
Soot pipeline, based on whatever options you have in the Options.v.
singleton. For performance reasons, Flowdroid only runs the bare minimum
of the Soot pipeline, so you may get some differences there.

So you may be running your code when the callgraph isn't created yet, so
this will affect your algorithm.

Regarding the second question, I vaguely remember an edge filter in the
InterproceduralCFG object. It would be good to double-check that one.
Also, the JDK methods are excluded by default, and Flowdroid's options
probably mean that the code segments in the JDK responsible for actually
executing those threads is missing from the analysis. Try adding
java.lang.Thread in the inclusions.

Also, I'd double-check the cg.implicit-entry option just in case,
although I don't feel this is likely to be the issue.

Regards,



Marc-André Laverdière-Papineau
Doctorant - PhD Candidate

On 11/20/2014 02:29 PM, John Foster wrote:
> Hi everyone,
> 
> I'm trying to analyze a malicious Android app (malware) using FlowDroid.
> 
> My goal is to print out all the methods and units of the app by iterating
> the Scene's classes, methods, and units using the code below. In addition,
> for each method, I also use some information from the callgraph (again
> obtained
> from the Scene) to find out other methods that are called from that method,
> as well as other methods that call that particular method.
> The code is as follows:
> 
>         public void printAppInfoFromScene()
>         {
>                 CallGraph cg = Scene.v().getCallGraph();
> 
>                 Chain<SootClass> classes = Scene.v().getClasses();
>                 Iterator classIterator = classes.iterator();
>                 while (classIterator.hasNext()) {
>                         SootClass aClass = (SootClass) classIterator.next();
>                         System.out.println("\nSoot class: " + aClass);
>                       
>                         List<SootMethod> methodList = aClass.getMethods();
>                         Iterator methodIterator = methodList.iterator();
>                       
>                         while (methodIterator.hasNext()) {
>                                 SootMethod aMethod = (SootMethod)
> methodIterator.next();
>                                 System.out.println("\tSoot method: " +
> aMethod);
>                               
>                                 if (aMethod.hasActiveBody()) {
>                                         PatchingChain<Unit> units =
> aMethod.getActiveBody().getUnits();
>                                         Iterator<Unit> unitIterator =
> units.iterator();
>                                       
>                                         while (unitIterator.hasNext()) {
>                                                 Unit aUnit =
> unitIterator.next();
>                                                
> System.out.println("\t\t- Unit: " + aUnit);
>                                         }
>                                       
>                                         System.out.println("\n\tThis
> method is called by the following methods:");
>                                         Iterator sources = new
> Sources(cg.edgesInto(aMethod));
>                                         while (sources.hasNext()) {
>                                                 SootMethod src =
> (SootMethod) sources.next();
>                                                
> System.out.println("\t\t-" + src);
>                                         }
>               
>                                         System.out.println("\n\tThis
> method calls the following methods:");
>                                         Iterator targets = new
> Targets(cg.edgesOutOf(aMethod));
>                                         while (targets.hasNext()) {
>                                                 SootMethod tgt =
> (SootMethod) targets.next();
>                                                
> System.out.println("\t\t-" + tgt);
>                                         }
>                                         System.out.println("");
>                                 }
>                         }
>                 }
>         }
> 
> I use the method above to inspect a malware sample belonging to a family
> called Gone60.
> Before I call the method above from the beginning of the
> soot-infoflow-android's
> TestApps/Test.java, I execute the following two steps to make
> Soot/FlowDroid
> construct the callgraph :
>     initializeSoot();
>     PackManager.v().runPacks();
>           
> The problem is that, the particular malware runs a few threads from
> within its
> StartProcess() method as can be seen from the output of
> printAppInfoFromScene():
> 
> Soot method: <com.gone60.MyService: void StartProcess()>
>         - Unit: $r0 := @this: com.gone60.MyService
>         - Unit: $r0.<com.gone60.MyService: java.lang.String allData> = ""
>         - Unit: $r1 = new java.util.Random
>         - Unit: specialinvoke $r1.<java.util.Random: void <init>()>()
>         - Unit: $i2 = virtualinvoke $r1.<java.util.Random: int nextInt()>()
>         - Unit: $r3 = staticinvoke <java.lang.Integer: java.lang.String
> toString(int)>($i2)
>         - Unit: $r3 = staticinvoke <com.gone60.MyService:
> java.lang.String md5(java.lang.String)>($r3)
>         - Unit: $r0.<com.gone60.MyService: java.lang.String code> = $r3
>         - Unit: $r3 = $r0.<com.gone60.MyService: java.lang.String code>
>         - Unit: $r3 = virtualinvoke $r3.<java.lang.String:
> java.lang.String substring(int,int)>(0, 5)
>         - Unit: $r0.<com.gone60.MyService: java.lang.String code> = $r3
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: $r5 = $r0.<com.gone60.MyService: java.lang.String code>
>         - Unit: virtualinvoke $r4.<android.content.Intent:
> android.content.Intent
> putExtra(java.lang.String,java.lang.String)>("code", $r5)
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: virtualinvoke $r4.<android.content.Intent:
> android.content.Intent
> putExtra(java.lang.String,java.lang.String)>("status", "Start..")
>         - Unit: $r6 = $r0.<com.gone60.MyService: android.content.Context
> context>
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: virtualinvoke $r6.<android.content.Context: void
> sendBroadcast(android.content.Intent)>($r4)
>         - Unit: $r7 = new java.lang.Thread
>         - Unit: $r8 = $r0.<com.gone60.MyService: java.lang.Runnable
> ContactsCode>
>         - Unit: specialinvoke $r7.<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>(null,
> $r8, "MyService1")
>         - Unit: $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadCon> = $r7
>         - Unit: $r7 = $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadCon>
>         - Unit: virtualinvoke $r7.<java.lang.Thread: void start()>()
>         - Unit: $r7 = new java.lang.Thread
>         - Unit: $r8 = $r0.<com.gone60.MyService: java.lang.Runnable SmsCode>
>         - Unit: specialinvoke $r7.<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>(null,
> $r8, "MyService2")
>         - Unit: $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadSms> = $r7
>         - Unit: $r7 = $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadSms>
>         - Unit: virtualinvoke $r7.<java.lang.Thread: void start()>()
>         - Unit: $r7 = new java.lang.Thread
>         - Unit: $r8 = $r0.<com.gone60.MyService: java.lang.Runnable
> RecentCode>
>         - Unit: specialinvoke $r7.<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>(null,
> $r8, "MyService3")
>         - Unit: $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadRec> = $r7
>         - Unit: $r7 = $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadRec>
>         - Unit: virtualinvoke $r7.<java.lang.Thread: void start()>()
>         - Unit: $r7 = new java.lang.Thread
>         - Unit: $r8 = $r0.<com.gone60.MyService: java.lang.Runnable UrlCode>
>         - Unit: specialinvoke $r7.<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>(null,
> $r8, "MyService4")
>         - Unit: $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadUrl> = $r7
>         - Unit: $r7 = $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadUrl>
>         - Unit: virtualinvoke $r7.<java.lang.Thread: void start()>()
>         - Unit: $r7 = new java.lang.Thread
>         - Unit: $r8 = $r0.<com.gone60.MyService: java.lang.Runnable
> SendCode>
>         - Unit: specialinvoke $r7.<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>(null,
> $r8, "MyService5")
>         - Unit: $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadSend> = $r7
>         - Unit: $r7 = $r0.<com.gone60.MyService: java.lang.Thread
> ControlThreadSend>
>         - Unit: virtualinvoke $r7.<java.lang.Thread: void start()>()
>         - Unit: return
>         - Unit: $r9 := @caughtexception
>         - Unit: $r0.<com.gone60.MyService: java.lang.String
> ContactsData> = ""
>         - Unit: $r0.<com.gone60.MyService: boolean con_end> = 1
>         - Unit: goto [?= $r7 = new java.lang.Thread]
>         - Unit: $r10 := @caughtexception
>         - Unit: virtualinvoke $r10.<java.lang.Exception:
> java.lang.String getLocalizedMessage()>()
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: $r3 = $r0.<com.gone60.MyService: java.lang.String code>
>         - Unit: virtualinvoke $r4.<android.content.Intent:
> android.content.Intent
> putExtra(java.lang.String,java.lang.String)>("code", $r3)
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: virtualinvoke $r4.<android.content.Intent:
> android.content.Intent
> putExtra(java.lang.String,java.lang.String)>("status", "9")
>         - Unit: $r6 = $r0.<com.gone60.MyService: android.content.Context
> context>
>         - Unit: $r4 = $r0.<com.gone60.MyService: android.content.Intent
> intent>
>         - Unit: virtualinvoke $r6.<android.content.Context: void
> sendBroadcast(android.content.Intent)>($r4)
>         - Unit: goto [?= return]
>         - Unit: $r11 := @caughtexception
>         - Unit: $r0.<com.gone60.MyService: java.lang.String SmsData> = ""
>         - Unit: $r0.<com.gone60.MyService: boolean sms_end> = 1
>         - Unit: goto [?= $r7 = new java.lang.Thread]
>         - Unit: $r12 := @caughtexception
>         - Unit: $r0.<com.gone60.MyService: java.lang.String RecentData> = ""
>         - Unit: $r0.<com.gone60.MyService: boolean rec_end> = 1
>         - Unit: goto [?= $r7 = new java.lang.Thread]
>         - Unit: $r13 := @caughtexception
>         - Unit: $r0.<com.gone60.MyService: java.lang.String UrlData> = ""
>         - Unit: $r0.<com.gone60.MyService: boolean url_end> = 1
>         - Unit: goto [?= $r7 = new java.lang.Thread]
>         - Unit: $r2 := @caughtexception
>         - Unit: goto [?= return]
> 
>     This method is called by the following methods:
> 
>     This method calls the following methods:
> 
> As can be seen from the output above, the callgraph however doesn't show
> that StartProcess()
> refers to any run() methods of the thread-invoked runnable objects. In
> fact, no other methods
> are shown to call or be called by StartProcess(). FYI, one example of
> such run() methods is:
> 
>     Soot method: <com.gone60.MyService$1: void run()>
>         - Unit: $r0 := @this: com.gone60.MyService$1
>         - Unit: $r2 = $r0.<com.gone60.MyService$1: com.gone60.MyService
> this$0>
>         - Unit: $z0 = $r2.<com.gone60.MyService: boolean con_start>
>         - Unit: if $z0 == 0 goto $r2 = $r0.<com.gone60.MyService$1:
> com.gone60.MyService this$0>
>         - Unit: $r2 = $r0.<com.gone60.MyService$1: com.gone60.MyService
> this$0>               
>                 ...
> 
> Suspecting that the program point within Tests.java where I added the
> call to printAppInfoFromScene()
> does not contain a fully-constructed callgraph yet, I then did try to
> call it after FlowDroid has finished
> running its taint-flow analysis. Now, I obtain the following information
> on StartProcess():
> 
> Soot method: <com.gone60.MyService: void StartProcess()>
>     ...
>     This method is called by the following methods:
>         -<com.gone60.gone60: void onCreate(android.os.Bundle)>
> 
>     This method calls the following methods:
>         -<java.lang.Integer: void <clinit>()>
>         -<android.content.Intent: android.content.Intent
> putExtra(java.lang.String,java.lang.String)>
>         -<android.content.Intent: android.content.Intent
> putExtra(java.lang.String,java.lang.String)>
>         -<android.content.Intent: android.content.Intent
> putExtra(java.lang.String,java.lang.String)>
>         -<android.content.Intent: android.content.Intent
> putExtra(java.lang.String,java.lang.String)>
>         -<java.util.Random: int nextInt()>
>         -<java.util.Random: void <init>()>
>         -<java.lang.String: java.lang.String substring(int,int)>
>         -<java.lang.Thread: void run()>
>         -<java.lang.Thread: void start()>
>         -<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>
>         -<java.lang.Thread: void run()>
>         -<java.lang.Thread: void start()>
>         -<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>
>         -<java.lang.Thread: void run()>
>         -<java.lang.Thread: void start()>
>         -<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>
>         -<java.lang.Thread: void run()>
>         -<java.lang.Thread: void start()>
>         -<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>
>         -<java.lang.Thread: void run()>
>         -<java.lang.Thread: void start()>
>         -<java.lang.Thread: void
> <init>(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)>
>         -<java.lang.Throwable: java.lang.String getLocalizedMessage()>
>         -<java.lang.Integer: java.lang.String toString(int)>
>         -<com.gone60.MyService: java.lang.String md5(java.lang.String)>
> 
> As can be seen, this one shows the methods that StartProcess() calls and
> be called from.
> Yet, Soot/FlowDroid doesn't put an edge from StartProcess() to
> MyService$1.run() in its callgraph.
> 
> So I have two following questions:
> 
> - Why there's a discrepancy between calling the code block:
> initializeSoot(); PackManager.v().runPacks();
>   printAppInfoFromScene() before FlowDroid runs its taint-flow analysis,
> and calling printAppInfoFromScene()
>   right after FlowDroid has completed its taint-flow analysis.
>   What steps could possibly missing in the first case?
> 
> - Even if I use the results from the second case, still I can't have an
> information from
>   the callgraph that StartProcess() (indirectly) calls MyService$1.run()
> thru a thread.
>   That is, I can't assume that MyService$1.run() is reachable from 
> StartProcess().
>   This omission, I observe, makes MyService$1.run() becomes unreachable
> from any
>   entry points of the app.
> 
> Any helps on these two questions will be much appreciated!
> 
> Many Thanks!
> John
> 
> 
> 
> _______________________________________________
> Soot-list mailing list
> Soot-list at CS.McGill.CA
> https://mailman.CS.McGill.CA/mailman/listinfo/soot-list
> 


More information about the Soot-list mailing list