frida-trace
frida-trace 是一个用于动态跟踪函数调用的工具。
# Trace recv* and send* APIs in Safari, insert library names
# in logging
$ frida-trace --decorate -i "recv*" -i "send*" Safari
# Trace ObjC method calls in Safari
$ frida-trace -m "-[NSView drawRect:]" Safari
# Launch SnapChat on your iPhone and trace crypto API calls
$ frida-trace \
-U \
-f com.toyopagroup.picaboo \
-I "libcommonCrypto*"
# Launch YouTube on your Android device and trace Java methods
# with “certificate” in their signature (s), ignoring case (i)
# and only searching in user-defined classes (u)
$ frida-trace \
-U \
-f com.google.android.youtube \
--runtime=v8 \
-j '*!*certificate*/isu'
# Trace all JNI functions in Samsung FaceService app on Android
$ frida-trace -U -i "Java_*" com.samsung.faceservice
# Trace a Windows process's calls to "mem*" functions in msvcrt.dll
$ frida-trace -p 1372 -i "msvcrt.dll!*mem*"
# Trace all functions matching "*open*" in the process except
# in msvcrt.dll
$ frida-trace -p 1372 -i "*open*" -x "msvcrt.dll!*open*"
# Trace an unexported function in libjpeg.so
$ frida-trace -p 1372 -a "libjpeg.so!0x4793c"完整选项列表
$ frida-trace -h
usage: frida-trace [options] target
positional arguments:
args extra arguments and/or target
options:
-h, --help show this help message and exit
-D ID, --device ID connect to device with the given ID
-U, --usb connect to USB device
-R, --remote connect to remote frida-server
-H HOST, --host HOST connect to remote frida-server on HOST
--certificate CERTIFICATE
speak TLS with HOST, expecting CERTIFICATE
--origin ORIGIN connect to remote server with “Origin” header set to ORIGIN
--token TOKEN authenticate with HOST using TOKEN
--keepalive-interval INTERVAL
set keepalive interval in seconds, or 0 to disable (defaults to -1 to auto-select based on transport)
--p2p establish a peer-to-peer connection with target
--stun-server ADDRESS
set STUN server ADDRESS to use with --p2p
--relay address,username,password,turn-{udp,tcp,tls}
add relay to use with --p2p
-f TARGET, --file TARGET
spawn FILE
-F, --attach-frontmost
attach to frontmost application
-n NAME, --attach-name NAME
attach to NAME
-N IDENTIFIER, --attach-identifier IDENTIFIER
attach to IDENTIFIER
-p PID, --attach-pid PID
attach to PID
-W PATTERN, --await PATTERN
await spawn matching PATTERN
--stdio {inherit,pipe}
stdio behavior when spawning (defaults to “inherit”)
--aux option set aux option when spawning, such as “uid=(int)42” (supported types are: string, bool, int)
--realm {native,emulated}
realm to attach in
--runtime {qjs,v8} script runtime to use
--debug enable the Node.js compatible script debugger
--squelch-crash if enabled, will not dump crash report to console
-O FILE, --options-file FILE
text file containing additional command line options
--version show program's version number and exit
-I MODULE, --include-module MODULE
include MODULE
-X MODULE, --exclude-module MODULE
exclude MODULE
-i FUNCTION, --include FUNCTION
include [MODULE!]FUNCTION
-x FUNCTION, --exclude FUNCTION
exclude [MODULE!]FUNCTION
-a MODULE!OFFSET, --add MODULE!OFFSET
add MODULE!OFFSET
-T INCLUDE_IMPORTS, --include-imports INCLUDE_IMPORTS
include program's imports
-t MODULE, --include-module-imports MODULE
include MODULE imports
-m OBJC_METHOD, --include-objc-method OBJC_METHOD
include OBJC_METHOD
-M OBJC_METHOD, --exclude-objc-method OBJC_METHOD
exclude OBJC_METHOD
-y SWIFT_FUNC, --include-swift-func SWIFT_FUNC
include SWIFT_FUNC
-Y SWIFT_FUNC, --exclude-swift-func SWIFT_FUNC
exclude SWIFT_FUNC
-j JAVA_METHOD, --include-java-method JAVA_METHOD
include JAVA_METHOD
-J JAVA_METHOD, --exclude-java-method JAVA_METHOD
exclude JAVA_METHOD
-s DEBUG_SYMBOL, --include-debug-symbol DEBUG_SYMBOL
include DEBUG_SYMBOL
-q, --quiet do not format output messages
-d, --decorate add module name to generated onEnter log statement
-S PATH, --init-session PATH
path to JavaScript file used to initialize the session
-P PARAMETERS_JSON, --parameters PARAMETERS_JSON
parameters as JSON, exposed as a global named 'parameters'
-o OUTPUT, --output OUTPUT
dump messages to file
--ui-port UI_PORT the TCP port to serve the UI on-U, –usb:连接 USB 设备
此选项指示 frida-trace 在通过主机 USB 接口连接的远程设备上执行跟踪。
例如:你想从 Windows 主机跟踪 Android 设备上运行的应用程序。指定
-U / --usb 后,frida-trace 会完成在主机与远程设备之间传输全部数据所需的工作,
并相应地执行跟踪。
将 frida-server 二进制文件复制到远程设备
跟踪远程设备时,请记得将 适用于目标平台的 frida-server 二进制文件 复制到远程设备。复制完成后,请确保先运行 frida-server 二进制文件,再开始跟踪会话。
例如,要跟踪远程 Android 应用,可以将 “frida-server-12.8.0-android-arm”二进制文件复制到 Android 的 /data/local/tmp 目录。然后通过 adb shell 在后台运行该服务 (例如“frida-server-12.8.0-android-arm &”)。
-O:通过文本文件传递命令行选项
使用此选项,可以通过一个或多个文本文件传入任意数量的命令行选项。文本文件中的选项
可以分布在一行或多行中,每行可包含任意数量的选项,也可以包含其他 -O 命令选项。
此功能适合处理大量命令行选项,也能解决命令行长度超过操作系统最大限制的问题。
例如:
$ frida-trace -p 9753 --decorate -O additional-options.txt其中 additional-options.txt 的内容为:
-i "gdi32full.dll!ExtTextOutW"
-S core.js -S ms-windows.js
-O module-offset-options.txt而 module-offset-options.txt 的内容为:
-a "gdi32full.dll!0x3918DC" -a "gdi32full.dll!0xBE7458"
-a "gdi32full.dll!0xBF9904"-I, -X:包含/排除模块
借助这些选项,只需一个选项就能包含或排除某个特定模块(例如 .so、.dll)中的 所有函数。选项接受用于匹配一个或多个模块的文件名 glob 模式。任何匹配该 glob 模式的模块都会被整体包含或排除。
frida-trace 会为 -I 选项匹配到的每个函数生成一个 JavaScript 处理程序文件。
要在包含整个模块后排除特定函数,请参阅 -x 选项。
-i, -x:包含/排除函数(基于 glob)
借助这些选项,你可以按需包含或排除匹配的函数。它们十分灵活,粒度范围从所有模块中的 所有函数,一直到特定模块中的单个函数。
frida-trace 会为 -i 选项匹配到的每个函数生成一个 JavaScript 处理程序文件。
-i / -x 选项在语法上与对应的大写选项不同:它们接受以下任意形式
(MODULE 和 FUNCTION 均为 glob 模式):
- MODULE!FUNCTION - FUNCTION - !FUNCTION - MODULE!
以下是一些示例及其说明:
| 选项值 | 说明 |
|---|---|
| -i “msvcrt.dll!cpy” | 仅匹配 msvcrt.dll 中名称包含“cpy”的所有函数 |
| -i “free” | 匹配所有模块中名称包含“free”的所有函数 |
| -i “!free” | 与 -i “free” 完全相同 |
| -i “gdi32.dll!” | 跟踪 gdi32.dll 中的所有函数(与 -I “gdi32.dll” 完全相同) |
frida-trace 的工作集以及包含和排除操作的顺序
frida-trace 内部有一个“工作集”概念,即一组会在运行时跟踪其处理程序的 “module:function”对。工作集的内容可以通过包含/排除命令行选项 (-I / -X / -i / -x)更改。
必须理解,包含/排除选项的顺序非常重要。每个此类选项都会作用于工作集的当前状态, 不同的选项排列顺序可能产生不同的结果。换句话说,包含/排除选项是过程式的 (即顺序会影响结果),而非单纯的声明式选项。
例如,假设我们希望跟踪某个运行中进程里所有模块中的全部“str*”和“mem*”函数。 在本例中,这些函数存在于三个模块中:ucrtbase.dll、ntdll.dll 和 msvcrt.dll。 不过,为了减少干扰,我们不希望跟踪 msvcrt.dll 模块中的任何函数。
下面将说明三种不同的命令行选项顺序,并展示它们如何产生不同结果。
- -i "str*" -i "mem*" -X "msvcrt.dll"
-
'-i "str*"'在 3 个模块中匹配 80 个函数, 工作集包含 80 个条目
-
'-i "mem*"'在 3 个模块中匹配 18 个函数, 工作集包含 98 个条目
-
'-X "msvcrt.dll"'移除来自 msvcrt.dll 的 28 个“str”函数和 6 个“mem”函数,最终工作集包含 64 个条目。
- -i "str*" -X "msvcrt.dll" -i "mem*"
-
'-i "str*"'在 3 个模块中匹配 80 个函数, 工作集包含 80 个条目
-
'-X "msvcrt.dll"'移除来自 msvcrt.dll 的 28 个“str”函数,工作集包含 52 个条目。
-
'-i "mem*"'在 3 个模块(包括 msvcrt.dll)中 匹配 18 个函数,最终工作集包含 70 个条目
- -X "msvcrt.dll" -i "str*" -i "mem*"
-
'-X "msvcrt.dll"'尝试移除来自 msvcrt.dll 的 28 个“str”函数和 6 个“mem”函数。由于工作集为空,没有任何内容可移除, 工作集仍为 0 个条目。
-
'-i "str*"'在 3 个模块中匹配 80 个函数, 工作集包含 80 个条目
-
'-i "mem*"'在 3 个模块中匹配 18 个函数, 最终工作集包含 98 个条目
-a:包含函数(基于偏移量)
此选项可以跟踪名称未由所属模块导出的函数(例如静态 C/C++ 函数)。只要你知道函数入口点的 绝对偏移量,名称未导出就不应妨碍你跟踪此类函数。
示例:-a "libjpeg.so!0x4793c"
在此示例中,选项值同时给出了模块的完整名称(即 libjpeg.so)以及函数入口点在模块内的
十六进制偏移量(0x4793c)。
frida-trace 会为 -a 选项匹配到的每个函数生成一个 JavaScript 处理程序文件。
-P:使用可全局访问的 JSON 对象初始化 frida-trace 会话
此选项可以将一个 JSON 对象赋值给全局变量 parameters。处理程序可以访问这个全局变量,
因此,你可以通过修改命令行中传给 -P 的值来动态改变处理程序的行为。
传入的 JSON 对象可以任意复杂或庞大,只要它是有效的 JSON 即可。
示例
在一个会话中,你正在跟踪许多函数。有时你希望所有处理程序都输出进程 ID。 使用 `-P` 选项,可以让处理程序自行决定是否输出进程 ID。
首先,确定一个 JSON 对象格式,用来告知处理程序是否应显示进程 ID。这里采用以下格式:
请注意,这种写法适用于 Linux(即命令行中可以同时使用单引号和双引号)。在 Windows 下 只能使用双引号,因此需要通过输入两个双引号来转义内部的双引号,如下所示:
Frida-trace 会把 JSON 对象赋给全局 JavaScript 变量“parameters”。此时, 处理程序可以检查 parameters.displayPid 变量,以决定是否输出进程 ID:
{
onEnter(log, args, state) {
log('memcpy() [msvcrt.dll]');
if (parameters.displayPid) {
log(`Process ID: ${Process.id}`);
}
},
onLeave(log, retval, state) {
}
}
-S:使用 JavaScript 代码初始化 frida-trace 会话
此选项会执行你选择的一个或多个 JavaScript 代码文件,以初始化 frida-trace 会话。这些文件 可以声明全局可见的函数,并向全局“state”对象添加任意数据。当“state”对象传递给任一 处理程序时,你可以立即访问会话初始化期间保存到其中的所有内容。
这项强大功能可用于在会话开始前初始化 frida-trace 运行环境,也可用于共享经过精心调试的 JavaScript 函数和数据,供不同处理程序和开发项目调用。
有关如何使用这项强大功能的详细说明,请参阅 会话初始化入门指南。
-d, –decorate:在跟踪日志中添加模块名称
--decorate 选项适用于 frida-trace 自动生成 JavaScript 处理程序脚本的场景。
默认情况下,处理程序的 onEnter 函数如下所示:
onEnter(log, args, state) {
log('memcpy()');
},
它的缺点是:如果多个模块中存在同名函数,就很难区分不同函数的跟踪记录。
--decorate 功能会指示 frida-trace 在默认的 onEnter 跟踪语句中插入模块名称:
onEnter(log, args, state) {
log('memcpy() [msvcrt.dll]');
},