public boolean twoValueEquals(Value v1, Value v2) { if (v1.toString().equals(v2.toString()) && v1.getType().toString().equals(v2.getType().toString())) { return true; } return false; }
private static boolean checkIfIsArrayFunction( SootMethod method, InstanceInvokeExpr instanceInvokeExpr) { String methodName = method.getName(); Value base = instanceInvokeExpr.getBase(); System.out.println(base.getType()); if (base.getType().toString().equals("android.content.Intent")) { if (methodName.startsWith("get") && methodName.contains("Array")) { return true; } } return false; }
/** 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; }
/** * Returns <code>true</code> if both references may point to the same memory location. The current * implementation is conservative, as it does not take any points-to information into account. */ public static boolean maybeSameLocation(Value abstrRef, Value programRef) { // arrays are handled through their "base" pointer assert !(abstrRef instanceof ArrayRef); assert !(programRef instanceof ArrayRef); if (abstrRef == programRef) return true; // handle primtive types Type abstrRefType = abstrRef.getType(); Type programRefType = programRef.getType(); if (programRefType instanceof PrimType) { // we don't track primitive types, just Strings, ClassLoaders, etc. // ... return false; } if (abstrRefType instanceof PrimType) { // we don't track primitive types, just Strings, ClassLoaders, etc. // ... throw new InternalError("abstraction ref type is " + abstrRefType); } if (abstrRef instanceof Local && programRef instanceof Local) { // two locals only point to the same memory locations if they are // the same return abstrRef == programRef; } else if (abstrRef instanceof FieldRef && programRef instanceof FieldRef) { FieldRef fieldRef = (FieldRef) abstrRef; FieldRef fieldRef2 = (FieldRef) programRef; // references point to the same location if class and field name are // identical; // note that we ignore the receiver object of InstanceFieldRefs return fieldRef .getField() .getDeclaringClass() .equals(fieldRef2.getField().getDeclaringClass()) && fieldRef.getFieldRef().name().equals(fieldRef2.getFieldRef().name()); } else { return false; } }
@Override public Set<? extends IAllocNode> getPTSet(Value val, Context context) { // handle case for insensitive run if (k == 0) return getPTSetIns(val); final Set<AllocNode> allocNodes = new LinkedHashSet<AllocNode>(); final Type filteringType = val.getType(); PointsToSetInternal pts = null; try { if (val instanceof InstanceFieldRef) { final InstanceFieldRef ifr = (InstanceFieldRef) val; pts = (PointsToSetInternal) ptsProvider.reachingObjects(context, (Local) ifr.getBase(), ifr.getField()); } else if (val instanceof ArrayRef) { ArrayRef arrayRef = (ArrayRef) val; pts = (PointsToSetInternal) ptsProvider.reachingObjectsOfArrayElement( ptsProvider.reachingObjects(context, (Local) arrayRef.getBase())); } else if (val instanceof Local) { pts = (PointsToSetInternal) ptsProvider.reachingObjects(context, (Local) val); } else if (val instanceof StaticFieldRef) { SootField field = ((StaticFieldRef) val).getField(); pts = (PointsToSetInternal) ptsProvider.reachingObjects(field); } else if (val instanceof NullConstant) { return allocNodes; } else { logger.error("Unknown reference type for insenstive search: {} {}", val, val.getClass()); droidsafe.main.Main.exit(1); } // visit internal points to set and grab all allocnodes pts.forall( new P2SetVisitor() { public void visit(Node n) { if (typeManager.castNeverFails(n.getType(), filteringType)) allocNodes.add((AllocNode) n); } }); } catch (Exception e) { logger.info("Some sort of error getting context insensitive points to set for {}", val, e); // e.printStackTrace(); } return allocNodes; }
/** * Because the parameter passing in Java is generally pass-by-value, the traditional meaning of * reference parameter can hardly be used to judge whether a parameter should be considered in * binding in Java. * * <p>Here we choose use the type of a parameter to determined whether it is mutable. * Specifically, we just exclude some common immutable types, such as primitives, their wrappers, * and java.lang.String. * * @param v * @return */ private boolean isMutableRefParam(Value v) { Type type = v.getType(); // this condition excludes the primitive types, but not their wrappers if (type instanceof RefType) { // TODO: test the cases of Java generics String typeName = ((RefType) type).getClassName(); if (commonImmutableTypes.contains(typeName)) { return false; } else { // this is really a conservative design, as there may // be a lot of customized immutable types. return true; } } else { // if the type is a primitive type or // an other special type, e.g., NullType return false; } }
/** * Returns all possible ref/array types of instances that Value can represent as variables. * Returns null if no instance obj can be represented by Value (e.g., static method call). */ private static Set<RefLikeType> getAllPossibleRuntimeRefTypes(Value val) { Set<RefLikeType> typeTargets = new HashSet<RefLikeType>(); // 1.a) NewExpr (instance) if (val instanceof NewExpr) typeTargets.add((RefLikeType) ((NewExpr) val).getType()); // 1.b) NewArrayExpr (instance) else if (val instanceof NewArrayExpr) typeTargets.add((RefLikeType) ((NewArrayExpr) val).getType()); // 2. InvokeExpr (static or instance) else if (val instanceof InvokeExpr) { if (val instanceof StaticInvokeExpr) typeTargets = null; // special case else if (val instanceof SpecialInvokeExpr) typeTargets.add((RefType) ((SpecialInvokeExpr) val).getBase().getType()); else { assert val instanceof InstanceInvokeExpr; SootClass declCls = ((InvokeExpr) val).getMethod().getDeclaringClass(); typeTargets.add(declCls.getType()); for (SootClass clsSub : getAllSubtypes(declCls)) typeTargets.add(clsSub.getType()); } } // 3. Local/statfield ref var (instance) else if (val instanceof Local || val instanceof StaticFieldRef) { RefLikeType lType = (RefLikeType) val.getType(); typeTargets.add(lType); if (lType instanceof RefType) { // add all possible subtypes of ref type for (SootClass clsSub : getAllSubtypes(((RefType) lType).getSootClass())) typeTargets.add(clsSub.getType()); } else assert lType instanceof ArrayType; // array type has no subtypes } // 4. StringConstant (instance) else { assert (val instanceof StringConstant); typeTargets.add(Scene.v().getRefType("java.lang.String")); } return typeTargets; }
private Value generateCorrectObject(Body body, Value value, List<Unit> generated) { if (value.getType() instanceof PrimType) { // in case of a primitive type, we use boxing (I know it is not nice, but it works...) in // order to use the Object type if (value.getType() instanceof BooleanType) { Local booleanLocal = generateFreshLocal(body, RefType.v("java.lang.Boolean")); SootClass sootClass = Scene.v().getSootClass("java.lang.Boolean"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Boolean valueOf(boolean)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(booleanLocal, staticInvokeExpr); generated.add(newAssignStmt); return booleanLocal; } else if (value.getType() instanceof ByteType) { Local byteLocal = generateFreshLocal(body, RefType.v("java.lang.Byte")); SootClass sootClass = Scene.v().getSootClass("java.lang.Byte"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Byte valueOf(byte)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(byteLocal, staticInvokeExpr); generated.add(newAssignStmt); return byteLocal; } else if (value.getType() instanceof CharType) { Local characterLocal = generateFreshLocal(body, RefType.v("java.lang.Character")); SootClass sootClass = Scene.v().getSootClass("java.lang.Character"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Character valueOf(char)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(characterLocal, staticInvokeExpr); generated.add(newAssignStmt); return characterLocal; } else if (value.getType() instanceof DoubleType) { Local doubleLocal = generateFreshLocal(body, RefType.v("java.lang.Double")); SootClass sootClass = Scene.v().getSootClass("java.lang.Double"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Double valueOf(double)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(doubleLocal, staticInvokeExpr); generated.add(newAssignStmt); return doubleLocal; } else if (value.getType() instanceof FloatType) { Local floatLocal = generateFreshLocal(body, RefType.v("java.lang.Float")); SootClass sootClass = Scene.v().getSootClass("java.lang.Float"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Float valueOf(float)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(floatLocal, staticInvokeExpr); generated.add(newAssignStmt); return floatLocal; } else if (value.getType() instanceof IntType) { Local integerLocal = generateFreshLocal(body, RefType.v("java.lang.Integer")); SootClass sootClass = Scene.v().getSootClass("java.lang.Integer"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Integer valueOf(int)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(integerLocal, staticInvokeExpr); generated.add(newAssignStmt); return integerLocal; } else if (value.getType() instanceof LongType) { Local longLocal = generateFreshLocal(body, RefType.v("java.lang.Long")); SootClass sootClass = Scene.v().getSootClass("java.lang.Long"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Long valueOf(long)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(longLocal, staticInvokeExpr); generated.add(newAssignStmt); return longLocal; } else if (value.getType() instanceof ShortType) { Local shortLocal = generateFreshLocal(body, RefType.v("java.lang.Short")); SootClass sootClass = Scene.v().getSootClass("java.lang.Short"); SootMethod valueOfMethod = sootClass.getMethod("java.lang.Short valueOf(short)"); StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(valueOfMethod.makeRef(), value); Unit newAssignStmt = Jimple.v().newAssignStmt(shortLocal, staticInvokeExpr); generated.add(newAssignStmt); return shortLocal; } else throw new RuntimeException("Ooops, something went all wonky!"); } else // just return the value, there is nothing to box return value; }
/** * @param cfg * @param sink * @param assignmentStatement */ private void instrumentSourceToSinkConnections( BiDiInterproceduralCFG<Unit, SootMethod> cfg, ResultSinkInfo sink, boolean assignmentStatement) { sourceSinkConnectionCounter += 1; // loop through the sinks for (ResultSinkInfo key : results.getResults().keySet()) { log.debug("compare: " + key); log.debug(" to: " + sink); // if the current sink is the sink at the unit tagged with 'sink' if (key.equals(sink)) { // loop through the sources for (ResultSourceInfo si : results.getResults().get(key)) { Stmt stmt = si.getSource(); SootMethod sm = cfg.getMethodOf(stmt); Body body = sm.retrieveActiveBody(); // Source instrumentation. The three type categories for the source are: // - callback // - ICC source method (i.e., Intent.getExtras()) // - not a callback and not an ICC source method (i.e., getLine1Number()) // if (isInterComponentSourceCallback(si, cfg)) { throw new RuntimeException("Callbacks as sources are not supported right now"); } else if (isInterComponentSourceNoCallback(si, cfg)) { // only invoke expression are treated here if (stmt.containsInvokeExpr()) { // only statements that return a android.os.Bundle are currently supported if (stmt instanceof DefinitionStmt) { DefinitionStmt defStmt = (DefinitionStmt) stmt; Value leftValue = defStmt.getLeftOp(); if (leftValue.getType().equals(RefType.v("android.os.Bundle"))) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("android.os.Bundle")); args.add(leftValue); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) { instrumentationPoint = getLastIdentityStmt(body); } else { instrumentationPoint = stmt; } body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert a: " + invStmt); } else { System.err.println("We do only support android.os.Bundle right now!"); } } } } else { String sourceCat = getSourceCategory(si); if (sourceCat != null) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("java.lang.String")); args.add(StringConstant.v(sourceCat)); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) instrumentationPoint = getLastIdentityStmt(body); else instrumentationPoint = stmt; body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert b: " + invStmt); } } // sink instrumentation if (sink.getSink().containsInvokeExpr()) { Body bodyOfSink = cfg.getMethodOf(key.getSink()).getActiveBody(); InvokeExpr invExpr = sink.getSink().getInvokeExpr(); List<Unit> generated = new ArrayList<Unit>(); generated.addAll( instrumentIntentAddings(cfg, stmt, invExpr, results.getResults().get(key))); EventInformation sinkEventInfo = allEventInformation.get(invExpr.getMethod().getSignature()); EventInformation sourceEventInfo = allEventInformation.get(si.getSource().getInvokeExpr().getMethod().getSignature()); generated.addAll( generatePolicyEnforcementPoint( key.getSink(), invExpr, bodyOfSink, sourceSinkConnectionCounter, assignmentStatement)); log.debug("body with data flow:\n" + body); for (Unit u : generated) { log.debug("gen: " + u); } if (sinkEventInfo.isInstrumentAfterStatement()) bodyOfSink.getUnits().insertAfter(generated, key.getSink()); else bodyOfSink.getUnits().insertBefore(generated, key.getSink()); } else throw new RuntimeException("Double-Check the assumption"); } // loop through the sources } // if the sink at the unit is the current sink } // loop through the sinks }