Android中模拟点击类软件实现原理探究

本文来自网易云社区


简介

按键触摸类模拟点击软件最早开始于PC时代,指的是可以通过设置、脚本控制等方式去实现模拟点击,解放双手,达到自动化操作的目的。在Android中,模拟点击对应的就是触发屏幕点击事件,多用于游戏中完成自动化操作、应用中抢红包等操作,随着现在的技术更新,一些模拟点击实现的方式也开始使用了一些特殊的技巧。

从触屏到执行

首先看一个完整点击操作背后的流程(图1来自网络):


图1 屏幕点击完整流程


从用户点击屏幕开始,触发中断,在内核态执行以下流程,见图2:


图2 从内核态过渡到用户态

直到进入用户态,开始访问设备驱动文件,进行事件的监听和分发操作,一步步走到UI层显示给用户。由整个流程可以看出用户态会走很多下发流程,如果在这些过程中能够构造点击事件传入,依然能够在UI层显示给用户。

实现模拟点击的方式

1、 Android单元测试Instrumentation框架,局限性比较严重,实现上有很多限制;

2、 AccessibilityService辅助功能类,可以监听手机的焦点、窗口、按钮点击等,只需要给予辅助功能相应的权限即可,无需root权限。缺点就是只适合一些定制化的功能,而且如游戏类的没有太多的控件,无法去很好的捕捉监控,当然该方式无需root权限的特点让其应用的场景也很多,如抢红包软件、应用市场自动化安装,都是通过它实现的;

3、 通过sendevent命令实现,向该命令传入参数设备路径名(/dev/input/event*)、事件类型、事件代码、事件值即可,通过getevent命令可以查看对应哪个设备是触摸屏驱动,但需注意的是,这些设备文件设置的权限是普通应用权限是无法访问的(见图3),因此需要root权限去实现;

图3 输入设备文件属性

4、 原理和3一样,只是利用代码实现,通过ioctl向设备文件中直接写入数据,如上,需要使用root权限去执行,目前市面上触摸精灵类的应用就是通过该方式实现的;

5、 找到从设备驱动文件开始到UI显示的过程中的某一个节点,构造点击事件传入。如果是应用中实现的话这种方式不难,但由于触摸类应用都是第三方的,因此实现的方式需要一些考究,在分析的过程中发现有一些厂商通过这种方式实现的,如触动精灵。

(注:只列举一些和本文涉及分析有关的模拟点击方法)

控制模拟点击的逻辑

模拟点击的方式实现了,但还缺少对点击时机的控制,多久点击?哪里点击?点击方式?这些是保证模拟点击有效性的根本。

1、应用类的模拟点击逻辑控制

通过辅助功能AccessibilityService实现的应用模拟点击中,可以通过推送消息判断是否需要进入到相应应用中,还可以获取到控件的信息,如文字,来判断是否为需要点击的控件,由于是系统自带的功能,已经有很好的接口去实现了。

2、游戏类的模拟点击逻辑控制

而如触摸精灵类应用,针对游戏的模拟点击没有这样的接口,因此他们的实现主要通过脚本去构造点击的逻辑,让脚本的解释器去解析参数传递给相应功能接口实现点击过程,这里以触动精灵为例,逻辑实现的流程大概如下:

①用户编写lua脚本或者通过屏幕录制lua脚本;

②程序启动后加载lua脚本,通过程序中的lua解释器去执行脚本内容,获取相应参数;

③将相应参数构造为规范的结构信息交由模拟点击功能代码去解析,并触发点击事件。


翻阅了他们的脚本开发文档,功能非常强大,包含了延时、点击、区域查色、文字识别等等功能,足够完成游戏内的许多功能。

逆向分析模拟点击的具体实现

原理和流程都清楚了,接下来具体看实例代码是如何实现的。

按键精灵:

采用比较简单的策略,也是市面上普遍的应用,直接向设备文件写入数据,具体分析功能代码及截图:

① 更改设备文件权限


图5 更改设备文件权限

② 打开设备、写入数据(C实现代码)


图6 向设备文件写入点击事件的示例代码

触动精灵:

分析老版本的触动精灵发现其实也是通过向设备直接写入的形式实现,不过在最新的版本中实现的方式比较特殊,是在触摸事件中间传递过程的一个节点上进行了模拟构造触摸事件,然后传入,下面分析他的具体过程。

① 获取root权限执行命令启动子进程

图7 ROOT权限启动进程

② 在文件中找到执行的命令,发现其实是通过app_process命令执行了一个jar包,那么关键实现就在jar包中了


图8 执行jar命令

③ 关键点1:反射获取injectInputEvent方法,该方法正是触摸事件中间流程会经过的一个点,正是它找到的切入点


图9 反射获取injectInputEvent方法

④ 关键点2:既然反射调用就能执行点击,为何还需要root权限执行呢?查看源码,发现在执行的过程中经过native层时,在事件分发的代码中对权限做了判断,需要Uid为0或是否有injectevent的权限


图10 判断Uid是否有权限执行

⑤ 关键点3:构造motionevent对象,反射调用injectinputevent方法执行


图11 构造motionevent执行injectinputevent

到此,实现的具体过程大概如此,方式比较简单也较新颖,也增加了对识别这种模拟点击软件的难度,一些更细节的地方没有列举出来(如injectinputevent执行流程),可以参考相关资料或者源码查看。

如何甄别模拟点击与真实点击

了解清楚市面上触摸类应用的实现原理后,针对它们的特征进行提取简单归纳了一些检测办法。从目前的分析看,实现完全的甄别比较困难,因为处于劣势的一方(没有ROOT权限),相当于拿着弓箭与敌人的手枪对击,简单列举一下目前检测的思路,可以通过特征和行为两方面进行检测,特征检测,比较简单的如进程名称、一些文件名来甄别,缺点不能覆盖所有情况;行为检测,通过对已知模拟点击的行为进行甄别,包括不限于特殊设备文件、执行点击的流程以及和人为操作的区别。

结尾

本文主要介绍了安卓模拟点击相关的实现原理,以及一些调研的检测方式,如有错误之处,请指正。


本文已由作者李沛然授权网易云社区发布。

编辑于 2018-06-04

文章被以下专栏收录