1. 程式人生 > >IDA簡單Switch-Case結構的彙編程式碼分析

IDA簡單Switch-Case結構的彙編程式碼分析

    使用IDA進行靜態逆向分析,很重要的一點是對高階語言程式結構的解析,比如Switch-Case結構。偏偏IDA的F5功能很多時候會無法生成C語言程式碼,此時就需要我們自己分析彙編程式碼,理解switch-case結構等。

   從簡單入手, 測試使用的C++程式碼如下:

int switch_case(char a,int b,int *c,int d,int e)
{
	switch(a)
	{
	case 'a':
		*c = d + 3;
		break;
	case 'b':
		*c = d + 4;
		break;
	case 'c':
		*c = d - 8;
		break;
	case 'd':
		*c = d + e;
		break;
	default:
		e -= 10;
		break;
	}

	switch(b)
	{
	case 1235:
		b += d;
		break;
	case 1236:
		b += e;
		break;
	case 1237:
		b += *c;
		break;
	case 1238:
		b -= 100;
		break;
	default:
		e += 100;
		break;
	}

	printf("a=%d\r\n,b=%d\r\n,*c=%d",a,b,*c);

	return e;
}

int main(int argc,char *argv[])
{
	int number = 0;
	int i = 0;
	int j = 0;
	int k = 0;
	scanf("%d",&number);
	scanf("%d",&i);
	scanf("%d",&j);
	scanf("%d",&k);

	char c = '\0';
	scanf("%c",&c);
	int m = switch_case(c,i,&number,j,k);

	printf("m = %d\r\n",m);

	return 0;
}
       編譯生成release版本的EXE執行檔案,刪除pdb檔案後,使用IDA載入EXE進行靜態分析。首先看main函式呼叫swcitch_case函式處如何傳遞引數:
.text:004010A0 var_14          = dword ptr -14h
.text:004010A0 var_10          = dword ptr -10h
.text:004010A0 var_C           = dword ptr -0Ch
.text:004010A0 var_8           = dword ptr -8
.text:004010A0 var_4           = dword ptr -4
.text:004010A0 argc            = dword ptr  4
.text:004010A0 argv            = dword ptr  8
.text:004010A0 envp            = dword ptr  0Ch
.text:004010A0
.text:004010A0                 sub     esp, 14h
.text:004010A3                 push    ebx
.text:004010A4                 push    esi
.text:004010A5                 mov     esi, ds:scanf
.text:004010AB                 push    edi
.text:004010AC                 lea     eax, [esp+20h+var_8]
.text:004010B0                 xor     ebx, ebx
.text:004010B2                 push    eax
.text:004010B3                 push    offset aD       ; "%d"
.text:004010B8                 mov     [esp+28h+var_8], ebx
.text:004010BC                 mov     [esp+28h+var_4], ebx
.text:004010C0                 mov     [esp+28h+var_C], ebx
.text:004010C4                 mov     [esp+28h+var_10], ebx
.text:004010C8                 call    esi ; scanf
.text:004010CA                 lea     ecx, [esp+28h+var_4]
.text:004010CE                 push    ecx
.text:004010CF                 push    offset aD       ; "%d"
.text:004010D4                 call    esi ; scanf
.text:004010D6                 lea     edx, [esp+30h+var_C]
.text:004010DA                 push    edx
.text:004010DB                 push    offset aD       ; "%d"
.text:004010E0                 call    esi ; scanf
.text:004010E2                 lea     eax, [esp+38h+var_10]
.text:004010E6                 push    eax
.text:004010E7                 push    offset aD       ; "%d"
.text:004010EC                 call    esi ; scanf
.text:004010EE                 lea     ecx, [esp+40h+var_14]
.text:004010F2                 push    ecx
.text:004010F3                 push    offset aC       ; "%c"
.text:004010F8                 mov     byte ptr [esp+48h+var_14], bl
.text:004010FC                 call    esi ; scanf
.text:004010FE                 mov     edx, [esp+48h+var_14]  ; char c 
.text:00401102                 mov     eax, [esp+48h+var_10]  ; int k 傳入值
.text:00401106                 mov     edi, [esp+48h+var_C]   ; int j 傳入值
.text:0040110A                 mov     ecx, [esp+48h+var_4]   ; int i 傳入值
.text:0040110E                 push    edx                    ; char c 通過入棧傳遞引數
.text:0040110F                 lea     edx, [esp+4Ch+var_8]   ; int number 傳入指標
.text:00401113                 call    sub_401000

      如上,sub_401000函式即為switch_case函式,該函式的起始地址為401000。

      Go on。再看看switch_case函式的彙編解析:

.text:00401000 sub_401000      proc near               ; CODE XREF: _main+73p
.text:00401000
.text:00401000 arg_0           = byte ptr  4   ; char c 通過入棧傳遞引數
.text:00401000
.text:00401000                 push    ebx
.text:00401001                 push    esi
.text:00401002                 movsx   esi, [esp+8+arg_0] ; arg_0 即為 char c
.text:00401007                 mov     ebx, eax        ; eax 為 int k 傳入值
.text:00401009                 lea     eax, [esi-61h]  ; switch 4 cases  61h = 'a'
.text:0040100C                 cmp     eax, 3
.text:0040100F                 ja      short loc_401034 ; default
.text:00401011                 jmp     ds:off_401078[eax*4] ; switch jump  off_401078 為第一個switch case的跳轉表首地址
.text:00401018
.text:00401018 loc_401018:                             ; DATA XREF: .text:off_401078o
.text:00401018                 lea     eax, [edi+3]    ; jumptable 00401011 case 97  edi 為 int j 傳入值
.text:0040101B                 mov     [edx], eax
.text:0040101D                 jmp     short loc_401037
.text:0040101F ; ---------------------------------------------------------------------------
.text:0040101F
.text:0040101F loc_40101F:                             ; CODE XREF: sub_401000+11j
.text:0040101F                                         ; DATA XREF: .text:off_401078o
.text:0040101F                 lea     eax, [edi+4]    ; jumptable 00401011 case 98
.text:00401022                 mov     [edx], eax
.text:00401024                 jmp     short loc_401037
.text:00401026 ; ---------------------------------------------------------------------------
.text:00401026
.text:00401026 loc_401026:                             ; CODE XREF: sub_401000+11j
.text:00401026                                         ; DATA XREF: .text:off_401078o
.text:00401026                 lea     eax, [edi-8]    ; jumptable 00401011 case 99
.text:00401029                 mov     [edx], eax
.text:0040102B                 jmp     short loc_401037
.text:0040102D ; ---------------------------------------------------------------------------
.text:0040102D
.text:0040102D loc_40102D:                             ; CODE XREF: sub_401000+11j
.text:0040102D                                         ; DATA XREF: .text:off_401078o
.text:0040102D                 lea     eax, [edi+ebx]  ; jumptable 00401011 case 100
.text:00401030                 mov     [edx], eax
.text:00401032                 jmp     short loc_401037
.text:00401034 ; ---------------------------------------------------------------------------
.text:00401034
.text:00401034 loc_401034:                             ; CODE XREF: sub_401000+Fj
.text:00401034                 sub     ebx, 0Ah        ; default
.text:00401037
.text:00401037 loc_401037:                             ; CODE XREF: sub_401000+1Dj
.text:00401037                                         ; sub_401000+24j ...
.text:00401037                 lea     eax, [ecx-4D3h] ; switch 4 cases  ; ecx 為 int i 傳入值
.text:0040103D                 cmp     eax, 3
.text:00401040                 ja      short loc_40105A ; default
.text:00401042                 jmp     ds:off_401088[eax*4] ; switch jump off_401088 為第二個switch case的跳轉表首地址
.text:00401049
.text:00401049 loc_401049:                             ; DATA XREF: .text:off_401088o
.text:00401049                 add     ecx, edi        ; jumptable 00401042 case 1235
.text:0040104B                 jmp     short loc_40105D
.text:0040104D ; ---------------------------------------------------------------------------
.text:0040104D
.text:0040104D loc_40104D:                             ; CODE XREF: sub_401000+42j
.text:0040104D                                         ; DATA XREF: .text:off_401088o
.text:0040104D                 add     ecx, ebx        ; jumptable 00401042 case 1236
.text:0040104F                 jmp     short loc_40105D
.text:00401051 ; ---------------------------------------------------------------------------
.text:00401051
.text:00401051 loc_401051:                             ; CODE XREF: sub_401000+42j
.text:00401051                                         ; DATA XREF: .text:off_401088o
.text:00401051                 add     ecx, [edx]      ; jumptable 00401042 case 1237
.text:00401053                 jmp     short loc_40105D
.text:00401055 ; ---------------------------------------------------------------------------
.text:00401055
.text:00401055 loc_401055:                             ; CODE XREF: sub_401000+42j
.text:00401055                                         ; DATA XREF: .text:off_401088o
.text:00401055                 sub     ecx, 64h        ; jumptable 00401042 case 1238
.text:00401058                 jmp     short loc_40105D
.text:0040105A ; ---------------------------------------------------------------------------
.text:0040105A
.text:0040105A loc_40105A:                             ; CODE XREF: sub_401000+40j
.text:0040105A                 add     ebx, 64h        ; default
.text:0040105D
.text:0040105D loc_40105D:                             ; CODE XREF: sub_401000+4Bj
.text:0040105D                                         ; sub_401000+4Fj ...
.text:0040105D                 mov     edx, [edx]
.text:0040105F                 push    edx
.text:00401060                 push    ecx
.text:00401061                 push    esi
.text:00401062                 push    offset Format   ; "a=%d\r\n,b=%d\r\n,*c=%d"
.text:00401067                 call    ds:printf
.text:0040106D                 add     esp, 10h
.text:00401070                 pop     esi
.text:00401071                 mov     eax, ebx
.text:00401073                 pop     ebx
.text:00401074                 retn
.text:00401074 sub_401000      endp
.text:00401074
.text:00401074 ; ---------------------------------------------------------------------------
.text:00401075                 align 4
.text:00401078 off_401078      dd offset loc_401018    ; DATA XREF: sub_401000+11r
.text:00401078                 dd offset loc_40101F    ; jump table for switch statement
.text:00401078                 dd offset loc_401026
.text:00401078                 dd offset loc_40102D
.text:00401088 off_401088      dd offset loc_401049    ; DATA XREF: sub_401000+42r
.text:00401088                 dd offset loc_40104D    ; jump table for switch statement
.text:00401088                 dd offset loc_401051
.text:00401088                 dd offset loc_401055
.text:00401098                 align 10h
.text:004010A0
       如上,2個switch_case函式裡面包括2個Switch-Case結構,彙編程式碼中就包含有2個跳轉表,每個跳轉表都包括4個case的跳轉地址,可以理解為跳轉陣列,然後程式根據跳轉陣列的索引值,通過jmp指令跳轉到各個分支即可。