VirtulApp

查看任意一个系统服务的stub

public class PowerManagerStub extends BinderInvocationProxy {

关键点是类BinderInvocationProxy
这个类继承于MethodInvocationProxy
最后会调用到
mInvocationStub.addMethodProxy

Virtul有一个引擎叫做io.virtualapp:x

            VirtualCore.get().waitForEngine();

启动native的引擎
public void waitForEngine() {
ServiceManagerNative.ensureServerStarted();
}

看看点击一个应用的调用顺序


start一个activity

妈的 直接从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.(ActivityManagerNative.java:11)
05-15 08:36:26.857 14727 14727 I RefClass: at com.lody.virtual.client.hook.proxies.am.ActivityManagerStub.(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的呢??还是要看启动流程。

应该是做了动态代理的。但是动态代理需要静态变量才行啊。

可以看到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数据如下


image.png

最后会在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 singleton = new IPCSingleton<>(IActivityManager.class);

最后还搞了个动态代理

    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的操作。


image.png

看看启动应用的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);

你可能感兴趣的:(VirtulApp)