TA的每日心情 | 擦汗 4 小时前 |
---|
签到天数: 1047 天 连续签到: 5 天 [LV.10]测试总司令
|
背景
应用软件合规最近一两年越来越规范和严格,对于不合规的应用,可能会有被通报甚至被下架的风险。
对于应用不合规的问题点,有些问题是开发者可以知道哪里不合规,直接找到修改就好。
但是还有另外一些问题,不是开发者故意为之,而是比较隐蔽难以被发现,比如第三方 SDK 里面的逻辑、非固定时机触发的逻辑等等,往往这类问题是比较容易遗漏的,从而给应用带来不可预期的合规风险。
所以需要有一种方式,可以用来检测 Android 里面比较敏感的方法是否会被调用到,常见的比如获取 Mac 地址、获取 IMEI、使用传感器、获取运行应用进程列表等。
也调研过一些方案,比如 Xposed、VirtualXposed 等,各有利弊,但是对于检测定制 ROM 上的预装软件来说,这两者都会遇到一些不适用的情况,本文主要是使用了 Frida 这个框架来做检测。
关于 Frida 环境如何搭建等,就不在这里展开,搜索一下会有比较多的教程。
Frida 检测隐私方法
Frida 里面内置了好几个工具,隐私 API 调用检测使用的是 Frida-trace 工具进行实现,文档可见:https://frida.re/docs/frida-trace/
隐私 API 调用检测实际上就是对方法的调用进行追踪,
以检测 getMacAddress 为例:
1、先从源码看到这个方法的所在类的路径:
可以看到是在 android.net.wifi.WifiInfo 里面,因此可以使用以下命令:
- Frida-trace -U -f com.xxx.xxxx -j 'android.net.wifi.WifiInfo*!*getMacAddress'
复制代码 参数解释:
-U: 连接到 USB 设备
-f: spawn 模式,会新拉起一个进程,下面第二部分会简单介绍
-j: JAVA 方法的意思,多个方法可以用多个 -j 拼接,如 -j 'xxx' -j 'xxxx'
2、执行完上述命令,可以看到设备上对应包名的应用被拉起了,同时可以看到有1个 function 正在被 tracing,说明上述命令写得没错,如果写错的话,会显示 0 function。
执行上述命令之前,需要先建立一个 adb 的转发:
- adb forward tcp:27042 tcp:27042
- adb forward tcp:27043 tcp:27043
复制代码 接着 demo 里面调用获取 Mac 地址操作,这时候可以看到命令行输出了信息,表明了什么时间点调用了什么方法,返回了什么值,前面的毫秒是从进程被拉起到调用经过的时间。
附上获取 Mac 地址调试代码:
- val manager: WifiManager = getSystemService(WIFI_SERVICE) as WifiManager
- val info: WifiInfo = manager.connectionInfo
- val address = info.macAddress
- Log.d("fridaDemo", "macAddress = $address"
复制代码 但是呢,上面这个例子比较简单,我们可以明确知道是哪里调用的,但我们实际应用的调用的时机可能不太确定,看到上面日志的时候,也只能知道有调用了获取 Mac 地址方法,但是是哪里调用了,相对来说很懵逼,所以如果能够看到调用堆栈,那岂不更好。
其实也是可以做到的,上面 Frida-trace 命令执行后,会在对应 __handlers_ 目录生成 getMacAddress.js 文件(命令行窗口可以看到路径),打开 js 文件,在 onEnter 方法后面加上:
- onEnter(log, args, state) {
- log(`WifiInfo.getMacAddress(${args.map(JSON.stringify).join(', ')})`);
- // 加入的代码块 start
- var Log = Java.use('android.util.Log');
- var Exception = Java.use('java.lang.Exception');
- var String = Java.use('java.lang.String')
- var stack = String.valueOf(Log.getStackTraceString(Exception.$new())).replaceAll("\n", 'newLine');
- log("stacktrace: " + stack.replaceAll("/(?:\r\n|\r|\n)/g", 'newLine'));
- // 加入的代码块 end
- },
复制代码 大概原理就是,trace 到这个方法的时候,就会调用到这个 js 的 onEnter 方法,这时候加入的这段代码,其实是模拟了一个异常抛出,并将异常的堆栈打印出来,这样就可以看到调用堆栈了,效果如下:
以上是 Frida 非常简单的一种实践,那么 Frida 的工作方式是怎样的?
Frida 工作模式
Frida 是一种动态插桩工具,可以插入一些代码到原生 app 的内存空间,从而达到动态地追踪和修改其行为。
这里列出它的两种主要的工作模式,可以结合这个例子稍作了解。
spawn模式
也就是我们上面例子中的模式,这种模式下 Frida 会启动一个新的进程并挂起,在启动的同时注入 Frida 代码 (也就是 __handlers_ 里面生成的 js 代码,Frida trace 自动生成的),这种模式比较适用于我们要检测应用启动时的一些方法调用。
attach模式
而我们可能会有另外的使用场景,就是 trace 已经启动的应用,这时候就可以用到 attach 模式。
attach 模式可以 trace 已经存在的进程,核心原理是 ptrace 修改进程内存。而 attach 模式使用也比较简单,只要对上面的命令稍加修改即可:
- Frida-trace -U -p $PID -j 'android.net.wifi.WifiInfo*!*getMacAddress'
复制代码 $PID 改为应用对应的进程 ID,可以通过 adb shell ps -e | grep 包名 查到。
以上,抛砖引玉;Frida 很强大也很深奥,有兴趣的可以深入学习。
|
|