public void apply() { try { for (String clazzBunch : CLASSES_TO_HOOK) { String[] classesToHook = clazzBunch.split(","); for (final String className : classesToHook) { Log.d(this.getClass().getName(), "LETS HOOK -" + className + "-"); MS.hookClassLoad( className, new MS.ClassLoadHook() { public void classLoaded(Class<?> hookedClass) { Log.d(this.getClass().getName(), "LOCATED CLASS: " + className); for (final Method method : hookedClass.getDeclaredMethods()) { String arguments = ""; StringBuilder parameters = new StringBuilder(); if (method.getParameterTypes().length > 0) { for (Class parameterClazz : method.getParameterTypes()) { parameters.append("," + parameterClazz.getName()); } arguments = parameters.substring(1); } final String methodSignature = className + "." + method.getName() + "(" + arguments + ")"; if (Modifier.isAbstract(method.getModifiers())) { Log.d(this.getClass().getName(), "IGNORED METHOD: " + methodSignature); } else { try { Log.d(this.getClass().getName(), "HOOKED METHOD: " + methodSignature); MS.hookMethod( hookedClass, method, new MS.MethodAlteration() { public Object invoked(Object capturedInstance, Object... args) throws Throwable { try { throw new Exception("==> STACK_TRACE_PRINT"); } catch (Exception e) { Log.i(this.getClass().getName(), "\n\n\n\n\n\n\n\n\n\n\n\n"); Log.i( this.getClass().getName(), "STACK_TRACE_START => " + methodSignature); Log.i(this.getClass().getName(), "\n\n\n\n\n\n\n\n\n\n\n\n"); e.printStackTrace(); Log.i(this.getClass().getName(), "\n\n\n\n\n\n\n\n\n\n\n\n"); Log.i( this.getClass().getName(), "STACK_TRACE_END => " + methodSignature); Log.i(this.getClass().getName(), "\n\n\n\n\n\n\n\n\n\n\n\n"); } try { String arguments = ""; StringBuilder stringBuilder = new StringBuilder(); if (args.length > 0) { for (int i = 0; i < args.length; i++) { stringBuilder.append("," + args[i]); } arguments = stringBuilder.substring(1); } Log.i( HOOK_LOG_BREADCRUMB, "ENTER " + methodSignature + PARAMETERS_SEPARATOR + arguments); Object result = this.invoke(capturedInstance, args); Log.i(HOOK_LOG_BREADCRUMB, "EXIT " + methodSignature); return result; } catch (Exception e1) { Log.d( "SubstratePlugin", "Error level 1-a caught: " + e1.getMessage()); } // if the previous code fails, then we try to keep at least the // trace try { Log.i( HOOK_LOG_BREADCRUMB, "ENTER " + methodSignature + PARAMETERS_SEPARATOR); Object result = this.invoke(capturedInstance, args); Log.i(HOOK_LOG_BREADCRUMB, "EXIT " + methodSignature); return result; } catch (Exception e1) { Log.d( "SubstratePlugin", "Error level 1-b caught: " + e1.getMessage()); // last attempt to recovery from an error return this.invoke(capturedInstance, args); } } }); } catch (Exception e2) { Log.d("SubstratePlugin", "Error level 2 caught: " + e2.getMessage()); } } } } }); } } } catch (Throwable e3) { Log.d("SubstratePlugin", "Error level 3 caught: " + e3.getMessage()); } }
protected void hookMethods( final HookerListener listener, final String className, final Map<String, Integer> methodsToHook) { MS.hookClassLoad( className, new MS.ClassLoadHook() { @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void classLoaded(final Class<?> classToHook) { Map<GenericDeclaration, String> allMethods = new HashMap<GenericDeclaration, String>(); try { Class clz = Class.forName(className); ApplicationConfig.setPackageName( new StringBuilder(clz.getPackage().getName()) .append(".") .append(clz.getSimpleName()) .toString()); for (Method method : clz.getMethods()) { allMethods.put(method, method.getName()); } } catch (ClassNotFoundException e1) { e1.printStackTrace(); } Iterator iterator = allMethods.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); final Method method = (Method) entry.getKey(); final String methodName = (String) entry.getValue(); if (!methodsToHook.containsKey(methodName)) continue; Log.v( Config.DEBUG_TAG, new StringBuilder("start to hook ") .append(className) .append(".") .append(methodName) .toString()); final int intrusiveLevel = methodsToHook.get(methodName); final MS.MethodPointer<Object, Object> old = new MethodPointer<Object, Object>(); MS.hookMethod( classToHook, method, new MS.MethodHook() { @Override public Object invoked(Object resources, Object... args) throws Throwable { InterceptEvent event = new InterceptEvent( hookerName, intrusiveLevel, System.identityHashCode(resources), "unknown", className, methodName); if (args != null) { for (Object arg : args) { if (arg != null) { StringBuilder argValue = new StringBuilder(); if (arg.getClass().isArray() && !arg.getClass().getName().equals("[B")) { argValue.append("["); int len = Array.getLength(arg); for (int i = 0; i < len - 1; i++) { argValue.append(Array.get(arg, i)).append(","); } argValue.append(Array.get(arg, len - 1)); argValue.append("]"); } else { argValue.append(arg.toString()); } event.addParameter(arg.getClass().getName(), argValue.toString()); } else { event.addParameter(null, null); } } } if (ApplicationConfig.getPackageName() != null) { event.setPackageName(ApplicationConfig.getPackageName()); } final Context appContext = ApplicationConfig.getContext(); if (appContext != null) { doBindService(appContext); Log.v( Config.DEBUG_TAG, new StringBuilder("hook context from****************>") .append(appContext.getPackageName()) .toString()); } if (listener != null) { listener.before(className, method, resources, event); } Object result = old.invoke(resources, args); if (result != null) { event.setReturns(result.getClass().getName(), result.toString()); } else { event.setReturns(null, null); } Log.v(Config.DEBUG_TAG, event.toJson()); insertEvent(event); if (listener != null) { listener.after(className, method, resources, event); } return result; } }, old); } } }); }