Skip to content

Commit

Permalink
1. fix the Application.attach may be hooked multi-times.
Browse files Browse the repository at this point in the history
2. reduce the log of Xposed.
  • Loading branch information
tiann committed Jun 19, 2018
1 parent 510f056 commit dfcf21c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 27 deletions.
2 changes: 1 addition & 1 deletion exposed-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies {
}

group = 'me.weishu.exposed'
version = '0.6.6'
version = '0.6.7'

apply plugin: 'com.novoda.bintray-release'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package de.robv.android.xposed;

import android.util.Log;

import java.lang.reflect.Member;

/**
* Created by weishu on 17/11/30.
*/
public class ExposedHelper {

private static final String TAG = "ExposedHelper";

public static void initSeLinux(String processName) {
SELinuxHelper.initOnce();
SELinuxHelper.initForProcess(processName);
}

public static boolean isIXposedMod(Class<?> moduleClass) {
XposedBridge.log("module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass());
XposedBridge.log("IXposedMod's classLoader : " + IXposedMod.class.getClassLoader());
Log.d(TAG, "module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass());
Log.d(TAG, "IXposedMod's classLoader : " + IXposedMod.class.getClassLoader());

return IXposedMod.class.isAssignableFrom(moduleClass);
}
Expand All @@ -30,4 +34,12 @@ public static void callInitZygote(String modulePath, Object moduleInstance) thro
param.startsSystemServer = false;
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
}

public static void beforeHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{
methodHook.beforeHookedMethod(param);
}

public static void afterHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{
methodHook.afterHookedMethod(param);
}
}
77 changes: 77 additions & 0 deletions exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package me.weishu.exposed;

import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.util.Log;

import java.lang.reflect.Member;
import java.lang.reflect.Method;

import de.robv.android.xposed.DexposedBridge;
import de.robv.android.xposed.ExposedHelper;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

/**
* @author weishu
* @date 2018/6/19.
*/
public final class CHAHelper {
private static final String TAG = "CHAHelper";

static class ApplicationHookProxy extends XC_MethodHook {

XC_MethodHook original;

ApplicationHookProxy(XC_MethodHook original) {
this.original = original;
}

@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
if (param.thisObject == null) {
throw new IllegalArgumentException("can not use static method!!");
}

if (param.thisObject instanceof Application) {
ExposedHelper.beforeHookedMethod(this.original, param);
} else {
Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject);
}
}

@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
if (param.thisObject == null) {
throw new IllegalArgumentException("can not use static method!!");
}

if (param.thisObject instanceof Application) {
ExposedHelper.afterHookedMethod(this.original, param);
} else {
Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject);
}
}
}

static XC_MethodHook.Unhook replaceForCHA(Member member, final XC_MethodHook callback) {

if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) {
XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA");
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback));
}

if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) {
XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA");
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback));

This comment has been minimized.

Copy link
@liangxiwei

liangxiwei May 6, 2020

为什么onCreate要改为attchBaseContext,本想hook onCreate方法,结果发现onCreate并没有执行完毕,在这里被attchBaseContext替代了,是作者写错了还是有其他原因?

}

return null;
}
}
33 changes: 9 additions & 24 deletions exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package me.weishu.exposed;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
Expand Down Expand Up @@ -36,7 +34,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -205,11 +202,11 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod
loadModuleConfig(rootDir, currentApplicationInfo.processName);

if (lastModuleList.second == null || !lastModuleList.second.contains(moduleApkPath)) {
log("module:" + moduleApkPath + " is disabled, ignore");
Log.i(TAG, "module:" + moduleApkPath + " is disabled, ignore");
return ModuleLoadResult.DISABLED;
}

log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT);
Log.i(TAG, "Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT);

if (!new File(moduleApkPath).exists()) {
log(moduleApkPath + " does not exist");
Expand Down Expand Up @@ -249,7 +246,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod
continue;
}
try {
log(" Loading class " + moduleClassName);
Log.i(TAG, " Loading class " + moduleClassName);
Class<?> moduleClass = mcl.loadClass(moduleClassName);

sModuleLoadListener.onLoadingModule(moduleClassName, currentApplicationInfo, mcl);
Expand Down Expand Up @@ -334,7 +331,10 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb
return null;
}

method = replaceForCHA(method);
XC_MethodHook.Unhook replaceUnhook = CHAHelper.replaceForCHA(method, callback);
if (replaceUnhook != null) {
return ExposedHelper.newUnHook(callback, replaceUnhook.getHookedMethod());
}

final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback);
return ExposedHelper.newUnHook(callback, unhook.getHookedMethod());
Expand All @@ -346,22 +346,7 @@ public static Object invokeOriginalMethod(Member method, Object thisObject, Obje
return DexposedBridge.invokeOriginalMethod(method, thisObject, args);
}

private static Member replaceForCHA(Member member) {

if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) {
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA");
return m;
}

if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) {
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA");
return m;
}

return member;
}

private static void initForXposedModule(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) {
InputStream inputStream = null;
Expand All @@ -370,7 +355,7 @@ private static void initForXposedModule(Context context, ApplicationInfo applica
inputStream = context.getAssets().open("xposed_init");
System.setProperty("epic.force", "true");
} catch (IOException e) {
log(applicationInfo.packageName + " is not a Xposed module");
Log.i(TAG, applicationInfo.packageName + " is not a Xposed module, do not init epic.force");
} finally {
closeSliently(inputStream);
}
Expand Down Expand Up @@ -440,7 +425,7 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl
if (!fakeVersionString.equals(oldVersion)) {
writeXposedProperty(xposedProp, fakeVersionString, true);
} else {
log("xposed version keep same, continue.");
Log.i(TAG, "xposed version keep same, continue.");
}
}

Expand Down

0 comments on commit dfcf21c

Please sign in to comment.