當前位置:
首頁 > 新聞 > AssetHook:Android應用資源數據運行時編輯工具

AssetHook:Android應用資源數據運行時編輯工具

AssetHook是一個工具,它可以讓Android安全研究人員和普通用戶能夠在無需修改APK本身的情況下隨時修改Android應用程序的部分Asset。這樣的修改使研究人員可以改變嵌入式數據,以更好地評估和測試移動應用程序。目前來看AssetHook比現有方法更容易使用,且比傳統方法更有效。

背景

去年年底,我開始關注Android啟用React Native 後 Facebook的新框架,它將跨平台移動開發統一到JavaScript,顯然JavaScript是一種不需要介紹的語言。在React Native之前,在JavaScript中構建跨平台移動應用程序的主要方法是使用PhoneGap(...或者現在是Cordova嗎?甚至不讓我從Ionic開始)。這些都是基於將JavaScript載入到Webview中(UIWebView在iOS上,WebView在Android上)的主要應用程序邏輯。然後,開發人員可以在平台的「本機」語言中編寫一些平台特定的代碼,並將它們與幽靈一般的webview魔術FFI連接在一起。

React Native將這種設計(也可能是理由)一腳踢開,然後顛覆了傳統。它不是使用webview和HTML / CSS進行渲染,它將JavaScript聲明的UI映射到平台的本地UI工具包,並嵌入WebKit的JavaScriptCore(JSC)庫來運行該JavaScript,完全避免了平台的Webview實現。JSC支持在沒有JIT的情況下解釋JavaScript,這在iOS上是必需的,因為它的安全模型是基於不允許任何人生成可執行內存的(而且人們說OpenBSD的人是Luddites for W ^ X ...); 最後我檢查過,V8隻是JIT(新的ignition interpreter似乎並沒有改變,因為「 JIT代碼生成仍然是IC和代碼存根 」)。

Android使用AssetManager該類作為應用程序的界面來訪問嵌入在其APK中的特定類型的文件資源(特別是APK中的assets/目錄中)。鑒於我知道(從開放一個發布版本的React Native應用程序)主要的後處理JavaScript軟體包作為資產存儲,所以hook不起作用是非常奇怪的。然後,我通過React Native的Android代碼庫開始測試,很快就發現使用C API為Android的資產管理器載入了C ++代碼,這解釋了為什麼Java函數掛起不起作用。

因為我想要修改這些軟體包的內容,而不需要創建和簽名修改的APK(然後需要更多的hook來欺騙他們的簽名),我設置了構建一個工具來hook這些資源負載。我在C ++中寫了最初的POC,然後在Rust中重寫。

(A)AssetHook

如果沒有像AssetHook這樣的東西的話,替換Android資產將需要解壓APK,替換資產文件,重新打包APK,可能會重新對齊,簽署新的APK文件,然後安裝它。這不但是一個繁瑣和緩慢的過程(特別是APK複製到設備並為更大的應用程序安裝過程),還必須處理新的簽名打破跨應用程序簽名檢查的後果。對於使用自定義許可權,共享用戶ID或自定義IPC訪問控制的應用程序組,此新簽名將阻止修改的應用程序與其他應用程序進行交互或完全不起作用。然後需要額外的hook來欺騙修改後的APK的簽名證書以匹配原來的APK。此外,如果沒有更多根深蒂固和靈活的功能hook基礎架構(例如修改系統分區二進位文件的Xposed),這種hook在Android上可能是不可能的。使用這種框架的一個關鍵問題是由於需要移植工作,因此必然會延遲支持新的Android版本。

C API Hooking 使用了 LD_PRELOAD

C API hooking變體(「AAssetHook」)是由vanilla的 LD_PRELOADhook來實現的,它聲明了一些重複的函數符號,儘管動態鏈接的魔力 - 在從其二進位文件外部訪問時重寫對這些函數的調用。然後在dlopen(3)/ dlsym(3)(在Unix上)使用一個Rust包裝庫來根據需要代理對原始函數的調用。之後,它會檢查一個APK中的給定文件路徑是否與設備文件系統上的現有路徑匹配,並欺騙C API返回磁碟文件的文件內容,而不是in-

C++ API Hooking 使用了 LD_PRELOAD

由於資產管理器的C ++實現不是公共API,C ++ APIhook變體(「AssetHook」)稍微複雜一點,這在很大程度上依賴於多態性,並且在較小的Android版本中可能會發生變化。當在C ++中使用多態時,通常將通過動態調度處理虛擬方法調用。在大多數「平穩」平台上,通過將虛擬表(vtable)指針作為類的內存結構的第一個元素之一來實現。該指針在構造期間設置,並指向一個填充有該類使用的特定虛擬方法的函數指針的表。LD_PRELOAD在這種情況下,函數hook非常有限,因為它只能掛接導出符號的二進位函數調用,而動態調度調用則使用直接函數指針。這樣可以避免基於vtable的呼叫被LD_PRELOAD符號覆蓋直接掛起。此外,這些函數指針的順序很可能會在次級類定義更改時發生更改。在不同的編譯器之間也是不一致的,通常可能難以推斷出多個版本的二進位文件。

注意:這完全取決於編譯器,但是這一點在Unix上的Clang和GCC(至少對於x86 / amd64和ARM / AArch64來說都是一致的)。

例如,下面的代碼片段的對象可以被布置,如下圖所示:

#include struct Base {

virtual void foo() {

puts("base!");

}

size_t a = (size_t)-};struct Derived : public Base {

virtual void foo() {

puts("derived!");

}

size_t b = (size_t)-};struct DDerived : public Derived {

void foo() final override {

puts("dderived!"); } size_t c = (size_t)-};void call_foo(Base& br.foo();}int main() {

Base b;

Derived d;

DDerived dd;

call_foo(b);

call_foo(d);

call_foo(dd);

return 0;}

功能搜索和vtable插槽映射

處理vtable排序的波動的一種方法是將給定的類「vtable」與其二進位文件的符號表進行交叉引用(用binutils的GPL bfd.h或libelfin解析)。使用手中的函數地址,可以對vtable進行交叉引用以找到其偏移量。然而,這可能不起作用,因為一些虛擬方法函數可能沒有符號,就像Android資產管理器的C ++實現一樣。另一種方法是掃描這種不符號的函數的原始位元組,但這不太可能跨越多個二進位版本。

事實上,這是完全可能的(使用類似Capstone的東西)去解析調用目標類的虛擬方法並提取這些方法的vtable偏移量的符號符號函數的彙編。

vtable Slot Knocking

AssetHook的C ++ APIhook實現使用了最後一種方法的一個變體,依靠這樣一個事實,即將虛擬方法調用的C API本身就是具有ABI穩定性保證的公共API。AssetHook不是分析C API函數的指令來剔除vtable偏移量,而是創建一個假的C ++對象,並使用它來配置vtable。該對象vtable指針指向一個虛構的vtable,其中包含一系列報告調用順序的函數指針。AssetHook將該對象作為嵌入到void*掩碼包裝結構體中的指針傳遞給C API,然後C API通過編譯器提供的偏移量調用關聯的虛擬方法。執行此調用時,將觸發嵌入式函數指針,暴露給定操作的vtable偏移量。這允許通過調用這個假的對象上已知的C API函數來逐個獲取實際的vtable順序,以獲得它們包裝的C ++方法的vtable偏移量。

注意:對於特殊的涉及 thunk的 「複雜」類,需要更加動態地分析vtable,因為類別的vtable段中的「正常」成員函數指針實際上是由編譯器生成的包裝函數。該函數相應地移動this指針,並從實際類的更大的vtable中的其他地方調用「真實」成員函數指針。

hook虛擬方法

之後,在返回對象指針LD_PRELOAD的AssetManager類的「公共」非虛擬方法的變形符號名稱上創建一個類型的hookAsset。這個hook確定文件是否應該被hooking,如果是這樣,返回一個指向一個修改後的Asset對象的指針,其中一個vtable包含了函數hook。

例子:

在這個例子中,我們將使用AssetHook將我們自己的JavaScript文件交換到Tic-tac-toe示例應用程序中(參考React Native文檔,我必須傳遞--dev false給react-native build它來使其大部分應用程序成為最小化的)。我們假設您按照文件中的描述安裝了它。

1、安裝一個「release」版本的應用程序(為了儘可能的縮小,AssetHook可以同時發布和調試Android APK版本)在一個根深蒂固的測試設備上(AssetHook已知可以與Android 5.x,6.x和7.x一起用32位和64位ARM,以及32位x86上的Android O Developer Preview)。

2、從APK文件中提取assets/index.android.bundle(從嵌入的Android來源app/build目錄或使用該設置adb shell pm list packages -f | grep

和adb pull)。

3、修改文件並注入JavaScript alert(...)。

4、運行以下命令:

$ adb push path/to/index.android.bundle /data/local/tmp/assethook/

/assets/

$ adb shell su -c setprop wrap.

LD_PRELOAD=/data/local/tmp/lib/libassethook_cppapi.so

注意: React Native使用32位二進位文件,甚至在64位Android上。因此,32位模式下進程載入,我們需要使用32位版本的AssetHook。

5、啟動應用程序(如果已經打開,請先關閉它)。

未來的工作

主要優先事項是在執行模式下完全啟用SEAndroid時支持Android。現在,AssetHook要求將SELinux置於允許模式,因為替換文件存在於Google試圖通過SELinux限制訪問現代Android版本的共享臨時目錄中。我正在尋求支持從應用程序自己的內部目錄載入替換資產文件,但這可能需要額外的工具來將文件上傳到設備上。

本文翻譯自

https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2017/may/assethook-a-redirector-for-android-asset-files-using-old-dogs-and-modern-tricks/

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

有了郵件防火牆你就安全了嗎?想法太單純了……
美國國防部承包商使用亞馬遜伺服器,一不小心泄露了機密文件
Check Point:神秘中國公司製作惡意廣告軟體,感染全球超2.5億台設備
Google 404頁面暗藏漏洞,可泄漏伺服器內部信息
界面大革新,只為更卓越的信息安全新媒體

TAG:嘶吼RoarTalk |

您可能感興趣

Google 的 Fuchsia OS 將能運行 Android 應用
Google 的新開源系統 Fuchsia OS 將支持 Android 應用運行
使用Wine 3.0在Android設備上運行Windows應用程序
Android端運行Tensorflow的demo去分類自己的數據集
谷歌新系統Fuchsia OS將能運行Android應用 為 Fuchsia 建構 ART
用英偉達Jetson Nano運行PyTorch&Fast.ai
微軟發布Windows Defender System Guard運行時認證技術
不只是Android:Chromebook現能運行Linux應用了
Surface Phone蹤跡再現:運行Andromeda系統
Anbox:在 Linux 上運行 Android 應用程序的簡單方式
Chromebook將能夠運行Linux應用 Pixelbook搶鮮
Motorola One/One Power發布:運行Android One
在 Kubernetes 上運行一個 Python 應用程序
LinkedIn 開源 TonY:在 Hadoop 上運行 TensorFlow 的框架
LinkedIn 開源 TonY:在 Hadoop 上運行 TensorFlow 的框架
[圖]Chrome OS新功能:像原生應用運行Progressive Web Apps
通過 Docker 實現在 Linux 容器中運行 Microsoft SQL Server 資料庫
運行Android Go!諾基亞Nokia 1 Plus泄露
使用Mono將C#編譯運行至WebAssembly平台
Pixel 3a/XL現身Google Play:運行Android 9 Pie