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

我是二黑,五一想必大家都过的很开心吧,今天分享的是用Frida做Android隐私API检测,文章持续更新,可以微信搜索【程序员二黑】第一时间阅读,回复【1】有我为大家准备的福利哟!

背景

应用软件合规最近一两年越来越规范和严格,对于不合规的应用,可能会有被通报甚至被下架的风险。

对于应用不合规的问题点,有些问题是开发者可以知道哪里不合规,直接找到修改就好。

但是还有另外一些问题,不是开发者故意为之,而是比较隐蔽难以被发现,比如第三方 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 很强大也很深奥,有兴趣的可以深入学习。

我是二黑,一个不太黑的测试人~
本次的分享就到这里了,文章持续更新中,可以微信搜索【程序员二黑】第一时间阅读,回复【1】有我为大家准备的福利哟!

猜你喜欢

转载自blog.csdn.net/weixin_54696666/article/details/124617878