51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 714|回复: 0
打印 上一主题 下一主题

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

[复制链接]
  • TA的每日心情
    擦汗
    昨天 09:04
  • 签到天数: 942 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-5-11 10:04:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    背景
      应用软件合规最近一两年越来越规范和严格,对于不合规的应用,可能会有被通报甚至被下架的风险。
      对于应用不合规的问题点,有些问题是开发者可以知道哪里不合规,直接找到修改就好。
      但是还有另外一些问题,不是开发者故意为之,而是比较隐蔽难以被发现,比如第三方 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 里面,因此可以使用以下命令:
    1. 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 的转发:
    1. adb forward tcp:27042 tcp:27042
    2. adb forward tcp:27043 tcp:27043
    复制代码
    接着 demo 里面调用获取 Mac 地址操作,这时候可以看到命令行输出了信息,表明了什么时间点调用了什么方法,返回了什么值,前面的毫秒是从进程被拉起到调用经过的时间。

    附上获取 Mac 地址调试代码:
    1. val manager: WifiManager = getSystemService(WIFI_SERVICE) as WifiManager
    2. val info: WifiInfo = manager.connectionInfo
    3. val address = info.macAddress
    4. Log.d("fridaDemo", "macAddress = $address"
    复制代码
     但是呢,上面这个例子比较简单,我们可以明确知道是哪里调用的,但我们实际应用的调用的时机可能不太确定,看到上面日志的时候,也只能知道有调用了获取 Mac 地址方法,但是是哪里调用了,相对来说很懵逼,所以如果能够看到调用堆栈,那岂不更好。
      其实也是可以做到的,上面 Frida-trace 命令执行后,会在对应 __handlers_ 目录生成 getMacAddress.js 文件(命令行窗口可以看到路径),打开 js 文件,在 onEnter 方法后面加上:
    1. onEnter(log, args, state) {
    2.   log(`WifiInfo.getMacAddress(${args.map(JSON.stringify).join(', ')})`);

    3.   // 加入的代码块 start
    4.   var Log = Java.use('android.util.Log');
    5.   var Exception = Java.use('java.lang.Exception');
    6.   var String = Java.use('java.lang.String')
    7.   var stack = String.valueOf(Log.getStackTraceString(Exception.$new())).replaceAll("\n", 'newLine');
    8.   log("stacktrace: " + stack.replaceAll("/(?:\r\n|\r|\n)/g", 'newLine'));
    9.   // 加入的代码块 end
    10. },
    复制代码
    大概原理就是,trace 到这个方法的时候,就会调用到这个 js 的 onEnter 方法,这时候加入的这段代码,其实是模拟了一个异常抛出,并将异常的堆栈打印出来,这样就可以看到调用堆栈了,效果如下:

    以上是 Frida 非常简单的一种实践,那么 Frida 的工作方式是怎样的?

      Frida 工作模式
      Frida 是一种动态插桩工具,可以插入一些代码到原生 app 的内存空间,从而达到动态地追踪和修改其行为。
      这里列出它的两种主要的工作模式,可以结合这个例子稍作了解。

      spawn模式
      也就是我们上面例子中的模式,这种模式下 Frida 会启动一个新的进程并挂起,在启动的同时注入 Frida 代码 (也就是 __handlers_ 里面生成的 js 代码,Frida trace 自动生成的),这种模式比较适用于我们要检测应用启动时的一些方法调用。

      attach模式
      而我们可能会有另外的使用场景,就是 trace 已经启动的应用,这时候就可以用到 attach 模式。
      attach 模式可以 trace 已经存在的进程,核心原理是 ptrace 修改进程内存。而 attach 模式使用也比较简单,只要对上面的命令稍加修改即可:
    1. Frida-trace -U -p $PID -j 'android.net.wifi.WifiInfo*!*getMacAddress'
    复制代码
    $PID 改为应用对应的进程 ID,可以通过 adb shell ps -e | grep 包名 查到。
      以上,抛砖引玉;Frida 很强大也很深奥,有兴趣的可以深入学习。





    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-5-7 11:25 , Processed in 0.069542 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表