/** * Finds the last assignment to the given String local by searching upwards * from the given statement * * @param stmt * The statement from which to look backwards * @param local * The variable for which to look for assignments * @return The last value assigned to the given variable */ private String findLastStringAssignment(Stmt stmt, Local local, BiDiInterproceduralCFG<Unit, SootMethod> cfg) { if (stmt instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt; if (assign.getLeftOp() == local) { // ok, now find the new value from the right side if (assign.getRightOp() instanceof StringConstant) return ((StringConstant) assign.getRightOp()).value; } } // Continue the search upwards for (Unit pred : cfg.getPredsOf(stmt)) { if (!(pred instanceof Stmt)) continue; String lastAssignment = findLastStringAssignment((Stmt) pred, local, cfg); if (lastAssignment != null) return lastAssignment; } return null; }
public static void runOneDirectionSolver(AnalysisConfigurationBuilder configBuilder) { Pair<IfdsReporter, AnalysisConfigurationBuilder> pair = configBuilder.decorateReporter(new PropagationReporterDecorator() { @Override public IfdsReporter decorate(IfdsReporter reporter) { return new DelayingReporter(reporter); } }); TabulationProblem problem = createTabulationProblem(pair.second); IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> solver = createSolver(problem); AnalysisReporting.analysisStarted(); _runOneDirectionSolver(problem, solver); pair.first.analysisFinished(); AnalysisReporting.analysisFinished(); }
public static void runInnerToOuterSolver(AnalysisConfigurationBuilder configBuilder) { Pair<IfdsReporter, AnalysisConfigurationBuilder> pair = configBuilder.decorateReporter(new PropagationReporterDecorator() { @Override public IfdsReporter decorate(IfdsReporter reporter) { return new DelayingReporter(reporter); } }); configBuilder = pair.second; TabulationProblem forwardTabulationProblem = createTabulationProblem(configBuilder.direction(FORWARDS)); IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> forwardSolver = createSolver(forwardTabulationProblem); TabulationProblem backwardTabulationProblem = createTabulationProblem(configBuilder.direction(BACKWARDS)); IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> backwardSolver = createSolver(backwardTabulationProblem); AnalysisReporting.analysisStarted(); _runOneDirectionSolver(forwardTabulationProblem, forwardSolver); _runOneDirectionSolver(backwardTabulationProblem, backwardSolver); pair.first.analysisFinished(); AnalysisReporting.analysisFinished(); }
public static void runBiDirectionSolver(AnalysisConfigurationBuilder configBuilder) { Pair<IfdsReporter, AnalysisConfigurationBuilder> pair = configBuilder.decorateReporter(new PropagationReporterDecorator() { @Override public IfdsReporter decorate(IfdsReporter reporter) { return new DelayingReporter(reporter); } }); configBuilder = pair.second; TabulationProblem backwardsTabulationProblem = new TabulationProblem(configBuilder.direction(BACKWARDS).build()); TabulationProblem forwardsTabulationProblem = new TabulationProblem(configBuilder.direction(FORWARDS).build()); BiDiIFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> biDiIFDSSolver = new BiDiIFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>>( forwardsTabulationProblem, backwardsTabulationProblem); AnalysisReporting.analysisStarted(); AnalysisReporting.ifdsStarting(backwardsTabulationProblem.getContext(), biDiIFDSSolver); AnalysisReporting.ifdsStarting(forwardsTabulationProblem.getContext(), biDiIFDSSolver); biDiIFDSSolver.solve(); AnalysisReporting.ifdsFinished(backwardsTabulationProblem.getContext(), biDiIFDSSolver, FlowFunctionFactory.propCounter.get()); AnalysisReporting.ifdsFinished(forwardsTabulationProblem.getContext(), biDiIFDSSolver, FlowFunctionFactory.propCounter.get()); pair.first.analysisFinished(); AnalysisReporting.analysisFinished(); }
@SuppressWarnings("unchecked") @Before public void setup() { plotter = new TrackableGraphPlotter(); sut = new PathBuilder(new MergeEqualSelectorStrategy()) { @Override protected Set<SootMethod> getInitialDeclaration(Unit callSite) { return newHashSet(callSiteToDeclarationMapping.get(callSite)); } }; callSiteToDeclarationMapping = HashMultimap.create(); icfg = mock(BiDiInterproceduralCFG.class); context = new AnalysisContext(new AnalysisConfiguration(Lists.<AnalysisTarget> newLinkedList(), null, null, null, null, null, null), icfg); targetUnit = mock(Unit.class); when(targetUnit.toString()).thenReturn("targetUnit"); }
/** * Return true if the method corresponding to the source 'si' is an * Inter Component Communication source method such as "Intent.getExtras()". * @param si * @param cfg * @return */ private boolean isInterComponentSourceNoCallback(ResultSourceInfo si, BiDiInterproceduralCFG<Unit, SootMethod> cfg){ if(!si.getSource().containsInvokeExpr()) return false; InvokeExpr invExpr = si.getSource().getInvokeExpr(); SootMethod sm = invExpr.getMethod(); for(SourceSinkDefinition meth : sources){ AndroidMethod am = (AndroidMethod) meth.getMethod(); if(am.getCategory() == CATEGORY.INTER_APP_COMMUNICATION){ if(am.getSubSignature().equals(sm.getSubSignature())) { log.info("source is: "+ am); return true; } } } return false; }
private static IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> createSolver( final TabulationProblem tabulationProblem) { IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> solver = new PathTrackingIFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>>( tabulationProblem) { @Override protected String getDebugName() { if (tabulationProblem.getContext().direction == FORWARDS) return "FW"; else return "BW"; } }; return solver; }
private static BiDiInterproceduralCFG<Unit, SootMethod> makeICFG(AnalysisDirection direction) { JimpleBasedInterproceduralCFG fwdIcfg = new JimpleBasedInterproceduralCFG(); if (direction == AnalysisDirection.FORWARDS) return fwdIcfg; else return new BackwardsInterproceduralCFG(fwdIcfg); }
@Before public void setup() { plotter = new TrackableGraphPlotter(); icfg = mock(BiDiInterproceduralCFG.class); context = new AnalysisContext(new AnalysisConfiguration(Lists.<AnalysisTarget> newLinkedList(), null, null, null, null, null, null), icfg); }
private boolean isInterComponentSourceCallback(ResultSourceInfo si, BiDiInterproceduralCFG<Unit, SootMethod> cfg){ if(isSourceInfoParameter(si)){ SootMethod sm = cfg.getMethodOf(si.getSource()); if(entryPointCreator.getCallbackFunctions().containsKey(sm.getDeclaringClass())){ if(entryPointCreator.getCallbackFunctions().get(sm.getDeclaringClass()).contains(sm.getSignature())) return true; } } return false; }
public BackwardsPathConstructor<Unit, AccessGraph, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> getPathConstructor() { return getSubQuery().getPathConstructor(); }
public BiDiInterproceduralCFG<N, M> getICFG() { return icfg; }
public BackwardsPathConstructor<Unit, AccessGraph, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> getPathConstructor() { return BW_PATH_CONSTRUCTOR; }
public InfoflowCFG(BiDiInterproceduralCFG<Unit, SootMethod> delegate) { this.delegate = delegate; }
/** * Checks whether the given call site indicates a UI source, e.g. a password * input * * @param sCallSite * The call site that may potentially read data from a sensitive * UI control * @param cfg * The bidirectional control flow graph * @return True if the given call site reads data from a UI source, false * otherwise */ private boolean isUISource(Stmt sCallSite, InterproceduralCFG<Unit, SootMethod> cfg) { // If we match input controls, we need to check whether this is a call // to one of the well-known resource handling functions in Android if (this.layoutMatching != LayoutMatchingMode.NoMatch && sCallSite.containsInvokeExpr()) { InvokeExpr ie = sCallSite.getInvokeExpr(); final String signature = methodToSignature.getUnchecked(ie.getMethod()); if (signature.equals(Activity_FindViewById) || signature.equals(View_FindViewById)) { // Perform a constant propagation inside this method exactly // once SootMethod uiMethod = cfg.getMethodOf(sCallSite); if (analyzedLayoutMethods.add(uiMethod)) ConstantPropagatorAndFolder.v().transform(uiMethod.getActiveBody()); // If we match all controls, we don't care about the specific // control we're dealing with if (this.layoutMatching == LayoutMatchingMode.MatchAll) return true; // If we don't have a layout control list, we cannot perform any // more specific checks if (this.layoutControls == null) return false; // If we match specific controls, we need to get the ID of // control and look up the respective data object if (ie.getArgCount() != 1) { System.err.println("Framework method call with unexpected " + "number of arguments"); return false; } int id = 0; if (ie.getArg(0) instanceof IntConstant) id = ((IntConstant) ie.getArg(0)).value; else if (ie.getArg(0) instanceof Local) { Integer idVal = findLastResIDAssignment(sCallSite, (Local) ie.getArg(0), (BiDiInterproceduralCFG<Unit, SootMethod>) cfg, new HashSet<Stmt>(cfg.getMethodOf(sCallSite).getActiveBody().getUnits().size())); if (idVal == null) { System.err.println("Could not find assignment to local " + ((Local) ie.getArg(0)).getName() + " in method " + cfg.getMethodOf(sCallSite).getSignature()); return false; } else id = idVal.intValue(); } else { System.err.println("Framework method call with unexpected " + "parameter type: " + ie.toString() + ", " + "first parameter is of type " + ie.getArg(0).getClass()); return false; } LayoutControl control = this.layoutControls.get(id); if (control == null) { System.err.println("Layout control with ID " + id + " not found"); return false; } if (this.layoutMatching == LayoutMatchingMode.MatchSensitiveOnly && control.isSensitive()) return true; } } return false; }
/** * Finds the last assignment to the given local representing a resource ID * by searching upwards from the given statement * * @param stmt * The statement from which to look backwards * @param local * The variable for which to look for assignments * @return The last value assigned to the given variable */ private Integer findLastResIDAssignment(Stmt stmt, Local local, BiDiInterproceduralCFG<Unit, SootMethod> cfg, Set<Stmt> doneSet) { if (!doneSet.add(stmt)) return null; // If this is an assign statement, we need to check whether it changes // the variable we're looking for if (stmt instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt; if (assign.getLeftOp() == local) { // ok, now find the new value from the right side if (assign.getRightOp() instanceof IntConstant) return ((IntConstant) assign.getRightOp()).value; else if (assign.getRightOp() instanceof FieldRef) { SootField field = ((FieldRef) assign.getRightOp()).getField(); for (Tag tag : field.getTags()) if (tag instanceof IntegerConstantValueTag) return ((IntegerConstantValueTag) tag).getIntValue(); else System.err.println("Constant " + field + " was of unexpected type"); } else if (assign.getRightOp() instanceof InvokeExpr) { InvokeExpr inv = (InvokeExpr) assign.getRightOp(); if (inv.getMethod().getName().equals("getIdentifier") && inv.getMethod().getDeclaringClass().getName().equals("android.content.res.Resources") && this.resourcePackages != null) { // The right side of the assignment is a call into the // well-known // Android API method for resource handling if (inv.getArgCount() != 3) { System.err.println("Invalid parameter count for call to getIdentifier"); return null; } // Find the parameter values String resName = ""; String resID = ""; String packageName = ""; // In the trivial case, these values are constants if (inv.getArg(0) instanceof StringConstant) resName = ((StringConstant) inv.getArg(0)).value; if (inv.getArg(1) instanceof StringConstant) resID = ((StringConstant) inv.getArg(1)).value; if (inv.getArg(2) instanceof StringConstant) packageName = ((StringConstant) inv.getArg(2)).value; else if (inv.getArg(2) instanceof Local) packageName = findLastStringAssignment(stmt, (Local) inv.getArg(2), cfg); else { System.err.println("Unknown parameter type in call to getIdentifier"); return null; } // Find the resource ARSCFileParser.AbstractResource res = findResource(resName, resID, packageName); if (res != null) return res.getResourceID(); } } } } // Continue the search upwards for (Unit pred : cfg.getPredsOf(stmt)) { if (!(pred instanceof Stmt)) continue; Integer lastAssignment = findLastResIDAssignment((Stmt) pred, local, cfg, doneSet); if (lastAssignment != null) return lastAssignment; } return null; }
public BackwardsInfoflowProblem(BiDiInterproceduralCFG<Unit, SootMethod> icfg, ISourceSinkManager sourceSinkManager) { super(icfg, sourceSinkManager); }
public AbstractInfoflowProblem(BiDiInterproceduralCFG<Unit, SootMethod> icfg, ISourceSinkManager sourceSinkManager) { super(icfg); this.sourceSinkManager = sourceSinkManager; }
protected static void _runOneDirectionSolver(final TabulationProblem tabulationProblem, IFDSSolver<Unit, Trackable, SootMethod, BiDiInterproceduralCFG<Unit, SootMethod>> solver) { AnalysisReporting.ifdsStarting(tabulationProblem.getContext(), solver); solver.solve(); AnalysisReporting.ifdsFinished(tabulationProblem.getContext(), solver, FlowFunctionFactory.propCounter.get()); FlowFunctionFactory.propCounter.set(0); }
public AnalysisContext(AnalysisConfiguration config, BiDiInterproceduralCFG<Unit, SootMethod> icfg) { super(config); this.icfg = icfg; }
private List<Unit> instrumentIntentAddings(BiDiInterproceduralCFG<Unit, SootMethod> cfg, Unit unit, InvokeExpr sinkExpr, Set<ResultSourceInfo> sourceInfo){ if(isMethodInterComponentSink(sinkExpr.getMethod())){ SootMethod method = cfg.getMethodOf(unit); Body body = null; if(method.hasActiveBody()) body = method.retrieveActiveBody(); else throw new RuntimeException("No body found!"); Set<String> sourceCategories = getDataIdList(sourceInfo); final String hashSetType = "java.util.HashSet"; List<Unit> generated = new ArrayList<Unit>(); //HashSet initialization Local hashSetLocal = generateFreshLocal(body, RefType.v(hashSetType)); NewExpr newExpr = Jimple.v().newNewExpr(RefType.v(hashSetType)); AssignStmt assignStmt = Jimple.v().newAssignStmt(hashSetLocal, newExpr); generated.add(assignStmt); //constructor call SpecialInvokeExpr constructorCall = Jimple.v().newSpecialInvokeExpr(hashSetLocal, Scene.v().getMethod("<java.util.HashSet: void <init>()>").makeRef()); InvokeStmt constructorCallStmt = Jimple.v().newInvokeStmt(constructorCall); generated.add(constructorCallStmt); //add categories to HashSet for(String cat : sourceCategories){ InterfaceInvokeExpr addCall = Jimple.v().newInterfaceInvokeExpr(hashSetLocal, Scene.v().getMethod("<java.util.Set: boolean add(java.lang.Object)>").makeRef(), StringConstant.v(cat)); InvokeStmt addCallStmt = Jimple.v().newInvokeStmt(addCall); generated.add(addCallStmt); } //get Intent Value intent = sinkExpr.getArg(0); List<Object> args = new ArrayList<Object>(); args.add(RefType.v("android.content.Intent")); args.add(intent); args.add(RefType.v(hashSetType)); args.add(hashSetLocal); StaticInvokeExpr sie = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "addTaintInformationToIntent", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(sie); generated.add(invStmt); return generated; } return Collections.emptyList(); }
/** * Handler function that is invoked when a new taint is generated in the data * flow engine * @param stmt The statement over which the taint is propagated * @param d1 The abstraction at the beginning of the current method * @param incoming The original abstraction from which the outgoing ones * were computed * @param outgoing The set of taints being propagated * @param cfg The interprocedural control flow graph containing the current * method * @param type The type of data flow edge being processed * @return The new abstractions to be propagated on. If you do not want to * change the normal propagation behavior, just return the value of the * "taints" parameter as-is. */ public Set<Abstraction> notifyFlowOut(Unit stmt, Abstraction d1, Abstraction incoming, Set<Abstraction> outgoing, BiDiInterproceduralCFG<Unit, SootMethod> cfg, FlowFunctionType type);
/** * Handler function that is invoked when a taint is proagated in the data * flow engine * @param stmt The statement over which the taint is propagated * @param taint The taint being propagated * @param cfg The interprocedural control flow graph containing the current * method * @param type The type of data flow edge being processed */ public void notifyFlowIn (Unit stmt, Abstraction taint, BiDiInterproceduralCFG<Unit, SootMethod> cfg, FlowFunctionType type);
/** * Callback that is invoked when information flow results are available * @param cfg The program graph * @param results The results that were computed */ public void onResultsAvailable(BiDiInterproceduralCFG<Unit, SootMethod> cfg, InfoflowResults results);
/** * Handler function that is invoked when a taint is proagated in the data * flow engine * @param stmt The statement over which the taint is propagated * @param taints The set of taints being propagated * @param cfg The interprocedural control flow graph containing the current * method * @param type The type of data flow edge being processed */ public void notifyFlowIn (Unit stmt, Set<Abstraction> taints, BiDiInterproceduralCFG<Unit, SootMethod> cfg, FlowFunctionType type);