来看看这个应用怎么做模拟器检测的

某次系统发版后,有用户反馈说一个自己下载安装的三方应用打不开,点了以后没有反应。应用是一个并不多见的视频类应用,像这种小应用出现问题是很常见的。但是测试报告说我们旗下几个机型,只有一个比较古早的机型会有这种问题,一开始接手这个问题的同事也没有看出来问题原因,因此抽出时间瞅瞅。

首先看看现象,应用安装后,在桌面点击打开,点击打开的时候连启动动画、Splash页面在内的任何画面、窗口、Activity都没有出现,说明"崩溃"的很早。但诡异的是,应用的进程还在,没有崩溃日志,并且pid没有变化,能确认不是崩溃后重启,可以断定没有发生崩溃。既然应用没有崩溃,又没有显示出画面,那先看看应用启动到哪一步了:

通过events日志可以确认应用是到了onCreate()的,旧Activity正常退出,新Activity(即问题应用的Activity)正常启动。但是在问题Activity resume完成之前,它就退出了(wm_finish_activity),并且原因是应用自己请求的退出(app-request)。

这就有意思了,看来这个问题要分析一下应用的逻辑。挂上调试器,定位一下应用Activity退出时的堆栈:

看,SplashActivity的onCreate()里面调用了initData(),这个initData()里面调用了finish()。由于该Activity是Splash Activity,退出后没有跳转到Main Activity,这种情况下应用不会显示出任何画面,因此让用户感受到就是点了之后没有反应,点不动,点不开。

initData()是问题的关键,它调用finish()的逻辑决定了应用是否正常启动。逆向一下这个app,定位关键逻辑:

可见前两个if case都可能导致finish(),其中第二个case EmulatorDetector,一看就没问题,毕竟咱是真机,不可能让你检测为模拟器吧?

第一个if case SecurityUtil非常简单:

但是也很诡异,因为它通过查找su来检测设备是否root,我们的发行版本是不会有这个东西的,必然不会让if case判断为true,也就不可能是导致finish()的原因。那只能硬着头皮来看第二个if case:

EmulatorDetector通过检测了模拟器特征,包括模拟器特有的文件、系统属性、包名、sdk等。这部分检测比较常规,在我们的发行版本不可能检测为模拟器。逐一排查后发现一个非主流的、也是导致问题根因的检测:

这个检测的逻辑非常简单,就是查看一下设备有没有光线传感器(type为5)。App的逻辑很简单,模拟器是没有光线传感器的,App的思路是"无光线传感器那就是模拟器"。这里设备如果没有光线传感器(我们这台古早的设备还真的没有)就会return true->if case里面会进入finish()。

实锤一下是这个东西导致的问题。我们的设备因年代古早加上场景特殊,确实没有光线传感器,返回为null理所应当。由于App在这里获取的传感器并没有实际使用,仅仅用于判空,因此我们构造一个空的Sensor返回给应用,是足够安全且有效的(当然,仅用作实锤这个问题)。在getDefaultSensor()这个方法这里返回一个空的Sensor实例:

放入系统验证一下,很快啊,应用就成功启动了。真相终于大白,应用想出来这一招非常得劲,确实能检测到一些模拟器,但是说不定也会错杀呢?

相关推荐
androidwork32 分钟前
Android LinearLayout、FrameLayout、RelativeLayout、ConstraintLayout大混战
android·java·kotlin·androidx
每次的天空33 分钟前
Android第十三次面试总结基础
android·面试·职场和发展
wu_android35 分钟前
Android 相对布局管理器(RelativeLayout)
android
李斯维2 小时前
循序渐进 Android Binder(二):传递自定义对象和 AIDL 回调
android·java·android studio
androidwork3 小时前
OkHttp 3.0源码解析:从设计理念到核心实现
android·java·okhttp·kotlin
像风一样自由3 小时前
【001】frida API分类 总览
android·frida
casual_clover3 小时前
Android 之 kotlin 语言学习笔记四(Android KTX)
android·学习·kotlin
移动开发者1号5 小时前
Android 大文件分块上传实战:突破表单数据限制的完整方案
android·java·kotlin
移动开发者1号5 小时前
单线程模型中消息机制解析
android·kotlin
每次的天空8 小时前
Android第十五次面试总结(第三方组件和adb命令)
android