/**
   * 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;
      }
    }
  }
  /**
   * 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());
    }
  }
  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();
  }
示例#4
0
  private void dumpTextGraph(SootMethod caller, PrintStream printStream, int level) {

    String indent = indentString(level);
    caller.getTags();
    printStream.printf("%s %s\n", indent, caller.toString());
    Iterator<Edge> iterator = callGraph.edgesOutOf(caller);
    callgraphSet.add(caller);

    // boolean appClass = caller.getDeclaringClass().isApplicationClass();
    boolean systemApi = API.v().isSystemMethod(caller);

    /*
      printStream.printf("%s Declaring method %s: app %s\n", indent,
      caller.toString(), systemApi? "False": "True");
    */

    String subindent = indentString(level + 1);
    Set<Object> calleeSet = new HashSet<Object>();

    while (iterator != null && iterator.hasNext()) {
      Edge edge = iterator.next();
      if (!systemApi) {
        List<Stmt> invokeStmtList = SootUtils.getInvokeStatements(caller, edge.tgt());
        for (Stmt stmt : invokeStmtList) {
          if (calleeSet.contains(stmt)) continue;
          printStream.printf("%s #[%s] ", subindent, stmt);
          SourceLocationTag tag = SootUtils.getSourceLocation(stmt);
          if (tag != null) {
            printStream.printf(": %s", tag.toString());
          }
          printStream.printf("\n");
          calleeSet.add(stmt.toString());
        }
      }

      if (!callgraphSet.contains(edge.tgt())) {
        dumpTextGraph(edge.tgt(), printStream, level + 1);
      } else {
        // already in the call graph, just print it out
        if (calleeSet.contains(edge.tgt())) continue;
        printStream.printf("%s %s\n", subindent, edge.tgt().toString());
        calleeSet.add(edge.tgt());
      }
    }
  }
  /**
   * Return true if the clone already contains a method that would resolve to this method, this is
   * the test that mimics virtual dispatch, so we don't clone in methods that would not be called.
   */
  private boolean containsMethod(String signature) {
    // check this class for the method with polymorpism
    String mName = SootUtils.grabName(signature);
    String[] args = SootUtils.grabArgs(signature);
    String rtype = SootUtils.grabReturnType(signature);

    for (SootMethod curr : methods) {
      if (!curr.getName().equals(mName) || curr.getParameterCount() != args.length) continue;

      // check the return types
      Type returnType = SootUtils.toSootType(rtype);
      if (!SootUtils.isSubTypeOfIncluding(returnType, curr.getReturnType())) continue;

      boolean foundIncompArg = false;
      for (int i = 0; i < args.length; i++) {
        if (!SootUtils.isSubTypeOfIncluding(
            SootUtils.toSootType(args[i]), curr.getParameterType(i))) {
          foundIncompArg = true;
          continue;
        }
      }

      // at least one parameter does not match!
      if (foundIncompArg) continue;

      return true;
    }

    // didn't find it
    return false;
  }
示例#6
0
  private static String getReachableLines() {
    int totalReachableLines = 0;

    for (SootMethod sm : PTABridge.v().getReachableMethods()) {
      totalReachableLines += SootUtils.getNumLines(sm);
    }

    return Integer.toString(totalReachableLines);
  }
  /**
   * Make sure that all invoke special targets are cloned into the class from ancestors. This might
   * mean that we have to clone hidden methods, and change their names. So clone them in, and update
   * the clone to original map, and update the invoke special Also, this will update invoke specials
   * that target methods cloned in previous call to above cloneReachableNonHiddenAncestorMethods()
   */
  private void cloneHiddenAncestorMethodsAndFixInvokeSpecial() {
    Set<SootClass> parents = SootUtils.getParents(clazz);

    boolean debug = false; // (clazz.getName().contains("ResultDisplayer"));

    boolean cloneAdded = false;
    do {
      cloneAdded = false;
      for (SootMethod method : clazz.getMethods()) {

        if (method.isAbstract() || method.isPhantom() || !method.isConcrete()) continue;

        if (debug) System.out.println(method);

        Body body = null;
        try {
          body = method.retrieveActiveBody();
        } catch (Exception ex) {
          logger.info("Exception retrieving method body {}", ex);
          continue;
        }

        StmtBody stmtBody = (StmtBody) body;

        Chain units = stmtBody.getUnits();
        Iterator stmtIt = units.iterator();

        while (stmtIt.hasNext()) {
          Stmt stmt = (Stmt) stmtIt.next();

          if (stmt.containsInvokeExpr() && stmt.getInvokeExpr() instanceof SpecialInvokeExpr) {
            SpecialInvokeExpr si = (SpecialInvokeExpr) stmt.getInvokeExpr();

            SootMethod target = resolveSpecialInvokeTarget(si); // si.getMethod();

            if (debug) System.out.printf("\t%s %s", si, target);

            if (clonedToOriginal.values().contains(target)) {
              // found target of invoke special, and it has been cloned, so change the invoke
              // special
              SootMethod cloneOfTarget = clonedToOriginal.inverse().get(target);
              si.setMethodRef(cloneOfTarget.makeRef());
              if (debug) System.out.println("\tChange ref " + cloneOfTarget);
            } else if (parents.contains(target.getDeclaringClass())) {
              // target has not been cloned, but should be cloned, so clone it and change ref of
              // invoke
              String name = target.getName() + CLONED_METHOD_SUFFIX + (cloned_method_id++);
              SootMethod clonedMethod = cloneMethod(target, name);
              si.setMethodRef(clonedMethod.makeRef());
              cloneAdded = true;
              if (debug) System.out.println("\tClone and Change ref " + clonedMethod);
            }
          }
        }
      }
    } while (cloneAdded);
  }
  /** Dumps out the call chain in json format * */
  public void dump_json(PrintStream fp, String indent) {
    fp.printf("%s{ %s,\n", indent, json_field("type", type));
    fp.printf("%s  %s,\n", indent, json_field("link", link));
    String sig = method.getSignature();
    fp.printf("%s  %s,\n", indent, json_field("signature", sig));
    if (stmt != null) {
      SootMethodRef invoke = stmt.getInvokeExpr().getMethodRef();
      String invokeSig;
      try {
        SootMethod concrete = SootUtils.resolve(stmt.getInvokeExpr().getMethodRef());
        invokeSig = concrete.getSignature();
      } catch (CannotFindMethodException e1) {
        logger.debug("Cannot find concrete method for {} in SourceCallChainInfo.dump_json()", stmt);
        invokeSig = invoke.getSignature();
      }
      if (!invokeSig.equals(sig)) {
        fp.printf("%s  %s,\n", indent, json_field("source-signature", invokeSig));
      }
    }
    SourceLocationTag slt =
        (stmt == null) ? SootUtils.getMethodLocation(method) : getSourceLocation(stmt);
    if (slt != null) {
      fp.printf("%s  %s", indent, json_field("src-loc"));
      fp.printf(
          "{ %s, %s},\n", json_field("class", slt.getClz()), json_field("line", slt.getLine()));
    }
    fp.printf("%s  %s,\n", indent, json_field("syscalls", syscalls));
    fp.printf("%s  %s,\n", indent, json_field("calls", calls));

    if ((contents != null) && (contents.length > 0)) {
      fp.printf("%s  %s,\n", indent, json_field("score", score));
      fp.printf("%s  %s [\n", indent, json_field("contents"));
      String delim = "";
      for (SourceCallChainInfo cci : contents) {
        fp.print(delim);
        delim = ",\n";
        cci.dump_json(fp, indent + "  ");
      }
      fp.printf("\n%s]}", indent);
    } else {
      fp.printf("%s  %s\n", indent, json_field("score", score));
      fp.printf("%s}", indent);
    }
  }
示例#9
0
  /** 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;
  }
 /** gets the source location for unit (which must be a stmt) * */
 public static SourceLocationTag getSourceLocation(Unit s) {
   return SootUtils.getSourceLocation((Stmt) s);
 }