ida pro 反彙編 Android so 庫後修改 arm 彙編指令的方法總結

1 前言

最近博主在學習Android逆向的時候,參照吾愛破解論壇的《教我兄弟學Android逆向系列課程》學習的時候,學到第8章《教我兄弟學Android逆向08 IDA爆破簽名驗證》的時候,開始上手 ida pro 反彙編 so 庫,在動手修改 so 庫指令的時候遇到了困難,經過一番研究,終於搞懂了在 ida pro 中修改 so 庫中 arm 彙編指令的方法,並完成了課後習題:

爆破李華Demo中的用戶名和密碼 要求輸入任意用戶名和密碼 會提示登陸成功

在這裏插入圖片描述

於是寫下這篇博客記錄研究過程,並把被作者一筆帶過的最核心問題如何修改so庫講清楚。
附上原吾愛破解教程地址:

《教我兄弟學Android逆向系列課程+附件導航帖》
《教我兄弟學Android逆向08 IDA爆破簽名驗證》

2 準備

(1) 下載 ida pro 7.0

原貼中使用的是ida pro 6.6,博主使用的是 ida pro 7.0,這一版是免安裝的綠色版,下載地址:

IDA Pro 7.0 綠色版

(2) 下載 Android Killer

AndroidKiller_v1.3.1.zip

(3) 下載夜神模擬器

如果有真機也可以使用真機,這裏我們使用夜神模擬器:

夜神模擬器官網

(4) 下載demo

原貼中的demo:黑寶寶.apk 下載地址:

鏈接:https://pan.baidu.com/s/1h6pX2ARE3qtiKiYbcnJ-3g 密碼:duv5

(5) 下載 jni.h

下載鏈接:https://pan.baidu.com/s/1n16NEx67zLHfGtVpU-CKAA 密碼:7xg6

(6) Arm指令手冊

https://download.csdn.net/download/fuchaosz/12243691

(7) arm指令轉換網站

Arm彙編指令轉機器碼網站:http://armconverter.com/

3 SO庫的選擇

首先把 黑寶寶.apk 拖進 Android Killer 中反編譯,我們可以看到在 lib 中有三個 libJniTes.so :
在這裏插入圖片描述

armeabi     : 32位 arm cpu 庫,幾乎所有手機都支持
armeabi-v7a : 64位 arm cpu 庫,現在我們買的手機基本上都是64位的cpu了
x86         : 在電腦上運行的模擬器或者基於Intel x86的平板電腦上用的

這裏要說一下歷史,在電腦CPU芯片領域,Intel獨霸天下,x86代表32位cpu,x86_64代表64位的cpu,cpu位數增加不僅意味着運算速度更快,同時還代表着可以使用的內存更大,例如32位系統最大隻能使用4G內存,所以windos xp上裝8G內存條完全是浪費;但在手機領域arm纔是龍頭老大,可以說壟斷了市場,因爲arm制定了標準,所以,我們經常聽說的高通驍龍芯片,雖然芯片是高通生產的,但卻是arm的架構和指令集,因爲我們的app到底層最終都被翻譯成了arm指令。
這次,我們選擇 armeabi 目錄下的 libJniTes.so
在這裏插入圖片描述

因爲這是幾乎所有手機都支持的,而且網上資料是最多的,並且這三個版本的庫在指令上有很多差別,例如:在 armeabi 中跳轉指令是 BNE:
在這裏插入圖片描述
但在 armeabi-v7a 中跳轉指令卻是 CBNZ:
在這裏插入圖片描述
在 x86 中跳轉指令則是 jnz:

在這裏插入圖片描述
所以,作爲初學者,我們選擇 armeabi 下的 libJniTest.so 庫作爲研究對象,便於在網上查找資料。
另外,值得一提的是,以前很多 app 只提供 armeabi 版本的 so 庫,所以在安卓模擬器上很多app運行不了,尤其是很多遊戲無法在模擬器上運行,好在現在主流安卓模擬器已經可以運行 armeabi 庫了,例如夜神模擬器,所以,這次我們修改後的 armeabi 下的 libJniTest.so 是可以運行在夜神模擬器上的。

4 引出問題

參照 《教我兄弟學Android逆向08 IDA爆破簽名驗證》 這篇文章一步一步來,先將 黑寶寶.apk 拖入 Android Killer 中反編譯,然後再將 armeabi 目錄下的 libJniTest.so 用 ida pro 7.0 打開,接着在 Export 窗口中搜索 check 函數,接着導入 jni.h,接着替換 _JniEnvenv 兩個參數,然後就到了關鍵的地方,在函數流程圖中,作者要改變函數流程,要將 BNE 改爲 BEQ,如下圖:
在這裏插入圖片描述
在這裏插入圖片描述
看關鍵的代碼:

cmp R0,#0
BNE loc_F62

cmp 是比較兩個數是否相等
loc_F62 代表的函數是 “簽名不一致,退出程序”
BNE 指不相等的時候跳轉(branch not equal)
BEQ 指相等的時候跳轉(branch equal)

結合反彙編後的C代碼和函數流程圖,我們可以很明顯的知道這段代碼的含義就是:如果簽名不相等,則跳轉到loc_F62,即直接退出程序。很明顯我們回編譯後的apk簽名和作者預設的簽名是絕對不可能一致的,所以會直接退出程序。

搞清楚了邏輯,那麼爆破這個apk的簽名其實就是把 BNE loc_F62 改爲 BEQ loc_F62,即簽名一致則跳轉到 loc_F62退出程序,我們的簽名和作者簽名一定不同,所以程序不會直接退出,爆破成功。

接下來就是核心的地方:如何將 BNE 改爲 BEQ ?

參照原貼方法,鼠標點擊BNE那一行,然後View->Open subviews->Hex dump 查看那一行指令對應的機器碼:

在這裏插入圖片描述
在這裏插入圖片描述
10 D1上點右鍵Edit,修改爲10 D0:
在這裏插入圖片描述
接着右鍵apply changes:
在這裏插入圖片描述
再回到函數流程圖,可以看到 BNE已經變爲BEQ

在這裏插入圖片描述
那麼問題來了:爲什麼要這樣改?

我們可以看到上圖第2個BEQ loc_F74命令對應的機器碼是09 D0:
在這裏插入圖片描述
鋪墊結束,問題來了:我們要修改操作碼而不是操作數,爲什麼是把10 D1改爲10 D0,而不是改爲09 D1?

這個問題是最核心的問題,但是原帖裏面作者一帶而過了,加入現在我要把BNE指令改爲無條件跳轉指令 B 又該怎麼改呢?

博主在這裏卡了一天,最後經過實踐得出了結論,所以寫了這篇博客。下面我們來深入探討這個問題。

5 深入問題

先來回顧一下《彙編》和《計算機組成原理》的內容,計算機只認識0和1,所有的操作聽歌、看視頻、打遊戲等等,歸根結底都是對0和1進行操作,在Intel x86架構中,一條指令是32位,因爲32位CPU一次必須讀入32位,不多不少,這一次讀入的32個0或1就是一條指令,那麼一秒鐘可以讀多少次呢,這就是cpu的主頻決定的,所以理論上,cpu主頻越高,一秒鐘執行的指令越多,性能越高。接着思考,cpu是如何知道這32個數字(一條指令)中哪些數字代表操作,哪些數字代表被操作的數據呢,這就是指令格式,x86指令格式如下:

一條指令(32位) = 操作碼(前16位):操作數(後16位)

操作碼代表做哪些運算,例如:ADD、MOV、B 等等
操作數就代表被操作的數據,即可以是數據也可以是地址。

前面16位操作碼排列組合起來就是指令集,每家廠商對指令集是不同,arm指令集也是同理,這就是彙編指令和機器碼的關係。當然,實際指令格式不一定是這樣平分的,但都是由操作碼和操作數兩部分組成的。

回到正題,我們梳理一下:

BNE loc_F62  對應機器碼 10 D1 對應二進制 0001 0000 1101  0001
BEQ loc_F74  對應機器碼 09 D0 對應二進制 0000 1001 1101  0000

根據上面的知識,我們要改的是操作碼,所以應該是把 操作碼 10 改爲 09 纔對呀,即改爲 09 D1 而不是 10 D0,博主被這個問題深深的卡住了,於是查閱資料,搜到了arm的官方指令手冊,查看了官方給的機器碼錶,結果更懵逼了。

打開arm指令手冊,並沒有BNE、BEQ指令,再看B指令的解釋,翻到A6-3.1:

在這裏插入圖片描述
對照下面的條件碼錶:
在這裏插入圖片描述
通過官方手冊和條件碼錶,我們組合起來就得到BNE指令的機器碼:

1101 + 0001 + 8_bit_signed_offset

可是ida pro裏面 BNE loc_F62 對應的正確的機器碼明明是:

0001 0000 1101 0001

這就把博主整崩潰了,經過一天的谷歌百度,再經過反覆實踐,博主得出以下結論(敲黑板、劃重點、記筆記),該結論沒有找到確切資料,但抓住老鼠就是好貓。

6 結論

ida pro 反彙編 Android SO庫(armeabi版本) ,一條彙編指令如果由4個十六進制數組成的,則前面2個(十六進制數)是操作數,後面2個(十六進制數)纔是操作碼,即so庫的指令格式如下:

一條SO的彙編指令(16位) = 操作數(前8位) :操作碼(後8位)

劃重點:
1、一條指令是4個十六進制數
2、前面2個是操作數,後面2個纔是操作碼
3、如果你發現一條指令是8個十六進制數(例如BL),那麼以上結論不適用
4、SO庫的字節數是不能變的,我們只能替換,不能增刪

注意:4位十六進制機器碼的指令都遵循上述規律,但是8位十六進制的指令規律還沒有總結出來,如果你知道了,歡迎給我留言。

7 解決問題

根據以上結論,我們很容易就能理解爲什麼要把 D1 改爲 D0 了,因爲操作碼是後面兩位,根據arm手冊和條件碼錶,我們很容易組合出來BNE的操作碼是D1BEQ 的操作碼是 D0,所以,正確的操作是把 10 D1 改爲 10 D0 ,問題解決。

如果我們每次修改指令都要去查arm手冊的話,那是very dan疼的,那英文太酸爽,arm生怕多寫幾句浪費紙,所以,我們在實際操作中有以下兩種方法來修改指令:

(1) 方法一:照葫蘆畫瓢

既然我們已經知道改指令就是改後面2個數,那就so easy了,我們只要在ida pro裏面查看目標指令的機器碼後面2個數,然後照着改就可以了,例如:我們接着要把BEQ loc_F62 改爲 B loc_F62 呢,B指令是無條件跳轉指令,首先鼠標點擊到其他 B 指令上,View->Open subviews->Hex dump 查看機器碼爲14 E0

在這裏插入圖片描述
在這裏插入圖片描述
接着我們將 10 D0 改爲 10 E0,這樣 BEQ loc_F62 就又被改爲了 B loc_F62
在這裏插入圖片描述
在這裏插入圖片描述
改動成功,成功應用了我們總結的知識,這裏只是個演示,改動完後記得還原。

(2) 方法二:在線轉換機器碼

我們還可以打開以下網站:

http://armconverter.com/

直接輸入我們想要的指令,直接轉換爲機器碼,一個小技巧,如果需要操作數的話可以用#0,例如我們想知道B指令的機器碼,則可以構造一條語句 B #0 就可以了
在這裏插入圖片描述
從這個網站我們也可以發現一點,就是ida pro反編譯SO庫用的是 Thumb-2 指令集,這個指令集是 arm 指令集的子集,標準arm指令集是操作碼後跟操作數,這個thumb-2指令集反過來了,坑啊,關鍵是網上還查不到資料。

8 完成課後練習

理論知識學習完了,接着我們來完成課後習題:

爆破李華Demo中的用戶名和密碼 要求輸入任意用戶名和密碼 會提示登陸成功

通過第4節的C語言代碼我們可以看到,check這個函數很簡單,除了檢驗簽名外,就是當你輸入用戶名koudai和密碼black後顯示登陸成功,只要一個輸入不對,就登陸失敗,博主看了網上很多破解教程,都是把原來等於koudai 和 等於black的判斷邏輯改爲不等於,這樣有個很明顯的問題,雖然輸入其他用戶名密碼可以登陸成功,但當我們用戶名輸入koudai 或 密碼輸入 black就會登陸失敗,不符合題意:要求輸入任意用戶名和密碼 會提示登陸成功。

所以,這裏我們要改函數調用邏輯,要求不管輸入什麼,都要跳轉到正確的函數中,還記得上節提到的B指令嗎,這就是無條件跳轉指令,下面開始。

首先解決輸入任意用戶名調到正確的函數,先看流程圖:
在這裏插入圖片描述
很明顯不管輸入什麼,最後必須無條件跳轉到loc_F74所在的函數,那就簡單了,直接BEQ loc_F74改爲B loc_F74,還記得怎麼改爲B指令嗎,這裏把09 D0改爲09 E0
在這裏插入圖片描述
改完後我們發現,無論輸入什麼都會進入校驗密碼的函數模塊,那麼用戶名輸入問題解決,下面處理密碼輸入。

仔細看上面的流程圖,校驗密碼的函數有個函數首地址loc_F74,但是登陸成功的函數塊沒有首地址,反而是登陸失敗的函數有首地址loc_F8C,所以照葫蘆畫瓢行不通了,怎麼辦呢?

博主在這裏也卡了一下,後來想了一下,BNE loc_F8C這條指令真是多餘,要是沒有這條指令不就可以直接進入登陸成功的函數塊了嗎,那麼問題又來了:怎麼清除一條指令?

前面說了,so庫只能替換,不能增刪,網上搜了一下,說是有個nop指令用於清除目標指令,就是00 00,於是直接把這條指令的4個數全部改爲0,即04 D1改爲00 00,然後就可以了,看改完後的流程圖:

在這裏插入圖片描述
看流程圖,不管用戶名和密碼輸入什麼,都會顯示登陸成功,至此,作業完成,接着把ida pro中的改動保存到so文件:

在這裏插入圖片描述
關閉ida pro,將修改後的libJniTest.so文件替換掉原來armeabi目錄下的so文件,接着刪除armeabi-v7a和x86目錄,再回編譯後安裝到夜神模擬器,輸入任意字符串都可以提示登陸成功:

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

9 總結

通過本篇文章的學習,我們掌握了4個十六進制數指令的格式和修改方法,同時我們學會了修改 B系列 跳轉指令,並且明白了爲什麼要這樣改,以後就可以隨心所欲的修改函數的流程了,所以,很多高級語言的語法和保護措施在底層都失效了,這就是無法無天的底層,也是搞底層的樂趣。

當然,8個十六進制數的指令(例如BL指令)我們還沒有弄清楚規律,但是目前已經夠用了,所以,以後再來研究,如果你弄清楚了,歡迎在下方給我留言。

10 補充

如果你在實踐中遇到了 ida pro 7.0 無法顯示中文的問題,請參照下面這篇博客解決:

ida pro 7.0 無法顯示中文的問題解決方法

如果你在用 Android Killer 回編譯的時候遇到錯誤導致回編譯失敗,請參照下面這篇文章解決:

Android Killer反編譯失敗:No resource identifier found for attribute 問題解決方法

11 轉載請註明來自“梧桐那時雨”的博客:https://blog.csdn.net/fuchaosz/article/details/104804026

Tips:
如果覺得這篇博客對你有幫助或者喜歡博主的寫作風格,就關注一下博主或者給博主留個言唄,鼓勵博主創作出更多優質博客,Thank you.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章