IDA簡單Switch-Case結構的彙編程式碼分析
阿新 • • 發佈:2019-01-23
使用IDA進行靜態逆向分析,很重要的一點是對高階語言程式結構的解析,比如Switch-Case結構。偏偏IDA的F5功能很多時候會無法生成C語言程式碼,此時就需要我們自己分析彙編程式碼,理解switch-case結構等。
從簡單入手, 測試使用的C++程式碼如下:
編譯生成release版本的EXE執行檔案,刪除pdb檔案後,使用IDA載入EXE進行靜態分析。首先看main函式呼叫swcitch_case函式處如何傳遞引數: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; }
.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函式的彙編解析:
如上,2個switch_case函式裡面包括2個Switch-Case結構,彙編程式碼中就包含有2個跳轉表,每個跳轉表都包括4個case的跳轉地址,可以理解為跳轉陣列,然後程式根據跳轉陣列的索引值,通過jmp指令跳轉到各個分支即可。.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