frida-trace
frida-trace is a tool for dynamically tracing function calls.
Full List of Options
-U, –usb: connect to USB device
This option tells frida-trace
to perform tracing on a remote device
connected via the host machine’s USB connection.
Example: You want to trace an application running on an Android device
from your host Windows machine. If you specify -U / --usb
,
frida-trace will perform the necessary work to transfer all data to
and from the remote device and trace accordingly.
Copy frida-server binary to remote device
When tracing a remote device, remember to copy the platform-appropriate frida-server binary to the remote device. Once copied, be sure to run the frida-server binary before beginning the tracing session.
For example, to trace a remote Android application, you might copy the 'frida-server-12.8.0-android-arm' binary to the Android's /data/local/tmp folder. Using adb shell, you would run the server in the background (e.g. "frida-server-12.8.0-android-arm &").
-O: pass command line options via text file
Using this option, you can pass any number of command line options via one or
more text files. The options in the text file can be on one or more lines, with
any number of options per line, including other -O
command options.
This feature is useful for handling a large number of command line options, and solves the problem when the command line exceeds the operating system maximum command line length.
For example:
where additional-options.txt is:
and module-offset-options.txt is:
-I, -X: include/exclude module
These options allow you to include or exclude, in one single option, all functions in a particular module (e.g., *.so, *.dll) in one, single option. The option expects a filename glob for matching one or more modules. Any module that matches the glob pattern will be either included or excluded in its entirety.
frida-trace
will generate a JavaScript handler file for each function matched
by the -I
option.
To exclude specific functions after including an entire module, see the -x
option.
-i, -x: include/exclude function (glob-based)
These options enable you to include or exclude matching functions according to your needs. These are flexible options, allowing a granularity ranging from all functions in all modules down to a single function in a specific module.
frida-trace
will generate a JavaScript handler file for each function matched
by the -i
option.
The -i / -x
options differ syntactically from their uppercase counterparts
in that they accept any of the following forms (MODULE and FUNCTION are both
glob patterns):
- MODULE!FUNCTION - FUNCTION - !FUNCTION - MODULE!
Here are some examples and their descriptions:
Option Value | Description |
---|---|
-i “msvcrt.dll!cpy” | Matches all functions with ‘cpy’ in its name, ONLY in msvcrt.dll |
-i “free” | Matches all functions with ‘free’ in its name in ALL modules |
-i “!free” | Identical to -i “free” |
-i “gdi32.dll!” | Trace all functions in gdi32.dll (identical to -I “gdi32.dll”) |
frida-trace's working set and the order of inclusions and exclusions
frida-trace has an internal concept of a "working set", i.e., a set of "module:function" pairs whose handlers will be traced at runtime. The contents of the working set can be changed by an include / exclude command line option (-I / -X / -i / -x).
It is important to understand that the order of the include / exclude options is important. Each such option works on the current state of the working set, and different orderings of options can lead to different results. In other words, the include/exclude options are procedural (i.e., order counts) rather than simply declarative.
For example, suppose we want to trace all "str*" and "mem*" functions in all modules in a running process. In our example, these functions are found in three modules: ucrtbase.dll, ntdll.dll, and msvcrt.dll. To reduce the noise, however, we do not want to trace any functions found in the msvcrt.dll module.
We will describe three different option orders on the command line and show that they produce different results.
- -i "str*" -i "mem*" -X "msvcrt.dll"
- '-i "str*"'matches 80 functions in 3 modules, working set has 80 entries
- '-i "mem*"'matches 18 functions in 3 modules, working set has 98 entries
- '-X "msvcrt.dll"'removes the 28 "str" and 6 "mem" functions originating in msvcrt.dll, final working set has 64 entries.
- -i "str*" -X "msvcrt.dll" -i "mem*"
- '-i "str*"'matches 80 functions in 3 modules, working set has 80 entries
- '-X "msvcrt.dll"'removes the 28 "str" functions originating in msvcrt.dll, working set has 52 entries.
- '-i "mem*"'matches 18 functions in 3 modules including msvcrt.dll, final working set has 70 entries
- -X "msvcrt.dll" -i "str*" -i "mem*"
- '-X "msvcrt.dll"'tries to remove the 28 "str" and 6 "mem" functions originating in msvcrt.dll. Since the working set is empty, there is nothing to remove, working set has 0 entries.
- '-i "str*"'matches 80 functions in 3 modules, working set has 80 entries
- '-i "mem*"'matches 18 functions in 3 modules, final working set has 98 entries
-a: include function (offset-based)
This option enables tracing functions whose names are not exported by their parent modules (e.g., a static C/C++ function). This should not prevent you from tracing such functions, so long as you know the absolute offset of that function’s entry point.
Example: -a "libjpeg.so!0x4793c"
In this example, the option’s value provides both the full name of the module
(i.e., libjpeg.so
) and the hex offset (0x4793c
) of the function entry point
within the module.
frida-trace
will generate a JavaScript handler file for each function matched
by the -a
option.
-P: Initialize frida-trace session with a globally-accessible JSON object
This option enables assigning a JSON object to the parameters
global variable.
Your handlers can access this global variable, enabling you to dynamically
change the handlers’ behavior by modifying the value of -P
passed on the
command line.
The JSON object passed can be as complicated or extensive as you wish, so long as it is valid JSON.
Example
In your session, you are tracing many functions. At times you want all handlers to print out their process ID. Using the `-P` option, you can enable a handler to decide whether or not to print the process ID.
First, decide on the JSON object format that notifies a handler whether it
should display the process ID. Let's use the following format:
Note that this form is the one you might use under Linux (i.e., you can use both single- and double-quotes on the command line). Under Windows you can only use double quotes, so you should escape the inner double quotes by inserting two double quotes, like this:
Frida-trace will assign your JSON object to the global JavaScript variable "parameters". Now, your handler can check the parameters.displayPid variable to decide whether to print the process ID:
{
onEnter(log, args, state) {
log('memcpy() [msvcrt.dll]');
if (parameters.displayPid) {
log(`Process ID: ${Process.id}`);
}
},
onLeave(log, retval, state) {
}
}
-S: Initialize frida-trace session with JavaScript code
This option initializes your frida-trace session by executing one or more JavaScript code files of your choice, which may declare globally visible functions and add arbitrary data to the global “state” object. When the “state” object is passed to any of your handlers, you have immediate access to anything you saved to it during session initialization.
Uses of this powerful feature include initializing the frida-trace running environment before the session begins, and sharing finely-tuned and debugged JavaScript functions and data that can be invoked across different handlers and development projects.
For a detailed explanation of how to use this powerful feature, consult the session initialization primer.
-d, –decorate: add module name to log tracing
The --decorate
option is relevant when frida-trace
auto-generates JavaScript
handler scripts. By default, a handler’s onEnter
function looks like this:
onEnter(log, args, state) {
log('memcpy()');
},
The drawback is that, if the same function name exists in multiple modules,
it will be difficult to differentiate between function traces. The --decorate
function instructs frida-trace
to insert the module name in the default
onEnter
trace instruction:
onEnter(log, args, state) {
log('memcpy() [msvcrt.dll]');
},