恶意软件检测之高效MonkeyTest
背景
Monkey测试是Google开发的、安卓系统自带的自动化测试工具。正如其名,monkey工具会像猴子一样对手机屏幕“乱点一通”,随机触发点击、滑动、组件启动等事件。Monkey本来是用作应用压力测试的,但是近年来(也不是近年了,一直都是),几乎所有的动态恶意软件检测相关的论文用的自动化测试工具都是monkey(包括我正在做的,嘿嘿)。所以觉得有必要总结一下如何高效利用Monkey测试。
Monkey Test命令
monkey的命令很简单,就是
adb shell monkey + 一些参数
我上网扒拉了一下相关的参数表,如下:
比较有趣的是monkey通过–throttle指定测试频率(ms为单位),也可以指定随机事件数,并通过这俩参数控制整个Monkey测试的总时间(两个参数乘一下就行了),并没有直接的时间限制参数。而发送事件类型里的trackball在手机行业基本没人用了,所以这个事件类型在测试里也很少被用到,其他参数按需设置即可。
测试高效化
monkey测试仅仅是这些简单的命令吗?当然不是。通过adb monkey我们可以让手机生成随机触发事件了,但是,总有一些意外触发的事件会影响monkey测试的效率。比如某一次motion操作可能会下拉状态栏,那么接下来的所有touch操作都会按到状态栏上,好点的结果是无事发生,浪费一点时间,而比较糟糕的情况下,monkey会错误的关闭状态栏里的wifi、流量等必要设置,造成整个自动化测试的结果误差较大。这种意外事件首先影响测试效率,其次,无论测试者是在做压力测试还是动态恶意软件检测,都会影响其测试精确度。
接下来总结一些测试过程中遇到的、使得Monkey测试高效化的trick:
禁用输入键盘
输入键盘是影响Monkey测试效率的一点,一旦打开键盘,monkey的事件触发全部点到按键上,时间就全部浪费了。虽然有些事件确实要输入一些内容才能触发,但是考虑一般情况,还是禁用键盘为好。指令为:
adb shell ime disable com.android.inputmethod.latin/.LatinIME
状态栏+导航栏隐藏
除了键盘,双栏——状态栏+导航栏也是
一般来说可以通过adb命令
adb shell settings put global policy_control immersive.full=*
来隐藏导航栏+状态栏,但是后来发现 monkey test中的 –pct-motion(滑动操作)会重新唤起双栏,所以这个方法不太可行。后来转念一想,我直接让屏幕显示区域里没有双栏的位置不就行了吗?于是考虑以下命令:
adb shell wm overscan //设置显示区域大小,坐标值为左、上、右、下
当参数设置为 0,-210,0,-210 时可以永久隐藏双栏,0,0,0,0恢复,也就是说隐藏adb命令为:
adb shell wm overscan 0,-210,0,-210
经测试此方法有效
自动授权
这个是比较重要的一环,因为安卓手机是经典的基于权限的系统,所以在大规模自动化测试时,每新安装一个app,刚打开时必定会弹权限请求窗口,如果不自动授权的话,会浪费很多时间。在pixel 3xl上我一共碰到过两种权限检查情况,第一种是最常见的:
第二种是要full control的(比较危险,但是自动化测试要的就是危险哈哈)
那么怎么自动授权呢,一个很直观的方法是获取到“CONTINUE”和”ALLOW“按钮的位置,然后使用adb模拟点击该位置坐标即可。那么为了获取按钮坐标,可以dump出当前页面的Xml,然后从Xml中识别对应元素坐标。
以”ALLOW“为例,使用命令
adb shell "uiautomator dump && cat /sdcard/window_dump.xml"
将当前ui dump到window_dump.xml并读取,然后找到ALLOW按钮相关信息
node里几个关键信息是text、resource-id(凭借这两个信息即可确定是allow的node),然后bounds变量给出了ALLOW按钮的左上和右下坐标信息。模拟按键只需要按这两个坐标的均值即可,比如对于这里的[93,2075],[1347,2271],中值坐标为[720,2173],输入命令
adb shell input tap 720,2173
即可顺利触发ALLOW按钮
版本警告
压力测试可能不需要,但是动态恶意软件检测可能需要测试年份比较老的app,这些app的版本很旧,在比较新的安卓版本下可能会有如下警告信息:
这里的话和上面的自动授权一样,读取XML并模拟点击一次即可。