在使用FlowDroid对apk进行静态分析和绘制函数调用图(CallGraph)时,遇到了一个问题,如下:
SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();
执行该行代码时,抛出空指针异常,打断点发现这个getEntryPointCreator()返回了null,这是什么问题?
有的apk是正常的,能正确的绘制CG,其他的都在这里出错,问题出在哪了啊

解决方案 »

  1.   

    全部代码如下:
    package CGPackage;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;import soot.MethodOrMethodContext;
    import soot.PackManager;
    import soot.Scene;
    import soot.SootMethod;
    import soot.jimple.infoflow.android.SetupApplication;
    import soot.jimple.infoflow.entryPointCreators.AndroidEntryPointCreator;
    import soot.jimple.toolkits.callgraph.CallGraph;
    import soot.jimple.toolkits.callgraph.Targets;
    import soot.options.Options;
    import soot.util.dot.DotGraph;
    import soot.util.dot.DotGraphEdge;public class CGGenerator {
        // 设置android的jar包目录
        public final static String androidPath = "C:\\AndroidSDK\\sdk\\platforms\\android-27\\android.jar";
        // 设置要分析的APK文件
        public final static String apkPath = "C:\\DynamicLoad\\Apks\\weibo.apk";
        // dot保存目录
        public final static String dotpath = "C:\\DynamicLoad\\CallGraph";
        // 设置sourceAndSink目录
        public final static String sourceAndSink = "C:\\SourcesAndSinks.txt";    private static Map<String, Boolean> visited = new HashMap<String, Boolean>();
        //private static CGExporter cge = new CGExporter();    private static DotGraph dotGraph = new DotGraph("dot");    public static void main(String[] args) {
            SetupApplication app = new SetupApplication(androidPath, apkPath);
            try {
                // 计算APK的入口点
                app.calculateSourcesSinksEntrypoints(sourceAndSink);
            } catch (Exception e) {
                e.printStackTrace();
            }
            soot.G.reset();        Options.v().set_src_prec(Options.src_prec_apk);
            Options.v().set_process_dir(Collections.singletonList(apkPath));
            Options.v().set_force_android_jar(androidPath);
            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();
            AndroidEntryPointCreator creator = app.getEntryPointCreator();
            SootMethod entryPoint = creator.createDummyMain();
            Options.v().set_main_class(entryPoint.getSignature());
            Scene.v().setEntryPoints(Collections.singletonList(entryPoint));
            PackManager.v().runPacks();
            // 获取函数调用图
            CallGraph cg = Scene.v().getCallGraph();
            System.out.println("*********************************");
            System.out.println(entryPoint);
            System.out.println("*********************************");
            // System.out.println(cg.toString());
            System.out.println("*********************************");
            toDot(cg, entryPoint);
            File file = new File(dotpath, "test.dot");
            OutputStream out;
            try {
                out = new FileOutputStream(file);
                dotGraph.render(out, 0);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }    private static void toDot(CallGraph cg, SootMethod m) {        Iterator<MethodOrMethodContext> inTargets = new Targets(cg.edgesInto(m));
            visited.put(m.getSignature(), true);
            if (inTargets != null) {
                while (inTargets.hasNext()) {
                    SootMethod in = (SootMethod) inTargets.next();
                    if (in == null) {
                        System.out.println("in is null");
                    }
                    System.out.println("----------------In Edge-----------");
                    System.out.println(in + "  -->  " + m);
                    DotGraphEdge dotGraphEdge = dotGraph.drawEdge(in + "", m + "");
                    dotGraphEdge.setLabel("inEdge");
                    dotGraph.drawNode(in + "");
                    dotGraph.drawNode(m + "");
                    System.out.println("************************************");
                    if (!visited.containsKey(in.getSignature())) {
                        toDot(cg, in);
                    }
                }
            }        Iterator<MethodOrMethodContext> outTargets = new Targets(cg.edgesOutOf(m));
            if (outTargets != null) {
                while (outTargets.hasNext()) {
                    SootMethod out = (SootMethod) outTargets.next();
                    if (out == null) {
                        System.out.println("out is null");
                    }
                    System.out.println("----------------Out Edge-----------");
                    System.out.println(m + "  -->  " + out);
                    DotGraphEdge dotGraphEdge = dotGraph.drawEdge(m + "", out + "");
                    dotGraphEdge.setLabel("outEdge");
                    dotGraph.drawNode(m + "");
                    dotGraph.drawNode(out + "");
                    System.out.println("************************************");
                    if (!visited.containsKey(out.getSignature())) {
                        toDot(cg, out);
                    }
                }
            }
        }
    }
      

  2.   

    更进一步发现,代码在前面  app.calculateSourcesSinksEntrypoints(sourceAndSink);处抛“Could not find method”异常,对应AbstractCallbackAnalyzer.java中的如下代码:
      private SootMethod getMethodFromHierarchyEx(SootClass c, String methodSignature) {
    if (c.declaresMethod(methodSignature))
    return c.getMethod(methodSignature);
    if (c.hasSuperclass())
    return getMethodFromHierarchyEx(c.getSuperclass(), methodSignature);
    throw new RuntimeException("Could not find method");
    }