package playFlowDroid;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.xmlpull.v1.XmlPullParserException;
import soot.Body;
import soot.BodyTransformer;
import soot.EquivalentValue;
import soot.G;
import soot.PackManager;
import soot.Scene;
import soot.SootMethod;
import soot.Transform;
import soot.jimple.infoflow.android.SetupApplication;
import soot.jimple.toolkits.infoflow.InfoFlowAnalysis;
import soot.jimple.toolkits.infoflow.SimpleMethodInfoFlowAnalysis;
import soot.options.Options;
import soot.toolkits.graph.BriefUnitGraph;
import soot.toolkits.graph.HashMutableDirectedGraph;
import soot.toolkits.graph.pdg.HashMutablePDG;
import soot.toolkits.graph.pdg.PDGNode;
public class ProgramDependencyGraphDemo {
public static void main(String args[]) {
File file = new File("/home/gary/dev/testAPKs/crackme.apk");
String apkPath = file.getAbsolutePath();
System.out.println(apkPath);
String platformPath = "/home/gary/dev/android-platforms";
SetupApplication app = new SetupApplication(platformPath, apkPath, null);
try {
app.calculateSourcesSinksEntrypoints("./SourcesAndSinks.txt");
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
G.reset();
Options.v().set_src_prec(Options.src_prec_apk);
Options.v().set_process_dir(Collections.singletonList(apkPath));
Options.v().set_android_jars(platformPath);
Options.v().set_whole_program(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_output_format(Options.output_format_jimple);
Scene.v().loadNecessaryClasses();
if (app.getEntryPointCreator() == null) {
System.out
.println("EntryPointCreator is null! Make sure you have called calculateSourcesSinksEntryPoints()");
}
SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();
Options.v().set_main_class(entryPoint.getSignature());
Scene.v().setEntryPoints(Collections.singletonList(entryPoint));
Transform PDGTransform = new Transform("jtp.mypdg", new BodyTransformer() {
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
G.v().out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
G.v().out.println("Starting User-defined period jtp.mypdg:" + b.getMethod().getSignature());
InfoFlowAnalysis dfa = new InfoFlowAnalysis(true, true, true);
G.v().out.println("!----------dfa Constructed-------------------");
HashMutableDirectedGraph<EquivalentValue> ifg = dfa.getMethodInfoFlowSummary(b.getMethod());
G.v().out.println("!----------InfoFlow graph Generated----------");
HashMutablePDG pdg = new HashMutablePDG(new BriefUnitGraph(b));
G.v().out.println("!----------PDG graph Generated --------------");
generateIFG(ifg, b.getMethod().getSignature());
generatePDG(pdg, b.getMethod().getSignature());
G.v().out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
});
PackManager.v().getPack("jtp").add(PDGTransform);
PackManager.v().runPacks();
}
public static void generateIFG(HashMutableDirectedGraph<EquivalentValue> ifg, String methodSignature) {
StringBuffer ifgFile = new StringBuffer("");
for (EquivalentValue node : ifg) {
ifgFile.append("Node = " + node + '\n');
ifgFile.append("Preds:" + '\n');
for (EquivalentValue p : ifg.getPredsOf(node)) {
ifgFile.append(" ");
ifgFile.append(p.toString() + '\n');
}
ifgFile.append("Succs:" + '\n');
for (EquivalentValue s : ifg.getSuccsOf(node)) {
ifgFile.append(" ");
ifgFile.append(s.toString() + '\n');
}
}
File outFile = new File("sootOutput/" + methodSignature + ".ifg");
try {
if (outFile.exists()) {
if (!outFile.delete()) {
System.err.println("Delete file " + outFile + " failed ....");
}
}
if (outFile.createNewFile()) {
PrintWriter p = new PrintWriter(new FileOutputStream(outFile.getAbsolutePath()));
p.write(ifgFile.toString());
p.close();
} else {
System.err.println("Create file " + outFile + "failed ....");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatePDG(HashMutablePDG pdg, String methodSignature) {
StringBuffer pdgFile = new StringBuffer("");
for (PDGNode node : pdg) {
pdgFile.append("Node = " + node + '\n');
pdgFile.append("Preds:" + "\n");
for (PDGNode pred : pdg.getPredsOf(node)) {
DGEdge<PDGNode> edge = new DGEdge<PDGNode>(pred, node);
List<String> labels = pdg.edgeToLabels.get(edge);
pdgFile.append(" " + pred + " [" + labels + "]" + '\n');
}
pdgFile.append("Succs:" + '\n');
for (PDGNode succ : pdg.getSuccsOf(node)) {
DGEdge<PDGNode> edge = new DGEdge<PDGNode>(node, succ);
List<String> labels = pdg.edgeToLabels.get(edge);
pdgFile.append(" " + succ + " [" + labels + "]" + '\n');
}
}
File outFile = new File("sootOutput/" + methodSignature + ".pdg");
try {
if (outFile.exists()) {
if (!outFile.delete()) {
System.err.println("Delete file " + outFile + " failed ....");
}
}
if (outFile.createNewFile()) {
PrintWriter p = new PrintWriter(new FileOutputStream(outFile.getAbsolutePath()));
p.write(pdgFile.toString());
p.close();
} else {
System.err.println("Create file " + outFile + "failed ....");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}