運行環境
● Python – latest 3.x is highly recommended
● Windows, macOS, or Linux
安裝方法
使用命令 sudo pip install frida
或從https://build.frida.re/frida/下載
以cat命令為例,檢查frida是否正確安裝:
$ cp /bin/cat /tmp/cat $ /tmp/cat
打開一個新的終端,創建example.py ,寫入如下代碼:
import frida session = frida.attach("cat") print([x.name for x in session.enumerate_modules()])
在linux系統下,還需執行如下命令確保開啟調試非子進程:
$ sudo sysctl kernel.yama.ptrace_scope=0
然后運行examp.py,應該得到類似如下結果:

基本使用方法
源碼:frida/core.py 和frida/tracer.py
1.枚舉模塊
如果我們執行print(session.enumerate_modules())
就會得到類似如下的結果:
[Module(name="cat", base_address=0x400000, size=20480, path="/bin/cat"), ...]
其中base_address是模塊的基地址
2.枚舉內存范圍
枚舉當前目標進程映射的所有內存范圍:enumerate_ranges(mask)
執行print s.enumerate_ranges('rw-'),會得到類似如下的結果:
[Range(base_address=0x2d4160a06000, size=1019904, protection='rwx'), ...]
base_address是這個范圍的基址。
3.讀寫內存
read_bytes(address, n):從目標進程地址address中讀取n字節數據。
write_bytes(address, data):將data以字節形式寫入到address中。

操作模式
(1)注入模式
主要在root或者越獄的手機上使用
(2)嵌入模式
非root非越獄機上使用。通過嵌入一個叫frida-gadget的共享庫到目標app中
(3)預加載模式
不涉及到任何TCP或者對外的通信,同意需要用到共享庫frida-gadget。需要設置環境變量FRIDA_GADGET_SCRIPT用於指向一個js文件。
如linux環境下,可以創建一個包含以下內容的hook.js文件:
'use strict'; rpc.exports = { init: function () { Interceptor.attach(Module.findExportByName(null, 'open'), { onEnter: function (args) { var path = Memory.readUtf8String(args[0]); console.log('open("' + path + '")'); } }); } };
最新的frida-gadget地址:https://github.com/frida/frida/releases/tag/10.2.1
然后設置兩個環境變量
LD_PRELOAD=/path/to/frida-gadget.so FRIDA_GADGET_SCRIPT=/path/to/hook.js
然后啟動目標進程。
同樣可以使用FRIDA_GADGET_ENV=development來開發自己的邏輯,以便於frida-gadget 監控文件更改,一旦發現文件更改后自動重新加載。
函數操作
首先我們來創建一個實驗代碼hello.c
#include <stdio.h> #include <unistd.h> void f (int n) { printf ("Number: %d\n", n); } int main (int argc, char * argv[]) { int i = 0; printf ("f() is at %p\n", f); while (1) { f (i++); sleep (1); } }
執行命令gcc -Wall hello.c -o hello進行編譯,然后運行,記錄f()函數的地址0x40057d

(1)hook函數
編寫hook代碼hook.py用於hook函數調用,返回函數參數,具體代碼如下:
from __future__ import print_function import frida import sys session = frida.attach("hello") script = session.create_script(""" Interceptor.attach(ptr("%s"), { onEnter: function(args) { send(args[0].toInt32()); } }); """ % int(sys.argv[1], 16)) def on_message(message, data): print(message) script.on('message', on_message) script.load() sys.stdin.read()
執行 python hook.py 0x40057d
得到如下結果:

(2)修改函數參數
創建modify.py,代碼如下:
import frida import sys session = frida.attach("hello") script = session.create_script(""" Interceptor.attach(ptr("%s"), { onEnter: function(args) { args[0] = ptr("1337"); } }); """ % int(sys.argv[1], 16)) script.load() sys.stdin.read()
執行python modify.py 0x400544后會發現輸出的值變了

(3)函數調用
創建call.py
import frida import sys session = frida.attach("hello") script = session.create_script(""" var f = new NativeFunction(ptr("%s"), 'void', ['int']); f(1911); f(1911); f(1911); """ % int(sys.argv[1], 16)) script.load()
運行得到如下結果:

(4)注入字符串並調用函數
創建hello.c
#include <stdio.h> #include <unistd.h> int f (const char * s) { printf ("String: %s\n", s); return 0; } int main (int argc, char * argv[]) { const char * s = "Testing!"; printf ("f() is at %p\n", f); printf ("s is at %p\n", s); while (1) { f (s); sleep (1); } }
創建腳本stringhook.py,使用frida注入一段字符串到內存中,然后調用f()函數:
from __future__ import print_function import frida import sys session = frida.attach("hi") script = session.create_script(""" var st = Memory.allocUtf8String(" I love you!"); var f = new NativeFunction(ptr("%s"), 'int', ['pointer']); // In NativeFunction param 2 is the return value type, // and param 3 is an array of input types f(st); """ % int(sys.argv[1], 16)) def on_message(message, data): print(message) script.on('message', on_message) script.load()
運行python stringhook.py 0x40057d,得到如下結果:

