C語言與組合語言對照分析

來源:互聯網
上載者:User

標籤:編譯器   圖片   文法   com   流程   慢慢   規則   跳轉   對齊   

遊戲通常會包含各種各樣的功能,如戰鬥系統、UI渲染、經濟系統、生產系統等,每個系統又包含各式各樣子功能,如傷害判定、施法、使用道具、角色移動、玩家之間交易等等。這些遊戲功能在代碼實現中往往少不了條件判斷(如傷害判定)、迴圈(遍曆物品列表,播放遊戲動畫)等。

 

       在逆向過程中如果可以從組合語言識別出對應的文法結構,在分析過程中將彙編代碼轉換為C語言文法結構,可以協助對程式執行流程的理解。

 

下面分別介紹最常見的邏輯文法結構:

a) if...else

b) switch...case

c) for、while

註:文中使用的反組譯碼工具為IDA

 

一、 if...else

 

彙編代碼:

 

if...else結構比較固定,通常包含cmp指令、jcc指令以及滿足條件後執行的指令塊。

 

if...else結構可以串聯,串聯後的if...else有明顯的代碼塊邊界,逆向工具通常可以將代碼塊標識出來(圖中虛線)。

 

二、 switch...case

  1. 一個簡單switch...case

  

 

彙編代碼:

 

顯示了switch...case基本的結構:a) 跳轉運算式;b) 分支代碼;c) 跳轉表

a) 跳轉運算式

其中loc_401235代碼塊對應switch...case中default分支。

當nGameEvent > 4時,跳轉到loc_401235代碼塊,即default分支。

當nGameEvent <= 4時,根據跳轉運算式進行跳轉:

jmp     ds:off_40123C[nGameEvent*4]

其中off_40123C為跳轉表地址,跳轉表中每一項代表一個32位地址(4個位元組),當nGameEvent為0按第一項地址跳轉,當nGameEvent為1按第二項地址跳轉,依次類推。

b) 分支代碼

 

各個分支的處理邏輯都在這裡,範例程式碼中僅僅簡單的調用對應函數。
(PS:這裡用jmp而不用call是編譯器最佳化的結果)

c) 跳轉表

 

跳轉表實際是一個地址數組,存放了每個跳轉分支的地址(32位絕對位址),當nGameEvent為0時,跳轉運算式讀取數組中第一項資料(0x0040121C),即

.text:0040121C E9 8F FF FF+     jmp     [email protected]@YAXXZ

調用DoLogin函數。

(PS: 實際運行時,由於隨機化基址,從調試器看到的跳轉表內容可能與靜態分析時不同,這是重定位引起的,關於重定位的原理可以參考相關文檔,這裡不再詳述)

  1. 不連續的switch...case

 

上面的樣本中case的值是連續的,因此跳轉表比較規則。在實際使用中可能會遇到不規則的case值,如:

 

彙編代碼:

 

 

上面的代碼有兩個特點:

  1. 最小case值非0
    中最小case值為3,為了不浪費跳轉資料表空間,編譯器會將索引值減去3保證最小的case值對應跳轉表中的第一項。

     

  2.case值不連續
  編譯器會在跳轉表間隔中插入default跳轉,保證邏輯正確。(以空間換取時間)

 

  3.雙重跳轉表

 

 

彙編代碼:

 

相對於前一個樣本,此處case值間隔更大。如果按照之前的方法,跳轉表的大小需要(110-30 + 1)* 4 = 324位元組,佔用記憶體空間大。

編譯器為了節省空間的,使用了雙重跳轉:跳轉表、間接跳轉表。其中跳轉表與之前介紹的跳轉表一致,而間接跳轉表儲存的不是分支地址,而是索引值,指向跳轉表中的索引。

跳轉表:

 


間接跳轉表:

 

在進入switch...case時,先算根據間接跳轉表獲得索引號,再根據索引號尋找跳轉表,擷取實際分支地址。

 

使用雙重跳轉表後,實際佔用空間:5*4 +(110 – 30 + 1)= 101位元組,大大減少空間佔用。

  1. swtich...case退化

當case值間隔過大,使用跳轉表、雙重跳轉表消耗的空間太大,編譯器會將switch...case退化為if...else,如:

 

 

彙編代碼:

 

這裡沒有跳轉表結構,只剩下cmp/jcc指令,可見編譯器已經將swtich...case轉換為等價的if...else。但在轉換過程中,編譯還是做了力所能及的最佳化:通過二叉尋找法加快跳轉分支的尋找。

  1. 嵌套switch...case

 

 

彙編代碼:

可以看出嵌套的switch...case結構在彙編代碼上是相對獨立的,外層和內層switch結構有各自的跳轉表。

外層跳轉表:

 

記憶體跳轉表(雙重跳轉表):

 

根據跳轉表中的地址項,也可以清楚的區分外層和內層的跳轉分支。

三、 迴圈語句

a) for迴圈

 

彙編代碼:

 

其中nop dword ptr[eax+00h] 為指令對齊,沒有實際意義。迴圈的彙編實現為:

 

b) while迴圈

 

彙編代碼:

 

其中nop dword ptr[eax+eax+00h] 為指令對齊,沒有實際意義。迴圈的彙編實現為:

 

 

從上面可以看出,for和while結構的彙編實現幾乎一摸一樣,僅僅是使用的寄存器有些區別。實際逆向過程中將迴圈映射為for或者while結構都是可以的。同時還可以看出,迴圈有個明顯的特徵:往回跳轉(向地址小的方向跳轉),大部分情況下遇到往回跳轉的指令就是迴圈,極少數如編譯器代碼結構最佳化產生的往回跳轉不是迴圈除外。

 

四、 總結

文法結構對應的彙編代碼與編譯器有很大關係,同一份原始碼不同編譯器產生的彙編代碼結構不一樣;即使是同一個編譯器,不同的編譯選項產生的彙編代碼結構也不盡相同。需要在逆向過程中慢慢熟悉編譯器的特性。

 

*轉載請註明來自遊戲安全實驗室(GSLAB.QQ.COM)

C語言與組合語言對照分析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.