0x00 Frida是什么
这是一个神通广大的框架,已经编写好的程序只能运行同一结果太无趣?Frida可以让你注入/预加载/集成你自己的代码,于是就能愉快的和已经写好的程序交互,让你拦截、记录、修改程序的运行过程,乐趣多多。支持Windows, macOS, GNU/Linux, iOS, Android, and QNX.
0x01 Frida原理(简单介绍版)
frida-core - Frida core library intended for static linking into bindings. frida-core对服务端监听,注入,控制执行等通用操作进行API抽象管理。
frida-gum - Low-level code instrumentation library used by frida-core. frida-gum提供底层代码执行的支持,如果你在安卓则执行安卓兼容的控制代码,同样的,其他Linux平台IOS平台都使用会对应frida-gum的底层执行版本。
在注入一个脚本时,脚本将通过frida-core核心控制通过TCP协议推送到frida-server注入到目标进程,之后通过frida-gum解释执行底层代码并回传结果。
0x02 Frida自带功能组件
除了自己写功能,frida也提供了一些现成的实用工具。
组件名称 | 功能描述 | 实例 |
frida-server | 如果你正在对远程系统,例如USB连接的手机,这个组件将作为中间件提供统一的API访问。因此本地运行无需额外开启frida-server。 | Github下载对应版本frida-server推送到远程设备ROOT运行即可。 |
frida-ps | 列举正在运行的进程名和进程号。
frida-ps --help Usage: frida-ps [options]
Options: --version show program's version number and exit -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 -a, --applications list only applications -i, --installed include all installed applications | >frida-ps
PID Name ----------------------------- 7008 ApplicationFrameHost.exe 6008 Calculator.exe 6744 svchost.exe 5888 taskhostw.exe ... |
frida-CLI | frida控制台游乐园模式开启入口。 允许你将frida框架对目标程序进行启动/附加,之后可以进行控制台交互。
frida --help Usage: frida [options] target
Options: --version show program's version number and exit -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 -f FILE, --file=FILE spawn FILE -n NAME, --attach-name=NAME attach to NAME -p PID, --attach-pid=PID attach to PID --debug enable the Node.js compatible script debugger --enable-jit enable JIT -l SCRIPT, --load=SCRIPT load SCRIPT -c CODESHARE_URI, --codeshare=CODESHARE_URI load CODESHARE_URI -e CODE, --eval=CODE evaluate CODE -q quiet mode (no prompt) and quit after -l and -e --no-pause automatically start main thread after startup -o LOGFILE, --output=LOGFILE output to log file | # 首先,在本机Windows上运行calc,即计算器。
>frida-ps | findstr /I calc 6008 Calculator.exe
>frida -p 6008 ____ / _ | Frida 12.6.8 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/
[Local::PID::6008]-> var a = 123; undefined [Local::PID::6008]-> a; 123
# 由于frida的注入使用GoogleV8引擎来执行,后面的都是JavaScript语法 操作。 |
frida-discover | frida-discover is a tool for discovering internal functions in a program, which can then be traced by using frida-trace.
在执行期间内对目标进行Profiling,用于发现有追踪价值的函数。
frida-discover --help Usage: frida-discover [options] target
Options: --version show program's version number and exit -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 -f FILE, --file=FILE spawn FILE -n NAME, --attach-name=NAME attach to NAME -p PID, --attach-pid=PID attach to PID --debug enable the Node.js compatible script debugger --enable-jit enable JIT |
>frida-ps | findstr /I calc 35112 Calculator.exe >frida-discover -p 35112
Attaching... Injecting script... Tracing 24 threads. Press ENTER to stop.
Windows.UI.Xaml.dll Calls Function 24121 sub_35d540 1486 sub_121d20 601 sub_121d90 51 sub_17ae60 49 sub_353368 48 sub_168870 1 sub_22b37c 1 sub_1620f0
ntdll.dll Calls Function 1600 RtlEnterCriticalSection 1595 RtlLeaveCriticalSection 435 RtlAcquireSRWLockShared 1 sub_1c690 1 AlpcInitializeMessageAttribute 1 ZwAlpcQueryInformation
KERNELBASE.dll Calls Function 212 GetProcessHeap 157 GetLastError 133 sub_896e0 76 sub_8a78c 76 QuirkIsEnabled 1 CallbackMayRunLong 1 sub_8bfbc 1 FlsGetValue
# 吐槽一下,控制不是很完善,Ctrl+C都停不下来非要关掉目标进程。但总体还是很实用的。 |
frida-trace | frida-trace is a tool for dynamically tracing function calls.
用于动态追踪函数调用。
frida-trace --help Usage: frida-trace [options] target
Options: --version show program's version number and exit -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 -f FILE, --file=FILE spawn FILE -n NAME, --attach-name=NAME attach to NAME -p PID, --attach-pid=PID attach to PID --debug enable the Node.js compatible script debugger --enable-jit enable JIT -I MODULE, --include-module=MODULE include MODULE -X MODULE, --exclude-module=MODULE exclude MODULE -i FUNCTION, --include=FUNCTION include FUNCTION -x FUNCTION, --exclude=FUNCTION exclude FUNCTION -a MODULE!OFFSET, --add=MODULE!OFFSET add MODULE!OFFSET -T, --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 -s DEBUG_SYMBOL, --include-debug-symbol=DEBUG_SYMBOL include DEBUG_SYMBOL -q, --quiet do not format output messages -o OUTPUT, --output=OUTPUT dump messages to file | #上面的frida-discover追踪到了模块KERNELBASE.dll里面有调用函数GetProcessHeap,那么frida-trace追踪一下调用吧。
>frida-trace -p 36164 -i GetProcessHeap Instrumenting functions... GetProcessHeap: Auto-generated handler at "Desktop\test\__handlers__\KERNELBASE.dll\GetProcessHeap.js" GetProcessHeap: Auto-generated handler at "Desktop\test\__handlers__\KERNEL32.DLL\GetProcessHeap.js" Started tracing 2 functions. Press Ctrl+C to stop. /* TID 0x97ec */ 860 ms GetProcessHeap() 860 ms GetProcessHeap() 860 ms GetProcessHeap() 860 ms GetProcessHeap() 860 ms GetProcessHeap() ...
# 比较鸡肋,传入参数传出返回值都没有log,sub_8bfbc这种匿名函数还不识别。 |
frida-ls-devices | This is a command-line tool for listing attached devices, which is very useful when interacting with multiple devices.
有多个设备时用于区分ID。 | >frida-ls-devices Id Type Name -------- ------ ------------------ local local Local System beac33b8 usb Xiaomi MI NOTE LTE tcp remote Local TCP |
frida-kill | 杀死进程
frida-kill --help Usage: frida-kill [options] process
Options: --version show program's version number and exit -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 |
0x03 做个小实验,熟悉一下Frida的运行环境
// test.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 test -o test.c
$ ./test
f() is at 0x400544
Number: 0
Number: 1
Number: 2
…
以上这段C程序将打印出f函数的地址,然后循环每间隔1秒将调用一次f函数。Frida有附加进程并注入代码运行的能力,那么来一段hook代码,在f函数执行时同步触发执行我们的函数。
import frida
import sys
# 获取进程会话
session = frida.attach("test")
# 对当前进程会话创建一个脚本
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, data)
# 绑定回调事件
script.on('message', on_message)
# 将脚本注入会话进程
script.load()
# 阻塞主线程,防止脚本主动退出
sys.stdin.read()
//-------Shell Code-------//
$ sudo /usr/bin/python3 /home/root2/Desktop/Test2/frida/test.py 0x400544
# 以上命令最后传了一个地址,正是之前C代码运行出来的f函数地址
{'type': 'send', 'payload': 310} None
{'type': 'send', 'payload': 311} None
{'type': 'send', 'payload': 312} None
...
# 'payload'就是Js层send函数发出来的值,也就是当时传入f函数的值
修改注入脚本Interceptor.attach的onEnter事件,就可以实现读取写入,阻塞等基本功能。
Frida的用法精髓在于活用内置函数,且数目巨大不便挨个翻译讲解,还需参考官方文档。
https://www.frida.re/docs/javascript-api/