想做Android隐私API检测?用Frida呀!

发表于:2022-5-11 08:55

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:暴走老伯伯    来源:掘金

  背景
  应用软件合规最近一两年越来越规范和严格,对于不合规的应用,可能会有被通报甚至被下架的风险。
  对于应用不合规的问题点,有些问题是开发者可以知道哪里不合规,直接找到修改就好。
  但是还有另外一些问题,不是开发者故意为之,而是比较隐蔽难以被发现,比如第三方 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 很强大也很深奥,有兴趣的可以深入学习。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号