[Soot-list] Spark & Android Source Code no main class

438 views
Skip to first unread message

Jason Ott

unread,
Mar 27, 2015, 5:20:17 AM3/27/15
to soot...@cs.mcgill.ca
I would like to build a callgraph for each class of the android framework and I am struggling.  I haven't found much in the way of documentation or examples for using SPARK in general.

I have a basic program that does the following:

public class DumpClass {
public static void main(String[] args) {

Scene.v().loadBasicClasses();
    SootClass mclass;
        mclass = Scene.v().loadClassAndSupport(args[0]);
        mclass.setApplicationClass();

Options.v().set_whole_program(true);
Options.v().setPhaseOption("cg.spark", "on");
Scene.v().loadNecessaryClasses();

Options.v().set_main_class(mclass.getMethods().get(0).toString());
PackManager.v().runPacks();

  new SparkTest(mclass);
    }
}

Now, when I run this, I get: Exception in thread "main" java.lang.RuntimeException: There is no main class set!

I'm not quite sure what to do with that or what to do next if this thing ever works.

Steven Arzt

unread,
Mar 27, 2015, 6:15:00 AM3/27/15
to Jason Ott, soot...@cs.mcgill.ca

Hi Jason,

 

You should never need to call „loadClassAndSupport“ on your own. This is done internally by Soot.

 

For creating a callgraph, you need an entry point. For normal Java applications, this is the main() method. You can either explicitly specify it or have Soot automatically select the only main() method in your Soot classpath.

 

The easiest way to get a callgraph is to call the Soot main method and pass the correct command-line parameters:

 

                -p cg.spark on                   This enables SPARK

                -process-dir                       Path to the classes you want to analyze

                -cp                                        Path to other classes that might be referenced from your analysis target

                -main-class                        The main class to use

 

After the call to soot.Main.main(), you should be able to access the callgraph.

 

A more involved example that calls the required parts of Soot manually goes here:

 

       public static void main(String[] args) {

             Options.v().parse(args);

             Scene.v().loadNecessaryClasses();

             SootClass sc = Scene.v()

                           .forceResolve("soot.Examples", SootClass.BODIES);

             sc.setApplicationClass();

             SootMethod method = sc.getMethodByName("main");

             List<SootMethod> entryPoints = new ArrayList<SootMethod>();

             entryPoints.add(method);

             Scene.v().setEntryPoints(entryPoints);

             Options.v().set_main_class(method.getSignature());

 

             PackManager.v().runPacks();

 

             CallGraph callgraph = Scene.v().getCallGraph();

             System.out.println("[TestSpark] Call graph size " + callgraph.size());

            

             for (Edge edge : callgraph)

                    System.out.println(edge + "");

 

       }

 

This is essentially what the normal Soot main method would do.

 

Best regards,

  Steven

Jason Ott

unread,
Mar 27, 2015, 1:29:10 PM3/27/15
to Steven Arzt, soot...@cs.mcgill.ca
So if I wanted to generate a call graph for WifiManager.java (http://androidxref.com/5.1.0_r1/xref/frameworks/base/wifi/java/android/net/wifi/WifiManager.java) a class within the Android framework.  Would I have to create and compile a main.java that instantiates a WifiManager object on the fly, pass that to Soot and then generate the call graph with the dynamically created main file as my starting point?

So the code would change a bit to:

dynamically create the java file:

public static void main(String[] args) {
     WifiManager m = new WifiManager();
}

as main.java

Run the following command:

java -cp ../bin/jasminclasses-2.4.0.jar:../bin/polyglot.jar:../bin/sootclasses-2.4.0.jar:../soot/DumpClass/bin:. callGrapher.GenerateCallGraph WifiManager.java


public static void main(String[] args) {

             Scene.v().loadNecessaryClasses();

             SootClass sc = Scene.v()

                           .forceResolve(args[0], SootClass.BODIES);

             sc.setApplicationClass();

             SootMethod method = sc.getMethodByName("main");

             List<SootMethod> entryPoints = new ArrayList<SootMethod>();

             entryPoints.add(method);

             Scene.v().setEntryPoints(entryPoints);

             Options.v().set_main_class(method.getSignature());

 

             PackManager.v().runPacks();

 

             CallGraph callgraph = Scene.v().getCallGraph();

             System.out.println("[TestSpark] Call graph size " + callgraph.size());

            

             for (Edge edge : callgraph)

                    System.out.println(edge + "");

 

       }


Assuming this is the case, I'd have to do this for any class or file I'd want to generate a callgraph for within the Android framework, is that correct?

On Fri, Mar 27, 2015 at 3:14 AM, Steven Arzt <Steve...@cased.de> wrote:

Hi Jason,

 

You should never need to call „loadClassAndSupport“ on your own. This is done internally by Soot.

 

For creating a callgraph, you need an entry point. For normal Java applications, this is the main() method. You can either explicitly specify it or have Soot automatically select the only main() method in your Soot classpath.

 

The easiest way to get a callgraph is to call the Soot main method and pass the correct command-line parameters:

 

                -p cg.spark on                   This enables SPARK

                -process-dir                       Path to the classes you want to analyze

                -cp                                        Path to other classes that might be referenced from your analysis target

                -main-class                        The main class to use

 

After the call to soot.Main.main(), you should be able to access the callgraph.

 

A more involved example that calls the required parts of Soot manually goes here:

 

       public static void main(String[] args) {

             Options.v().parse(args);

             Scene.v().loadNecessaryClasses();

             SootClass sc = Scene.v()

                           .forceResolve("soot.Examples", SootClass.BODIES);

             sc.setApplicationClass();

             SootMethod method = sc.getMethodByName("main");

             List<SootMethod> entryPoints = new ArrayList<SootMethod>();

             entryPoints.add(method);

             Scene.v().setEntryPoints(entryPoints);

             Options.v().set_main_class(method.getSignature());

 

             PackManager.v().runPacks();

 

             CallGraph callgraph = Scene.v().getCallGraph();

             System.out.println("[TestSpark] Call graph size " + callgraph.size());

            

             for (Edge edge : callgraph)

                    System.out.println(edge + "");

 

       }

 

This is essentially what the normal Soot main method would do.

 

Best regards,

  Steven

 

Von: soot-lis...@CS.McGill.CA [mailto:soot-lis...@CS.McGill.CA] Im Auftrag von Jason Ott
Gesendet: Mittwoch, 25. März 2015 06:31
An: soot...@CS.McGill.CA
Betreff: [Soot-list] Spark & Android Source Code no main class

 

I would like to build a callgraph for each class of the android framework and I am struggling.  I haven't found much in the way of documentation or examples for using SPARK in general.

Steven Arzt

unread,
Mar 27, 2015, 1:33:26 PM3/27/15
to Jason Ott, soot...@cs.mcgill.ca

Hi Jason,

 

Yes, the general structure of your approach is correct. You do not necessarily need to generate an own main() method for every Android framework method for which you want to compute a callgraph, though. You can also put that all together into a single main method.

 

Best regards,

  Steven

Steven Arzt

unread,
Dec 10, 2015, 4:32:38 AM12/10/15
to Anshul Vij, soot, soot...@cs.mcgill.ca, jot...@ucr.edu

Hi Anshul,

 

Android apps have no main class like traditional Java programs. Instead, they form plugins to the Android OS. If you just specify the onCreate() method of an Activity as your entry point, you have two problems: Firstly, the SPARK callgraph builder needs a static method as the entry point, or it will not find any outgoing edges for virtual calls on the “this” variable. You callgraph would thus be greatly unsound. Secondly, you would miss all the other methods that are not transitively reachable from your onCreate() method. You  would, for instance, never end up in onPause().

 

In FlowDroid, we solved the problem by automatically generating an artificial dummy main method that emulates the method call sequences that would normally be done within the Android OS. You can re-use the FlowDroid dummy main generator if you like:

 

             SetupApplication app = new SetupApplication

                           ("D:/Tools/adt-bundle-windows-x86_64-20140321/sdk/platforms",

                           "D:/Temp/com.tweakersoft.aroundme-1.apk");

             app.calculateSourcesSinksEntrypoints("D:/Arbeit/Android Analyse/soot-infoflow-android/SourcesAndSinks.txt");

             soot.G.reset();

             

             Options.v().set_src_prec(Options.src_prec_apk);

             Options.v().set_process_dir(Collections.singletonList("D:/Temp/com.tweakersoft.aroundme-1.apk"));

             Options.v().set_android_jars("D:/Tools/adt-bundle-windows-x86_64-20140321/sdk/platforms");

             Options.v().set_whole_program(true);

             Options.v().set_allow_phantom_refs(true);

             Options.v().set_output_format(Options.output_format_class);

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

            

             Scene.v().loadNecessaryClasses();

            

             SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();

             Options.v().set_main_class(entryPoint.getSignature());

             Scene.v().setEntryPoints(Collections.singletonList(entryPoint));

             System.out.println(entryPoint.getActiveBody());

            

             PackManager.v().runPacks();

             System.out.println(Scene.v().getCallGraph().size());

 

Best regards,

  Steven

 

Von: Anshul Vij [mailto:vijan...@gmail.com]
Gesendet: Sonntag, 6. Dezember 2015 14:55
An: soot
Cc: jot...@ucr.edu; soot...@cs.mcgill.ca; Steve...@cased.de
Betreff: Re: [Soot-list] Spark & Android Source Code no main class

 

Hi Steven Arzt,

I am also using Soot framework for creating and using Android application's call graph. 

Can you help me in understanding which class should I use as main class?

For me callgraph.size() always returning 0.

 

I want to find a particular method invocation in all method bodies and backtrack (using edgesInto(method)) until I reach a method that is Android callback method.

I have a list to match the signatures with callback method.

Current problem is that the callgraph contains nothing.

 

I believe as you pointed here that I need to set a main class and entry point.

So should I make an Activity as a main class and onCreate() as entry point?

 

Please help in this regard.

 

Thank you!

 

Kind regards,

Anshul

Anshul Vij

unread,
Feb 10, 2016, 2:18:57 PM2/10/16
to soot, soot...@cs.mcgill.ca, jot...@ucr.edu, Steve...@cased.de
Hi Steven Arzt,
I am also using Soot framework for creating and using Android application's call graph. 
Can you help me in understanding which class should I use as main class?
For me callgraph.size() always returning 0.

I want to find a particular method invocation in all method bodies and backtrack (using edgesInto(method)) until I reach a method that is Android callback method.
I have a list to match the signatures with callback method.

Current problem is that the callgraph contains nothing.

I believe as you pointed here that I need to set a main class and entry point.
So should I make an Activity as a main class and onCreate() as entry point?

Please help in this regard.

Thank you!

Kind regards,
Anshul
 

On Friday, 27 March 2015 11:15:00 UTC+1, Steven Arzt wrote:

Steven Arzt

unread,
Feb 28, 2016, 2:52:18 PM2/28/16
to Anshul Vij, soot, soot...@cs.mcgill.ca, jot...@ucr.edu

Hi Anshul,

 

For using SPARK, you need a proper entry point. This entry point must be a public static method that is the starting point of your program execution. In a Java program, this would be the main() method. Unfortunately, there is no such method in an Android app. Therefore, you need to create your own. For a precise callgraph, this custom entry point must faithfully model the interaction of the Android framework with the app. As this is very complex, I would recommend using the existing implementation in FlowDroid:

 

             SetupApplication app = new SetupApplication

                           ("D:/Tools/adt-bundle-windows-x86_64-20140321/sdk/platforms",

                           "D:/Temp/com.tweakersoft.aroundme-1.apk");

             app.calculateSourcesSinksEntrypoints("D:/Arbeit/Android Analyse/soot-infoflow-android/SourcesAndSinks.txt");

             soot.G.reset();

             

             Options.v().set_src_prec(Options.src_prec_apk);

             Options.v().set_process_dir(Collections.singletonList("D:/Temp/com.tweakersoft.aroundme-1.apk"));

             Options.v().set_android_jars("D:/Tools/adt-bundle-windows-x86_64-20140321/sdk/platforms");

             Options.v().set_allow_phantom_refs(true);

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

            

             Scene.v().loadNecessaryClasses();

            

             SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();

             Options.v().set_main_class(entryPoint.getSignature());

             Scene.v().setEntryPoints(Collections.singletonList(entryPoint));

             System.out.println(entryPoint.getActiveBody());

            

             PackManager.v().runPacks();

             System.out.println(Scene.v().getCallGraph().size());

 

This code should give you a non-empty callgraph.

 

Best regards,

  Steven

 

 

Von: soot-lis...@CS.McGill.CA [mailto:soot-lis...@CS.McGill.CA] Im Auftrag von Anshul Vij


Gesendet: Sonntag, 6. Dezember 2015 14:55
An: soot

Cc: soot...@CS.McGill.CA; jot...@ucr.edu; Steve...@cased.de
Betreff: Re: [Soot-list] Spark & Android Source Code no main class

Hi Steven Arzt,

I am also using Soot framework for creating and using Android application's call graph. 

Can you help me in understanding which class should I use as main class?

For me callgraph.size() always returning 0.

 

I want to find a particular method invocation in all method bodies and backtrack (using edgesInto(method)) until I reach a method that is Android callback method.

I have a list to match the signatures with callback method.

Current problem is that the callgraph contains nothing.

 

I believe as you pointed here that I need to set a main class and entry point.

So should I make an Activity as a main class and onCreate() as entry point?

 

Please help in this regard.

 

Thank you!

 

Kind regards,

Anshul

 


On Friday, 27 March 2015 11:15:00 UTC+1, Steven Arzt wrote:

Reply all
Reply to author
Forward
0 new messages