LBE平行空间检测(沙盒环境检测)
LBE平行空间的功能主要是以插件的形式加载第三方的应用并让其在自己的进程空间内运行。以满足需要在手机上同时运行两个相同App的需求。LBE的这种类似在沙盒环境内运行App的模式,给App的风控系统带来了一定的影响。
首先风控系统是为了唯一的识别一台设备,在这个过程中就需要获取大量的手机信息以及设备信息。而运行在沙盒环境内,使得系统获取到的参数变得不再可信,甚至无法获取,从而影响了整个设备指纹系统的数据完整性。
其次风控系统主要是帮助宿主识别设备的异常行为。而相同设备运行多个账号,且沙盒环境的多变性等会产生多种异常的行为,所以识别沙盒环境对风控系统有重要的意义。
同时LBE的沙箱环境无法完全隔离各个应用的权限,其他应用可以直接执行system(“cp ..”)命令将App目录拷贝走。这也带来了很大的安全问题。
1. LBE实现原理(1)Activity的启动:
LBE的实现理念主要是在自身的App端实现一个代理框架,作为一个中间层负责插件(第三方App)和系统的交互。其首先解决的最重要的问题就是Android App的所有Activity都需要在AndroidManifest.xml中事先进行声明,而LBE是无法知道第三方应用中的具体Activity名称的。为了解决这个问题,LBE使用了类似于”占坑“的概念的方式,就是提前在自身的AndroidManifest.xml中声明一系列不同类型的代理Activity,在第三方应用需要启动Activity时,LBE就作为代理向系统请求启动自身的代理Activity,同时得到系统响应后,LBE却在自身的进程空间内实现启动第三方应用中的Activity,并将其与代理Activity关联从而绕过系统对Activity启动的限制。
通过阅读Android源码可以知道Activity的启动请求主要通过 IActivityManager类型的binder句柄和system_server进行通信来完成。当第三方App调用startActivity时,LBE需要hook这个通信过程将目标target Activity替换成LBE的代理Activity。这个App端的通信句柄是一个静态变量,其获取的代码为
android 源码1234static public IActivityManager getDefault() { return gDefault.get();}
LBE主要通过替换这个gDefault来实现了Hook。其替换中主要使用到了Java的动态代理InvocationHandler
android 源码1234567new_binder = Proxy.newProxyInstance(old_binder.getClassLoader, new Class[]{binder.class}, new InvocationHandler(old_binder));//replacegDefault.set(new_binder);
LBE就是通过生成的动态代理来实现替换target activity的操作的,这样就实现了向系统请求代理Activity启动的过程。但是这个时候第三方App的Activity还没有真正启动。由Android的原理可知在startActivity时,App向system_server传递了一个callBack的binder对象,在系统通过校验允许Activity启动时,callBack就会被调用触发App端实现Activity的创建。
LBE要实现第三方的Activity启动,还需要hook Activity的创建过程,将target Activity再换回第三方App的Activity。
最终的callBack调用触发了performLaunchActivity函数的执行
android 源码12345678Activity performLaunchActivity( ActivityClientRecord r, Intent customIntent) { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); })
LBE主要通过hook掉了mInstrumentation对应的实现,来达到hook逻辑的。
(2)系统参数的修改
Android中的许多参数都是通过调用了Binder对象和系统进程通信来获取,如android_id就是通过ContentProvider服务来获取的,以及常用的getDeviceID()则对应phone_service中一个服务请求。
和activity_manager_service一样只要替换了所有服务的binder句柄就可以接管第三方App所有与系统的通信。其替换方式为将生成的代理binder句柄插入ServiceManager.sCache字典中,覆盖原有的系统句柄。
查看LBE的源码发现对于大部分的系统函数调用,LBE并非是一个透明的代理过程,而是返回了自己配置好的结果。如device_id和android_id都是LBE自己生成的。而附近wifi热点的扫描,LBE则直接返回了空。
2.沙盒的检测(1)Activity启动过程的hook检测
由前面的介绍,LBE主要替换了IActivityManager通信接口的gDefault变量,以及android.app.ActivityThread类中的mInstrumentation变量来实现第三方App的Activity启动。所以只要通过反射的形式获取两个静态变量就可获知App是否运行在沙盒环境之下。
android 源码12345678910111213141516Class classThread = Class.forName(“android.app.ActivityThread”); Method method = classThread.getMethod(“currentActivityThread”); Object threadObject = method.invoke(“null”); Filed instrumentFiled = threadObject.getFiled(“instrument”); Object instrument = instrumentFiled.get(threadObject); String instrument_class_string = instrument.getClassName(); If (thread_class_string != system_thread_string) { Log(“hooked”);}
获取两个变量之后,可以发现其已经被替换成了LBE中定义的类的实例了。如instrumentation从android.app.Instrumentation变为了com.lbe.doubleagent.client.f。
(2)系统服务hook的检测
由于第三方APP无法与系统直接通信,中间通过了LBE作为代理。所以可以通过获取系统服务通信句柄的方式检测hook。
android 源码123456Class serviceManager = Class.forName("android.os.ServiceManager");Method method = serviceManager.getMethod("getService", String.class);Object phone = method.invoke(serviceManager.newInstance(), "phone");If (phone.className != system_phone) {Log.i(“hooked”); }
实际获取的phone的className为:com.lbe.doubleagent.client.hook.BinderProxy。
而系统的为android.os.BinderProxy。
Android
2017 年 01 月 18 日