Android hook神器frida(一)


運行環境
● 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,得到如下結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM