查看任意一個(gè)系統(tǒng)服務(wù)的stub
public class PowerManagerStub extends BinderInvocationProxy {
關(guān)鍵點(diǎn)是類BinderInvocationProxy
這個(gè)類繼承于MethodInvocationProxy
最后會調(diào)用到
mInvocationStub.addMethodProxy
Virtul有一個(gè)引擎叫做io.virtualapp:x
VirtualCore.get().waitForEngine();
啟動native的引擎
public void waitForEngine() {
ServiceManagerNative.ensureServerStarted();
}
看看點(diǎn)擊一個(gè)應(yīng)用的調(diào)用順序
媽的 直接從binder就已經(jīng)hook住了M匦汀毕箍!
內(nèi)部虛擬了一套啟動流程帝美。
public ActivityManagerStub() {
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
}
這個(gè)定義了ActivityManage的代理對象,代理了所有的方法。
看看這個(gè)類的定義
public class ActivityManagerStub extends MethodInvocationProxy<MethodInvocationStub<IInterface>> {
看看他的構(gòu)造函數(shù)
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
媽耶 構(gòu)造函數(shù)好怪嗎,沒有看到ActivityManagerNative.getDefault有new澳跫Α!栏豺!
field.set(null, constructor.newInstance(realClass, field));
設(shè)置一個(gè)變量
相當(dāng)與 (field = 使用構(gòu)造函數(shù))構(gòu)造一個(gè)東西彬碱,這個(gè)構(gòu)造函數(shù)有兩個(gè)參數(shù)
public RefObject(Class<?> cls, Field field) throws NoSuchFieldException {
this.field = cls.getDeclaredField(field.getName());
this.field.setAccessible(true);
}
看上面,field實(shí)際上就是系統(tǒng)中ActivityManagerNative的field奥洼。巷疼。。臥槽灵奖,因?yàn)閏ls就是android.app.ActivityManagerNative
//在inject的時(shí)候構(gòu)造了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.<clinit>(ActivityManagerNative.java:11)
05-15 08:36:26.857 14727 14727 I RefClass: at com.lody.virtual.client.hook.proxies.am.ActivityManagerStub.<init>(ActivityManagerStub.java:44)
05-15 08:36:26.857 14727 14727 I RefClass: at com.lody.virtual.client.core.InvocationStubManager.injectInternal(InvocationStubManager.java:118)
那他如何hook住binder的呢嚼沿??還是要看啟動流程瓷患。
應(yīng)該是做了動態(tài)代理的骡尽。但是動態(tài)代理需要靜態(tài)變量才行啊。
可以看到binder的回調(diào)時(shí)在
public class TransformBinder extends Binder {
這個(gè)東西是在類public class IPCBus {
中實(shí)例化的
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中實(shí)例化的。傳入了一個(gè)IServerCache,看上去是緩存服務(wù)的寂曹。
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());
進(jìn)而調(diào)用
sCache.join(serverInterface.getInterfaceName(), binder);
ServiceCache.addService(serverName, binder);
感覺就是把TransformBinder和VActivityManagerService連接起來了。
所以服務(wù)應(yīng)該都是通過ServiceCache來找谭贪。
所以我們找一下點(diǎn)擊后發(fā)生了什么,應(yīng)該就知道了锦担。
找點(diǎn)擊的入口俭识。
下面這個(gè)是入口,很快找到6从妗鱼的!
mPresenter.launchApp(data);
data數(shù)據(jù)如下
最后會在LoadingActivity中啟動應(yīng)用
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函數(shù)才真正去用假裝的ActivityManager(VActivityManager)去拉起他T彻妗V钥臁!
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)
有一個(gè)單例
private IPCSingleton<IActivityManager> singleton = new IPCSingleton<>(IActivityManager.class);
最后還搞了個(gè)動態(tài)代理
public static <T> 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));
}
動態(tài)代理有三個(gè)參數(shù)姨俩,一個(gè)是classloader蘸拔,一個(gè)是class 的interface师郑,第三個(gè)是代理對象。
put的時(shí)候是怎么put的调窍?宝冕?
IPCBus.register(IActivityManager.class, VActivityManagerService.get());
最終保存在sCache中,key是name邓萨,value是binder
就這里來說地梨,key應(yīng)該是com.lody.virtual.server.interfaces.IActivityManager,
value是public class VActivityManagerService implements IActivityManager
VActivityManagerService也是一個(gè)IActivityManager
終于來到了動態(tài)代理對象這里
public class IPCInvocationBridge implements InvocationHandler {
如何建立起來關(guān)系呢缔恳?宝剖?
binder
天 找到了,通過IServiceFetcherd.aidl文件實(shí)現(xiàn)binder通信歉甚。
BinderProvider是服務(wù)端万细,而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的實(shí)體在類BinderProvider中砰诵。
最終在IPCInvocationBridge類中征唬,用代理去執(zhí)行方法
@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實(shí)體是什么?
TransformBinder
服務(wù)端如何管理Activity茁彭?总寒??
原來是使用一個(gè)provider來表示一個(gè)進(jìn)程
<provider
android:name="com.lody.virtual.client.stub.StubContentProvider$C47"
android:authorities="${applicationId}.virtual_stub_47"
android:exported="false"
android:process=":p47" />
創(chuàng)建進(jìn)程會進(jìn)入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;
}
后面調(diào)用VClientImpl的initProcess方法來執(zhí)行新建程序摄闸。
實(shí)際VClientImpl就是一個(gè)客戶端。
virtulcore的startActivity會進(jìn)入到HookInvocationHandler妹萨,難道是動態(tài)代理了年枕??
還有一個(gè)MethodInvocationStub乎完?熏兄?
在構(gòu)造ActivityManagerStub的時(shí)候new 了他出來!!
super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
貌似對gDefault進(jìn)行了動態(tài)代理
Singleton.mInstance.set(gDefault, getInvocationStub().getProxyInterface());
getInvocationStub是什么摩桶?
看上去任何方法都會去到
MethodInvocationStub的HookInvocationHandler動態(tài)代理中處理桥状。
代理方法貌似在
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);
}
這個(gè)who就是原生的class android.app.ActivityManagerProxy
哪個(gè)過程啟動正式的Activity呢?貌似是下面的過程硝清。因?yàn)橛術(shù)ettype的操作辅斟。
看看啟動應(yīng)用的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這個(gè)東西了。
從這里inject進(jìn)來了
addInjector(AppInstrumentation.getDefault());
基本上發(fā)現(xiàn)了他的指導(dǎo)思想了芦拿,就是每一個(gè)代理都有一個(gè)base士飒,這個(gè)base來自與mirror。通過inject方法實(shí)現(xiàn)動態(tài)代理防嗡。
后續(xù)在啟動一個(gè)頁面會怎樣变汪,會再次startActivity,然后有啟動c0的stub蚁趁,然后在用inject的instrmentation去處理裙盾。
通過下面這句修改了進(jìn)程名字
VirtualRuntime.setupRuntime(data.processName, data.appInfo);