ARM64下的Android Native Hook工具實踐(未完成)
本文講的是 Android-Native-Hook-Practice/" rel="nofollow,noindex" target="_blank">Android Native Hook工具實踐 一文的後續。為了使得安全測試人員可以在ARM64的手機上進行Android Native Hook而繼續做的一些工作。
本文對測試機環境配置的要求較高,文中使用的裝置是Pixel。
背景
ARM64的手機晶片是向下相容ARM32和Thumb-2指令集的,這也導致許多App其實並沒有管使用者手機是32位的還是64位的,依然只在apk中打包32位的.so而並沒有arm64-v8a的so檔案。並且有的App的32位so還不是armeabi-v7a,例如微信依然在使用ARMv5,這個架構老得連Thumb-2都不支援。由此可見市面上相當多的App其實並沒有急著去使用ARM64。
第一部64位的谷歌親兒子手機是2015年的nexus 6p,它搭載了高通的第一個ARM64架構的晶片——驍龍810。而最後一部32位的谷歌親兒子手機是2014年的nexus 5。也就是說nexus 5已經發布4年了,我們且不討論一部手機能不能正常工作4年,但它的效能是肯定已經開始跟不上當前的許多使用者需求了。我的nexus 5測試機在僅僅安裝了微信,QQ等5個常用App後的不久便開始卡了起來。
2018年初的時候Android 4.4及以前的手機比例已經低於30%了,Nexus 5也是最後一部能刷Android 4.4的谷歌親兒子,多巧啊。當初做這個Native Hook工具的初衷就是認為Android 4.4及之前的手機在市面上的比例在未來的幾年會進一步縮小,測試人員遲早需要面對在5.0以上的測試機環境中進行安全測試的情況,因為2015年後釋出的手機幾乎出廠設定版本都高於Android 5.0,再沒有4.4的手機給我們用了。
也許這些Neuxs 5同時代的手機可以用模擬器模擬,但是目前反模擬器技術也是一大熱門,在測試前先過掉各個App的反模擬器檢測會耽誤不少功夫。
因此,過不了幾年,等32位手機急劇下降到一定比例的時候,不少App會為了追求更高的效能而選擇ARM64的。因此有必要對ARM64指令集進行一定的知識儲備和工具開發。
環境準備
想要開發這個工具,那我至少需要一個ARM64的執行環境,有如下三種選擇:
採用
那麼選哪款谷歌親兒子好呢?
採用
刷什麼系統?
採用
如何獲取ROOT許可權並搭建基本除錯環境?
- Kingroot等root工具都失敗了
- twrp+Magisk——可以獲得ROOT許可權,但Magisk與正常的Xposed框架存在衝突,只能使用Magisk定製版的Xposed,但那個不穩定,老是使得手機在開機畫面中無線迴圈。
- twrp+SuperSU——可以獲得ROOT許可權,但發現在企圖把IDA pro的除錯服務端android-server64放入/system/bin下時會報錯:read-only file system。這個錯誤按理來說用
adb root
adb remount
就能解決了,但這裡並沒有效果,直接使用mount
命令也無果,最後使用需要執行adb disable verity
而這條命令在官方編譯好的user版本系統中並沒有執行許可權。 - AOSP——由於眾所周知的原因國內對AOSP的編譯工作會比國外麻煩,下載程式碼的過程也不能按照官方教程來進行。最後編譯上的小錯誤也很多,每次編譯時間長,磁碟佔用超過了150GB。但是現在我也只能靠它了。
採用
AOSP編譯哪個版本?
採用
系統編譯好刷好機以後,開始打算按照老套路,裝個Xposed來載入我們的so檔案從而開展Native Hook的工作。但是產生了一系列的報錯,經過測試和推測,最終的原因應該是Android 7.0之後對於非公開API的呼叫限制。這下就得先解決這個問題,否則我們的so根本就載入不起來。有如下幾條路讓我選擇:
採用
那為什麼要做ARM64上的Android Native Hook?
原因
Some e-mails was sent to me about the B..
problems. They find I change BLS to BHI, BNE to BEQ and they think I make a mistake. In fact, I changed them all :
- BEQ –> BNE
- BNE –> BEQ
- BCS –> BCC
- BCC –> BCS
- BMI –> BPL
- BPL –> BMI
- BVS –> BVC
- BVC –> BVS
- BHI –> BLS
- BLS –> BHI
- BGE –> BLT
- BLT –> BGE
- BGT –> BLE
- BLE –> BGT
But I do this on purpose. Let’s see the picture below, it’s beautiful right? Every code has a piece of fix codes, because there isn’t any B..
code.
If there is an B.. code in it, the fix can be the picture below. OMG, I feel sick! The fix code is in two part! And the second part is at the end of the entire fix code! And the X in BLS X
is hard to know… , but I use pstInlineHook->backUpFixLengthList
to predict and get value of X.
Even worse when there are two B..
code, it’s more complicated, and I wanna vomit:
So how to make the two part in one? I try this, and the fix code is beautiful again~:
But the 12 bytes with 3 jump? I think maybe it can be more beautiful… More pithy and more short, an great idea come to my mind —- opposite logic
! This can be 4 bytes shorter in arm32 and thumb32 without adding NOP. And the jump logic is less. It’s like this:
Now the fix code with B..
is beautiful and short. Hahahahaha……..
That’s why you can see the BNE
is changed to BEQ
in fix code.
If you still have some questions please create issue in the repo so the other people can see and help us. I will try my best to answer them in English.