[逆向]順序結構:四則運算

簡單的順序結構逆向分析-->四則運算

使用工具:VS2013,Ollydbg

 

源代碼:

#include <windows.h>

//定義全局變量
int nGlobal = 5; 
char cGlobal = 'a';

int main()
{
	//定義局部變量
	int nLocal_1 = 0;
	int nLocal_2 = 8;
	//變量之間進行運算
	nLocal_1 += nGlobal;
	nLocal_2 = nLocal_1 * 4;
	nLocal_1 += cGlobal;
	cGlobal += 2;
	nLocal_1 -= 5;
	nLocal_2 /= 2;

	return 0;
}

 

爲了更好的鍛鍊讀彙編的能力,在VS的debug或者release目錄下,把pdb符號文件刪除,否則加載到Ollydbg中會出現很多提示,導致分析難度大大降低

 

使用OllyDbg加載後,main()函數:

00121380    55              push ebp
00121381    8BEC            mov ebp,esp
00121383    81EC D8000000   sub esp,0xD8
00121389    53              push ebx
0012138A    56              push esi                             ; Reverse_.<ModuleEntryPoint>
0012138B    57              push edi
0012138C    8DBD 28FFFFFF   lea edi,dword ptr ss:[ebp-0xD8]
00121392    B9 36000000     mov ecx,0x36
00121397    B8 CCCCCCCC     mov eax,0xCCCCCCCC
0012139C    F3:AB           rep stos dword ptr es:[edi]
0012139E    C745 F8 0000000>mov dword ptr ss:[ebp-0x8],0x0       ; 局部變量1 int nLocal_1 = 0;
001213A5    C745 EC 0800000>mov dword ptr ss:[ebp-0x14],0x8      ; 局部變量2 int nLocal_2 = 8;
001213AC    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]       ; 局部變量1放到EAX中,爲後面的加法做準備
001213AF    0305 00801200   add eax,dword ptr ds:[0x128000]      ; nLocal_1 = nLocal_1+nGlobal
001213B5    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; 把加完之後的值賦值給nLocal_1,相當於更新nLocal_1的值
001213B8    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]       ; 把新的nLocal_1的值放到EAX中,爲後面的乘法做準備
001213BB    C1E0 02         shl eax,0x2                          ; 左移2,就相當於*4
001213BE    8945 EC         mov dword ptr ss:[ebp-0x14],eax      ; nLocal_2 = nLocal_1 * 
001213C1    0FBE05 04801200 movsx eax,byte ptr ds:[0x128004]     ; 把全局變量cGlobal放到EAX中,準備加法
001213C8    0345 F8         add eax,dword ptr ss:[ebp-0x8]       ; nLocal_1 = nLocal_1+cGlobal
001213CB    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; 更新nLocal_1的值
001213CE    0FBE05 04801200 movsx eax,byte ptr ds:[0x128004]
001213D5    83C0 02         add eax,0x2
001213D8    A2 04801200     mov byte ptr ds:[0x128004],al        ; cGlobal = cGlobal + 2;
001213DD    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]
001213E0    83E8 05         sub eax,0x5
001213E3    8945 F8         mov dword ptr ss:[ebp-0x8],eax       ; nLocal_1 = nLocal_1 - 5;
001213E6    8B45 EC         mov eax,dword ptr ss:[ebp-0x14]
001213E9    99              cdq                                  ; 下面會有介紹
001213EA    2BC2            sub eax,edx
001213EC    D1F8            sar eax,1                            ; 右移1位,相當於除以2
001213EE    8945 EC         mov dword ptr ss:[ebp-0x14],eax      ; nLocal_2 = nLocal_2 / 2;
001213F1    33C0            xor eax,eax                          ; 把EAX清零
001213F3    5F              pop edi                              ; 還原edi,保證edi的值和剛進入函數時的值相同
001213F4    5E              pop esi                              ; 還原esi
001213F5    5B              pop ebx                              ; 還原ebx
001213F6    8BE5            mov esp,ebp
001213F8    5D              pop ebp                              ; Reverse_.<ModuleEntryPoint>
001213F9    C3              retn

 

上面出現了幾個不是很常見的指令,接下來單獨介紹一下:

1、rep stos

rep是重複指令,stos表示把EAX中的值放到EDI指向的地址中,相當於是給堆棧初始化一片區域

EDI地址變化的方向由DF決定,DF = 1,EDI的值會往遞減的方向變化;如果DF= 0,那麼EDI的值就會往遞增的方向變化

 

完整的指令:

mov ecx,0x36

mov eax,0xCCCCCCCC

rep stos dword ptr es:[edi]

上面的指令功能就是把edi中地址指向的值賦值成EAX中的值,賦值的次數爲ECX中的值

 

可以在OD中觀察一下指令執行之後堆棧中的變化

在指令執行之前,EDI的值是0xDDFB40

DF = 0

 

 

堆棧中情況是這樣的:

 

接下來執行一下rep stos這條指令

可以看到從0xDDFB40這個地址開始,堆棧中的值都被賦值成了0xCCCCCCCC

 

因爲 DF = 0,所以可以看到EDI的地址是往遞增的方向變化的

循環次數ECX = 0x36,所以地址的變化是0x36 * 4 = 0xD8,也就是賦值一直到0xDDFB40 + 0xD8 = 0xDDFC18 爲止

 

 

2、movsx

movsx eax,byte ptr ds:[0x128004]

帶符號擴展,並把擴展之後的值給eax

如果最高位是1,那麼擴展位就用1填充,如果最高位是0,那麼擴展位就用0填充

比如說 

mov BL,0x80

movsx AX,BL

執行完movsx之後AX中的值就是0xFF80,因爲0x80轉換成二進制來看的話就是1000 0000,對於有符號的數來說,最高位爲1就是表示負數,所以由一個字節擴展成兩個字節,結果就是1111 1111 1000 0000,擴展位用1填充,轉換成十六進制就是0xFF80

如果是

mov BL,0x50

movsx AX,BL

那就是0x50 = 0101 0000,最高位爲0,擴展位也是用0填充,一個字節擴展成兩字節就是 0000 0000 0101 0000,執行完movsx之後AX=0x0050

 

3、cdq

Convert Double to Quad,意思就是把雙字(四字節,一個字 = 兩字節)擴展爲四字(八字節),因爲擴展成了8字節,一個EAX放不到,所以把八字節的高四字節放到了EDX中。

這個指令常用於擴展 被除數 ,在以前指令集規定除數必須是被除數的一半長,目前還在用這個規定。

這個指令一般是在計算除法的時候出現

 

4、shl

邏輯左移,最低位補0

格式:

SHL DST,常量

或者

SHL DST,CL

左移的位數根據常量的值和CL的值來確定

比如說:

mov eax,0x12

shl eax,2

首先0x12 = 0001 0010

左移2位,結果變成 0100 1000=0x48

左移指令可以用在乘法計算中,左移1位表示乘以2,左移2位表示乘以4,以此類推

所以0x12左移2位就是0x12*4=0x48

 

5、sar

算術右移,最高位補什麼值由符號位決定,如果最高位是0,那麼補0;如果最高位是1,那麼補1,也就是算術右移最高位保持不變

比如說

mov eax,0x80

sar eax,1

由於0x80最高位是符號位,所以右移的時候最高位補1

1000 0000 -> 1110 0000

如果是

mov eax,0x52

sar eax,2

那麼結果就是 0101 0010 -> 0001 0100 

右移也相當於是除法,右移一位除以2,右移2位除以4

 

6、xor

用來計算兩個數異或的結果,如果是異或兩個相同的寄存器,那就是在執行寄存器置零操作

 

搜索關注公衆號[逆向小生],不定期更新逆向工程師需要掌握的技能,包括Windows和Android方面的逆向,還有作爲一個逆向工程師的思維模式。

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