您的位置:首页 > 其它

编译器对switch case结构的优化

2012-10-16 23:10 148 查看
在使用IDA分析Crack Me的时候,发现IDA对switch case结构的分析很是清晰,还发现了一个jump table for switch statement,也就是所谓的跳转表了,是编译器优化的结果。对于case分支的值是连续的那种,所有分支的跳转地址都会存入一个数组之中,然后通过case的值来寻址,如果值超出边界则直接跳到default分支所在地址。

.text:004010EA align 4

.text:004010EC off_4010EC dd offset loc_401038 ; DATA XREF: _wmain+31

.text:004010EC dd offset loc_40104B ; jump table for switch statement

.text:004010EC dd offset loc_40105E

.text:004010EC dd offset loc_401071

.text:004010EC dd offset loc_401084

.text:004010EC dd offset loc_401097

.text:004010EC dd offset loc_4010AA

.text:004010EC dd offset loc_4010BD.text:00401000 push ecx

.text:00401001 push esi

.text:00401002 lea eax, [esp+8+var_4]

.text:00401006 push eax

.text:00401007 push offset Format ; "%d"

.text:0040100C mov [esp+10h+var_4], 0

.text:00401014 call ds:scanf

.text:0040101A mov eax, [esp+10h+var_4]

.text:0040101E mov esi, ds:putchar

.text:00401024 dec eax

.text:00401025 add esp, 8

.text:00401028 cmp eax, 7 ; switch 8 cases

.text:0040102B ja loc_4010D0 ; default

.text:00401031 jmp ds:off_4010EC[eax*4] ; switch jump

如果case分支的值之间有一定的间隔,但是差距又不是很大,则会先生成一个数组(可能比较大),先通过switch的变量当做下标在一个数组中取得对应的值,然后把这个值当做下标再在跳转地址表中取得对应的地址。

如果case分支的部分值之间有一定的间隔,而又有一些分支的值没有规律,比如很大,且分布不均匀等。那么分布均匀的那一部分将采用两级跳转表的形式,而其他分支则采用简单的比较判断方式。

如果case分支值没有规律,则会采用二叉树查找的方式进行优化。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#include "stdafx.h"

#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])

{

int nMax = 0;

scanf("%d", &nMax);

switch (nMax)

{

case 1:

putchar('1');

break;

case 256:

putchar('2');

break;

case 3:

putchar('3');

break;

case 999:

putchar('4');

break;

case 512:

putchar('5');

break;

case 0x0FFFFFFF:

putchar('6');

break;

case 10000:

putchar('7');

break;

case 0:

putchar('8');

break;

default:

printf("default");

}

putchar('\n');

return 0;

}

IDA Pro中的截图:

.text:00401000 _wmain proc near ; CODE XREF: ___tmainCRTStartup+10A

.text:00401000

.text:00401000 var_4 = dword ptr -4

.text:00401000

.text:00401000 push ecx

.text:00401001 push esi

.text:00401002 lea eax, [esp+8+var_4]

.text:00401006 push eax

.text:00401007 push offset Format ; "%d"

.text:0040100C mov [esp+10h+var_4], 0

.text:00401014 call ds:scanf

.text:0040101A mov eax, [esp+10h+var_4]

.text:0040101E mov esi, ds:putchar

.text:00401024 add esp, 8

.text:00401027 cmp eax, 200h

.text:0040102C jg short loc_4010A7

.text:0040102E jz short loc_401094

.text:00401030 cmp eax, 3

.text:00401033 jg short loc_40107A

.text:00401035 jz short loc_401067

.text:00401037 sub eax, 0

.text:0040103A jz short loc_401054

.text:0040103C sub eax, 1

.text:0040103F jnz short loc_4010BC

.text:00401041 push 31h ; Ch

.text:00401043 call esi ; putchar

.text:00401045 add esp, 4

.text:00401048 push 0Ah ; Ch

.text:0040104A call esi ; putchar

.text:0040104C add esp, 4

.text:0040104F xor eax, eax

.text:00401051 pop esi

.text:00401052 pop ecx

.text:00401053 retn

.text:00401054 ; ---------------------------------------------------------------------------

.text:00401054

.text:00401054 loc_401054: ; CODE XREF: _wmain+3A

.text:00401054 push 38h ; Ch

.text:00401056 call esi ; putchar

.text:00401058 add esp, 4

.text:0040105B push 0Ah ; Ch

.text:0040105D call esi ; putchar

.text:0040105F add esp, 4

.text:00401062 xor eax, eax

.text:00401064 pop esi

.text:00401065 pop ecx

.text:00401066 retn

.text:00401067 ; ---------------------------------------------------------------------------

.text:00401067

.text:00401067 loc_401067: ; CODE XREF: _wmain+35

.text:00401067 push 33h ; Ch

.text:00401069 call esi ; putchar

.text:0040106B add esp, 4

.text:0040106E push 0Ah ; Ch

.text:00401070 call esi ; putchar

.text:00401072 add esp, 4

.text:00401075 xor eax, eax

.text:00401077 pop esi

.text:00401078 pop ecx

.text:00401079 retn

.text:0040107A ; ---------------------------------------------------------------------------

.text:0040107A

.text:0040107A loc_40107A: ; CODE XREF: _wmain+33

.text:0040107A cmp eax, 100h

.text:0040107F jnz short loc_4010BC

.text:00401081 push 32h ; Ch

.text:00401083 call esi ; putchar

.text:00401085 add esp, 4

.text:00401088 push 0Ah ; Ch

.text:0040108A call esi ; putchar

.text:0040108C add esp, 4

.text:0040108F xor eax, eax

.text:00401091 pop esi

.text:00401092 pop ecx

.text:00401093 retn

.text:00401094 ; ---------------------------------------------------------------------------

.text:00401094

.text:00401094 loc_401094: ; CODE XREF: _wmain+2E

.text:00401094 push 35h ; Ch

.text:00401096 call esi ; putchar

.text:00401098 add esp, 4

.text:0040109B push 0Ah ; Ch

.text:0040109D call esi ; putchar

.text:0040109F add esp, 4

.text:004010A2 xor eax, eax

.text:004010A4 pop esi

.text:004010A5 pop ecx

.text:004010A6 retn

.text:004010A7 ; ---------------------------------------------------------------------------

.text:004010A7

.text:004010A7 loc_4010A7: ; CODE XREF: _wmain+2C

.text:004010A7 cmp eax, 3E7h

.text:004010AC jz short loc_4010FC

.text:004010AE cmp eax, 2710h

.text:004010B3 jz short loc_4010E9

.text:004010B5 cmp eax, 0FFFFFFFh

.text:004010BA jz short loc_4010D6

.text:004010BC

.text:004010BC loc_4010BC: ; CODE XREF: _wmain+3F

.text:004010BC ; _wmain+7F

.text:004010BC push offset aDefault ; "default"

.text:004010C1 call ds:printf

.text:004010C7 add esp, 4

.text:004010CA push 0Ah ; Ch

.text:004010CC call esi ; putchar

.text:004010CE add esp, 4

.text:004010D1 xor eax, eax

.text:004010D3 pop esi

.text:004010D4 pop ecx

.text:004010D5 retn

.text:004010D6 ; ---------------------------------------------------------------------------

.text:004010D6

.text:004010D6 loc_4010D6: ; CODE XREF: _wmain+BA

.text:004010D6 push 36h ; Ch

.text:004010D8 call esi ; putchar

.text:004010DA add esp, 4

.text:004010DD push 0Ah ; Ch

.text:004010DF call esi ; putchar

.text:004010E1 add esp, 4

.text:004010E4 xor eax, eax

.text:004010E6 pop esi

.text:004010E7 pop ecx

.text:004010E8 retn

.text:004010E9 ; ---------------------------------------------------------------------------

.text:004010E9

.text:004010E9 loc_4010E9: ; CODE XREF: _wmain+B3

.text:004010E9 push 37h ; Ch

.text:004010EB call esi ; putchar

.text:004010ED add esp, 4

.text:004010F0 push 0Ah ; Ch

.text:004010F2 call esi ; putchar

.text:004010F4 add esp, 4

.text:004010F7 xor eax, eax

.text:004010F9 pop esi

.text:004010FA pop ecx

.text:004010FB retn

.text:004010FC ; ---------------------------------------------------------------------------

.text:004010FC

.text:004010FC loc_4010FC: ; CODE XREF: _wmain+AC

.text:004010FC push 34h ; Ch

.text:004010FE call esi ; putchar

.text:00401100 add esp, 4

.text:00401103 push 0Ah ; Ch

.text:00401105 call esi ; putchar

.text:00401107 add esp, 4

.text:0040110A xor eax, eax

.text:0040110C pop esi

.text:0040110D pop ecx

.text:0040110E retn

.text:0040110E _wmain endp

简单的画一个二叉树的图就是这个样子:

512

/ \

/ \

3 999

/ \ \

/ \ \

0 256 10000

\ \

\ \

1 0x0FFFFFFF

不明白的同学可以参考下往上的一篇文档《C++逆向学习三步走》,下载地址:直接下载 迅雷下载

--------------------------------------------------------------------------------

本博客很少转载他人文章,如未特别标明,均为原创,转载请注明出处:

本文出自程序人生 >> 编译器对switch case结构的优化

Copyed From 程序人生

Home Page:http://www.programlife.net

Source URL:http://www.programlife.net/switch-case-optimization.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: