隨着移動安全愈來愈火,各類調試工具也都層出不窮,但由於環境和需求的不一樣,並無工具是萬能的。另外工具是死的,人是活的,若是能搞懂工具的原理再結合上自身的經驗,你也能夠創造出屬於本身的調試武器。所以,筆者將會在這一系列文章中分享一些本身常常用或原創的調試工具以及手段,但願能對國內移動安全的研究起到一些催化劑的做用。java
目錄以下:
安卓動態調試七種武器之長生劍 - Smali Instrumentation
安卓動態調試七種武器之孔雀翎 – Ida Pro
安卓動態調試七種武器之離別鉤 – Hooking (上)
安卓動態調試七種武器之離別鉤 – Hooking (下)
安卓動態調試七種武器之碧玉刀- Customized DVM
安卓動態調試七種武器之多情環- Customized Kernel
安卓動態調試七種武器之霸王槍 - Anti Anti-debugging
安卓動態調試七種武器之拳頭 - Tricks & Summarypython
文章中全部提到的代碼和工具均可以在個人github下載到,地址是: https://github.com/zhengmin1989/TheSevenWeaponsandroid
咱們在離別鉤(上)中已經能夠作到動態的加載自定義so文件而且運行so文件中的函數了,但還不能作到hook目標函數,這裏咱們須要用到函數掛鉤的技術來作到這一點。函數掛鉤的基本原理是先用mprotect()將原代碼段改爲可讀可寫可執行,而後修改原函數入口處的代碼,讓pc指針跳轉到動態加載的so文件中的hook函數中,執行完hook函數之後再讓pc指針跳轉回本來的函數中。git
用來注入的程序hook5邏輯與以前的hook4相比並無太大變化,僅僅少了「調用 dlclose 卸載so文件」這一個步驟,由於咱們想要執行的hook後的函數在so中,因此並不須要調用dlclose進行卸載。基本步驟以下:github
保存當前寄存器的狀態 -> 獲取目標程序的mmap, dlopen, dlsym, dlclose 地址 -> 調用mmap分配一段內存空間用來保存參數信息 –> 調用dlopen加載so文件 -> 調用dlsym找到目標函數地址 -> 使用ptrace_call執行目標函數 -> 恢復寄存器的狀態算法
hook5的主要代碼邏輯以下:
數組
咱們知道arm處理器支持兩種指令集,一種是arm指令集,另外一種是thumb指令集。因此要hook的函數多是被編譯成arm指令集的,也有多是被編譯成thumb指令集的。Thumb指令集能夠看做是arm指令壓縮形式的子集,它是爲減少代碼量而提出,具備16bit的代碼密度。Thumb指令體系並不完整,只支持通用功能,必要時仍須要使用ARM指令,如進入異常時。須要注意的一點是thumb指令的長度是不固定的,但arm指令是固定的32位長度。緩存
爲了讓你們更容易的理解hook的原理,咱們先只考慮arm指令集,由於arm相比thumb要簡單一點,不須要考慮指令長度的問題。因此咱們須要將target和hook的so編譯成arm指令集的形式。怎麼作呢?很簡單,只要在Android.mk中的文件名後面加上」.arm」便可 (真正的文件不用加)。
安全
肯定了指令集之後,咱們來看實現掛鉤最重要的邏輯,這個邏輯是在注入後的so裏實現的。首先咱們須要一個結構體保存彙編代碼和hook地址:
微信
咱們接着來看注入的邏輯,最重要的函數爲hook_direct(),他有三個參數,一個參數是咱們最開始定義的用來保存彙編代碼和hook地址的結構體,第二個是咱們要hook的原函數的地址,第三個是咱們用來執行hook的函數。函數的源碼以下:
雖然android有ASLR,但並無PIE,因此program image是固定在0x8000這個地址的,所以咱們用mprotect()函數將整個target代碼段變成RWX,這樣咱們就能修改函數入口處的代碼了。是否修改爲功能夠經過cat /proc/[pid]/maps查看:
隨後咱們須要肯定目標函數的地址,這個有兩種方法。若是目標程序自己沒有被strip的話,那些symbol都是存在的,所以可使用dlopen()和dlsym()等方法來獲取目標函數地址。但不少狀況,目標程序都會被strip,特別是能夠直接運行的二進制文件默認都會被直接strip。好比target中的sevenWeapons()這個函數名會在編譯的時候去掉,因此咱們使用dlsym()的話是沒法找到這個函數的。這時候咱們就須要使用ida或者objdump來定位一下目標函數的地址。好比咱們用objdump找一下target程序裏面sevenWeapons(int number)這個函數的地址:
雖然target這個binary被strip了,但仍是能夠找到sevenWeapons()這個函數的起始地址是在0x84f4。由於」mov r2, r0」就是加載number這個參數的指令,隨後調用了<printf@plt>用來輸出結果。 最後一個參數也就是咱們要執行的hook函數的地址。獲得這個地址很是簡單,由於是so中的函數,調用hook_direct()的時候直接寫上函數名便可。
hook_direct(&eph,hookaddr,my_sevenWeapons);
接下來咱們看如何修改函數入口(modify function entry),首先咱們保存一下原函數的地址和那個函數的前三條指令。隨後咱們把目標函數的第一條指令修改成 LDR pc, [pc, #0],這條指令的意思是跳轉到PC指針所指的地址,因爲pc寄存器讀出的值其實是當前指令地址加8,因此咱們把後面兩處指令都保存爲hook函數的地址,這樣的話,咱們就能控制PC跳轉到hook函數的地址了。
最後咱們再調用hook_cacheflush()這個函數來刷新一下指令的緩存。由於雖然前面的操做修改了內存中的指令,但有可能被修改的指令已經被緩存起來了,再執行的話,CPU可能會優先執行緩存中的指令,使得修改的指令得不到執行。因此咱們須要使用一個隱藏的系統調用來刷新一下緩存。hook_cacheflush()代碼以下:
刷新完緩存後,再執行到原函數的時候,pc指針就會跳轉到咱們自定義的hook函數中了,hook函數裏的代碼以下:
首先在hook函數中,咱們能夠得到原函數的參數,而且咱們能夠對原函數的參數進行修改,好比說將數字乘2。隨後咱們使用hook_precall(&eph);將本來函數的內容進行還原。hook_precall()內容以下:
在hook_precall()中,咱們先對本來的三條指令進行還原,而後使用hook_cacheflush()對內存進行刷新。通過處理以後,咱們就能夠執行原來的函數orig_sevenWeapons(number)了。執行完後,若是咱們還想再次hook這個函數,就須要調用hook_postcall(&eph)將本來的三條指令再進行一次修改。
下面咱們來使用hook5和libinject2.so來注入一下target這個程序:
能夠看到通過注入後,咱們成功的獲取了參數number的值,而且將」Hello,LiBieGou!」後面的數字變成了原來的兩倍。
咱們在上一節中介紹瞭如何hook native層的函數。下面咱們再來說講如何利用adbi來hook JNI層的函數。Adbi是一個android平臺上的一個注入框架,自己是開源的。Hook的原理和咱們以前介紹的技術是同樣的,這個框架支持arm和thumb指令集,也支持經過字符串定位symbol函數的地址。
首先咱們須要一個例子用來說解,因此我寫了程序叫test2。
enter image description here
點擊程序中的button後,程序會調用so中的Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI(JNIEnv* env,jobject thiz,jint a,jint b)函數用來計算a+b的結果。咱們默認傳的參數是a=1, b=1。接下來我就來教你如何利用adbi來hook這個JNI函數。
由於adbi是一個注入框架,咱們下載好源碼後,只要對應着源碼中給的example照貓畫虎便可。Hijack那個文件夾是保存的用來注入的程序,和咱們以前講的hook5.c的原理是同樣的,因此不用作任何修改。咱們只須要修改example中的代碼,也就是將要注入的so文件的源碼。
首先,咱們在/adbi-master/instruments/example這個文件夾下新建兩個文件」hookjni.c」和」 hookjni_arm.c」。「hookjni_arm.c」其實只是一個殼,用來將hook函數的入口編譯成arm指令集的,內容以下:
這個文件的目的僅僅是爲了用arm指令集進行編譯,能夠看到Android.mk中在」hookjni_arm.c」後面多了個」.arm」:
下面咱們來看」hookjni.c」:
這段代碼和我上一節講的代碼很是像,my_init()用來進行hook操做,咱們須要提供想要hook的so文件名和函數名,而後再提供thumb指令集和arm指令集的hook函數地址。
my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI()就是咱們提供的hook函數了。咱們在這個hook函數中把a和b都改爲了10。除此以外,咱們還使用counter這個全局變量來控制hook的次數,這裏咱們把counter設置爲3,當hook了3次之後,就再也不進行hook操做了。
編輯好代碼後,咱們只須要在adbi的根目錄下執行」 build.sh」進行編譯:
編譯好後,咱們把hijack和libexample.so拷貝到/data/local/tmp目錄下。而後使用hijack進行注入:
而後咱們再點擊button就能夠看到咱們已經成功的修改了a和b的值爲10了,最後顯示1+1=20。
經過cat adbi_example.log咱們能夠看到hook過程當中打印的log:
能夠看到adbi是經過thumb指令集進行hook的,緣由是test2程序是用thumb指令集進行編譯的。其實hook thumb指令集和arm指令集差很少,在」/adbi-master/instruments/base」中能夠找到hook thumb指令集的邏輯:
其實h->jumpt[20]這個字符數組保存的就是thumb指令集下控制pc指針跳轉到hook函數地址的代碼。Hook完以後的流程就和arm指令集的hook同樣了。
關於Cydia和Xposed的文章和例子已經不少了,這裏就再也不重複的進行介紹了。這裏推薦一下瘦蛟舞和我寫的文章,基本上就知道怎麼使用這兩個框架了:
Android.Hook框架xposed篇(Http流量監控) http://drops.wooyun.org/papers/7488
Android.Hook框架Cydia篇(脫殼機制做) http://drops.wooyun.org/tips/8084
手把手教你當微信運動第一名 – 利用Android Hook進行微信運動做弊 http://drops.wooyun.org/tips/8416
我的感受Xposed框架要作的更好一些,主要緣由是Cydia的做者已經好久沒有更新過Cydia框架了,不光有不少bug還不支持ART。可是有不少不錯的調試軟件/插件是基於兩個框架製做的,因此有時候仍是須要用到Cyida的。
接下來就推薦幾個很實用的基於Cydia和Xposed的插件:
ZjDroid: ZjDroid是基於Xposed Framewrok的動態逆向分析模塊,逆向分析者能夠經過ZjDroid完成如下工做: 一、DEX文件的內存dump 二、基於Dalvik關鍵指針的內存BackSmali,有效破解主流加固方案 三、敏感API的動態監控 四、指定內存區域數據dump 五、獲取應用加載DEX信息。 六、獲取指定DEX文件加載類信息。 七、dump Dalvik java堆信息。 八、在目標進程動態運行lua腳本。 https://github.com/halfkiss/ZjDroid
XPrivacy: XPrivacy是一款基於Xposed框架的模塊應用,能夠對全部應用可能泄露隱私的權限進行管理,對禁止可能會致使崩潰的應用採起欺騙策略,提供僞造信息,好比說能夠僞造手機的IMEI號碼等。 https://github.com/M66B/XPrivacy
Introspy: Introspy是一款能夠追蹤分析移動應用的黑盒測試工具而且能夠發現安全問題。這個工具支持不少密碼庫的hook,還支持自定義hook。 https://github.com/iSECPartners/Introspy-Android
咱們使用alictf上的evilapk400做爲例子講解如何利用introspy來調試程序。Evilapk400使用了比較複雜的dex加殼技術,若是不利用基於自定義dalvik的脫殼工具來進行脫殼的話作起來會很是麻煩。但咱們若是換一種思路,直接經過動態調試的方法來獲取加密算法的字符串,key和IV等信息就能夠直接獲取答案了。
首先咱們安裝cyida.apk,Introspy-Android Config.apk到手機上,而後用eclipse打開「Introspy-Android Core」的源碼增長一個自定義的hook函數。雖然Introspy默認對密碼庫進行了hook,但卻沒有對一些strings的函數進行hook。因此咱們手動添加一個對String.equals()的hook:
而後咱們編譯,生成並安裝Introspy-Android Core.apk到手機上。而後咱們安裝上EvilApk400。而後打開Introspy-Android Config勾選com.ali.encryption。
接着打開evilapk400,而後隨便輸入點內容並點擊登錄。
而後咱們使用adb logcat就能看到Introspy輸出的信息了:
經過log,很容易就能看出來evilapk400使用了DES加密。經過log咱們獲取了密文,Key以及IV,因此咱們能夠寫一個python程序來計算出最後的答案:
本篇介紹了native層,JNI層以及JAVA層的hook,基本上能夠知足咱們平時對於android上hook的需求了。 另外文章中全部提到的代碼和工具均可以在個人github下載到,地址是: https://github.com/zhengmin1989/TheSevenWeapons
Android平臺下hook框架adbi的研究(下)http://blog.csdn.net/roland_sun/article/details/36049307
ALICTF Writeups from Dr. Mario
做者:蒸米@阿里聚安全,更多技術文章,請訪問阿里聚安全博客