/** * Resolve the concrete target of a special invoke using our modified semantics for special invoke * expression. */ private SootMethod resolveSpecialInvokeTarget(SpecialInvokeExpr si) { SootMethod target = null; try { target = SootUtils.resolve(si.getMethodRef()); } catch (CannotFindMethodException e) { logger.error("Cannot find concrete method target for special invoke: {}", si); return null; } String targetSubSig = target.getSubSignature(); SootClass current = target.getDeclaringClass(); while (true) { if (current.declaresMethod(targetSubSig)) { return current.getMethod(targetSubSig); } // not a match in current, try superclass on next loop if (current.hasSuperclass()) current = current.getSuperclass(); else { logger.error("Cannot find concrete method target for special invoke: {}", si); droidsafe.main.Main.exit(1); return null; } } }
/** * Uses EXACT of possible runtime types referenced by values. These types of Value can represent * an object: 1. NewExpr/NewArrayExpr (instance) 2. InvokeExpr (static or instance) 3. * Local/statfield ref var (instance) 4. StringConstant (instance) */ public static boolean objValuesMustEqual(Value v1, Value v2) { // case 5: (lib) object, either static or instance // objects are (possibly) the same if they are both static or both instance, // and there is at least one object type that v1 and v2 can refer to in their call. // NOTE: includes automatically constructed Strings, represented by StringConstant values // first, handle special case with more precision: both values are string constants if (v1 instanceof StringConstant && v2 instanceof StringConstant) return ((StringConstant) v1).value.equals(((StringConstant) v2).value); // get list of ref types of instances to which each value can refer // (null if val refers to class itself, not instances) Set<RefLikeType> clsTargets1 = getAllPossibleRuntimeRefTypes(v1); Set<RefLikeType> clsTargets2 = getAllPossibleRuntimeRefTypes(v2); // first, handle special case of values referring to class object (static) if (clsTargets1 == null) { if (clsTargets2 != null) return false; SootClass cls1 = ((StaticInvokeExpr) v1).getMethod().getDeclaringClass(); SootClass cls2 = ((StaticInvokeExpr) v2).getMethod().getDeclaringClass(); return cls1.equals(cls2); } else if (clsTargets2 == null) return false; // // now, just check for intersection of returned lists of possible target classes // return clsTargets1.removeAll(clsTargets2); // *** Strengthened to be completely equal, respecting TRANSITIVITY of equality return clsTargets1.equals(clsTargets2); }
private void createLookupFunction(SootMethod m) { // TODO: This should use a virtual method table or interface method table. Function function = FunctionBuilder.lookup(m); mb.addFunction(function); Variable reserved0 = function.newVariable(I8_PTR_PTR); function.add(new Getelementptr(reserved0, function.getParameterRef(0), 0, 4)); Variable reserved1 = function.newVariable(I8_PTR_PTR); function.add(new Getelementptr(reserved1, function.getParameterRef(0), 0, 5)); function.add(new Store(getString(m.getName()), reserved0.ref())); function.add(new Store(getString(getDescriptor(m)), reserved1.ref())); Value lookupFn = sootClass.isInterface() ? BC_LOOKUP_INTERFACE_METHOD : BC_LOOKUP_VIRTUAL_METHOD; List<Value> args = new ArrayList<Value>(); args.add(function.getParameterRef(0)); if (sootClass.isInterface()) { Value info = getInfoStruct(function); args.add(info); } args.add(function.getParameterRef(1)); args.add(getString(m.getName())); args.add(getString(getDescriptor(m))); Value fptr = call(function, lookupFn, args); Variable f = function.newVariable(function.getType()); function.add(new Bitcast(f, fptr, f.getType())); Value result = call(function, f.ref(), function.getParameterRefs()); function.add(new Ret(result)); }
private void loadClasses() { Date start = new Date(); if (entryClass != null) { SootUtils.loadClassesForEntry(entryClass); } else { for (JavaCriticalSection cs : results) { String clsname = cs.getClassName(); String regex = "\\$\\d"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(clsname); if (matcher.find()) { System.out.println("can't find the class created randomly by compiler"); continue; } SootClass cls = Scene.v().loadClassAndSupport(clsname); if (setMainClass == true && cls.declaresMethod( Scene.v().getSubSigNumberer().findOrAdd("void main(java.lang.String[])"))) { Scene.v().setMainClass(cls); setMainClass = false; } } Scene.v().loadNecessaryClasses(); } Date end = new Date(); System.out.println( "load " + Scene.v().getClasses().size() + " classes in " + getTimeConsumed(start, end)); }
private void run(String cls, boolean app_class) { SootClass soot_class = Scene.v().getSootClass(cls); List<SootMethod> methods = soot_class.getMethods(); for (SootMethod method : methods) { visit(method); } }
private static boolean hasFinalizer(SootClass clazz) { // Don't search interfaces or java.lang.Object if (clazz.isInterface() || !clazz.hasSuperclass()) { return false; } return clazz.declaresMethod("finalize", Collections.emptyList(), VoidType.v()); }
public static boolean isInstanceOfClass(SootClass sc, String className) { SootClass clazz = sc; if (className.equals(clazz.getName())) { return true; } return isSubclass(sc, className); }
protected void internalTransform(String pn, Map map) { SymbiosisTransformer.tlo = new ThreadLocalObjectsAnalysis(new SynchObliviousMhpAnalysis()); SymbiosisTransformer.ftea = new XFieldThreadEscapeAnalysis(); SymbiosisTransformer.pecg = new PegCallGraph(Scene.v().getCallGraph()); Iterator<SootClass> classIt = Scene.v().getApplicationClasses().iterator(); while (classIt.hasNext()) { SootClass sc = classIt.next(); Iterator<SootMethod> methodIt = sc.getMethods().iterator(); while (methodIt.hasNext()) { SootMethod sm = methodIt.next(); if (sm.isAbstract() || sm.isNative()) continue; try { Body body = sm.retrieveActiveBody(); SymbFindSVPass.v().internalTransform(body, pn, map); } catch (Exception e) { System.err.println("[SymbiosisTransformer] SymbScenePass: " + e.getMessage()); e.printStackTrace(); continue; } } } }
private static StructureType getInstanceType0( SootClass clazz, int subClassAlignment, int[] superSize) { List<Type> types = new ArrayList<Type>(); List<SootField> fields = getInstanceFields(clazz); int superAlignment = 1; if (!fields.isEmpty()) { // Pad the super type so that the first field is aligned properly SootField field = fields.get(0); superAlignment = getFieldAlignment(field); } if (clazz.hasSuperclass()) { types.add(getInstanceType0(clazz.getSuperclass(), superAlignment, superSize)); } int offset = superSize[0]; for (SootField field : fields) { int falign = getFieldAlignment(field); int padding = (offset & (falign - 1)) != 0 ? (falign - (offset & (falign - 1))) : 0; types.add(padType(getType(field.getType()), padding)); offset += padding + getFieldSize(field); } int padding = (offset & (subClassAlignment - 1)) != 0 ? (subClassAlignment - (offset & (subClassAlignment - 1))) : 0; for (int i = 0; i < padding; i++) { types.add(I8); offset++; } superSize[0] = offset; return new StructureType(types.toArray(new Type[types.size()])); }
public void staticBlockInlining(SootClass sootClass) { this.sootClass = sootClass; // retrieve the clinit method if any for sootClass if (!sootClass.declaresMethod("void <clinit>()")) { System.out.println("no clinit"); return; } SootMethod clinit = sootClass.getMethod("void <clinit>()"); // System.out.println(clinit); // retireve the active body if (!clinit.hasActiveBody()) throw new RuntimeException("method " + clinit.getName() + " has no active body!"); Body clinitBody = clinit.getActiveBody(); Chain units = ((DavaBody) clinitBody).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode AST = (ASTNode) units.getFirst(); if (!(AST instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); AST.apply(new MethodCallFinder(this)); }
protected boolean differentPackageAndPrivate(RefType ref_inspecting) { RefType ref_type = (RefType) m_thisRef.getType(); SootClass this_class = getClassForType(ref_type); SootClass class_inspecting = getClassForType(ref_inspecting); if (this_class.getPackageName().equals(class_inspecting.getPackageName())) return false; if (class_inspecting.isPublic() == false) return true; return false; }
public void caseStaticInvokeExpr(StaticInvokeExpr arg0) { SootMethod soot_method = arg0.getMethod(); SootClass soot_class = soot_method.getDeclaringClass(); if (soot_class.getName().equals("java.lang.Object")) return; OpenCLMethod ocl_method = new OpenCLMethod(soot_method, soot_class); m_output.append(ocl_method.getStaticInvokeString(arg0)); setCheckException(); }
public static SootMethod mockSootMethod( String clsName, String methodSubSignature, boolean isStatic) { SootClass sc = mockSootClass(clsName); SootMethod sm = null; try { sm = sc.getMethod(methodSubSignature); } catch (Exception ex) { sm = null; } if (null == sm) { int m = Modifier.PUBLIC; if (isStatic) { m = m | Modifier.STATIC; } List<Type> paramTypes = new ArrayList<Type>(); paramTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1)); String[] strs = methodSubSignature.split(" "); String methodName = strs[1].trim().substring(0, strs[1].trim().indexOf("(")); if (null == methodName || methodName.isEmpty()) { return null; } sm = new SootMethod(methodName, paramTypes, RefType.v("java.lang.Object"), m); sc.addMethod(sm); // Add body of sm JimpleBody b = Jimple.v().newBody(sm); sm.setActiveBody(b); // LocalGenerator lg = new LocalGenerator(b); { b.insertIdentityStmts(); // Local rtLoc = lg.generateLocal(RefType.v("java.lang.Object")); // Local param0 = lg.generateLocal(ArrayType.v(RefType.v("java.lang.Object"), 1)); // Unit param0U = Jimple.v().newIdentityStmt(rtLoc, // Jimple.v().newParameterRef(ArrayType.v(RefType.v("java.lang.Object"), 1), 0)); // Unit rtLocAssignU = Jimple.v().newAssignStmt(rtLoc, param0); Unit returnU = Jimple.v().newReturnStmt(b.getParameterLocal(0)); // b.getUnits().add(param0U); b.getUnits().add(returnU); } System.out.println("validation:" + b); b.validate(); } return sm; }
/** * For a concrete method (declared in an application class), find statements containing an invoke * expression for which the method is one of the method in 'allEventInformation' (i.e., * getLine1Number(), ...). * * @param cfg */ private void doAccessControlChecks(BiDiInterproceduralCFG<Unit, SootMethod> cfg) { for (SootClass sc : Scene.v().getApplicationClasses()) { for (SootMethod sm : sc.getMethods()) { if (sm.isConcrete()) { Body body = sm.retrieveActiveBody(); // only instrument application methods (i.e., not methods declared in PEP helper classes // or in a Java library classes or in an Android classes, ...) if (isInstrumentationNecessary(sm)) { // important to use snapshotIterator here Iterator<Unit> i = body.getUnits().snapshotIterator(); log.debug("method: " + sm); while (i.hasNext()) { Stmt s = (Stmt) i.next(); if (s.containsInvokeExpr()) { InvokeExpr invExpr = s.getInvokeExpr(); String methodSignature = invExpr.getMethod().getSignature(); if (allEventInformation.containsKey(methodSignature)) { log.debug("statement " + s + " matches " + methodSignature + "."); ResultSinkInfo sink = null; outer: for (ResultSinkInfo key : results.getResults().keySet()) { // iterate over all the arguments of the invoke expression // and check if an argument is a tainted sink. If one is // set variable 'sink' to the ResultSinkInfo key. for (Value v : invExpr.getArgs()) { Value pathValue = key.getAccessPath().getPlainValue(); if (v == pathValue) { sink = key; log.debug("found a sink: " + pathValue); break outer; } } } if (sink != null) { log.debug("instrument with data flow information )" + s + ")"); instrumentSourceToSinkConnections(cfg, sink, s instanceof AssignStmt); instrumentWithNoDataFlowInformation( methodSignature, s, invExpr, body, s instanceof AssignStmt); } else { log.debug("instrument without data flow information (" + s + ")"); instrumentWithNoDataFlowInformation( methodSignature, s, invExpr, body, s instanceof AssignStmt); } } } // if stmt containts invoke expression } // loop on statements } } } } }
public static List<ExceptionalUnitGraph> getMethodExceptionalUnitGraphs( String className, SootClassLoader loader) { SootClass sootClass = getExceptionalUnitGraph(className, loader); List<ExceptionalUnitGraph> methodExceptionalUnitGraphs = new ArrayList<ExceptionalUnitGraph>(); for (SootMethod sootMethod : sootClass.getMethods()) { methodExceptionalUnitGraphs.add(Util.getUnitGraph(sootMethod)); } return methodExceptionalUnitGraphs; }
public static boolean isSubclass(SootClass sc, String className) { SootClass clazz = sc; while (clazz.hasSuperclass()) { clazz = clazz.getSuperclass(); if (className.equals(clazz.getName())) { return true; } } return false; }
public static SootClass createSootClass(String clsName) { SootClass sc = new SootClass(clsName); sc.setSuperclass(Scene.v().getSootClass("java.lang.Object")); sc.setApplicationClass(); sc.setPhantom(false); sc.setInScene(true); return sc; }
public static SootClass mockSootClass(String clsName) { SootClass sc = null; if (Scene.v().containsClass(clsName)) { sc = Scene.v().getSootClass(clsName); if (sc.isPhantom()) { // sc.setPhantom(false); sc.setApplicationClass(); sc.setInScene(true); try { for (Field field : sc.getClass().getFields()) { if (field.getName().equals("isPhantom")) { field.setAccessible(true); field.setBoolean(sc, false); } } } catch (Exception e) { e.printStackTrace(); } } } else { sc = new SootClass(clsName); sc.setSuperclass(Scene.v().getSootClass("java.lang.Object")); sc.setPhantom(false); sc.setApplicationClass(); sc.setInScene(true); } mockConstructor(sc); return sc; }
/** * Transform the Scene according to the information specified in the model for this transform. * * @param phaseName The phase this transform is operating under. * @param options The options to apply. */ protected void internalTransform(String phaseName, Map options) { // For some reason, soot 2.0.1 gives java.lang.Object as // its own superclass! PtolemyUtilities.objectClass.setSuperclass(null); for (Iterator classes = Scene.v().getApplicationClasses().snapshotIterator(); classes.hasNext(); ) { SootClass theClass = (SootClass) classes.next(); theClass.setLibraryClass(); } }
public ResolvedEntry resolve(SootClass clazz) { while (clazz != null) { for (SootMethod m : clazz.getMethods()) { if (m.getName().equals(name) && desc.equals(Types.getDescriptor(m))) { return new ResolvedEntry(this, m); } } clazz = clazz.hasSuperclass() ? clazz.getSuperclass() : null; } return null; }
public static boolean isAssignable(SootClass taintType, SootClass declaredType) { if (taintType.equals(declaredType)) return true; if (taintType.hasSuperclass() && isAssignable(taintType.getSuperclass(), declaredType)) { return true; } for (SootClass interf : taintType.getInterfaces()) { if (isAssignable(interf, declaredType)) return true; } return false; }
public ITable get(SootClass clazz) { if (!clazz.isInterface()) { throw new IllegalArgumentException("Not an interface: " + clazz.getName()); } ITable itable = cache.get(clazz.getName()); if (itable != null) { return itable; } itable = new ITable(clazz); cache.put(clazz.getName(), itable); return itable; }
private void iterateAllMethods() { // Find methods Iterator<SootClass> getClassesIt = Scene.v().getApplicationClasses().iterator(); while (getClassesIt.hasNext()) { SootClass appClass = getClassesIt.next(); Iterator<SootMethod> getMethodsIt = appClass.getMethods().iterator(); while (getMethodsIt.hasNext()) { SootMethod method = getMethodsIt.next(); analyzeMethod(method); } } }
public void transform() { if (clazz.isPhantom()) return; // build ancestor // List<SootClass> ancestors = Scene.v().getActiveHierarchy().getSuperclassesOf(clazz); List<SootClass> ancestors = new LinkedList<SootClass>(); // fill in ancestor list without using Soot.Hierarchy SootClass curAncestor = clazz; while (curAncestor.hasSuperclass()) { ancestors.add(curAncestor.getSuperclass()); curAncestor = curAncestor.getSuperclass(); } for (SootClass ancestor : ancestors) { if (ancestor.isPhantom()) continue; cloneReachableNonHiddenAncestorMethods(ancestor); } // modify ancestors fields for (SootClass ancestor : ancestors) { if (ancestor.isPhantom()) continue; SootUtils.makeFieldsVisible(ancestor); } cloneHiddenAncestorMethodsAndFixInvokeSpecial(); }
/** For instance invokes */ public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) { final NumberedString mSubsignature = methodRef.getSubSignature(); if (tgtType instanceof RefType) { // find first class upwards in hierarchy, starting from cls, that implements method (i.e., // *concrete* method) SootClass cls = ((RefType) tgtType).getSootClass(); while (!cls.declaresMethod(mSubsignature)) cls = cls .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a // superclass must exist if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method // finally, store resolved app method SootMethod m = cls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); methods.add(m); // just one element, directly resolved return methods; } if (tgtType instanceof AnySubType) { // return set of all app subtypes that implement referenced method SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass(); List subClasses = baseCls.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls) : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); for (Object oSubCls : subClasses) { SootClass subCls = (SootClass) oSubCls; if (subCls.hasTag(ClassTag.TAG_NAME)) { try { SootMethod m = subCls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); if (!m.isAbstract()) methods.add(m); } catch (RuntimeException e) { } } } return methods; } assert tgtType instanceof ArrayType; // only other case observed so far return new ArrayList(); // no array class/method is in app }
private static void writeFile(Set<SootClass> reachableClasses) { try { TreeSet<String> treeSet = new TreeSet<>(); for (SootClass sootClass : reachableClasses) { treeSet.add(sootClass.toString()); } FileWriter writer = new FileWriter(new File("reachableClasses.txt")); for (String sootClass : treeSet) { writer.write(sootClass + "\n"); } writer.close(); } catch (IOException e) { e.printStackTrace(); } }
protected List<OpenCLField> getRefFields(SootClass soot_class) { OpenCLClass ocl_class = OpenCLScene.v().getOpenCLClass(soot_class); if (ocl_class == null) { System.out.println("ocl_class == null: " + soot_class.getName()); } return ocl_class.getInstanceRefFields(); }
/** * 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()); } }
/** * Clone given method into this class with given name. Update necessary state of prior analyses. */ private SootMethod cloneMethod(SootMethod ancestorM, String cloneName) { // check if we are cloning a method multiple times if (clonedToOriginal.containsValue(ancestorM)) { logger.error("Cloning method twice: {}", ancestorM); droidsafe.main.Main.exit(1); } SootMethod newMeth = new SootMethod( cloneName, ancestorM.getParameterTypes(), ancestorM.getReturnType(), ancestorM.getModifiers(), ancestorM.getExceptions()); // System.out.printf("\tAdding method %s.\n", ancestorM); // register method methods.addMethod(newMeth); clazz.addMethod(newMeth); clonedToOriginal.put(newMeth, ancestorM); API.v().cloneMethodClassifications(ancestorM, newMeth); // clone body Body newBody = (Body) ancestorM.retrieveActiveBody().clone(); newMeth.setActiveBody(newBody); JSAStrings.v().updateJSAResults(ancestorM.retrieveActiveBody(), newBody); return newMeth; }
/** Conveniently create a class deriving from Code.testClass */ public Pair<SootClass, SignatureTable<Level>> makeDerivedClass( String name, SootClass superClass, List<MethodWithSignature<Level>> methods) { SootClass result = makeFreshClass(name); result.setSuperclass(superClass); SignatureTable<Level> newSignatures = this.signatures; for (MethodWithSignature<Level> m : methods) { result.addMethod(m.method); newSignatures = newSignatures.extendWith( m.method, Interop.asJavaStream(m.signature.constraints.stream()).collect(Collectors.toList()), m.signature.effects); } return Pair.of(result, newSignatures); }