[Soot-list] Generating Android APK CallFlowGraph

Monika Mashalkar monikamashalkar at gmail.com
Tue Feb 24 23:30:08 EST 2015


Hi Lokesh,

I am very new to the SOOT Framework and Flow-droid. I want to find the flow 
graph from android apk in my project and I am trying to run the code posted 
in this thread to do the same. I am trying to run the following command on 
Ubuntu 

Command : java -cp 
soot-trunk.jar:soot-infoflow.jar:soot-infoflow-android.jar:slf4j-api-1.7.5.jar:slf4j-simple-1.7.5.jar:axml-2.0.jar 
-cp .:/usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar CFG

but I am getting Error as : Error: Could not find or load main class CFG

Could you please tell me the command to execute the CFG program.

Thank you,
Monika

On Monday, 21 July 2014 13:46:37 UTC+5:30, LOKESH JAIN wrote:
>
> Hi all,
>
> I resolved the issue and finally i am getting the call graph. Thank you 
> all of you for your time and help. :)
>
> 1. But Stevan I am still curious to know how to work with QueueReader 
> Object for generating dot format.
> 2. And why the size of call graph for RV2013.apk is 54. And is there any 
> way to remove unnecessary size.
>
> Thanks&Regards
> Lokesh
>
>
> On Mon, Jul 21, 2014 at 11:38 AM, LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>> wrote:
>
> Hi all,
> Steven I still couldn't figure it out how to work with queuereader object 
> for generating dot format.
>
> I have used dot graph class manually as suggested to me by Stefan but,
> I am getting NullPointerException. I don't know why. I have pasted the 
> complete code.
> Please help me out.
>
> Exception in thread "main" java.lang.NullPointerException
>  at DotGraph.getNode(DotGraph.java:53)
> at DotGraph.drawNode(DotGraph.java:61)
> at CFG.visit(CFG.java:114)
>  at CFG.main(CFG.java:94)
>
>
> CFG.java
>
> import java.io.BufferedOutputStream;
> import java.io.FileOutputStream;
>  import java.io.IOException;
> import java.io.OutputStream;
> import java.util.Collections;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Iterator;
>  import java.util.LinkedList;
> import java.util.List;
>
> import org.xmlpull.v1.XmlPullParserException;
>
> import soot.MethodOrMethodContext;
> import soot.PackManager;
> import soot.Scene;
> import soot.SootMethod;
> import soot.jimple.infoflow.android.SetupApplication;
> import soot.jimple.toolkits.callgraph.CallGraph;
> import soot.jimple.toolkits.callgraph.Targets;
>  import soot.options.Options;
> import soot.util.dot.DotGraphUtility;
> import soot.util.dot.Renderable;
> public class CFG {
> private static DotGraph dot = new DotGraph("callgraph");
> private static HashMap <String,Boolean> visited = new 
> HashMap<String,Boolean>(); 
> public CFG() {
>
>
> }
>
> public static void main(String[] args) {
>
> // TODO Auto-generated method stub
>
> SetupApplication app = new 
> SetupApplication("/home/lokesh/Desktop/android-sdk-linux/platforms/android-19/android.jar","/home/lokesh/Desktop/android-instrumentation-tutorial-master/app-example/RV2013/bin/RV2013.apk");
>  try {
>
>
> app.calculateSourcesSinksEntrypoints("/home/lokesh/Downloads/soot-infoflow-android-develop/SourcesAndSinks.txt");
>
>
> } catch (IOException e) {
>
> // TODO Auto-generated catch block
>
> e.printStackTrace();
>
> } catch (XmlPullParserException e) {
>
> // TODO Auto-generated catch block
>
> e.printStackTrace();
>
> }
>
> soot.G.reset();
>
> Options.v().set_src_prec(Options.src_prec_apk);
>
>
> Options.v().set_process_dir(Collections.singletonList("/home/lokesh/Desktop/android-instrumentation-tutorial-master/app-example/RV2013/bin/RV2013.apk"));
>
>
> Options.v().set_force_android_jar("/home/lokesh/Desktop/android-sdk-linux/platforms/android-19/android.jar");
>
> Options.v().set_whole_program(true);
>
> Options.v().set_allow_phantom_refs(true);
>
> Options.v().set_output_format(Options.output_format_none);
>
> Options.v().setPhaseOption("cg.spark verbose:true", "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());
> CallGraph cg = Scene.v().getCallGraph();
>
> visit(cg, entryPoint);
> dot.plot("/home/lokesh/Desktop/soot1"+ dot.DOT_EXTENSION);
>
> }
> private static void visit(CallGraph cg, SootMethod k)
> {
> String identifier = k.getName();
>
> visited.put(k.getSignature(),true);
>
>
> dot.drawNode(identifier);
>
>
> //iterate over unvisited parents
> Iterator<MethodOrMethodContext> ptargets = new Targets(cg.edgesInto(k));
>
>
> if(ptargets != null){
> while(ptargets.hasNext())
> {
> SootMethod p = (SootMethod) ptargets.next();
>
>
> if(p == null) System.out.println("p is null");
>
>
> if(!visited.containsKey(p.getSignature()))
> visit(cg,p);
> }
> }
>
>
> //iterate over unvisited children
> Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(k));
>
>  
> if(ctargets != null){
> while(ctargets.hasNext())
> {
> SootMethod c = (SootMethod) ctargets.next();
> if(c == null) System.out.println("c is null");
> dot.drawEdge(identifier, c.getName());
>
>
> if(!visited.containsKey(c.getSignature()))
> visit(cg,c);
> }
> }
> }
> }
>
>
>
>
> DotGraph.java
>
> import java.io.BufferedOutputStream;
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.io.OutputStream;
> import java.util.HashMap;
> import java.util.LinkedList;
> import java.util.List;
>
> import soot.util.dot.DotGraphEdge;
> import soot.util.dot.DotGraphNode;
> import soot.util.dot.DotGraphUtility;
> import soot.util.dot.Renderable;
>
> public class DotGraph implements Renderable
> {
> public final static String DOT_EXTENSION = ".dot";
> private HashMap<String, DotGraphNode> nodes;
>  private boolean isSubGraph;
> private List<Renderable> drawElements;
> private String graphname;
> public DotGraph(String graphname)
> {
> this.drawElements = new LinkedList<Renderable>();
> }
> public DotGraph createSubGraph(String label)
> {
> DotGraph subgraph = new DotGraph(label);
> subgraph.isSubGraph = true;
> this.drawElements.add(subgraph);
> System.out.println(subgraph);
> return subgraph;
> }
> @Override
> public void render(OutputStream out, int indent) throws IOException {
> String graphname = this.graphname;
>     if (!isSubGraph) {
>       DotGraphUtility.renderLine(out, "digraph \""+graphname+"\" {", 
> indent);
>     } else {
>  DotGraphUtility.renderLine(out, "subgraph \""+graphname+"\" {", indent);
>
>     }
>  }
> public void plot(String filename) {
>     try {
>       BufferedOutputStream out =new BufferedOutputStream(new 
> FileOutputStream(filename));
>       render(out, 0);
>       out.close();
>     } catch (IOException ioe) {
>     }
>   }
> public DotGraphNode getNode(String name){
> DotGraphNode node = nodes.get(name);
> if (node == null) {
> node = new DotGraphNode(name);
> nodes.put(name, node);
> }
> return node;
> }
> public DotGraphNode drawNode(String name){
> DotGraphNode node = getNode(name);
> if(node == null)
> throw new RuntimeException("Assertion failed.");
> if(!this.drawElements.contains(node))
> this.drawElements.add(node);
> return node;
>   }
>  
> public DotGraphEdge drawEdge(String from, String to) {
> DotGraphNode src = drawNode(from);
> DotGraphNode dst = drawNode(to);
> DotGraphEdge edge = new DotGraphEdge(src, dst);
> this.drawElements.add(edge);
> return edge;
>
>   }
> } 
>
> Thanks & Regards
> Lokesh
>
>  
>
> On Sun, Jul 20, 2014 at 5:10 PM, Stefan Gommer <
> gom... at informatik.uni-bremen.de <javascript:>> wrote:
>
> Hi Lokesh,
>
> sorry I misspelled it. Originally it is of type Hash*Map*<String,Boolean>.
>
> You can also use HashSet<String>. In this case you have to use 
> visited.add(k.getSignature());
>
> Regards,
> Stefan
>
> Am 20.07.2014 um 13:35 schrieb LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>>:
>
> Hi Stefan,
> HashSet<String,Boolean> type is giving error whereas HashSet<String> is 
> correct form. But
>
> then
> visited.put(k.getSignature(),true) is giving error.
> How do i resolve this?
>
> Thanks & Regards
> Lokesh
>
>
> On Sun, Jul 20, 2014 at 4:52 PM, LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>> wrote:
>
> Hi Stefan,
> HashSet<String,Boolean> type is giving error whereas HashSet<String> is 
> correct form. But
>
> then
> visited.put(k.getSignature(),true) is giving error.
>
> Thanks & Regards
> Lokesh
>  
>
> On Sun, Jul 20, 2014 at 4:16 PM, Stefan Gommer <
> gom... at informatik.uni-bremen.de <javascript:>> wrote:
>
> Hi Lokesh,
>
> visited is of type HashSet<String,Boolean> but can also be any kind of 
> List like HashSet<String>
>
> Regards
> Stefan 
>
> Am 20.07.2014 um 12:44 schrieb LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>>:
>
> Hey Stefan!
>
> What is the type of "visited" ?
>
> Thanks & Regards
> Lokesh
>
>
> On Sun, Jul 20, 2014 at 2:57 PM, Stefan Gommer <
> gom... at informatik.uni-bremen.de <javascript:>> wrote:
>
> Hi Lokesh,
>
> I did it like this (I skipped the standard soot settings:
>
> private static DotGraph dot = new DotGraph("CallGraph“);
> ...
> SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();
>> PackManager.v().runPacks();
> CallGraph cg = Scene.v().getCallGraph();
> visit(cg, entryPoint);
>> dot.plot("/Users/neji/Desktop/graph"+ dot.DOT_EXTENSION);
>>
>
> private static void visit(CallGraph cg, SootMethod k)
>  {
> String identifier = k.getName();
>  
>  visited.put(k.getSignature(), true);
>  
> dot.drawNode(identifier);
>  
> //iterate over unvisited parents
>  Iterator<MethodOrMethodContext> ptargets = new Targets(cg.edgesInto(k));
>
>  if(ptargets != null){
> while(ptargets.hasNext())
>  {
> SootMethod p = (SootMethod) ptargets.next();
>  
> if(p == null) System.out.println("p is null");
>  
> if(!visited.containsKey(p.getSignature()))
>  visit(cg,p);
> }
> }
>  
> //iterate over unvisited children
>  Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(k));
>  
> if(ctargets != null){
>  while(ctargets.hasNext())
> {
> SootMethod c = (SootMethod) ctargets.next();
>  if(c == null) System.out.println("c is null");
>  dot.drawEdge(identifier, c.getName());
>
>  if(!visited.containsKey(c.getSignature()))
>  visit(cg,c);
>  }
> }
> }
>
>
> Am 20.07.2014 um 09:44 schrieb LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>>:
>
> I have tried DotGraph class from the soot.util.dot package but it's giving 
> me null pointer exception. Following is the tried code.
>
> I have converted QueueReader object into string as DotGraph takes only 
> string argument. It's getting complicated. Please suggest some simple 
> solution.
>
> import java.io.IOException;
> import java.io.OutputStream;
> import java.util.Collections;
> import java.util.LinkedList;
> import java.util.List;
>
> import org.xmlpull.v1.XmlPullParserException;
>
> import soot.PackManager;
> import soot.Scene;
> import soot.SootMethod;
> import soot.jimple.infoflow.android.SetupApplication;
> import soot.options.Options;
> import soot.util.dot.DotGraphUtility;
> import soot.util.dot.Renderable;
> public class CFG {
>      //private static Map options;
>     static DotGraph dg;
> public CFG() {
> //this.options=options;
> // TODO Auto-generated constructor stub
>
> }
> /*public DotGraph createSubGraph(String label)
> {
>
> DotGraph createSubGraph = 
> DotGraph.createSubGraph(Scene.v().getCallGraph().listener().toString());    
> }*/
> public static void main(String[] args) {
>
> // TODO Auto-generated method stub
>
> SetupApplication app = new 
> SetupApplication("/home/lokesh/Desktop/android-sdk-linux/platforms/android-19/android.jar","/home/lokesh/Desktop/android-instrumentation-tutorial-master/app-example/RV2013/bin/RV2013.apk");
>    
> try {
>
>
> app.calculateSourcesSinksEntrypoints("/home/lokesh/Downloads/soot-infoflow-android-develop/SourcesAndSinks.txt");
>
>
> } catch (IOException e) {
>
> // TODO Auto-generated catch block
>
> e.printStackTrace();
>
> } catch (XmlPullParserException e) {
>
> // TODO Auto-generated catch block
>
> e.printStackTrace();
>
> }
>
> soot.G.reset();
>
> Options.v().set_src_prec(Options.src_prec_apk);
>
>
> Options.v().set_process_dir(Collections.singletonList("/home/lokesh/Desktop/android-instrumentation-tutorial-master/app-example/RV2013/bin/RV2013.apk"));
>
> Options.v().set_force_android_jar("/home/lokesh/Desktop/android-sdk-linux/platforms/android-19/android.jar");
>
> Options.v().set_whole_program(true);
>
> Options.v().set_allow_phantom_refs(true);
>
> Options.v().set_output_format(Options.output_format_none);
>
> Options.v().setPhaseOption("cg.spark verbose:true", "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());
> String label = Scene.v().getCallGraph().listener().toString();
> dg.createSubGraph(label);
> }
> }
>
> import java.io.IOException;
> import java.io.OutputStream;
> import java.util.LinkedList;
> import java.util.List;
>
> import soot.util.dot.DotGraphUtility;
> import soot.util.dot.Renderable;
>
> public class DotGraph implements Renderable
> {
> private boolean isSubGraph;
> private List<Renderable> drawElements;
> private String graphname;
> public DotGraph(String graphname)
> {
> this.drawElements = new LinkedList<Renderable>();
> }
> public DotGraph createSubGraph(String label)
> {
> DotGraph subgraph = new DotGraph(label);
> subgraph.isSubGraph = true;
> this.drawElements.add(subgraph);
> System.out.println(subgraph);
> return subgraph;
> }
> @Override
> public void render(OutputStream out, int indent) throws IOException {
>     String graphname = this.graphname;
>         if (!isSubGraph) {
>           DotGraphUtility.renderLine(out, "digraph \""+graphname+"\" {", 
> indent);
>         } else {
>  DotGraphUtility.renderLine(out, "subgraph \""+graphname+"\" {", indent);
>
>         }
>     
> }
> } 
>
> Thanks & Regards
> Lokesh
>
>
> On Sat, Jul 19, 2014 at 10:57 PM, Stefan Gommer <gommer... at googlemail.com 
> <javascript:>> wrote:
>
> Hi Lokesh,
>
> you could use the DotGraph class from the soot.util.dot package and build 
> a Graph on your own while traversing through the cfg. I don’t know if there 
> is a method to do this automatically.
>
> Stefan
>
>
> Am 19.07.2014 um 15:16 schrieb LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>>:
>
> Hi Steven,
> this Scene.v().getCallgraph().listener() is giving me QueueReader object. 
> But I am not able to create a dot file from it. I have tried dump_cfg and 
> various others options but all are of no help. 
>
> 1. Please can you tell me how do i print a dot file out of QueueReader 
> object?
>
> Also I am getting the call graph size as 54 for the general example apk 
> "RV2013.apk".
>
> 2. How come call graph size is 54?
>
>
>
> On Fri, Jul 18, 2014 at 9:37 PM, Steven Arzt <Steve... at cased.de 
> <javascript:>> wrote:
>
> Hi Lokesh,
>
>  
>
> You can manually iterate over the callgraph using 
> Scene.v().getCallgraph().listener() and print it out in dot format  which 
> should be fairly simple as it is just a QueueReader over the edges. Still, 
> I think Soot can also directly do that, but I have never used  the dot 
> visualizer for callgraphs.
>
>  
>
> Afterwards, you can visualize the dot file using GraphViz.
>
>  
>
> Best regards,
>
>   Steven
>
>  
>
> *Von:* LOKESH JAIN [mailto:lokesh... at gmail.com <javascript:>] 
> *Gesendet:* Freitag, 18. Juli 2014 18:04
> *An:* Steven Arzt
> *Cc:* Modhi Alsobiehy; soot... at cs.mcgill.ca <javascript:>; 
> soot... at sable.mcgill.ca <javascript:>; soot... at googlegroups.com 
> <javascript:>
>
> *Betreff:* Re: [Soot-list] Generating Android APK CallFlowGraph
>
>  
>
> Hi,
>
> A gentle reminder. Please reply fast. I need it for my research project.
>
>  
>
> Regards
>
> Lokesh
>
>  
>
> On Thu, Jul 17, 2014 at 9:21 PM, LOKESH JAIN <lokesh... at gmail.com 
> <javascript:>> wrote:
>
> Thanks a lot Steven and Modhi. It worked.
>
> It is showing call graph in words. How can I graphically see the call 
> graph for apk files as we see for java files??
>
>  
>
> Regards
>
> Lokesh Jain
>  
>  
>
> On Thu, Jul 17, 2014 at 6:11 PM, Steven Arzt <Steve... at cased.de 
> <javascript:>> wrote:
>
> Hi Lokesh,
>
>  
>
> It seems that you are missing the axml-2.0.jar library on your Java 
> classpath.
>
>  
>
> Best regards,
>
>   Steven
>
>  
>
> *Von:* soot-lis... at CS.McGill.CA <javascript:> [mailto:
> soot-lis... at CS.McGill.CA <javascript:>] *Im Auftrag von *Modhi Alsobiehy
> *Gesendet:* Donnerstag, 17. Juli 2014 14:39
> *An:* LOKESH JAIN
> *Cc:* soot... at cs.mcgill.ca <javascript:>; soot... at sable.mcgill.ca 
> <javascript:>; soot... at googlegroups.com <javascript:>
> *Betreff:* Re: [Soot-list] Generating Android APK CallFlowGraph
>
>  
>
> Hi Lokesh,
>
>  
>
> Open the folder of your project and add the call back file into it.
>
>  
>
> -Best,
>
> Modhi
>
>
> On Jul 17, 2014, at 12:03 PM, "LOKESH JAIN" <lokesh... at gmail.com 
> <javascript:>> wrote:
>
> Hi all,
>
> Modhi, I am using your code for generating call graph for apk file. But, I 
> am getting following error
>  
> Exception in thread "main" java.lang.NoClassDefFoundError: 
> pxb/android/axml/NodeVisitor
>     at 
> soot.jimple.infoflow.android.manifest.ProcessManifest.handle(Unknown Source)
>     at 
> soot.jimple.infoflow.android.manifest.ProcessManifest.<init>(Unknown Source)
>     at 
> soot.jimple.infoflow.android.manifest.ProcessManifest.<init>(Unknown Source)
>     at 
> soot.jimple.infoflow.android.SetupApplication.calculateSourcesSinksEntrypoints(Unknown 
> Source)
>     at 
> soot.jimple.infoflow.android.SetupApplication.calculateSourcesSinksEntrypoints(Unknown 
> Source)
>     at CFG.main(CFG.java:33)
> Caused by: java.lang.ClassNotFoundException: pxb.android.axml.NodeVisitor
>     at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
>     at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
>     at java.security.AccessController.doPrivileged(Native Method)
>     at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
>     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
>     ... 6 more
>
> It's pretty much the same error that you were getting. Though I had 
> checked , there is no duplicate library added. Also there is already 
> AndroidCallbacks.txt in soot-infoflow-android, i haven't understood how to 
> add it into my project.
> Any help would be appreciated. Thank You
> Regards
> Lokesh
>
>
> On Saturday, 5 July 2014 23:04:49 UTC+5:30, Modhi Alsobiehy wrote:
>
> Hi all,
>
> I need to traverse the call flow graph of android apps( apk files).
>
> I understand that I must set an entry point so to start, I tried the 
> following code :
>
>  
>
> ---------------------
>
> ...

-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20150224/3ac03590/attachment-0003.html 


More information about the Soot-list mailing list