Пример #1
0
  private List<Unit> instrumentIntentAddings(
      BiDiInterproceduralCFG<Unit, SootMethod> cfg,
      Unit unit,
      InvokeExpr sinkExpr,
      Set<ResultSourceInfo> sourceInfo) {
    if (isMethodInterComponentSink(sinkExpr.getMethod())) {
      SootMethod method = cfg.getMethodOf(unit);
      Body body = null;
      if (method.hasActiveBody()) body = method.retrieveActiveBody();
      else throw new RuntimeException("No body found!");

      Set<String> sourceCategories = getDataIdList(sourceInfo);

      final String hashSetType = "java.util.HashSet";
      List<Unit> generated = new ArrayList<Unit>();

      // HashSet initialization
      Local hashSetLocal = generateFreshLocal(body, RefType.v(hashSetType));
      NewExpr newExpr = Jimple.v().newNewExpr(RefType.v(hashSetType));
      AssignStmt assignStmt = Jimple.v().newAssignStmt(hashSetLocal, newExpr);
      generated.add(assignStmt);

      // constructor call
      SpecialInvokeExpr constructorCall =
          Jimple.v()
              .newSpecialInvokeExpr(
                  hashSetLocal,
                  Scene.v().getMethod("<java.util.HashSet: void <init>()>").makeRef());
      InvokeStmt constructorCallStmt = Jimple.v().newInvokeStmt(constructorCall);
      generated.add(constructorCallStmt);

      // add categories to HashSet
      for (String cat : sourceCategories) {
        InterfaceInvokeExpr addCall =
            Jimple.v()
                .newInterfaceInvokeExpr(
                    hashSetLocal,
                    Scene.v().getMethod("<java.util.Set: boolean add(java.lang.Object)>").makeRef(),
                    StringConstant.v(cat));
        InvokeStmt addCallStmt = Jimple.v().newInvokeStmt(addCall);
        generated.add(addCallStmt);
      }

      // get Intent
      Value intent = sinkExpr.getArg(0);
      List<Object> args = new ArrayList<Object>();
      args.add(RefType.v("android.content.Intent"));
      args.add(intent);
      args.add(RefType.v(hashSetType));
      args.add(hashSetLocal);
      StaticInvokeExpr sie =
          Instrumentation.createJimpleStaticInvokeExpr(
              Settings.INSTRUMENTATION_HELPER_JAVA, "addTaintInformationToIntent", args);
      InvokeStmt invStmt = Jimple.v().newInvokeStmt(sie);
      generated.add(invStmt);

      return generated;
    }
    return Collections.emptyList();
  }
Пример #2
0
  /**
   * Generate a default assignment with 'local' as left-hand-side value.
   *
   * @param local
   * @return
   */
  private Unit createCorrectDummyAssignment(Local local) {
    Unit dummyAssignemnt = null;
    if (local.getType() instanceof PrimType) {
      if (local.getType() instanceof IntType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyInteger", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof BooleanType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyBoolean", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof ByteType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyByte", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof CharType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(
                Settings.SANITIZER, "dummyCharacter", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof DoubleType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyDouble", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof FloatType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyFloat", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof LongType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyLong", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else if (local.getType() instanceof ShortType) {
        StaticInvokeExpr sie =
            Instrumentation.createJimpleStaticInvokeExpr(Settings.SANITIZER, "dummyShort", null);
        dummyAssignemnt = Jimple.v().newAssignStmt(local, sie);
      } else throw new RuntimeException("Oops, the primitive type is not correct");
    } else {
      if (local.getType().equals(RefType.v("java.lang.String")))
        dummyAssignemnt = Jimple.v().newAssignStmt(local, StringConstant.v(""));
      else dummyAssignemnt = Jimple.v().newAssignStmt(local, NullConstant.v());
    }

    return dummyAssignemnt;
  }
Пример #3
0
  /**
   * Generate Policy Enforcement Point (PEP) for Unit 'unit'.
   *
   * @param unit
   * @param invExpr
   * @param body
   * @param dataFlowAvailable
   * @param assignmentStatement
   * @return
   */
  private List<Unit> generatePolicyEnforcementPoint(
      Unit unit,
      InvokeExpr invExpr,
      Body body,
      int dataFlowAvailable,
      boolean assignmentStatement) {

    log.debug("Dataflow available: " + dataFlowAvailable);

    List<Unit> generated = new ArrayList<Unit>(); // store all new units that are generated

    String methodSignature = invExpr.getMethod().getSignature();
    EventInformation eventInfo = allEventInformation.get(methodSignature);
    String eventName = eventInfo.getEventName();

    Set<Pair<Integer, String>> allParameterInformation = eventInfo.getParameterInformation();

    // This list containts types and parameters that are used to build the
    // invoke expression to "isStmtExecutionAllowed':
    //
    // java.lang.String   "eventName"
    // IntType            "dataFlowAvailable"
    // java.lang.Object[] "parameters"
    //
    List<Object> parameterForHelperMethod = new ArrayList<Object>();
    List<Object> categories = new ArrayList<Object>();

    // add event name information
    Type eventNameType = RefType.v("java.lang.String");
    parameterForHelperMethod.add(eventNameType);
    StringConstant eventNameConstant = StringConstant.v(eventName);
    parameterForHelperMethod.add(eventNameConstant);

    // add information about dataflow availability
    parameterForHelperMethod.add(IntType.v());
    parameterForHelperMethod.add(IntConstant.v(dataFlowAvailable));

    // add information about parameters
    parameterForHelperMethod.add(getParameterArrayType());
    List<Value> paramValues = new ArrayList<Value>();

    for (Pair<Integer, String> parameterInfo : allParameterInformation) {
      paramValues.add(StringConstant.v("param" + parameterInfo.getLeft() + "value"));
      paramValues.add(invExpr.getArg(parameterInfo.getLeft()));
    }

    Pair<Value, List<Unit>> arrayRefAndInstrumentation = generateParameterArray(paramValues, body);

    generated.addAll(arrayRefAndInstrumentation.getRight());

    parameterForHelperMethod.add(arrayRefAndInstrumentation.getLeft());

    // Generate PEP call to the PDP. Store the result send by the PDP to 'resultPDPLocal'
    // Pseudo code looks like this:
    //
    // resultPDPLocal = isStmtExecutionAllowed(eventName, dataFlowAvailable, parameters);
    //
    StaticInvokeExpr sie =
        Instrumentation.createJimpleStaticInvokeExpr(
            Settings.INSTRUMENTATION_HELPER_JAVA,
            "isStmtExecutionAllowed",
            parameterForHelperMethod);

    Local resultPDPLocal = generateFreshLocal(body, soot.IntType.v());
    AssignStmt asssCondition = Jimple.v().newAssignStmt(resultPDPLocal, sie);
    generated.add(asssCondition);

    for (Unit u : generated) {
      System.out.println("isStmt gen: " + u);
    }

    if (assignmentStatement) {
      // If the method call before which the PEP in inserted is an assignment statement of
      // the form "resultPDPLocal = originalCallThatIsChecked()", generate a new assignment
      // statement that stores a default value to "resultPDPLocal" if the PDP does not
      // allow the call of method originalCallThatIsChecked().
      //
      // Pseudo-code:
      //
      // if(resultPDPLocal == 0) goto dummyLabel:
      // result = originalCallThatIsChecked();
      // goto dummyLabel2:
      // dummyLabel:
      // result = dummyValue (i.e., 0 for IntType, false for BooleanType, ...)
      // dummyLabel2:
      // nop
      //

      if (unit instanceof DefinitionStmt) {
        DefinitionStmt defStmt = (DefinitionStmt) unit;

        Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0));

        // insert nop
        Unit label2Nop = Jimple.v().newNopStmt();
        body.getUnits().insertAfter(label2Nop, unit);

        // insert result = dummyValue
        Unit dummyStatement = createCorrectDummyAssignment((Local) defStmt.getLeftOp());
        body.getUnits().insertAfter(dummyStatement, unit);
        log.debug("insert c: " + dummyStatement);

        // insert goto dummyLabel2:
        body.getUnits().insertAfter(Jimple.v().newGotoStmt(label2Nop), unit);

        IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, dummyStatement);
        generated.add(ifStmt);
      } else {
        throw new RuntimeException(
            "error: expected DefinitionStmt got " + unit + " -> " + unit.getClass());
      }

    } else {
      // If the method call before which the PEP in inserted is a call statement of
      // the form "originalCallThatIsChecked()", generate a new nop statement
      // to jump to if the PDP does not allow the call of method originalCallThatIsChecked().
      //
      // Pseudo-code:
      //
      // if(resultPDPLocal == 0) goto nopLabel:
      // result = originalCallThatIsChecked();
      // nopLabel:
      // nop
      //
      Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0));

      NopStmt nopStmt = Jimple.v().newNopStmt();
      body.getUnits().insertAfter(nopStmt, unit);
      log.debug("insert d: " + nopStmt);

      IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, nopStmt);

      generated.add(ifStmt);
    }

    return generated;
  }
Пример #4
0
  /**
   * @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
  }