逆向脫殼分析基礎學習筆記八 反彙編分析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函式
函式內部
接著進到函式的內部
有了之前畫堆疊圖的經驗,我們不難看出,儘管我們的函式是個空函式,但其彙編程式碼依然完成了以下流程:
- 提升堆疊
- 保護現場
- 初始化提升的堆疊
- 恢復現場
- 返回
提升堆疊
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 原創,歡迎分享本文,轉載請保留出處