快速开始指南

对于想快速上手的开发者,这里有一个使用Frida进行函数追踪的例子:

~ $ pip install frida-tools
~ $ frida-trace -i "recv*" -i "read*" twitter
recv: Auto-generated handler: …/recv.js
# (snip)
recvfrom: Auto-generated handler: …/recvfrom.js
Started tracing 21 functions. Press Ctrl+C to stop.
    39 ms	recv()
   112 ms	recvfrom()
   128 ms	recvfrom()
   129 ms	recvfrom()

如你所见,Frida将自身注入到Twitter,枚举已经加载的共享库,然后拦截所有名称以。 recv or read 开始的函数. Frida同时还生成了一份代码模板,该代码默认会在目标函数被调用时打印目标函数的名字。这些代码会在修改后自动加载进Frida。你可以修改代码模板以修改其行为。

我们先看一下生成的代码模板 recvfrom.js:

/*
 * Auto-generated by Frida. Please modify to match the
 * signature of recvfrom.
 *
 * This stub is somewhat dumb. Future verions of Frida
 * could auto-generate based on OS API references, manpages,
 * etc. (Pull-requests appreciated!)
 *
 * For full API reference, see:
 * https://frida.re/docs/javascript-api/
 */

{
    /**
     * Called synchronously when about to call recvfrom.
     *
     * @this {object} - Object allowing you to store state for
     * use in onLeave.
     * @param {function} log - Call this function with a string
     * to be presented to the user.
     * @param {array} args - Function arguments represented as
     * an array of NativePointer objects.
     * For example use args[0].readUtf8String() if the first
     * argument is a pointer to a C string encoded as UTF-8.
     * It is also possible to modify arguments by assigning a
     * NativePointer object to an element of this array.
     * @param {object} state - Object allowing you to keep
     * state across function calls.
     * Only one JavaScript function will execute at a time, so
     * do not worry about race-conditions. However, do not use
     * this to store function arguments across onEnter/onLeave,
     * but instead use "this" which is an object for keeping
     * state local to an invocation.
     */
    onEnter(log, args, state) {
        log("recvfrom()");
    },

    /**
     * Called synchronously when about to return from recvfrom.
     *
     * See onEnter for details.
     *
     * @this {object} - Object allowing you to access state
     * stored in onEnter.
     * @param {function} log - Call this function with a string
     * to be presented to the user.
     * @param {NativePointer} retval - Return value represented
     * as a NativePointer object.
     * @param {object} state - Object allowing you to keep
     * state across function calls.
     */
    onLeave(log, retval, state) {
    }
}

现在,我们把 log() 行代码替换成一下代码:

log("recvfrom(socket=" + args[0].toInt32()
    + ", buffer=" + args[1]
    + ", length=" + args[2].toInt32()
    + ", flags=" + args[3]
    + ", address=" + args[4]
    + ", address_len=" + args[5].readPointer().toInt32()
    + ")");

保存该文件 (该文件会自动重新加载) 之后,Twitter应用触发一些特殊的网络活动时,会有一些特别的行为。你现在应该可以在终端看到以下类似的输出:

  8098 ms	recvfrom(socket=70,
                         buffer=0x32cc018, length=65536,
                         flags=0x0,
                         address=0xb0420bd8, address_len=16)

这些对Frida来说是小菜一碟。 当你使用构造frida-trace的API构造自己的工具时,Frida的强大魔法才会体现出来。