All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.infoflow.android.iccta.IccInstrumenter Maven / Gradle / Ivy

package soot.jimple.infoflow.android.iccta;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import soot.Body;
import soot.Local;
import soot.LocalGenerator;
import soot.RefType;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.Unit;
import soot.Value;
import soot.jimple.Jimple;
import soot.jimple.Stmt;
import soot.jimple.infoflow.android.entryPointCreators.components.ComponentEntryPointCollection;
import soot.jimple.infoflow.entryPointCreators.SimulatedCodeElementTag;
import soot.jimple.infoflow.handlers.PreAnalysisHandler;
import soot.util.Chain;
import soot.util.HashMultiMap;
import soot.util.MultiMap;

public class IccInstrumenter implements PreAnalysisHandler {

	protected final Logger logger = LoggerFactory.getLogger(getClass());

	protected final String iccModel;
	protected final SootClass dummyMainClass;
	protected final ComponentEntryPointCollection componentToEntryPoint;

	protected IccRedirectionCreator redirectionCreator = null;

	protected final SootMethod smMessengerSend;
	protected final SootMethod smSendMessage;
	protected final Set processedMethods = new HashSet<>();
	protected final MultiMap instrumentedUnits = new HashMultiMap<>();

	public IccInstrumenter(String iccModel, SootClass dummyMainClass,
			ComponentEntryPointCollection componentToEntryPoint) {
		this.iccModel = iccModel;
		this.dummyMainClass = dummyMainClass;
		this.componentToEntryPoint = componentToEntryPoint;

		// Fetch some Soot methods
		smMessengerSend = Scene.v().grabMethod("");
		smSendMessage = Scene.v().grabMethod("");
	}

	@Override
	public void onBeforeCallgraphConstruction() {
		logger.info("[IccTA] Launching IccTA Transformer...");

		logger.info("[IccTA] Loading the ICC Model...");
		Ic3Provider provider = new Ic3Provider(iccModel);
		List iccLinks = provider.getIccLinks();
		logger.info("[IccTA] ...End Loading the ICC Model");

		// Create the redirection creator
		if (redirectionCreator == null)
			redirectionCreator = new IccRedirectionCreator(dummyMainClass, componentToEntryPoint);
		else
			redirectionCreator.undoInstrumentation();

		logger.info("[IccTA] Lauching ICC Redirection Creation...");
		for (IccLink link : iccLinks) {
			if (link.fromU == null) {
				continue;
			}
			redirectionCreator.redirectToDestination(link);
		}

		// Remove any potential leftovers from the last last instrumentation
		undoInstrumentation();

		// Instrument the messenger class
		instrumentMessenger();

		// Remove data that is no longer needed
		processedMethods.clear();

		logger.info("[IccTA] ...End ICC Redirection Creation");
	}

	/**
	 * Removes all units generated through instrumentation
	 */
	protected void undoInstrumentation() {
		for (Body body : instrumentedUnits.keySet()) {
			for (Unit u : instrumentedUnits.get(body)) {
				body.getUnits().remove(u);
			}
		}
		instrumentedUnits.clear();
	}

	protected void instrumentMessenger() {
		logger.info("Launching Messenger Transformer...");

		Chain applicationClasses = Scene.v().getApplicationClasses();
		Map> appClasses = new HashMap<>();
		Map handlerInner = new HashMap<>();

		for (Iterator iter = applicationClasses.snapshotIterator(); iter.hasNext();) {
			SootClass sootClass = iter.next();
			Map handlerClass = new HashMap<>();
			// We copy the list of methods to emulate a snapshot iterator which
			// doesn't exist for methods in Soot
			List methodCopyList = new ArrayList<>(sootClass.getMethods());
			for (SootMethod sootMethod : methodCopyList) {
				if (sootMethod.isConcrete()) {
					final Body body = sootMethod.retrieveActiveBody();

					// Mark the method as processed
					if (!processedMethods.add(sootMethod))
						continue;

					for (Iterator unitIter = body.getUnits().snapshotIterator(); unitIter.hasNext();) {
						Unit unit = unitIter.next();
						Stmt stmt = (Stmt) unit;
						// +++ collect handler fields signature
						if (stmt.containsFieldRef())
							if (stmt.getFieldRef().getType() instanceof RefType)
								if (((RefType) stmt.getFieldRef().getType()).getSootClass().getName()
										.contains("android.os.Handler")) {
									if (stmt.getUseBoxes().size() > 1)
										handlerInner.putIfAbsent(stmt.getFieldRef().getField().getSignature(),
												stmt.getUseBoxes().get(1).getValue().getType().toString());
									// use value as locator
									handlerClass.put(stmt.getDefBoxes().get(0).getValue(),
											stmt.getFieldRef().getField().getSignature());
								}
					}

				}

			}

			appClasses.putIfAbsent(sootClass, handlerClass);

		}
		// instrument the outerclass
		for (SootClass sc : appClasses.keySet()) {
			if (sc != null)
				generateSendMessage(sc, appClasses.get(sc), handlerInner);
		}
	}

	public void generateSendMessage(SootClass sootClass, Map appClasses,
			Map handlerInner) {
		if (appClasses.isEmpty() || handlerInner.isEmpty())
			return;
		List methodCopyList = new ArrayList<>(sootClass.getMethods());
		for (SootMethod sootMethod : methodCopyList) {
			if (sootMethod.isConcrete()) {
				final Body body = sootMethod.retrieveActiveBody();
				final LocalGenerator lg = Scene.v().createLocalGenerator(body);

				for (Iterator unitIter = body.getUnits().snapshotIterator(); unitIter.hasNext();) {
					Unit unit = unitIter.next();
					Stmt stmt = (Stmt) unit;
					if (stmt.containsInvokeExpr()) {
						SootMethod callee = stmt.getInvokeExpr().getMethod();

						// For sendMessage(), we directly call the respective handler.handleMessage()
						if (callee == smMessengerSend || callee == smSendMessage) {
							// collect the value for sendMessage()
							String hc = appClasses.get(stmt.getInvokeExpr().getUseBoxes().get(1).getValue());
							Set handlers = MessageHandler.v().getAllHandlers();
							for (SootClass handler : handlers) {
								// matching the handler and its signature
								if (hc != null && handlerInner.get(hc) == handler.getName()) {
									Local handlerLocal = lg.generateLocal(handler.getType());
									SootMethod hmMethod = handler.getMethod("void handleMessage(android.os.Message)");
									Unit callHMU = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(
											handlerLocal, hmMethod.makeRef(), stmt.getInvokeExpr().getArg(0)));
									callHMU.addTag(SimulatedCodeElementTag.TAG);
									body.getUnits().insertAfter(callHMU, stmt);
									instrumentedUnits.put(body, callHMU);
									break;
								}
							}
						}
					}

				}

			}
		}

	}

	@Override
	public void onAfterCallgraphConstruction() {
		//
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy