概述
screenshot_u3d.png分析
因为只有2条路可以拿到fps值,而DUMP权限那条是根本行不通的,因为三方app是不可能有系统签名的何况还是这么多个系统。所以真相应该只有一个,就是通过shell权限那条路拿到的。
进程分析
一个三方app如何能以shell权限运行呢?答案当然是: 不可能
想要获取进程之间的秘密,还是先让我们来看看启动GameBench后,多了哪些进程吧。
在运行GameBench前,使用命令adb shell ps | tee xxx/xxx/before.pid
将所有的进程信息保存到before.pid文件中
然后在打开GameBench,并启动我们的Unity3d demo,当fps显示出来后再使用命令adb shell ps | tee xxx/xxx/after.pid
保存所有的进程信息
然后使用对比工具BeyondCompare对比前后2支文件,接下来就是见证奇迹的时刻。
除了多了我们的Unity3d进程外,还多了如下的一个进程
shell 9007 1 18652 3992 ffffffff f74bd9ac S /data/local/tmp/gbhelperdaemon
是不是很激动?让我们来看看这个gbhelperdaemon是什么东西
gbhelperdaemon
从名字看,这应该是一个daemon程序,gb就是gamebench的缩写
我们知道它的位置在/data/local/tmp/ 我们先看看它是什么
- 首先查看权限
ls -l /data/local/tmp/gbhelperdaemon
输出结果如下
-rwxrwxrwx shell shell 34276 2016-08-23 15:13 gbhelperdaemon
注意:这里是777的权限,并且owner和group都是shell
- 先使用如下命令将gbhelperdaemon pull出来
adb pull /data/local/tmp/gbhelperdaemon xxx/xxx/
- 查看它的格式
file xxx/xxx/gbhelperdaemon
输出结果如下
/home/hly/work/gbhelperdaemon: ELF 32-bit LSB shared object, ARM, version 1 (SYSV),
dynamically linked (uses shared libs), stripped
可以看出这是一个32位的ELF文件
- 以文本的方式编辑该文件,给出部分重要截图
gb_efl_screenshot.png
gb_efl_screenshot2.png
这里有4个关键的地方已经用红色对话框标示出来。这个ELF文件应该至少会做3件事,首先开启了一个线程,然后使用了socket或者pipe来进行RPC。RPC传递的数据就是使用的dumpsys surfaceflinger --latency - gen.sh
查看/data/local/tmp/目录 ,你还会发现多了一个文件叫做gen.sh,内容很简单
#!/bin/sh
/data/local/tmp/gbhelperdaemon &
推测
综上所述,gamebench的实现原理应该是这么的
- 首先将gen.sh和gbhelperdaemon push到手机里面
- 运行gen.sh脚本来启动daemon程序(或者直接启动daemon程序)
- daemon程序会一直运行,并且等待其他socket来连接以便发送数据
- 当我们运行gamebench这个app的时候,app会和daemon程序建立连接
- 因为gbhelperdaemon 是拥有shell权限的,所以可以使用dumpsys surfaceflinger --latency来获取数据并计算出fps
- 建立连接后,daemon程序会将获得的数据发送到我们的app端,app再显示出来。
疑问
验证
- 杀掉/data/local/tmp/gbhelperdaemon进程
当正常运行gamebench的时候,杀掉gbhelperdaemon进程后,gamebench的fps一直显示为60。所以app是没办法获得fps数据,只能是daemon进程传递过来的 -
关掉gamebench app直接运行gen.sh,会得到如下结果
sh_gen.png
可以看出来,daemon是一直在等待connection的
- 杀掉daemon,打开app
当杀掉damon运行app的时候,会让你把手机连接电脑运行gb的一个桌面程序,才能继续运行。
这个时候直接执行
sh /data/local/tmp/gen.sh
开启deamon程序,就可以不用再运行gb的桌面程序,并且会有如下的一些log输出
sh_gen2.png
总结
gamebench的这种工作方式,不仅仅可以拿到fps还能拿到全部shell权限能访问的信息。运行在界面上的app就只是相当于一个外壳,包装的是shell。