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

John Foster johnfostercs at gmail.com
Thu Nov 20 14:29:25 EST 2014


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20141121/abffe89f/attachment-0001.html 


More information about the Soot-list mailing list