Skip to content

Commit

Permalink
Add transformer architecture to deal with new features from Soot 4.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
smeyer198 committed Feb 19, 2024
1 parent 7dd0d4f commit 3d80bc5
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 52 deletions.
1 change: 0 additions & 1 deletion CryptoAnalysis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.77</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bctls-jdk18on -->
<dependency>
Expand Down
22 changes: 15 additions & 7 deletions CryptoAnalysis/src/main/java/crypto/HeadlessCryptoScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import boomerang.callgraph.ObservableICFG;
import boomerang.debugger.Debugger;
import boomerang.debugger.IDEVizDebugger;
import boomerang.preanalysis.BoomerangPretransformer;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import crypto.analysis.CrySLAnalysisListener;
Expand All @@ -16,8 +15,8 @@
import crypto.analysis.IAnalysisSeed;
import crypto.exceptions.CryptoAnalysisException;
import crypto.exceptions.CryptoAnalysisParserException;
import crypto.preanalysis.ExceptionAwareTransformer;
import crypto.preanalysis.SeedFactory;
import crypto.preanalysis.TransformerSetup;
import crypto.providerdetection.ProviderDetection;
import crypto.reporting.CSVReporter;
import crypto.reporting.CSVSummaryReporter;
Expand Down Expand Up @@ -138,7 +137,7 @@ public void exec() {
} catch (CryptoAnalysisException e) {
LOGGER.error("Error happened when executing HeadlessCryptoScanner.", e);
}
ExceptionAwareTransformer.setup(rules);

LOGGER.info("Analysis soot setup done in {} ", stopwatch);
analyse();
LOGGER.info("Analysis finished in {}", stopwatch);
Expand Down Expand Up @@ -189,8 +188,8 @@ private Transformer createAnalysisTransformer() {

@Override
protected void internalTransform(String phaseName, Map<String, String> options) {
BoomerangPretransformer.v().reset();
BoomerangPretransformer.v().apply();
TransformerSetup.v().setupPreTransformer(rules);

ObservableDynamicICFG observableDynamicICFG = new ObservableDynamicICFG(false);
List<CrySLRule> rules = HeadlessCryptoScanner.rules;

Expand Down Expand Up @@ -336,6 +335,14 @@ private void initializeSootWithEntryPointAllReachable(boolean wholeProgram) thro
Options.v().set_no_bodies_for_excluded(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_keep_line_number(true);

/* This phase is new in soot 4.3.0 and manipulates the jimple code in a
* way that CryptoAnalysis is not able to find seeds in some cases (see
* https://github.com/CROSSINGTUD/CryptoAnalysis/issues/293). Therefore,
* it is disabled.
*/
Options.v().setPhaseOption("jb.sils", "enabled:false");

// JAVA 8
if(getJavaVersion() < 9)
{
Expand Down Expand Up @@ -380,13 +387,14 @@ private List<String> getIncludeList() {
includeList.add("java.lang.String");
includeList.add("java.lang.StringCoding");
includeList.add("java.lang.StringIndexOutOfBoundsException");
return includeList;
return new LinkedList<>();
}

private List<String> getExcludeList() {
List<String> exList = new LinkedList<String>();
List<CrySLRule> rules = getRules();
for(CrySLRule r : rules) {

for (CrySLRule r : rules) {
exList.add(r.getClassName());
}
return exList;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package crypto.preanalysis;

import soot.Body;
import soot.UnitPatchingChain;
import soot.Value;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.Constant;

import java.util.Map;

/**
* This transformer removes explicit cast expressions from the jimple code.
* Since Soot 4.3.0, it transforms the expression 'int a = 65000' into the jimple
* statement '$v = (int) 65000'. However, Boomerang is not able to extract the
* value 65000 from the statement because of the explicit cast operation (int).
* For the analysis, this operation is irrelevant because the variables always
* have the correct type (i.e. $v is of type int), so we can remove the cast
* operation.
*/
public class CastTransformer extends PreTransformer {

private static CastTransformer instance;

public CastTransformer() {
super();
}

@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
if (!body.getMethod().getDeclaringClass().isApplicationClass()) {
return;
}

final UnitPatchingChain units = body.getUnits();
units.snapshotIterator().forEachRemaining(unit -> {
if (!(unit instanceof AssignStmt)) {
return;
}
AssignStmt assignStmt = (AssignStmt) unit;

Value rightSide = assignStmt.getRightOp();
if (!(rightSide instanceof CastExpr)) {
return;
}

CastExpr castExpr = (CastExpr) rightSide;
if (!(castExpr.getOp() instanceof Constant)) {
return;
}
Constant constant = (Constant) castExpr.getOp();

assignStmt.setRightOp(constant);
});
}

public static CastTransformer v() {
if (instance == null) {
instance = new CastTransformer();
}
return instance;
}

public void reset() {
instance = null;
}

}
Original file line number Diff line number Diff line change
@@ -1,48 +1,33 @@
package crypto.preanalysis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

import crypto.constraints.ExceptionConstraint;
import crypto.rules.CrySLExceptionConstraint;
import crypto.rules.CrySLRule;
import crypto.typestate.CrySLMethodToSootMethod;
import crypto.typestate.LabeledMatcherTransition;
import soot.Body;
import soot.BodyTransformer;
import soot.PackManager;
import soot.PhaseOptions;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.Transform;
import soot.Unit;
import soot.UnitPatchingChain;
import soot.jimple.NullConstant;
import soot.jimple.Stmt;
import soot.jimple.internal.JEqExpr;
import soot.jimple.internal.JIfStmt;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
* This transformer adds a branch after each statement, that may throw an
* Exception, to the handler of that Exception.
* The exceptions that a statement may throw are declared in the CrySLRule.
*/
public class ExceptionAwareTransformer extends BodyTransformer {

public static void setup(final List<CrySLRule> rules) {
for (final CrySLRule rule : rules) {
final String phaseName = "jap.etr-" + rule.getClassName();
PackManager.v().getPack("jap").remove(phaseName);
PackManager.v().getPack("jap").add(new Transform(phaseName, new ExceptionAwareTransformer(rule)));
PhaseOptions.v().setPhaseOption(phaseName, "on");
}
}
public class ExceptionAwareTransformer extends PreTransformer {

private final SootClass spec;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package crypto.preanalysis;

import soot.BodyTransformer;
import soot.MethodOrMethodContext;
import soot.Scene;
import soot.SootMethod;
import soot.jimple.toolkits.callgraph.ReachableMethods;
import soot.util.queue.QueueReader;

import java.util.HashMap;

public abstract class PreTransformer extends BodyTransformer {

private boolean applied;

public PreTransformer() {
applied = false;
}

public final void apply() {
if (isApplied()) {
return;
}

/* Following the concept of Soot, each transformer is applied to each method
* body individually. It may be more efficient to apply all transformers at once
* to a method body.
*/
ReachableMethods reachableMethods = Scene.v().getReachableMethods();
QueueReader<MethodOrMethodContext> listener = reachableMethods.listener();
while (listener.hasNext()) {
SootMethod method = listener.next().method();
if (method.hasActiveBody()) {
internalTransform(method.getActiveBody(), "preTrans", new HashMap<>());
}
}
applied = true;
}

public boolean isApplied() {
return applied;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package crypto.preanalysis;

import boomerang.preanalysis.BoomerangPretransformer;
import crypto.rules.CrySLRule;

import java.util.List;

public class TransformerSetup {

private static TransformerSetup instance;

public void setupPreTransformer(List<CrySLRule> rules) {
// Transformer related to the analysis
setupCastTransformer();
setupExceptionAwareTransformer(rules);

// Transformer related to Boomerang
setupBoomerangTransformer();
}

public void setupCastTransformer() {
CastTransformer.v().reset();
CastTransformer.v().apply();
}

public void setupExceptionAwareTransformer(List<CrySLRule> rules) {
for (CrySLRule rule : rules) {
ExceptionAwareTransformer transformer = new ExceptionAwareTransformer(rule);
transformer.apply();
}
}

public void setupBoomerangTransformer() {
BoomerangPretransformer.v().reset();
BoomerangPretransformer.v().apply();
}

public static TransformerSetup v() {
if (instance == null) {
instance = new TransformerSetup();
}
return instance;
}

public void reset() {
instance = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ private Collection<SootMethod> _convert(CrySLMethod label) {
for(SootClass c : classes) {
for (SootMethod m : c.getMethods()) {
if (m.getName().equals(methodNameWithoutDeclaringClass) && m.getParameterCount() == noOfParams) {
if (parametersMatch(label.getParameters(), m.getParameterTypes())){
if (parametersMatch(label.getParameters(), m.getParameterTypes())) {
res.add(m);

// Set the class defining the target method to phantom to avoid analyzing the method,
// if it is defined in a superclass
c.setPhantomClass();
}
}
}
Expand Down
Loading

0 comments on commit 3d80bc5

Please sign in to comment.