android 怎么调用js项目_APP逆向神器之Frida【Android初级篇】
說到逆向APP,很多人首先想到的都是反編譯,但是單看反編譯出來的代碼很難得知某個(gè)函數(shù)在被調(diào)用時(shí)所傳入的參數(shù)和它返回的值,極大地增加了逆向時(shí)的復(fù)雜度,有沒有什么辦法可以方便地知道被傳入的參數(shù)和返回值呢?
答案是有的,這個(gè)方法就是Hook,Hook的原理簡單地說就是用一個(gè)新的函數(shù)替代掉原來的函數(shù),在這個(gè)新的函數(shù)中你想做什么都可以,為所欲為。
本文中的Frida就是一個(gè)很常用的Hook工具,只需要編寫一段Javascript代碼就能輕松地對指定的函數(shù)進(jìn)行Hook,而且它基本上可以算是全平臺(tái)的(主流平臺(tái)全覆蓋),除了Android以外,iOS和PC端的APP也可以用它來進(jìn)行Hook,非常方便。
那么怎么使用呢?首先我們在Frida官方文檔中的Installation頁可以看到,我們需要有Python環(huán)境,并且用pip安裝一個(gè)叫frida-tools的庫,然后才可以開始使用。
Python環(huán)境相信大家都有了,直接打開命令行,執(zhí)行一波pip install frida-tools吧。
安裝完畢以后,因?yàn)檫@一頁文檔的下半部分用于測試剛裝好的庫是否可用的話過于麻煩,我們這里就直接使用frida-ps命令來測試吧。
看起來是沒問題了,然后我們怎么Hook Android手機(jī)上的APP呢?別急,還需要在手機(jī)上做一些操作你才能這么做。
我們需要有一臺(tái)已經(jīng)Root了的Android手機(jī),因?yàn)椴煌吞柕氖謾C(jī)Root方法存在差異,本文中就不指導(dǎo)如何對手機(jī)進(jìn)行Root操作了,請自行通過搜索引擎查找方法。實(shí)在沒有可以Root的Android手機(jī)的話可以選擇使用模擬器,推薦使用Genymotion之類系統(tǒng)較為原生的模擬器,并將Android版本選擇在6.0以上,否則可能會(huì)出現(xiàn)一些奇奇怪怪的問題。
手機(jī)準(zhǔn)備好了之后,找到Frida文檔中Tutorials欄里的Android頁,開始進(jìn)行Frida的手機(jī)端準(zhǔn)備工作。
文檔中能看到,Frida官方最近的大部分測試都是在運(yùn)行著Android 9的Pixel 3上進(jìn)行的,所以理論上來講如果你在使用中遇到任何奇怪的問題,都可能是你手機(jī)的系統(tǒng)導(dǎo)致,所以這里再次建議,使用較為原生和偏高版本的系統(tǒng)(建議至少6.0)進(jìn)行操作。
接著往下看,我們需要在手機(jī)上以Root權(quán)限運(yùn)行一個(gè)叫frida-server的東西,這個(gè)東西需要在Frida官方的GitHub倉庫中下載,文檔中有鏈接可以直接跳轉(zhuǎn)。
打開GitHub之后你會(huì)發(fā)現(xiàn),這里有很多個(gè)不同的版本,應(yīng)該下載哪一個(gè)呢?
可以看到這一排的文件中,末尾處都有個(gè)系統(tǒng)和CPU架構(gòu)的標(biāo)識(shí),我們直接看Android的。這里標(biāo)了Android的一共有四個(gè),然后X86的因?yàn)椴皇鞘謾C(jī)使用的CPU架構(gòu),可以直接pass掉,剩下的就是arm和arm64兩種了,那么我們需要怎么判斷自己的手機(jī)/模擬器屬于哪一種CPU架構(gòu)的呢?
查CPU架構(gòu)的方法很多,這里介紹一個(gè)比較方便快捷的——使用一個(gè)名叫Device Info HW的APP。
安裝后打開它,在芯片欄中我們可以看到一個(gè)叫ABI的東西,右邊就是我們手機(jī)的CPU架構(gòu)了,如下:
所以這里我需要下載的是arm64版本的frida-server,下載后解壓出來一個(gè)沒后綴的文件,然后我們需要將這個(gè)文件放入手機(jī)中運(yùn)行起來。先把這個(gè)文件的名字改成frida-server,然后在這個(gè)文件所在的目錄下打開命令行(Windows下為Shift+鼠標(biāo)右鍵,選擇“在此處打開CMD/PowerShell”),執(zhí)行以下命令:
1adb?root2adb?push?frida-server?/data/local/tmp/?
3adb?shell?"chmod?755?/data/local/tmp/frida-server"
4adb?shell?"/data/local/tmp/frida-server?&"
如果你的手機(jī)和我的一樣,直接這么運(yùn)行會(huì)提示權(quán)限不足的話,可以先進(jìn)入adb shell,在執(zhí)行su命令獲取Root權(quán)限后(手機(jī)端可能會(huì)彈出Root授權(quán)提示),再運(yùn)行/data/local/tmp/frida-server &啟動(dòng)frida-server。
啟動(dòng)后,我們先照慣例來測試一下是否能正常使用了,和前面一樣,使用frida-ps命令,但在后面加一個(gè)-U參數(shù),這個(gè)參數(shù)的意思是讓它對USB連接的設(shè)備操作,如果不出意外的話,你應(yīng)該能看到與不加-U參數(shù)時(shí)截然不同的顯示。
至此,所有準(zhǔn)備工作均已完成。
小提示:在手機(jī)重啟后需要重新運(yùn)行一次frida-server,但可以不重新執(zhí)行adb push操作,因?yàn)槲募呀?jīng)放進(jìn)去了。
終于到了喜聞樂見的實(shí)戰(zhàn)環(huán)節(jié)了,就拿Frida官方文檔中的提到的CTF APP來開刀吧,找到文檔中Examples欄里的Android頁,經(jīng)過幾次跳轉(zhuǎn)后下載APP安裝、打開,會(huì)看到這樣的一個(gè)界面:
這個(gè)APP是一個(gè)石頭剪子布的游戲,點(diǎn)擊下面三個(gè)按鈕分別選擇石頭、剪子、布,玩起來的時(shí)候是這么一個(gè)效果(加號后面的是得分值,正常情況下連勝會(huì)每次在原來的基礎(chǔ)上+1):
我們先做個(gè)比較簡單的操作吧,讓我們的每次出招都必勝~先復(fù)制一下文檔中的代碼,建一個(gè).py文件粘貼進(jìn)去,將this.cnt.value = 999;這一條刪除或注釋掉,然后運(yùn)行這個(gè)python腳本,在注入完成后,不管你怎么點(diǎn),你都是必定勝利的,如下圖:
注:圖中左下方顯示的是Hook時(shí)產(chǎn)生的日志,其中value是得分值。
但是這樣子弄,如果我們需要讓分值達(dá)到很高的話,就需要點(diǎn)很多次了,怎么讓它一次就加到999呢?很簡單,直接把得分值也給改了就好了,我們把前面去掉的this.cnt.value = 999;再改回來,然后重新運(yùn)行一遍這個(gè)腳本。
正常情況下這個(gè)分值會(huì)是一個(gè)+999,這里顯示成這樣是因?yàn)檫@個(gè)樣例APP太老了,不兼容新版本系統(tǒng),導(dǎo)致出現(xiàn)這種情況,換舊版本系統(tǒng)可解,所以這里不糾結(jié)這個(gè)問題。
單看這么一通操作是不是覺得很懵?復(fù)制過來的代碼是干啥的都不知道,如果換一個(gè)APP咋搞?不慌,我把這個(gè)代碼的意思一行一行地給你解釋一遍,你就知道怎么用了。
首先import不用說了吧,大家都懂,直接看on_message這個(gè)函數(shù)。這個(gè)on_message的用途是接收下面Javascript代碼中調(diào)用send函數(shù)傳出的日志,通常我們可以不用管它,直接復(fù)制出來用就行了,或者可以使用console.log打日志,效果也是差不多的。
然后是jscode這個(gè)變量,這個(gè)變量其實(shí)建議使用一個(gè)單獨(dú)的.js文件代替,因?yàn)檫@樣的話可以使用各種編輯器、IDE的JavaScript代碼格式化、智能提示等功能,寫起來會(huì)舒服很多。如果你要替換掉的話,改成讀JS代碼文件之后read出內(nèi)容字符串賦值給jscode就行了。
接著是JS代碼中的部分。
先看看Java.perform,在Frida官方文檔的javascript-api頁中可以看到,它的用途是確保當(dāng)前線程已連接到VM用的,所以我們直接照著這么用就行了;
然后看看Java.use這個(gè)函數(shù),它的用途是獲取一個(gè)指向某個(gè)類的指針,參數(shù)中的com.example.seccon2015.rock_paper_scissors.MainActivity就是我們需要Hook的那個(gè)類;
接著就是真正執(zhí)行Hook的部分了,這個(gè)代碼中使用了一個(gè)MainActivity.onClick.implementation,意思就是Hook前面獲取到的類中的onClick方法,后面跟著的賦值函數(shù)的部分,函數(shù)的參數(shù)為對應(yīng)要Hook方法的參數(shù),內(nèi)部執(zhí)行的部分就是在對應(yīng)方法被調(diào)用時(shí)所執(zhí)行的代碼,這里它是先打了一個(gè)onClick日志,然后調(diào)用了原始方法(如果不調(diào)用的話原始方法不會(huì)被執(zhí)行),接著它將m、n、cnt(變量具體含義請自行反編譯APP后查看代碼)的值做了修改,最后,它又打了一個(gè)攜帶著cnt變量值的日志。
最后是一些常規(guī)操作,frida.get_usb_device().attach()是獲取指定APP(參數(shù)為包名)當(dāng)前運(yùn)行著的進(jìn)程,process.create_script(jscode)、script.load()是將前面的JS代碼注入進(jìn)去,script.on('message', on_message)是設(shè)置消息傳出時(shí)的回調(diào),最后的sys.stdin.read()是輸出日志用的。
總之,除了JS代碼部分,其他的其實(shí)只是個(gè)殼子,核心的Hook操作邏輯全在JS代碼中,我們在使用時(shí)一般只改JS代碼部分和指定包名的部分就可以了。
看了這一篇文章后你應(yīng)該會(huì)對使用Frida對Android手機(jī)上Java層的Hook有所了解了吧,如果覺得玩Frida官方文檔中的這個(gè)石頭剪子布APP不夠刺激,還可以看看我前面的《當(dāng)你寫爬蟲遇到APP的請求有加密參數(shù)時(shí)該怎么辦?【初級篇-秒殺模式】》這篇文章,里面使用的DEMO APP是有SSL Pinning、且對代碼進(jìn)行了混淆的,希望你能夠舉一反三,自己寫出一個(gè)干掉這個(gè)SSL Pinning的腳本。(如果還不會(huì)的話可以看更前面的《當(dāng)你寫爬蟲抓不到APP請求包的時(shí)候該怎么辦?【高級篇-混淆導(dǎo)致通用Hook工具失效】》這篇文章)
發(fā)送消息“Frida Android初級篇”到我的公眾號【小周碼字】即可獲得代碼和APP的下載地址~
這個(gè)時(shí)代各種東西變化太快,而網(wǎng)絡(luò)上的垃圾信息又很多,你需要有一個(gè)良好的知識(shí)獲取渠道,很多時(shí)候早就是一種優(yōu)勢,還不趕緊關(guān)注我的公眾號并置頂/星標(biāo)一波~?
總結(jié)
以上是生活随笔為你收集整理的android 怎么调用js项目_APP逆向神器之Frida【Android初级篇】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php页面不断弹出值_电脑自动弹出网页怎
- 下一篇: m1笔记本android开发,Apple