转自:https://www.jianshu.com/p/d47fdf3133c4
IPCBus
IPCBus
是虚拟app进程和ServerProcess
进程通信的核心。
public class IPCBus {
private static IServerCache sCache;
public static void initialize(IServerCache cache) {
sCache = cache;
}
private static void checkInitialized() {
if (sCache == null) {
throw new IllegalStateException("please call initialize() at first.");
}
}
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);
}
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));
}
}
IPCBus
主要有两个方法register
和get
,register
方法根据传入的class
对象构造ServerInterface
对象。
ServerInterface
public ServerInterface(Class<?> interfaceClass) {
this.interfaceClass = interfaceClass;
Method[] methods = interfaceClass.getMethods();
codeToInterfaceMethod = new SparseArray<>(methods.length);
methodToIPCMethodMap = new HashMap<>(methods.length);
for (int i = 0; i < methods.length; i++) {
int code = Binder.FIRST_CALL_TRANSACTION + i;
IPCMethod ipcMethod = new IPCMethod(code, methods[i], interfaceClass.getName());
codeToInterfaceMethod.put(code, ipcMethod);
methodToIPCMethodMap.put(methods[i], ipcMethod);
}
}
ServerInterface
构造函数里面通过反射获取methods
然后再根据Binder.FIRST_CALL_TRANSACTION
的自增去构造IPCMethod
实例(这个类后面会讲到,通过反射进行方法调用并将结果通过Parcel
进行回传),
接着通过键值code
,method
将IPCMethod
存储在两个Map
中。
TransformBinder
ServerInterface
实例构造完成后,再和传入的server
实例对象构造TransformBinder
。
public class TransformBinder extends Binder {
private ServerInterface serverInterface;
private Object server;
public TransformBinder(ServerInterface serverInterface, Object server) {
this.serverInterface = serverInterface;
this.server = server;
}
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {
reply.writeString(serverInterface.getInterfaceName());
return true;
}
IPCMethod method = serverInterface.getIPCMethod(code);
if (method != null) {
try {
method.handleTransact(server, data, reply);
} catch (Throwable e) {
e.printStackTrace();
}
return true;
}
return super.onTransact(code, data, reply, flags);
}
}
从代码可以看到TransformBinder
主要的方法是重载了Binder的onTransact
方法,这个方法通常是在IPC通信中接收消息然后进行回传处理的地方。
在这里我们又看到了IPCMethod
,是通过code
从ServerInterface
中获取,跟前面的serverInterface
构造就对应起来了,然后调用handleTransact
方法。
public void handleTransact(Object server, Parcel data, Parcel reply) {
data.enforceInterface(interfaceName);
Object[] parameters = data.readArray(getClass().getClassLoader());
if (parameters != null && parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
if (converters[i] != null) {
parameters[i] = converters[i].convert(parameters[i]);
}
}
}
try {
Object res = method.invoke(server, parameters);
reply.writeNoException();
reply.writeValue(res);
} catch (IllegalAccessException e) {
e.printStackTrace();
reply.writeException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
reply.writeException(e);
}
}
我们跟踪这个方法进去看到,果然就是反射调用在IPCMethod
的method
,并且将结果通过reply
写回请求进程完成IPC通信。
这样我们再回到IPCBus
中的register
方法中,在构造完这个TransformBinder
后调用sCache.join(serverInterface.getInterfaceName(), binder);
最终调用ServiceCache.addService
方法进行存储。
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);
}
});
我们再回到IPCBus
中的get(Class<?> interfaceClass)
方法,那其实就是调用ServiceManagerNative.getService()
的方法获取IBinder对象,并且返回interfaceClass
的proxy
类(参考上面的代码)。
JAVA的动态proxy
可以参考: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html(官方英文)
http://wiki.jikexueyuan.com/project/java-reflection/java-dynamic.html (官方英文)
https://www.cnblogs.com/LCcnblogs/p/6823982.html (简单易懂小示例)
我们再跟踪进去看下get(Class<?> interfaceClass)
方法中IPCInvocationBridge
这个类干了什么
public class IPCInvocationBridge implements InvocationHandler {
private ServerInterface serverInterface;
private IBinder binder;
public IPCInvocationBridge(ServerInterface serverInterface, IBinder binder) {
this.serverInterface = serverInterface;
this.binder = binder;
}
@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);
}
}
在重载InvocationHandler
的invoke
方法中我们又看到了熟悉的serverInterface
和IPCMethod
,然后调用IPCMethod
的callRmote
方法。
public Object callRemote(IBinder server, Object[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
Object result;
try {
data.writeInterfaceToken(interfaceName);
data.writeArray(args);
server.transact(code, data, reply, 0);
reply.readException();
result = readValue(reply);
if (resultConverter != null) {
result = resultConverter.convert(result);
}
} finally {
data.recycle();
reply.recycle();
}
return result;
}
这个方法主要就是发起一次IPC
请求,传入需要调用的类名称(data.writeInterfaceToken(interfaceName);
),参数( data.writeArray(args);
),对应的方法( server.transact(code, data, reply, 0);
),然后通过IBinder
的transact
进行IPC
调用。
到这里我们其实可以发现这和前面提到的handleTransact
方法对应起来,一个是请求,一个是应答处理。
我们再次回到IPCBus
的get(Class<?> interfaceClass)
方法,那其实这里的IBinder
应该就是TransformBinder
在调用进程的BinderProxy
,其他进程通过get
方法获取BinderProxy
来向TransformBinder
所在的进程发送IPC
调用。
到了这里大家可能会一头雾水,别急我们去看下sCache.query
也就是ServiceManagerNative.getService(serverName)
看看是不是返回的是BinderProxy
。
一次跨进程远程通信的过程是:
1.Client的代码调用BinderProxy.transact()
,发起远程调用。参数flags为0时方法阻塞,等待Server端对应方法返回后继续执行。参数flags为FLAG_ONEWAY
时立即返回。
2.Client中的transact()
调用传递式触发Server端Binder.transact()
的调用,进而调用Binder.onTransact()
。
3.Server端,Binder.onTransact()
中,子类的重写方法根据收到的code,执行对应业务逻辑,设置必要的返回数据到参数reply,然后Binder.transact()
方法返回。
4.Client端,BinderProxy.transact()
从阻塞状态返回,调用者解析得到必要的返回参数,继续执行。
ServiceManagerNative
public static IBinder getService(String name) {
if (VirtualCore.get().isServerProcess()) {
return ServiceCache.getService(name);
}
IServiceFetcher fetcher = getServiceFetcher();
if (fetcher != null) {
try {
return fetcher.getService(name);
} catch (RemoteException e) {
e.printStackTrace();
}
}
VLog.e(TAG, "GetService(%s) return null.", name);
return null;
}
在这里可以看到如果是ServerProcess
进程直接返回保存在ServiceCache
的TransformBinder
,如果是其他进程,则调用getServiceFetcher
,再通过其getService
进行返回。
private static IServiceFetcher getServiceFetcher() {
if (sFetcher == null || !sFetcher.asBinder().isBinderAlive()) {
synchronized (ServiceManagerNative.class) {
Context context = VirtualCore.get().getContext();
Bundle response = new ProviderCall.Builder(context, SERVICE_CP_AUTH).methodName("@").call();
if (response != null) {
IBinder binder = BundleCompat.getBinder(response, "_VA_|_binder_");
linkBinderDied(binder);
sFetcher = IServiceFetcher.Stub.asInterface(binder);
}
}
}
return sFetcher;
}
getServiceFetcher
方法主要是启动一个virtual.service.BinderProvider
的ContentProvider
并且调用"@"
方法。
<provider
android:name="com.lody.virtual.server.BinderProvider"
android:authorities="${applicationId}.virtual.service.BinderProvider"
android:exported="false"
android:process="@string/engine_process_name" />
BinderProvider
我们再来看看BinderProvider
这个类主要作用。
https://www.jianshu.com/p/5e893d814a53(ContentProvider 的简单示例)
public final class BinderProvider extends ContentProvider {
private final ServiceFetcher mServiceFetcher = new ServiceFetcher();
@Override
public boolean onCreate() {
Context context = getContext();
DaemonService.startup(context);
if (!VirtualCore.get().isStartup()) {
return true;
}
VPackageManagerService.systemReady();
IPCBus.register(IPackageManager.class, VPackageManagerService.get());
VActivityManagerService.systemReady(context);
IPCBus.register(IActivityManager.class, VActivityManagerService.get());
IPCBus.register(IUserManager.class, VUserManagerService.get());
VAppManagerService.systemReady();
IPCBus.register(IAppManager.class, VAppManagerService.get());
BroadcastSystem.attach(VActivityManagerService.get(), VAppManagerService.get());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
IPCBus.register(IJobService.class, VJobSchedulerService.get());
}
VNotificationManagerService.systemReady(context);
IPCBus.register(INotificationManager.class, VNotificationManagerService.get());
VAppManagerService.get().scanApps();
VAccountManagerService.systemReady();
IPCBus.register(IAccountManager.class, VAccountManagerService.get());
IPCBus.register(IVirtualStorageService.class, VirtualStorageService.get());
IPCBus.register(IDeviceInfoManager.class, VDeviceManagerService.get());
IPCBus.register(IVirtualLocationManager.class, VirtualLocationService.get());
return true;
}
@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;
}
...
private class ServiceFetcher extends IServiceFetcher.Stub {
@Override
public IBinder getService(String name) throws RemoteException {
if (name != null) {
return ServiceCache.getService(name);
}
return null;
}
@Override
public void addService(String name, IBinder service) throws RemoteException {
if (name != null && service != null) {
ServiceCache.addService(name, service);
}
}
@Override
public void removeService(String name) throws RemoteException {
if (name != null) {
ServiceCache.removeService(name);
}
}
}
}
BinderProvider
就启动了ServerProcess
进程,在这个进程里面我们看到通过BinderProvider
的onCreate
方法调用了大量的IPCBus.register
方法把一系列的VPackageManagerService
等对应的TransformBinder
保存了在这个ServerProcess
进程的ServiceCache
中。
我们再来看call
方法,返回了一个ServiceFetcher
通过键值"VA|binder"
进行存储的Bundle
。
我们再回到ServiceManagerNative
的getService
中,这个时候我们就明白了,如果是其他进程则先通过getServiceFetcher
获取ServiceFetcher
的BinderProxy
,然后再调用getService
方法获取对应的TransformBinder
在这个进程的BinderProxy
,然后通过Proxy
去调用ServerProcess
进程的对应VxxService
服务。这个时候其他VAppProcess
进程跟ServerProcess
进程的交互就通过这一系列IPCBus
,IPCMethod
,BinderTransformer
等来完成。
整个流程图如下:
InvocationStubManager
public final class InvocationStubManager {
...
void injectAll() throws Throwable {
for (IInjector injector : mInjectors.values()) {
injector.inject();
}
// XXX: Lazy inject the Instrumentation,
addInjector(AppInstrumentation.getDefault());
}
...
private void injectInternal() throws Throwable {
if (VirtualCore.get().isMainProcess()) {
return;
}
if (VirtualCore.get().isServerProcess()) {
addInjector(new ActivityManagerStub());
addInjector(new PackageManagerStub());
return;
}
if (VirtualCore.get().isVAppProcess()) {
addInjector(new LibCoreStub());
addInjector(new ActivityManagerStub());
addInjector(new PackageManagerStub());
addInjector(HCallbackStub.getDefault());
addInjector(new ISmsStub());
addInjector(new ISubStub());
addInjector(new DropBoxManagerStub());
addInjector(new NotificationManagerStub());
addInjector(new LocationManagerStub());
addInjector(new WindowManagerStub());
addInjector(new ClipBoardStub());
addInjector(new MountServiceStub());
addInjector(new BackupManagerStub());
addInjector(new TelephonyStub());
addInjector(new TelephonyRegistryStub());
addInjector(new PhoneSubInfoStub());
addInjector(new PowerManagerStub());
addInjector(new AppWidgetManagerStub());
addInjector(new AccountManagerStub());
addInjector(new AudioManagerStub());
addInjector(new SearchManagerStub());
addInjector(new ContentServiceStub());
addInjector(new ConnectivityStub());
if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR2) {
addInjector(new VibratorStub());
addInjector(new WifiManagerStub());
addInjector(new BluetoothStub());
addInjector(new ContextHubServiceStub());
}
if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
addInjector(new UserManagerStub());
}
if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
addInjector(new DisplayStub());
}
if (Build.VERSION.SDK_INT >= LOLLIPOP) {
addInjector(new PersistentDataBlockServiceStub());
addInjector(new InputMethodManagerStub());
addInjector(new MmsStub());
addInjector(new SessionManagerStub());
addInjector(new JobServiceStub());
addInjector(new RestrictionStub());
}
if (Build.VERSION.SDK_INT >= KITKAT) {
addInjector(new AlarmManagerStub());
addInjector(new AppOpsManagerStub());
addInjector(new MediaRouterServiceStub());
}
if (Build.VERSION.SDK_INT >= LOLLIPOP_MR1) {
addInjector(new GraphicsStatsStub());
addInjector(new UsageStatsManagerStub());
}
if (Build.VERSION.SDK_INT >= M) {
addInjector(new FingerprintManagerStub());
addInjector(new NetworkManagementStub());
}
if (Build.VERSION.SDK_INT >= N) {
addInjector(new WifiScannerStub());
addInjector(new ShortcutServiceStub());
addInjector(new DevicePolicyManagerStub());
}
if (Build.VERSION.SDK_INT >= 26) {
addInjector(new AutoFillManagerStub());
}
}
}
...
public <T extends IInjector, H extends MethodInvocationStub> H getInvocationStub(Class<T> injectorClass) {
T injector = findInjector(injectorClass);
if (injector != null && injector instanceof MethodInvocationProxy) {
// noinspection unchecked
return (H) ((MethodInvocationProxy) injector).getInvocationStub();
}
return null;
}
}
里面最主要的方法就是injectInternal
,从这里看到主进程(io.virtualapp
)没有进行hook
,ServerProcess(io.virtualapp:x)
对AMS
以及PMS
的BinderProxy
进行了hook
,而VAppProcess
则对大量的系统服务进行了hook
。
具体的hook
是通过MethodInvocationStub
,MethodInvocationProxy
,MethodProxy
这个基础框架来完成的,具体的原理也是生成需要hook
类的proxy
对象通过反射进行注入,这里就不在细说了。整个封装的Hook框架是在包名com.lody.virtual.hook下
两个进程一个是va的主进程(io.virtualapp
)通过ui处理安装和多开app等功能,一个ServerProcess
进程虚拟了VxxService
10个服务,来替代android
的systemservice
进程里的服务来完成和VAppProcess
进程的交互。