IDA遇到浮點數計算時F5解析失敗,如何復現計算過程

996.icu LICENSE

  • 問題背景
  • 解決方法
  • 總結

閱讀之前注意:

本文閱讀建議用時:25min
本文閱讀結構如下表:

項目 下屬項目 測試用例數量
問題背景 0
解決方法 1
總結 0

問題背景

問題背景也是寫這篇文章的原因,起因於博主在iosre論壇發的貼子:求助:大量浮點數運算IDA的F5操作無法解析

總結下貼子中內容,也就是說,IDA在遇到大量浮點數運算時,按Fn+F5解析爲僞代碼時,是不會把這些運算給解析出來的。而Hopper則會解析爲:在僞代碼中保留彙編運算。

對於需要完整復現一套算法的逆向工程師來說,這種無法解析的情況是必須邁過去的一道坎,也是一個追求卓越的逆向工程師的必經之路。

參考貼子中大佬給的建議,以下是博主個人的解決方法,也算是拋磚引玉,還望各位大佬不吝賜教,歡迎提出更好的解決方法或者改進建議(或許可以編寫一套自己的彙編解析方法,來自動生成僞代碼)。

解決方法

我們知道在arm64架構中,存在着x0-x28的通用寄存器,以及v0-v31的浮點型寄存器(如下圖,圖片來自Xcode的調試信息窗口/iPhone真機調試)。
在這裏插入圖片描述
而大量的浮點數運算,就是靠這些浮點型寄存器完成的。也就是上圖中的Floating Point Registers

正如函數傳遞通用參數(非浮點數)的調用約定是按x0-x7的順序來的,傳遞浮點數時,則是按照v0-v7的順序來的。因此,首先我們可以根據這個參數傳遞規則來確認輸入的參數。

接着,就是本文的核心了,如何復現函數中的浮點數計算過程。

浮點型寄存器的結構其實很簡單,從v0到v31,每一個浮點型寄存器都是16個字節組成的,形象的理解下,就是4個float數,即一個浮點型寄存器=4個float數。

因此,在復現的代碼中,我們可以用float數組來模擬浮點型寄存器,比如v0浮點型寄存器,就可以用如下數組定義來表示

float v0[4] = {0};//模擬v0寄存器並初始化爲0
float v1[4] = {0};/模擬v1寄存器並初始化爲0
...

其餘以此類推。
我們以一條非常簡單的指令爲例,來看看浮點數運算是怎麼被複現的:

FSUB		S1, S3, S4

即S1 = S3 - S4,這裏的S代表什麼呢?我們可以從《ios應用逆向與安全》這本書中找到答案,第230頁有如下說明:

128位寄存器,Q0-Q31
64位寄存器,D0-D31
32位寄存器,S0-S31

或者更直接的,通過動態調試,在調試信息窗口查看浮點型寄存器來進行確認。這樣我們就知道了:上面那個S,就是代表1個float,並且是浮點型寄存器的第1個float。因此可復現爲以下代碼:

v1[0] = v3[0] - v4[0];

如法炮製,對於以下指令:

FMUL		D6, D6, D7

則可復現爲:

*(double *)v6 = (*(double *)v6) * (*(double *)v7);

當然,除了以上這些非常簡單的運算指令,我們還會遇到其他的arm64彙編指令,這種情況我們就可以直接在armDeveloper這個網站搜索指令,瞭解意思後再進行復現即可。

雖然上面的網站可以直接搜索指令,但國內網絡體驗並不好,因此也可以參考《ios應用逆向與安全》書中第229頁的方法,在arm InfoCenter網站下載官方手冊。不過目前官網也給出了以下說明(技術內容被移動到了上面那個體驗並不好的armDeveloper網站= =),好在手冊還能下載:
在這裏插入圖片描述

總結

一句話總結:浮點數計算由浮點型寄存器完成,因此理解浮點型寄存器的組成結構,用float數組復現對應計算就行!

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