/** * Checks whether this invocation calls Android's Activity.setContentView * method * * @param inv * The invocaton to check * @return True if this invocation calls setContentView, otherwise false */ private boolean invokesSetContentView(InvokeExpr inv) { String methodName = SootMethodRepresentationParser.v() .getMethodNameFromSubSignature(inv.getMethodRef().getSubSignature().getString()); if (!methodName.equals("setContentView")) return false; // In some cases, the bytecode points the invocation to the current // class even though it does not implement setContentView, instead // of using the superclass signature SootClass curClass = inv.getMethod().getDeclaringClass(); while (curClass != null) { if (curClass.getName().equals("android.app.Activity") || curClass.getName().equals("android.support.v7.app.ActionBarActivity")) return true; if (curClass.declaresMethod("void setContentView(int)")) return false; curClass = curClass.hasSuperclass() ? curClass.getSuperclass() : null; } return false; }
/** * Checks whether this invocation calls Android's Activity.setContentView * method * @param inv The invocaton to check * @return True if this invocation calls setContentView, otherwise false */ private boolean invokesSetContentView(InvokeExpr inv) { String methodName = SootMethodRepresentationParser.v().getMethodNameFromSubSignature( inv.getMethodRef().getSubSignature().getString()); if (!methodName.equals("setContentView")) return false; // In some cases, the bytecode points the invocation to the current // class even though it does not implement setContentView, instead // of using the superclass signature SootClass curClass = inv.getMethod().getDeclaringClass(); while (curClass != null) { if (curClass.getName().equals("android.app.Activity") || curClass.getName().equals("android.support.v7.app.ActionBarActivity")) return true; if (curClass.declaresMethod("void setContentView(int)")) return false; curClass = curClass.hasSuperclass() ? curClass.getSuperclass() : null; } return false; }
@Override public void computeInfoflow(String path, IEntryPointCreator entryPointCreator, List<String> entryPoints, ISourceSinkManager sourcesSinks) { results = null; if (sourcesSinks == null) { logger.error("Sources are empty!"); return; } initializeSoot(path, SootMethodRepresentationParser.v().parseClassNames(entryPoints, false).keySet(), sourcesSinks); // entryPoints are the entryPoints required by Soot to calculate Graph - if there is no main method, // we have to create a new main method and use it as entryPoint and store our real entryPoints Scene.v().setEntryPoints(Collections.singletonList(entryPointCreator.createDummyMain(entryPoints))); // We explicitly select the packs we want to run for performance reasons PackManager.v().getPack("wspp").apply();//==> PackManager.v().getPack("cg").apply();//==> PackManager.v().getPack("wjtp").apply(); PackManager.v().getPack("wstp").apply();//==> //Main.v().main(args); ==> if (debug) PackManager.v().writeOutput(); }
@Override public Collection<String> getRequiredClasses() { Set<String> requiredClasses = new HashSet<String>(androidClasses); requiredClasses .addAll(SootMethodRepresentationParser.v().parseClassNames(additionalEntryPoints, false).keySet()); return requiredClasses; }
/*** * Static method to create AndroidMethod from Soot method signature * * @param signature The Soot method signature * @return The new AndroidMethod object */ public static AndroidMethod createFromSignature(String signature) { if (!signature.startsWith("<")) signature = "<" + signature; if (!signature.endsWith(">")) signature = signature + ">"; SootMethodAndClass smac = SootMethodRepresentationParser.v() .parseSootMethodString(signature); return new AndroidMethod(smac.getMethodName(), smac.getParameters(), smac.getReturnType(), smac.getClassName()); }
public EasyTaintWrapper(File f) throws IOException{ BufferedReader reader = null; try{ FileReader freader = new FileReader(f); reader = new BufferedReader(freader); String line = reader.readLine(); List<String> methodList = new LinkedList<String>(); List<String> excludeList = new LinkedList<String>(); List<String> killList = new LinkedList<String>(); this.includeList = new HashSet<String>(); while(line != null){ if (!line.isEmpty() && !line.startsWith("%")) if (line.startsWith("~")) excludeList.add(line.substring(1)); else if (line.startsWith("-")) killList.add(line.substring(1)); else if (line.startsWith("^")) includeList.add(line.substring(1)); else methodList.add(line); line = reader.readLine(); } this.classList = SootMethodRepresentationParser.v().parseClassNames(methodList, true); this.excludeList = SootMethodRepresentationParser.v().parseClassNames(excludeList, true); this.killList = SootMethodRepresentationParser.v().parseClassNames(killList, true); logger.info("Loaded wrapper entries for {} classes and {} exclusions.", classList.size(), excludeList.size()); } finally { if (reader != null) reader.close(); } }
@Override public Collection<String> getRequiredClasses() { Set<String> requiredClasses = new HashSet<String>(androidClasses); requiredClasses.addAll(SootMethodRepresentationParser.v().parseClassNames (additionalEntryPoints, false).keySet()); return requiredClasses; }
@Override public void computeInfoflow(String appPath, String libPath, String entryPoint, ISourceSinkManager sourcesSinks) { if (sourcesSinks == null) { logger.error("Sources are empty!"); return; } initializeSoot(appPath, libPath, SootMethodRepresentationParser.v().parseClassNames (Collections.singletonList(entryPoint), false).keySet(), entryPoint); if (!Scene.v().containsMethod(entryPoint)){ logger.error("Entry point not found: " + entryPoint); return; } SootMethod ep = Scene.v().getMethod(entryPoint); if (ep.isConcrete()) ep.retrieveActiveBody(); else { logger.debug("Skipping non-concrete method " + ep); return; } Scene.v().setEntryPoints(Collections.singletonList(ep)); Options.v().set_main_class(ep.getDeclaringClass().getName()); // Compute the additional seeds if they are specified Set<String> seeds = Collections.emptySet(); if (entryPoint != null && !entryPoint.isEmpty()) seeds = Collections.singleton(entryPoint); ipcManager.updateJimpleForICC(); // Run the analysis runAnalysis(sourcesSinks, seeds); }
@Test(timeout=300000) public void testParser(){ String s = "<soot.jimple.infoflow.test.TestNoMain: java.lang.String function1()>"; SootMethodRepresentationParser parser = SootMethodRepresentationParser.v(); SootMethodAndClass result = parser.parseSootMethodString(s); assertEquals("soot.jimple.infoflow.test.TestNoMain", result.getClassName()); assertEquals("function1", result.getMethodName()); assertEquals("java.lang.String", result.getReturnType()); }
@Override public void computeInfoflow(String path, String entryPoint, ISourceSinkManager sourcesSinks) { results = null; if (sourcesSinks == null) { logger.error("Sources are empty!"); return; } initializeSoot(path, SootMethodRepresentationParser.v().parseClassNames (Collections.singletonList(entryPoint), false).keySet(), sourcesSinks, entryPoint); if (!Scene.v().containsMethod(entryPoint)){ logger.error("Entry point not found: " + entryPoint); return; } SootMethod ep = Scene.v().getMethod(entryPoint); if (ep.isConcrete()) ep.retrieveActiveBody(); else { logger.debug("Skipping non-concrete method " + ep); return; } Scene.v().setEntryPoints(Collections.singletonList(ep)); Options.v().set_main_class(ep.getDeclaringClass().getName()); // We explicitly select the packs we want to run for performance reasons PackManager.v().getPack("wspp").apply(); PackManager.v().getPack("cg").apply(); PackManager.v().getPack("wjtp").apply(); PackManager.v().getPack("wstp").apply(); if (debug) PackManager.v().writeOutput(); }
private void addApplicationCallbackMethods(Body body) { if (!this.callbackFunctions.containsKey(applicationClass.getName())) return; // Do not try to generate calls to methods in non-concrete classes if (applicationClass.isAbstract()) return; if (applicationClass.isPhantom()) { System.err.println("Skipping possible application callbacks in " + "phantom class " + applicationClass); return; } for (String methodSig : this.callbackFunctions.get(applicationClass.getName())) { SootMethodAndClass methodAndClass = SootMethodRepresentationParser.v().parseSootMethodString(methodSig); // We do not consider lifecycle methods which are directly inserted // at their respective positions if (AndroidEntryPointConstants.getApplicationLifecycleMethods().contains(methodAndClass.getSubSignature())) continue; SootMethod method = findMethod(Scene.v().getSootClass(methodAndClass.getClassName()), methodAndClass.getSubSignature()); // If we found no implementation or if the implementation we found // is in a system class, we skip it. Note that null methods may // happen since all callback interfaces for application callbacks // are registered under the name of the application class. if (method == null) continue; if (method.getDeclaringClass().getName().startsWith("android.") || method.getDeclaringClass().getName().startsWith("java.")) continue; // Get the local instance of the target class Local local = this.localVarsForClasses.get(methodAndClass.getClassName()); if (local == null) { System.err.println( "Could not create call to application callback " + method.getSignature() + ". Local was null."); continue; } // Add a conditional call to the method JNopStmt thenStmt = new JNopStmt(); createIfStmt(thenStmt, body); buildMethodCall(method, body, local, generator); body.getUnits().add(thenStmt); } }
/** * Adds calls to the callback methods defined in the application class * @param applicationClass The class in which the user-defined application * is implemented * @param applicationLocal The local containing the instance of the * user-defined application */ private void addApplicationCallbackMethods() { if (!this.callbackFunctions.containsKey(applicationClass.getName())) return; // Do not try to generate calls to methods in non-concrete classes if (applicationClass.isAbstract()) return; if (applicationClass.isPhantom()) { System.err.println("Skipping possible application callbacks in " + "phantom class " + applicationClass); return; } for (String methodSig : this.callbackFunctions.get(applicationClass.getName())) { SootMethodAndClass methodAndClass = SootMethodRepresentationParser.v().parseSootMethodString(methodSig); // We do not consider lifecycle methods which are directly inserted // at their respective positions if (AndroidEntryPointConstants.getApplicationLifecycleMethods().contains (methodAndClass.getSubSignature())) continue; SootMethod method = findMethod(Scene.v().getSootClass(methodAndClass.getClassName()), methodAndClass.getSubSignature()); // If we found no implementation or if the implementation we found // is in a system class, we skip it. Note that null methods may // happen since all callback interfaces for application callbacks // are registered under the name of the application class. if (method == null) continue; if (method.getDeclaringClass().getName().startsWith("android.") || method.getDeclaringClass().getName().startsWith("java.")) continue; // Get the local instance of the target class Local local = this.localVarsForClasses.get(methodAndClass.getClassName()); if (local == null) { System.err.println("Could not create call to application callback " + method.getSignature() + ". Local was null."); continue; } // Add a conditional call to the method JNopStmt thenStmt = new JNopStmt(); createIfStmt(thenStmt); buildMethodCall(method, body, local, generator); body.getUnits().add(thenStmt); } }
@Override protected SootMethod createDummyMainInternal(SootMethod mainMethod) { Map<String, Set<String>> classMap = SootMethodRepresentationParser.v().parseClassNames(methodsToCall, false); // create new class: Body body = mainMethod.getActiveBody(); LocalGenerator generator = new LocalGenerator(body); HashMap<String, Local> localVarsForClasses = new HashMap<String, Local>(); // create constructors: for(String className : classMap.keySet()){ SootClass createdClass = Scene.v().forceResolve(className, SootClass.BODIES); createdClass.setApplicationClass(); Local localVal = generateClassConstructor(createdClass, body); if (localVal == null) { logger.warn("Cannot generate constructor for class: {}", createdClass); continue; } localVarsForClasses.put(className, localVal); } // add entrypoint calls int conditionCounter = 0; JNopStmt startStmt = new JNopStmt(); JNopStmt endStmt = new JNopStmt(); Value intCounter = generator.generateLocal(IntType.v()); body.getUnits().add(startStmt); for (Entry<String, Set<String>> entry : classMap.entrySet()){ Local classLocal = localVarsForClasses.get(entry.getKey()); for (String method : entry.getValue()){ SootMethodAndClass methodAndClass = SootMethodRepresentationParser.v().parseSootMethodString(method); SootMethod currentMethod = findMethod(Scene.v().getSootClass(methodAndClass.getClassName()), methodAndClass.getSubSignature()); if (currentMethod == null) { logger.warn("Entry point not found: {}", method); continue; } JEqExpr cond = new JEqExpr(intCounter, IntConstant.v(conditionCounter)); conditionCounter++; JNopStmt thenStmt = new JNopStmt(); JIfStmt ifStmt = new JIfStmt(cond, thenStmt); body.getUnits().add(ifStmt); buildMethodCall(currentMethod, body, classLocal, generator); body.getUnits().add(thenStmt); } } body.getUnits().add(endStmt); JGotoStmt gotoStart = new JGotoStmt(startStmt); body.getUnits().add(gotoStart); body.getUnits().add(Jimple.v().newReturnVoidStmt()); NopEliminator.v().transform(body); eliminateSelfLoops(body); return mainMethod; }
@Override public Collection<String> getRequiredClasses() { return SootMethodRepresentationParser.v().parseClassNames( methodsToCall, false).keySet(); }
@Override protected SootMethod createDummyMainInternal(SootMethod mainMethod) { Map<String, Set<String>> classMap = SootMethodRepresentationParser.v().parseClassNames(methodsToCall, false); // create new class: Body body = mainMethod.getActiveBody(); LocalGenerator generator = new LocalGenerator(body); // Create the classes for (String className : classMap.keySet()) { SootClass createdClass = Scene.v().forceResolve(className, SootClass.BODIES); createdClass.setApplicationClass(); Local localVal = generateClassConstructor(createdClass, body); if (localVal == null) { logger.warn("Cannot generate constructor for class: {}", createdClass); continue; } // Create the method calls for (String method : classMap.get(className)) { SootMethodAndClass methodAndClass = SootMethodRepresentationParser.v().parseSootMethodString(method); SootMethod methodToInvoke = findMethod(Scene.v().getSootClass( methodAndClass.getClassName()), methodAndClass.getSubSignature()); if (methodToInvoke == null) System.err.println("Method " + methodAndClass + " not found, skipping"); else if (methodToInvoke.isConcrete()) { // Load the method methodToInvoke.retrieveActiveBody(); buildMethodCall(methodToInvoke, body, localVal, generator); } } } // Jimple needs an explicit return statement body.getUnits().add(Jimple.v().newReturnVoidStmt()); return mainMethod; }
/** * Soot requires a main method, so we create a dummy method which calls all entry functions. * * @param classMap * the methods to call (signature as String) * @param createdClass * the class which contains the methods * @return list of entryPoints */ @Override protected SootMethod createDummyMainInternal(List<String> methods) { Map<String, List<String>> classMap = SootMethodRepresentationParser.v().parseClassNames(methods, false); // create new class: JimpleBody body = Jimple.v().newBody(); SootMethod mainMethod = createEmptyMainMethod(body); LocalGenerator generator = new LocalGenerator(body); HashMap<String, Local> localVarsForClasses = new HashMap<String, Local>(); // create constructors: for(String className : classMap.keySet()){ SootClass createdClass = Scene.v().forceResolve(className, SootClass.BODIES); createdClass.setApplicationClass(); Local localVal = generateClassConstructor(createdClass, body); if (localVal == null) { logger.warn("Cannot generate constructor for class: {}", createdClass); continue; } localVarsForClasses.put(className, localVal); } // add entrypoint calls int conditionCounter = 0; JNopStmt startStmt = new JNopStmt(); JNopStmt endStmt = new JNopStmt(); Value intCounter = generator.generateLocal(IntType.v()); body.getUnits().add(startStmt); for (Entry<String, List<String>> entry : classMap.entrySet()){ Local classLocal = localVarsForClasses.get(entry.getKey()); for (String method : entry.getValue()){ SootMethodAndClass methodAndClass = SootMethodRepresentationParser.v().parseSootMethodString(method); SootMethod currentMethod = findMethod(Scene.v().getSootClass(methodAndClass.getClassName()), methodAndClass.getSubSignature()); if (currentMethod == null) { logger.warn("Entry point not found: {}", method); continue; } JEqExpr cond = new JEqExpr(intCounter, IntConstant.v(conditionCounter)); conditionCounter++; JNopStmt thenStmt = new JNopStmt(); JIfStmt ifStmt = new JIfStmt(cond, thenStmt); body.getUnits().add(ifStmt); buildMethodCall(currentMethod, body, classLocal, generator); body.getUnits().add(thenStmt); } } body.getUnits().add(endStmt); JGotoStmt gotoStart = new JGotoStmt(startStmt); body.getUnits().add(gotoStart); body.getUnits().add(Jimple.v().newReturnVoidStmt()); return mainMethod; }