查看任意一个系统服务的stub
public class PowerManagerStub extends BinderInvocationProxy {
关键点是类BinderInvocationProxy
这个类继承于MethodInvocationProxy
最后会调用到
mInvocationStub.addMethodProxy
Virtul有一个引擎叫做io.virtualapp:x
VirtualCore.get().waitForEngine();
启动native的引擎
public void waitForEngine() {
ServiceManagerNative.ensureServerStarted();
}
看看点击一个应用的调用顺序
妈的 直接从binder就已经hook住了!!
内部虚拟了一套启动流程。
public ActivityManagerStub() {
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
}
这个定义了ActivityManage的代理对象,代理了所有的方法。
看看这个类的定义
public class ActivityManagerStub extends MethodInvocationProxy
看看他的构造函数
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
妈耶 构造函数好怪吗,没有看到ActivityManagerNative.getDefault有new啊!!
field.set(null, constructor.newInstance(realClass, field));
设置一个变量
相当与 (field = 使用构造函数)构造一个东西,这个构造函数有两个参数
public RefObject(Class> cls, Field field) throws NoSuchFieldException {
this.field = cls.getDeclaredField(field.getName());
this.field.setAccessible(true);
}
看上面,field实际上就是系统中ActivityManagerNative的field。。。卧槽,因为cls就是android.app.ActivityManagerNative
//在inject的时候构造了stub
05-15 08:36:26.857 14727 14727 I RefClass: at mirror.RefClass.load(RefClass.java:35)
05-15 08:36:26.857 14727 14727 I RefClass: at mirror.android.app.ActivityManagerNative.
05-15 08:36:26.857 14727 14727 I RefClass: at com.lody.virtual.client.hook.proxies.am.ActivityManagerStub.
05-15 08:36:26.857 14727 14727 I RefClass: at com.lody.virtual.client.core.InvocationStubManager.injectInternal(InvocationStubManager.java:118)
那他如何hook住binder的呢??还是要看启动流程。
应该是做了动态代理的。但是动态代理需要静态变量才行啊。
可以看到binder的回调时在
public class TransformBinder extends Binder {
这个东西是在类public class IPCBus {
中实例化的
public static void register(Class> interfaceClass, Object server) {
checkInitialized();
ServerInterface serverInterface = new ServerInterface(interfaceClass);
TransformBinder binder = new TransformBinder(serverInterface, server);
sCache.join(serverInterface.getInterfaceName(), binder);
}
IPCBus是在VirtualCore中实例化的。传入了一个IServerCache,看上去是缓存服务的。
IPCBus.initialize(new IServerCache() {
@Override
public void join(String serverName, IBinder binder) {
ServiceCache.addService(serverName, binder);
}
@Override
public IBinder query(String serverName) {
return ServiceManagerNative.getService(serverName);
}
});
怀疑是这句顶替了binder
IPCBus.register(IActivityManager.class, VActivityManagerService.get());
进而调用
sCache.join(serverInterface.getInterfaceName(), binder);
ServiceCache.addService(serverName, binder);
感觉就是把TransformBinder和VActivityManagerService连接起来了。
所以服务应该都是通过ServiceCache来找。
所以我们找一下点击后发生了什么,应该就知道了。
找点击的入口。
下面这个是入口,很快找到!!
mPresenter.launchApp(data);
data数据如下
最后会在LoadingActivity中启动应用
public static void launch(Context context, String packageName, int userId) {
Intent intent = VirtualCore.get().getLaunchIntent(packageName, userId);
if (intent != null) {
Intent loadingPageIntent = new Intent(context, LoadingActivity.class);
loadingPageIntent.putExtra(PKG_NAME_ARGUMENT, packageName);
loadingPageIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
loadingPageIntent.putExtra(KEY_INTENT, intent);
loadingPageIntent.putExtra(KEY_USER, userId);
context.startActivity(loadingPageIntent);
}
}
天,终于找到,原来上面的确是启动了LoadingActivity,但是在他的oncreate函数才真正去用假装的ActivityManager(VActivityManager)去拉起他!!!
VActivityManager.get().startActivity(intent, userId);
我们看看查找代理的过程
05-15 09:30:42.389 18979 19006 I IServerCache: querycom.lody.virtual.server.interfaces.IActivityManager
05-15 09:30:42.389 18979 19006 I IServerCache: java.lang.Throwable
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.client.core.VirtualCore$1.query(VirtualCore.java:194)
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.helper.ipcbus.IPCBus.get(IPCBus.java:35)
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.helper.ipcbus.IPCSingleton.get(IPCSingleton.java:19)
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.client.ipc.VActivityManager.getService(VActivityManager.java:52)
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.client.ipc.VActivityManager.startActivity(VActivityManager.java:58)
05-15 09:30:42.389 18979 19006 I IServerCache: at com.lody.virtual.client.ipc.VActivityManager.startActivity(VActivityManager.java:80)
05-15 09:30:42.389 18979 19006 I IServerCache: at io.virtualapp.home.LoadingActivity.lambda$onCreate$0$LoadingActivity(LoadingActivity.java:71)
有一个单例
private IPCSingleton
最后还搞了个动态代理
public static T get(Class> interfaceClass) {
checkInitialized();
ServerInterface serverInterface = new ServerInterface(interfaceClass);
IBinder binder = sCache.query(serverInterface.getInterfaceName());
if (binder == null) {
return null;
}
//noinspection unchecked
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new IPCInvocationBridge(serverInterface, binder));
}
动态代理有三个参数,一个是classloader,一个是class 的interface,第三个是代理对象。
put的时候是怎么put的??
IPCBus.register(IActivityManager.class, VActivityManagerService.get());
最终保存在sCache中,key是name,value是binder
就这里来说,key应该是com.lody.virtual.server.interfaces.IActivityManager,
value是public class VActivityManagerService implements IActivityManager
VActivityManagerService也是一个IActivityManager
终于来到了动态代理对象这里
public class IPCInvocationBridge implements InvocationHandler {
如何建立起来关系呢??
binder
天 找到了,通過IServiceFetcherd.aidl文件實現binder通信。
BinderProvider是服务端,而ServiceManagerNative是客户端。
获取代理的过程中,为什么要获取contentprovider??
private static ContentProviderClient acquireContentProviderClient(Context context, Uri uri) {
if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
return context.getContentResolver().acquireUnstableContentProviderClient(uri);
}
return context.getContentResolver().acquireContentProviderClient(uri);
}
返回bundle干嘛??
bundle怎么返回的,查看BinderProvider类
@Override
public Bundle call(String method, String arg, Bundle extras) {
if ("@".equals(method)) {
Bundle bundle = new Bundle();
BundleCompat.putBinder(bundle, "_VA_|_binder_", mServiceFetcher);
return bundle;
}
if ("register".equals(method)) {
}
return null;
}
所以最终client获得了ServiceFetcher的代理。。。ServiceFetcher的实体在类BinderProvider中。
最终在IPCInvocationBridge类中,用代理去执行方法
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
IPCMethod ipcMethod = serverInterface.getIPCMethod(method);
if (ipcMethod == null) {
throw new IllegalStateException("Can not found the ipc method : " + method.getDeclaringClass().getName() + "@" + method.getName());
}
return ipcMethod.callRemote(binder, args);
}
传递的binder实体是什么?
TransformBinder
服务端如何管理Activity???
原来是使用一个provider来表示一个进程
创建进程会进入public class StubContentProvider extends ContentProvider {
的call方法,如下
@Override
public Bundle call(String method, String arg, Bundle extras) {
if ("_VA_|_init_process_".equals(method)) {
return initProcess(extras);
}
return null;
}
private Bundle initProcess(Bundle extras) {
ConditionVariable lock = VirtualCore.get().getInitLock();
if (lock != null) {
lock.block();
}
IBinder token = BundleCompat.getBinder(extras,"_VA_|_binder_");
int vuid = extras.getInt("_VA_|_vuid_");
VClientImpl client = VClientImpl.get();
client.initProcess(token, vuid);
Bundle res = new Bundle();
BundleCompat.putBinder(res, "_VA_|_client_", client.asBinder());
res.putInt("_VA_|_pid_", Process.myPid());
return res;
}
后面调用VClientImpl的initProcess方法来执行新建程序。
实际VClientImpl就是一个客户端。
virtulcore的startActivity会进入到HookInvocationHandler,难道是动态代理了??
还有一个MethodInvocationStub??
在构造ActivityManagerStub的时候new 了他出来!!
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
貌似对gDefault进行了动态代理
Singleton.mInstance.set(gDefault, getInvocationStub().getProxyInterface());
getInvocationStub是什么?
看上去任何方法都会去到
MethodInvocationStub的HookInvocationHandler动态代理中处理。
代理方法貌似在
package com.lody.virtual.client.hook.proxies.am;
class MethodProxies {
可以看到流程控制是在MethodInvocationStub
if (useProxy && methodProxy.beforeCall(mBaseInterface, method, args)) {
res = methodProxy.call(mBaseInterface, method, args);
res = methodProxy.afterCall(mBaseInterface, method, args, res);
} else {
res = method.invoke(mBaseInterface, args);
}
最后掉用 if (ComponentUtils.isStubComponent(intent)) {
return method.invoke(who, args);
}
这个who就是原生的class android.app.ActivityManagerProxy
哪个过程启动正式的Activity呢?貌似是下面的过程。因为有gettype的操作。
看看启动应用的oncreate堆栈
05-15 22:54:35.601 6370 6370 I MainActivity: onCreate
05-15 22:54:35.601 6370 6370 I MainActivity: java.lang.Throwable
05-15 22:54:35.601 6370 6370 I MainActivity: at com.wenfengtou.wftgallery.MainActivity.onCreate(MainActivity.java:35)
05-15 22:54:35.601 6370 6370 I MainActivity: at android.app.Activity.performCreate(Activity.java:6682)
05-15 22:54:35.601 6370 6370 I MainActivity: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
05-15 22:54:35.601 6370 6370 I MainActivity: at com.lody.virtual.client.hook.delegate.InstrumentationDelegate.callActivityOnCreate(InstrumentationDelegate.java:244)
05-15 22:54:35.601 6370 6370 I MainActivity: at com.lody.virtual.client.hook.delegate.AppInstrumentation.callActivityOnCreate(AppInstrumentation.java:96)
05-15 22:54:35.601 6370 6370 I MainActivity: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619)
05-15 22:54:35.601 6370 6370 I MainActivity: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
看来他是hook了mInstrumentation这个东西了。
从这里inject进来了
addInjector(AppInstrumentation.getDefault());
基本上发现了他的指导思想了,就是每一个代理都有一个base,这个base来自与mirror。通过inject方法实现动态代理。
后续在启动一个页面会怎样,会再次startActivity,然后有启动c0的stub,然后在用inject的instrmentation去处理。
通过下面这句修改了进程名字
VirtualRuntime.setupRuntime(data.processName, data.appInfo);