/**
   * 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);
  }
  /**
   * 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 boolean isTarget(
      AnalysisDirection direction,
      SootMethod enclosingMethod,
      Unit unit,
      Iterable<AnalysisTarget> targets) {
    if (!(unit instanceof AssignStmt)) return false;

    Stmt s = (Stmt) unit;
    if (!s.containsInvokeExpr()) return false;

    InvokeExpr ie = s.getInvokeExpr();
    for (AnalysisTarget target : targets) {
      if (target.matches(direction, enclosingMethod, ie)) return true;
    }
    return false;
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  private Set<SootField> collectBlockField(JavaCriticalSection cs) {
    Set result = new HashSet();
    int startLine = cs.getStartLine();
    int endLine = cs.getEndline();
    Body body = cs.getSootMethod().getActiveBody();
    PatchingChain<Unit> units = body.getUnits();
    for (Unit u : units) {
      Stmt s = (Stmt) u;
      LineNumberTag linetag = (LineNumberTag) s.getTag("LineNumberTag");
      if (linetag == null) continue;
      int line = linetag.getLineNumber();
      if (line < startLine || line > endLine) {
        continue;
      }

      List<ValueBox> Fieldslist = u.getUseBoxes();
      Fieldslist.addAll(u.getDefBoxes());
      for (ValueBox box : Fieldslist) {
        Value v = box.getValue();
        if (v instanceof JInstanceFieldRef) {
          result.add(((JInstanceFieldRef) v).getField());
        }
      }
      if (s.containsInvokeExpr()) {
        // 用调用图获得调用目标
        Callees callees = new Callees(getCallGragh(), u);
        for (SootMethod invokeMethod : callees.explicits()) {
          if (invokeMethod == null) continue;
          Collection use = scaner.getUseInstanceFields(invokeMethod);
          Collection mod = new HashSet();
          if (needMod) {
            mod.addAll(scaner.getModInstanceFields(invokeMethod));
          }
          if (use != null) result.addAll(use);
          result.addAll(mod);
        }
      }
    }
    return result;
  }
  @Override
  public Type appliesInternal(AndroidMethod method) {
    SootMethod sm = getSootMethod(method);

    if (sm == null) {
      System.err.println("Method not declared: " + method);
      return Type.NOT_SUPPORTED;
    }

    // We are only interested in setters
    if (!sm.isConcrete()) return Type.NOT_SUPPORTED;

    try {
      Set<Value> paramVals = new HashSet<Value>();
      for (Unit u : sm.retrieveActiveBody().getUnits()) {
        // Collect the parameters
        if (u instanceof IdentityStmt) {
          IdentityStmt id = (IdentityStmt) u;
          if (id.getRightOp() instanceof ParameterRef) paramVals.add(id.getLeftOp());
        }

        // Check for invocations
        if (u instanceof Stmt) {
          Stmt stmt = (Stmt) u;
          if (stmt.containsInvokeExpr())
            if (stmt.getInvokeExpr() instanceof InstanceInvokeExpr) {
              InstanceInvokeExpr iinv = (InstanceInvokeExpr) stmt.getInvokeExpr();
              if (paramVals.contains(iinv.getBase()))
                if (iinv.getMethod().getName().startsWith(methodName)) return Type.TRUE;
            }
        }
      }
      return Type.FALSE;
    } catch (Exception ex) {
      System.err.println("Something went wrong:");
      ex.printStackTrace();
      return Type.NOT_SUPPORTED;
    }
  }
Beispiel #6
0
  /**
   * @param g
   * @param numFormals number of parameters need to be taken into account, since abc will generate
   *     auxiliary parameters for proceed call, so this analysis needs the number of parameters
   *     originly declared in around advice
   * @param withReturn if the around adivce has return value
   */
  public ProceedAnalysis(UnitGraph g, int numFormals, boolean withReturn) {

    super(g);
    this.g = g;

    exactProceedSet = new HashSet<Stmt>();
    nonExactProceedSet = new HashSet<Stmt>();

    UnchangedParamsAnalysis paramAnalysis = null;
    // if numformals = 0, dont need paramAnalysis
    if (numFormals >= 0) paramAnalysis = new UnchangedParamsAnalysis(g, numFormals);
    UnchangedReturnAnalysis returnAnalysis = new UnchangedReturnAnalysis(g);
    ExceptionBeforeProceedAnalysis exceptionAnalysis = new ExceptionBeforeProceedAnalysis(g);

    // calcualte exactProceedSet and nonExactProceedSet
    for (Iterator uIt = g.getBody().getUnits().iterator(); uIt.hasNext(); ) {
      Unit unit = (Unit) uIt.next();
      if (unit instanceof Stmt) {
        Stmt s = (Stmt) unit;
        if (withReturn) {
          // care only AssignStmt
          if (s instanceof AssignStmt
              && s.containsInvokeExpr()
              && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) {
            boolean exact = false;
            int matchArg = numFormals;
            // if numformals = 0, dont need paramAnalysis analysis
            if (numFormals > 0) {
              matchArg = numMatchArgs(numFormals, paramAnalysis, s);
            }
            // System.out.println("invoke match arg = " + matchArg);
            if (matchArg == numFormals) {
              // should check return value and exceptions
              if (returnAnalysis.isReachReturn(s)) {
                if (!exceptionAnalysis.hasExceptionBefore(s)) {
                  exact = true;
                }
              }
            }
            if (exact) exactProceedSet.add(s);
            else nonExactProceedSet.add(s);
          }
        } else {
          // care only InvokeStmt
          if (s instanceof InvokeStmt
              && s.containsInvokeExpr()
              && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) {
            boolean exact = false;
            int matchArg = numFormals;
            // if numformals = 0, dont need paramAnalysis analysis
            if (numFormals > 0) {
              matchArg = numMatchArgs(numFormals, paramAnalysis, s);
            }
            // System.out.println("invoke match arg = " + matchArg);
            if (matchArg == numFormals) {
              // should check exceptions
              if (!exceptionAnalysis.hasExceptionBefore(s)) {
                exact = true;
              }
            }
            if (exact) exactProceedSet.add(s);
            else nonExactProceedSet.add(s);
          }
        }
      }
    }

    doAnalysis();
  }
  public void assureAllSyncInCallGraph(Collection<JavaCriticalSection> criticalSections) {
    System.out.println("[assureAllSyncInCallgraph] starting");
    Date start = new Date();
    ReachableMethods oldReach = Scene.v().getReachableMethods();
    // Collection et = EntryPoints.v().all();
    // ReachableMethods reachableFromMain = new ReachableMethods(cg, et);
    // reachableFromMain.update();

    Set<SootMethod> notInCG = new HashSet<SootMethod>();
    for (JavaCriticalSection cs : criticalSections) {
      SootMethod m = cs.getSootMethod();
      if (!oldReach.contains(m)) notInCG.add(m);
    }
    Set<SootMethod> alreadyInCG = new HashSet<SootMethod>();
    for (Iterator<MethodOrMethodContext> it = oldReach.listener(); it.hasNext(); ) {
      alreadyInCG.add(it.next().method());
    }
    /*
     * for(Iterator<?> it=cg.sourceMethods();it.hasNext();){ SootMethod m =
     * (SootMethod)it.next(); alreadyInCG.add(m); if(notInCG.contains(m)){
     * notInCG.remove(m); } }
     */

    // add new methods to the call graph
    Stack<SootMethod> worklist = new Stack<SootMethod>();
    for (SootMethod m : notInCG) {
      worklist.push(m);
    }

    while (!worklist.isEmpty()) {
      SootMethod m = worklist.pop();
      if (alreadyInCG.contains(m) || m == null) {
        continue;
      }
      alreadyInCG.add(m);

      Body body = m.retrieveActiveBody();
      for (Unit u : body.getUnits()) {
        if (!(u instanceof Stmt)) {
          continue;
        }

        Stmt s = (Stmt) u;
        if (!s.containsInvokeExpr()) {
          continue;
        }

        InvokeExpr invoke = s.getInvokeExpr();
        SootMethod declCallee = invoke.getMethod();
        Collection<SootMethod> targets = new ArrayList<SootMethod>();
        if (declCallee.isStatic()) {
          targets.add(declCallee);
        } else {
          // XXX: pay attention to reflexive call, thread call, and
          // etc.
          // Here we do not add edges for implicit targets, as these
          // parts of methods is not reachable
          // from the entry, and they will most likely to be analyzed
          // in a very conservative ways.
          InstanceInvokeExpr iie = (InstanceInvokeExpr) invoke;
          Local receiver = (Local) iie.getBase();
          NumberedString subSig = iie.getMethodRef().getSubSignature();

          if (invoke instanceof SpecialInvokeExpr) {
            SootMethod tgt = VirtualCalls.v().resolveSpecial((SpecialInvokeExpr) invoke, subSig, m);
            targets.add(tgt);
          } else {
            Type t = receiver.getType();
            if (t instanceof ArrayType) {
              // t = RefType.v("java.lang.Object");
              targets.add(declCallee);
            }
            // BottomType bug
            else if (t instanceof soot.jimple.toolkits.typing.fast.BottomType) {
              System.out.println("BottomType:" + s);
            } else if (t instanceof soot.NullType) {
              System.out.println("NullType:" + s);
            } else {
              SootClass c = ((RefType) t).getSootClass();
              // Soot has a type resolving bug, and here may be
              // exceptions
              try {
                Set<SootMethod> callees =
                    Scene.v().getOrMakeFastHierarchy().resolveAbstractDispatch(c, declCallee);
                targets.addAll(callees);
              } catch (Exception e) {
                System.out.println(e.getMessage());
              }
            }
          }
        }

        for (SootMethod t : targets) {
          // add call edge
          Edge e = new Edge(m, s, t);
          Scene.v().getCallGraph().addEdge(e);

          // add to worklist
          if (t.isConcrete() && !alreadyInCG.contains(t)) {
            worklist.push(t);
          }
        }
      }
    }

    // infer entries for the methods not reachable from main entry
    List<SootMethod> entries = Scene.v().getEntryPoints();
    _patchedEntries = new ArrayList<SootMethod>(notInCG);
    for (SootMethod m : notInCG) {
      // XXX there can be recursive calls, so for simple processing, all
      // methods not in old
      // call graph should be added to the entry. Checking the
      // non-existence of incoming edges
      // may miss some recursively called methods
      // if(!cg.edgesInto(m).hasNext()){
      entries.add(m);
      // }
    }

    // update reachable methods
    Scene.v().setReachableMethods(null);
  }
Beispiel #8
0
 public static boolean isCtorCall(Stmt s) {
   return s.containsInvokeExpr()
       && (s.getInvokeExpr() instanceof SpecialInvokeExpr)
       && s.getInvokeExpr().getMethod().getName().equals("<init>");
 }
  /**
   * @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
  }