正文
{
return
gDefault.get();
}
private
static
final
Singleton<IActivityManager> gDefault =
new
Singleton<IActivityManager>() {
protected
IActivityManager
create
()
{
IBinder b = ServiceManager.getService(
"activity"
);
if
(
false
) {
Log.v(
"ActivityManager"
,
"default service binder = "
+ b);
}
IActivityManager am = asInterface(b);
if
(
false
) {
Log.v(
"ActivityManager"
,
"default service = "
+ am);
}
return
am;
}
};
getDefault方法返回了IActivityManager类型的对象,IActivityManager借助了Singleton类来实现单例,而且gDefault又是静态的,因此IActivityManager是一个比较好的Hook点。
Android8.0的Activity的启动会调用ActivityManager的getService方法,如下所示。
frameworks/base/core/java/android/app/ActivityManager.java
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
同样的,getService方法返回了了IActivityManager类型的对象,并且IActivityManager借助了Singleton类来实现单例,确定了无论是Android7.0还是Android8.0,IActivityManager都是比较好的Hook点。Singleton类如下所示,后面会用到。
frameworks/base/core/java/android/util/Singleton.java
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
由于Hook需要多次对字段进行反射操作,先写一个字段工具类FieldUtil:
FieldUtil.java
public class FieldUtil {
public static Object getField(Class clazz, Object target, String name) throws Exception {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(target);
}
public static Field getField(Class clazz, String name) throws Exception{
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field;
}
public static void setField(Class clazz, Object target, String name, Object value) throws Exception {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(target, value);
}
其中setField方法不会马上用到,接着定义替换IActivityManager的代理类IActivityManagerProxy,如下所示。
public class IActivityManagerProxy implements InvocationHandler {
private Object mActivityManager;
private static final String TAG = "IActivityManagerProxy";
public IActivityManagerProxy(Object activityManager) {
this.mActivityManager = activityManager;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if ("startActivity".equals(method.getName())) {
Intent intent = null;
int index = 0;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Intent) {
index = i;
break;
}
}
intent = (Intent) args[index];
Intent subIntent = new Intent();
String packageName = "com.example.liuwangshu.pluginactivity";
subIntent.setClassName(packageName,packageName+".StubActivity");
subIntent.putExtra(HookHelper.TARGET_INTENT, intent);
args[index] = subIntent;
}
return method.invoke(mActivityManager, args);
}
}
Hook点IActivityManager是一个接口,建议采用动态代理。在注释1处拦截startActivity方法,接着获取参数args中第一个Intent对象,它是原本要启动插件TargetActivity的Intent。注释2、3处新建一个subIntent用来启动的StubActivity,注释4处将这个TargetActivity的Intent保存到subIntent中,便于以后还原TargetActivity。注释5处用subIntent赋值给参数args,这样启动的目标就变为了StubActivity,用来通过AMS的校验。
最后用代理类IActivityManagerProxy来替换IActivityManager,如下所示。
HookHelper.java
public class HookHelper {
public static final String TARGET_INTENT = "target_intent";
public static void hookAMS() throws Exception {
Object defaultSingleton=null