运行环境
● 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#include
- 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#include
- 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,得到如下结果:
来源: http://www.cnblogs.com/goodhacker/p/7171575.html