Android逆向 Frida的Hook之旅

1 安裝python環(huán)境

mac 自帶不需要安裝

2 安裝pip

easy_install pip

3 安裝frida 安裝frida-tools

pip install frida
pip install frida-tools
//檢測(cè)是否安裝成功
frida-ps
//能看到系統(tǒng)進(jìn)程,表示安裝成功

4 下載frida-server

官網(wǎng)下載:https://github.com/frida/frida/releases 對(duì)應(yīng)的版本,
注意:Frida-server的版本必須跟你宿主機(jī)的Frida版本一致,比如我宿主機(jī)Frida的版本是12.2.28攀例,

getprop ro.product.cpu.abi
armeabi-v7a

Android手機(jī)是arm的它浅,那么應(yīng)該下載:rida-server-12.2.28-android-arm.xz 文件。

5 推送frida-server到root過(guò)的手機(jī)

#下載后解壓文件铭拧,并將文件重命名為: frida-server,然后推送到手機(jī)
adb push frida-server /data/local/tmp/
#修改權(quán)限并運(yùn)行frida-server
adb shell
su
cd /data/local/tmp/
chmod 777 frida-server
./frida-server
#如果要啟動(dòng)frida-server作為后臺(tái)進(jìn)程、可以使用這個(gè)命令./frida-server &

6 開(kāi)一個(gè)終端嫉父,使用frida-ps -U命令檢查Frida是否正常運(yùn)行沛硅,如果正常運(yùn)行則會(huì)列出Android設(shè)備上當(dāng)前正在運(yùn)行的進(jìn)程


7 開(kāi)始Hook

利用命令行工具h(yuǎn)ook libc.so的open()函數(shù)

frida這個(gè)命令行工具,可以通過(guò)frida -help 查看
"-U" 參數(shù)代表我們連接的是遠(yuǎn)程USB server绕辖,同理你也可以使用其他參數(shù)來(lái)連接稽鞭,
"-f "參數(shù)則表示在手機(jī)端啟動(dòng)一個(gè)你指定的android程序,那個(gè)FILE則表示應(yīng)用的包名引镊,
通常"-f"這個(gè)參數(shù)配合"--no-pause"參數(shù)來(lái)使用朦蕴,因?yàn)榭赡懿蛔屵M(jìn)程恢復(fù)的話可能會(huì)有奇怪的問(wèn)題,
"-p""-n"命令分別表示attach到進(jìn)程的名字或者pid弟头,
"-l"參數(shù)則是代表需要注入的javascript腳本吩抓,而這個(gè)javascript的腳本就是我們所寫的hook代碼,完成函數(shù)的hook赴恨,內(nèi)存的dump等一系列功能疹娶,

當(dāng)我們使用frida這個(gè)命令行工具成功attach到目標(biāo)進(jìn)程的時(shí)候,frida會(huì)給我們返回一個(gè)Frida CLI伦连,說(shuō)明白點(diǎn)就是一個(gè)交互窗口雨饺,下面我們就能看到
test.js

setImmediate(function() {
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {
        log("open() called!")
    },
    onLeave:function(retval){
    
    }
});
});
bogon:~ ljp$ frida -U -f com.android.chrome --no-pause
     ____
    / _  |   Frida 12.2.28 - 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/
[LGE Nexus 5::com.android.chrome]-> %load /Users/ljp/Documents/frida/test.js 

首先我們知道frida是python的一個(gè)模塊,那么這樣我們當(dāng)然可以通過(guò)寫python腳本import frida來(lái)實(shí)現(xiàn)對(duì)frida的利用惑淳,此外frida同時(shí)會(huì)提供幾個(gè)命令行工具(工具存放在python/Scripts目錄下面额港,所以你可以添加到系統(tǒng)環(huán)境變量方便使用),

# hook chrome進(jìn)程的libc.so中的函數(shù)open
import frida
import sys

device = frida.get_usb_device()
pid = device.spawn(["com.android.chrome"])
session = device.attach(pid)
device.resume(pid)

src = """
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {
        send("open called!");
    },
    onLeave:function(retval){
    
    }
});
"""
def on_message(message ,data):
    print(message['payload'])


script = session.create_script(src)
script.on("message" , on_message)
script.load()
sys.stdin.read()

這個(gè)args其實(shí)就包括我們想要的東西歧焦,
onEnter 表示在函數(shù)調(diào)用之前執(zhí)行的代碼移斩,
onLeave 表示在函數(shù)執(zhí)行后需要執(zhí)行的代碼,所以這個(gè)retval也就包括了返回值绢馍,關(guān)于我們用的Interceptor API向瓷,frida官方的JavaScript API 文檔是這么寫的:

image

Interceptor.attach()第一個(gè)參數(shù)是一個(gè)NativePointer指針,
在之前我們用的Module.findExportByName("libc.so" , "open")的返回值舰涌,關(guān)于Moudle同樣在文檔中可以找到猖任,
第二個(gè)參數(shù)則就是我們的js代碼塊,我們所要的打印參數(shù)與返回值也就是在這里完成瓷耙。

image

我們完善一下代碼朱躺,關(guān)于libc.so的open函數(shù)參數(shù)是這樣定義的,int open( const char * pathname, int flags);

//hook chrome進(jìn)程的libc.so中的函數(shù)open
import frida
import sys
import io
device = frida.get_usb_device()
pid = device.spawn(["com.android.chrome"])
session = device.attach(pid)

scr = """
setImmediate(function() {
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {
        send("open called! args[0]:",Memory.readByteArray(args[0],256));
    },
    onLeave:function(retval){

    }
});
});
"""

def on_message(message ,data):
    file_object=open("/Users/ljp/Documents/frida/log.txt",'ab+')
    file_object.write(message['payload'].encode())
    file_object.write(data.split(b'\x00')[0])
    file_object.write('\n'.encode())
    file_object.close()

script = session.create_script(scr)
script.on("message" , on_message)
script.load()
sys.stdin.read()

細(xì)心的同學(xué)可能會(huì)發(fā)現(xiàn)哺徊,我這次沒(méi)有用spawn()函數(shù)來(lái)啟動(dòng)chrome應(yīng)用室琢,因?yàn)槿绻阆雋ook的動(dòng)作如果不是在程序開(kāi)始就進(jìn)行的話,而是可控的動(dòng)作落追,那么你直接attach到其相應(yīng)的進(jìn)程上就好了盈滴,這樣可以避免我從程序一開(kāi)始就大量hook open,
此次我們啟動(dòng)的方式為python open.py

send("open called! args[0]:",Memory.readByteArray(args[0],256));

可以看到args[0]表示open的第一個(gè)參數(shù),由于我并不知道第一個(gè)參數(shù)的長(zhǎng)度有多長(zhǎng)巢钓,所以我用Memory.readByteArray(args[0],256)來(lái)讀取256個(gè)字節(jié)(文件名一般不會(huì)長(zhǎng)過(guò)256個(gè)字節(jié)吧)
然后傳遞給send(message[, data])的第二個(gè)參數(shù)data病苗,
關(guān)于send(message[, data])的介紹也在官網(wǎng)的JS的API中,如下截圖:

image

可見(jiàn)第二個(gè)參數(shù)是需要ArrayBuffer類型的症汹,而Memory.readByteArray(args[0],256)的返回值剛好是ArrayBuffer類型的硫朦,所以直接傳值就可以。
那么有的同學(xué)會(huì)問(wèn)背镇,如果不是ArrayBuffer類型的怎么辦咬展,比如說(shuō)文檔中的hexdump(target[, options])函數(shù),它的返回值不是ArrayBuffer類型的瞒斩,那么我們就需要利用下面的函數(shù)來(lái)轉(zhuǎn)換:

function str2ab(str) {
            var buf = new ArrayBuffer(str.length); // 1 bytes for each char
            var bufView = new Uint8Array(buf);
            for (var i=0, strLen=str.length; i < strLen; i++) {
                bufView[i] = str.charCodeAt(i);
                }
            return buf;
        }

將上面這段代碼放入hook代碼中破婆,然后調(diào)用它便可以解決問(wèn)題。
數(shù)據(jù)通過(guò)send(message[, data])傳遞給python的on_message(message,data)函數(shù)胸囱。
第一個(gè)參數(shù)message是一個(gè)python字典類型祷舀,message['payload']存放的是send(message[, data])參數(shù)1的內(nèi)容
第二個(gè)參數(shù)data是send(message[, data])的第二個(gè)參數(shù),不過(guò)是以bytes的類型傳遞給python data參數(shù)烹笔。
所以我們寫入文件的話裳扯,如果文件打開(kāi)方式為"ab+"那么直接可以寫進(jìn)去,否則如果是"a+"來(lái)打開(kāi)文件的話谤职,那么需要data.decode()轉(zhuǎn)換為str類型來(lái)寫入饰豺。
那細(xì)心的同學(xué)可能問(wèn)了,你為啥寫的data.split(b'\x00')[0]柬帕,首先我打開(kāi)方式是"ab+"哟忍,所以不需要轉(zhuǎn)換類型,其次由于我之前不知道args[0]有多長(zhǎng)陷寝,所以我讀取了256個(gè)字節(jié),那這256個(gè)字節(jié)肯定不是我全想要的其馏,我們知道文件名中肯定不能存在0x00字節(jié)凤跑,而且C語(yǔ)言中字符串是要以0x00'\0'作為截?cái)嗟模晕矣?strong>split(b'\x00')[0]分割字符串并且取列表中的第一項(xiàng)輸出到文件叛复。

到此我們的open函數(shù)就算是hook完了;

作者:SimonKoh
鏈接:http://www.reibang.com/p/b833fba1bffe
來(lái)源:簡(jiǎn)書
著作權(quán)歸作者所有仔引。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處褐奥。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咖耘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子撬码,更是在濱河造成了極大的恐慌儿倒,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異夫否,居然都是意外死亡彻犁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門凰慈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)汞幢,“玉大人,你說(shuō)我怎么就攤上這事微谓∩瘢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵豺型,是天一觀的道長(zhǎng)仲智。 經(jīng)常有香客問(wèn)我,道長(zhǎng)触创,這世上最難降的妖魔是什么坎藐? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮哼绑,結(jié)果婚禮上岩馍,老公的妹妹穿的比我還像新娘。我一直安慰自己抖韩,他們只是感情好蛀恩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著茂浮,像睡著了一般双谆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上席揽,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天顽馋,我揣著相機(jī)與錄音,去河邊找鬼幌羞。 笑死寸谜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的属桦。 我是一名探鬼主播熊痴,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼聂宾!你這毒婦竟也來(lái)了果善?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤系谐,失蹤者是張志新(化名)和其女友劉穎巾陕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惜论,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年许赃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馆类。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡混聊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乾巧,到底是詐尸還是另有隱情句喜,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布沟于,位于F島的核電站咳胃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏旷太。R本人自食惡果不足惜展懈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望供璧。 院中可真熱鬧存崖,春花似錦、人聲如沸睡毒。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)演顾。三九已至供搀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钠至,已是汗流浹背葛虐。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棉钧,地道東北人挡闰。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像掰盘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赞季,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344