MASTG-TECH-0034: 原生代码追踪

与 Java 方法跟踪相比,原生方法跟踪可以相对容易地执行。 frida-trace 是一种动态跟踪函数调用的 CLI 工具。 它可以简化原生函数的跟踪,并且对于收集有关应用程序的信息非常有用。

为了使用 frida-trace,Frida 服务器应该在设备上运行。 下面演示了一个使用 frida-trace 跟踪 libc 的 open 函数的示例,其中 -U 连接到 USB 设备,-i 指定要包含在跟踪中的函数。

frida-trace -U -i "open" com.android.chrome

请注意,默认情况下,仅显示传递给函数的参数,而不显示返回值。 在底层,frida-trace 在自动生成的 __handlers__ 文件夹中,为每个匹配的函数生成一个小型的 JavaScript 处理程序文件,然后 Frida 将其注入到进程中。 您可以编辑这些文件以进行更高级的用法,例如获取函数的返回值、其输入参数、访问内存等。 有关更多详细信息,请查看 Frida 的 JavaScript API

在本例中,跟踪 libc.so 中所有 open 函数调用的生成脚本位于 __handlers__/libc.so/open.js 中,它看起来如下所示

{
  onEnter: function (log, args, state) {
    log('open(' +
      'path="' + args[0].readUtf8String() + '"' +
      ', oflag=' + args[1] +
    ')');
  },


  onLeave: function (log, retval, state) {
      log('\t return: ' + retval);      \\ edited
  }
}

在上面的脚本中,onEnter 负责以正确的格式记录对该函数及其两个输入参数的调用。 您可以编辑 onLeave 事件以打印返回值,如上所示。

请注意,libc 是一个众所周知的库,Frida 能够推导出其 open 函数的输入参数并自动正确记录它们。 但对于其他库或 Android Kotlin/Java 代码来说,情况并非如此。 在这种情况下,您可能需要通过参考 Android 开发人员文档或首先反向工程应用程序来获取您感兴趣的函数的签名。

上面输出中需要注意的另一件事是它是彩色的。 应用程序可以运行多个线程,每个线程都可以独立调用 open 函数。 通过使用这样的配色方案,可以轻松地为每个线程在视觉上分离输出。

frida-trace 是一个非常通用的工具,有多个配置选项可用,例如

  • 包含 -I 和排除 -X 整个模块。
  • 使用 -i "Java_*" 跟踪 Android 应用程序中的所有 JNI 函数(请注意使用 glob * 来匹配所有以“Java_”开头的可能函数)。
  • 当没有函数名称符号可用时(剥离的二进制文件),按地址跟踪函数,例如 -a "libjpeg.so!0x4793c"
frida-trace -U -i "Java_*" com.android.chrome

许多二进制文件都被剥离了,并且没有可用的函数名称符号。 在这种情况下,也可以使用其地址来跟踪函数。

frida-trace -p 1372 -a "libjpeg.so!0x4793c"