/** Count taint on prims or strings */ private static Set<InfoValue> getTaintSet(Value v, MethodOrMethodContext momc) { Set<InfoValue> taints = null; if (v instanceof Local && v.getType() instanceof PrimType) { taints = InformationFlowAnalysis.v().getTaints(momc, (Local) v); } else if (PTABridge.v().isPointer(v) && SootUtils.isStringOrSimilarType(v.getType())) { taints = new HashSet<InfoValue>(); for (IAllocNode node : PTABridge.v().getPTSet(v, momc.context())) { taints.addAll(InformationFlowAnalysis.v().getTaints(node, momc)); } } return taints; }
/** * Clone non-static ancestor methods that are not hidden by virtual dispatch and that are * reachable based on a pta run. */ private void cloneReachableNonHiddenAncestorMethods(SootClass ancestor) { if (ClassCloner.isClonedClass(ancestor)) { logger.error("Cloning method from clone: {}", ancestor); droidsafe.main.Main.exit(1); } // create all methods, cloning body, replacing instance field refs for (SootMethod ancestorM : ancestor.getMethods()) { if (ancestorM.isAbstract() || ancestorM.isPhantom() || !ancestorM.isConcrete() || SootUtils.isRuntimeStubMethod(ancestorM)) continue; // never clone static methods if (ancestorM.isStatic()) continue; // clone only reachable methods if (!cloneAllMethods && !PTABridge.v().getReachableMethods().contains(ancestorM)) continue; // check if this method already exists if (containsMethod(ancestorM.getSignature())) { // System.out.printf("\tAlready contains method %s.\n", ancestorM); continue; } // turn off final for ancestor methods if (ancestorM.isFinal()) ancestorM.setModifiers(ancestorM.getModifiers() ^ Modifier.FINAL); cloneMethod(ancestorM, ancestorM.getName()); } }
private static String getReachableLines() { int totalReachableLines = 0; for (SootMethod sm : PTABridge.v().getReachableMethods()) { totalReachableLines += SootUtils.getNumLines(sm); } return Integer.toString(totalReachableLines); }
private static String finegrainedFlowResults() { int totalReachableIfs = 0; int taintedReachableIfs = 0; int totalCountOfTaintSets = 0; int totalSizeOfTaintSets = 0; long totalValues = 0; Set<InfoValue> allSrcs = new HashSet<InfoValue>(); Set<Set<InfoValue>> allSrcSets = new HashSet<Set<InfoValue>>(); StringBuffer buf = new StringBuffer(); for (MethodOrMethodContext momc : PTABridge.v().getReachableMethodContexts()) { // reset counted locals for each method Set<Value> countedLocals = new HashSet<Value>(); SootMethod method = momc.method(); if (!method.isConcrete()) continue; try { Body body = method.retrieveActiveBody(); Iterator<Unit> unitIt = body.getUnits().snapshotIterator(); while (unitIt.hasNext()) { Stmt stmt = (Stmt) unitIt.next(); for (ValueBox vb : stmt.getUseAndDefBoxes()) { Value v = vb.getValue(); if (countedLocals.contains(v)) continue; countedLocals.add(v); Set<InfoValue> taints = getTaintSet(v, momc); if (taints != null) totalValues++; if (taints != null && !taints.isEmpty()) { allSrcs.addAll(taints); totalCountOfTaintSets++; totalSizeOfTaintSets += taints.size(); if (!allSrcSets.contains(taints)) allSrcSets.add(taints); countedLocals.add(v); } } if (stmt instanceof IfStmt) { totalReachableIfs++; boolean hasTainted = false; for (ValueBox vb : stmt.getUseBoxes()) { Value v = vb.getValue(); Set<InfoValue> taints = getTaintSet(v, momc); if (taints != null && !taints.isEmpty()) { hasTainted = true; break; } } totalReachableIfs++; if (hasTainted) { taintedReachableIfs++; } } } } catch (Exception e) { // ignore and continue } } buf.append("Tainted Reachable if statements: " + taintedReachableIfs + "\n"); buf.append("Total Reachable if Statements: " + totalReachableIfs + "\n"); buf.append( "Count of non-zero taint sets for primitives and strings: " + totalCountOfTaintSets + "\n"); buf.append( "Total distinct reachable primitives or string values in code: " + totalValues + "\n"); buf.append( "Total size of non-zero taint sets for primitives and strings: " + totalSizeOfTaintSets + "\n"); buf.append("Count of distinct sources: " + allSrcs.size() + "\n"); buf.append("Total distinct source sets: " + allSrcSets.size() + "\n"); return buf.toString(); }
@Override public void tranformsInvoke( SootMethod containingMthd, SootMethod callee, InvokeExpr invokeExpr, Stmt stmt, Body body) { if (!Project.v().isSrcClass(containingMthd.getDeclaringClass())) { return; } if (modified.contains(stmt)) { return; } modified.add(stmt); IntentResolutionStats.v().contentProviderOps++; Value lvalue = null; if (stmt instanceof AssignStmt) { lvalue = ((AssignStmt) stmt).getLeftOp(); } Set<SootField> targetCPFields = new LinkedHashSet<SootField>(); boolean resolved = true; for (IAllocNode node : PTABridge.v().getPTSetIns(invokeExpr.getArg(0))) { resolved = addToTargets(node, targetCPFields, stmt); if (!resolved) { UnresolvedICC.v().addInfo(stmt, callee, "Unresolved URI for Content Provider"); // can break here because we added all possible content provider destinations IntentResolutionStats.v().contentProviderOpsUnresolvedUri++; break; } } // for each field of harness that is a content provider for (SootField cpField : targetCPFields) { SootClass cpClass = ((RefType) cpField.getType()).getSootClass(); SootMethod target = cpClass.getMethod(callee.getSubSignature()); // create local and add to body Local local = Jimple.v().newLocal("_$contentprovider_local_" + localID++, cpField.getType()); body.getLocals().add(local); // set field of cp to local [local = harness.contentproviderfield] // set local to field Stmt localAssign = Jimple.v().newAssignStmt(local, Jimple.v().newStaticFieldRef(cpField.makeRef())); // insert before original statement body.getUnits().insertBefore(localAssign, stmt); InvokeExpr newInvoke = Jimple.v().newVirtualInvokeExpr(local, target.makeRef(), invokeExpr.getArgs()); // create statement to invoke Stmt toInsert = null; if (lvalue == null) { // original call not in an assign; toInsert = Jimple.v().newInvokeStmt(newInvoke); } else { // original call in an assign toInsert = Jimple.v().newAssignStmt(lvalue, newInvoke); } // insert after original statement just to have all locals assigned in a block body.getUnits().insertAfter(toInsert, stmt); logger.info( "Adding {} call to ContentProvider {} in method {}", callee.getSubSignature(), cpClass, containingMthd); // ignore generated calls in rcfg RCFG.v().ignoreInvokeForOutputEvents(toInsert); } // if resolved and in app target, then don't report if (resolved) { IntentResolutionStats.v().contentProviderOpsResolvedUri++; if (targetCPFields.size() > 0) { RCFG.v().ignoreInvokeForOutputEvents(stmt); IntentResolutionStats.v().contentProviderOpsInAppTotalTargets += targetCPFields.size(); } else { IntentResolutionStats.v().contentProviderOpsInterAppTarget++; } } }