1. 程式人生 > 其它 >逆向脫殼分析基礎學習筆記八 反彙編分析C語言

逆向脫殼分析基礎學習筆記八 反彙編分析C語言

本文為本人在大神論壇破解脫殼學習筆記之一,為本人對以往所學的回顧和總結,可能會有謬誤之處,歡迎大家指出。

陸續將不斷有筆記放出,希望能對想要入門的萌新有所幫助,一起進步

反彙編分析C語言

環境:VC6.0

為什麼不使用Visual Studio?

Visual Studio的反彙編程式碼更復雜一些,如下為VS2019的空函式反彙編程式碼

可以看到有CheckForDebuggerJustMyCode等一些額外的函式

為了便於理解和學習,便採用VC6.0來進行學習

空函式反彙編

#include "stdafx.h"

//空函式        
void function(){

}

int main(int argc, char* argv[])
{
    //呼叫空函式
        function();
        return 0;
}

我們通過反彙編來分析這段空函式

函式外部

12:       function();
00401048   call        @ILT+5(function) (0040100a)
13:       return 0;
0040104D   xor         eax,eax
14:   }
0040104F   pop         edi
00401050   pop         esi
00401051   pop         ebx
00401052   add         esp,40h
00401055   cmp         ebp,esp
00401057   call        __chkesp (004010e0)
0040105C   mov         esp,ebp
0040105E   pop         ebp
0040105F   ret

函式內部

6:    void function(){
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,40h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-40h]
0040101C   mov         ecx,10h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
7:
8:    }
00401028   pop         edi
00401029   pop         esi
0040102A   pop         ebx
0040102B   mov         esp,ebp
0040102D   pop         ebp
0040102E   ret

分析函式

函式呼叫

00401048   call        @ILT+5(function) (0040100a)

首先就是通過call來呼叫我們的function函式

函式內部

接著進到函式的內部

有了之前畫堆疊圖的經驗,我們不難看出,儘管我們的函式是個空函式,但其彙編程式碼依然完成了以下流程:

  1. 提升堆疊
  2. 保護現場
  3. 初始化提升的堆疊
  4. 恢復現場
  5. 返回

提升堆疊

00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,40h

保護現場

00401016   push        ebx
00401017   push        esi
00401018   push        edi

PS:前面的push ebp也是保護現場

初始化提升的堆疊

00401019   lea         edi,[ebp-40h]
0040101C   mov         ecx,10h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]

恢復現場

00401028   pop         edi
00401029   pop         esi
0040102A   pop         ebx
0040102B   mov         esp,ebp
0040102D   pop         ebp

PS:這裡的mov esp,ebp就是降低堆疊,與前面的提升堆疊相對應,所以也屬於恢復現場的一部分

返回

0040102E   ret

函式返回後

函式返回後不出意料地返回到了呼叫CALL地下一行語句,我們接著看

0040104D   xor         eax,eax

這裡是將eax清零,注意到我們的語句為return 0 這裡就是將eax作為返回值來傳遞

一般來說eax都是作為函式的返回值,但不絕對,有的函式返回值是存在記憶體裡或其它情況,要具體情況具體分析

接著看下面的程式碼:

0040104F   pop         edi
00401050   pop         esi
00401051   pop         ebx

很明顯,這裡是在還原現場,別忘了我們的主程式main本身也是個函式,這是在還原呼叫main前保護的現場

接著往下走

00401052   add         esp,40h
00401055   cmp         ebp,esp
00401057   call        __chkesp (004010e0)

這裡首先是將esp減少了40h,然後比較ebp和esp,最後再呼叫一個chkesp函式

從名稱就不難看出chkesp = check esp ,檢查esp,這個函式就是用來檢查堆疊是否平衡

繼續

0040105C   mov         esp,ebp
0040105E   pop         ebp

依舊是恢復現場

最後就是返回

0040105F   ret

總結空函式分析

我們可以看到,即便一個空函式什麼都沒有做,但呼叫一個空函式所產生的彙編程式碼卻不少

保護現場、恢復現場以及堆疊平衡的檢查等等都沒少,可謂麻雀雖小五臟俱全

簡單加法函式反彙編

有了前面分析空函式的經驗,我們再來分析分析一個簡單的加法函式

#include "stdafx.h"
int Plus(int x,int y){
        return x+y;
}

int main(int argc, char* argv[])
{
        //呼叫加法函式
        Plus(1,2);
        return 0;
}

函式外部

16:       Plus(1,2);
004010A8   push        2
004010AA   push        1
004010AC   call        @ILT+0(Plus) (00401005)
004010B1   add         esp,8
17:       return 0;
004010B4   xor         eax,eax
18:   }
004010B6   pop         edi
004010B7   pop         esi
004010B8   pop         ebx
004010B9   add         esp,40h
004010BC   cmp         ebp,esp
004010BE   call        __chkesp (004010e0)
004010C3   mov         esp,ebp
004010C5   pop         ebp
004010C6   ret

函式內部

10:   int Plus(int x,int y){
00401060   push        ebp
00401061   mov         ebp,esp
00401063   sub         esp,40h
00401066   push        ebx
00401067   push        esi
00401068   push        edi
00401069   lea         edi,[ebp-40h]
0040106C   mov         ecx,10h
00401071   mov         eax,0CCCCCCCCh
00401076   rep stos    dword ptr [edi]
11:       return x+y;
00401078   mov         eax,dword ptr [ebp+8]
0040107B   add         eax,dword ptr [ebp+0Ch]
12:   }
0040107E   pop         edi
0040107F   pop         esi
00401080   pop         ebx
00401081   mov         esp,ebp
00401083   pop         ebp
00401084   ret

分析函式

函式呼叫

004010A8   push        2
004010AA   push        1
004010AC   call        @ILT+0(Plus) (00401005)

結合前面的空函式分析,我們可以明顯發現這裡的函式呼叫環節,多了兩個push

就是將函式所需的引數壓入堆疊,這裡的引數為 2 和 1,注意壓入的順序是反著的(由呼叫協定決定,下篇筆記會詳細說明)

函式內部

提升堆疊保護現場初始化

提升堆疊、保護現場、初始化部分和空函式如出一轍,這裡就不再贅述

00401060   push        ebp
00401061   mov         ebp,esp
00401063   sub         esp,40h
00401066   push        ebx
00401067   push        esi
00401068   push        edi
00401069   lea         edi,[ebp-40h]
0040106C   mov         ecx,10h
00401071   mov         eax,0CCCCCCCCh
00401076   rep stos    dword ptr [edi]

實際執行

00401078   mov         eax,dword ptr [ebp+8]
0040107B   add         eax,dword ptr [ebp+0Ch]

裡的[ebp+8]就是我們前面壓入的引數1,[ebp+c]就是前面壓入的引數2

於是這兩條語句其實就是

00401078   mov         eax,1
0040107B   add         eax,2

將1+2的結果儲存到eax中(此時eax又作為函式返回值的載體)

恢復現場和返回

接下來的內容就和空函式一樣了,恢復現場和返回,也不再贅述

0040107E   pop         edi
0040107F   pop         esi
00401080   pop         ebx
00401081   mov         esp,ebp
00401083   pop         ebp
00401084   ret

函式返回後

004010B1   add         esp,8
17:       return 0;
004010B4   xor         eax,eax
18:   }
004010B6   pop         edi
004010B7   pop         esi
004010B8   pop         ebx
004010B9   add         esp,40h
004010BC   cmp         ebp,esp
004010BE   call        __chkesp (004010e0)
004010C3   mov         esp,ebp
004010C5   pop         ebp
004010C6   ret

函式返回後我們會發現與先前的空函式相比多了這一行程式碼:

004010B1   add         esp,8

這裡是對應我們前面壓入的兩個引數1和2,壓入引數後esp減少了8,這裡我們函式呼叫結束後,就不再需要之前壓入的兩個引數了,於是將esp恢復到壓入引數前,這其實也算在恢復現場裡,用來平衡堆疊

我們可以發現,這條語句是在我們call呼叫完畢返回後執行的平衡堆疊操作,所以這種操作也被稱為堆疊外平衡

與之相對就是堆疊內平衡:即在call裡面就把堆疊平衡好了

之後的程式碼就和空函式無異了,也不再贅述,簡單的加法函式分析到這也就告一段落了

本系列逆向脫殼基礎學習都在下方連結中,歡迎下載並交流溝通

逆向脫殼分析基礎學習筆記八 反彙編分析C語言 - 『學習資料區』 - 大神論壇 |脫殼破解|易語言|病毒分析

版權宣告:本文由 lyl610abc 原創,歡迎分享本文,轉載請保留出處