我遇到了以下 x86(使用某些版本的 Visual Studio AFAIK 构建)switch 语句:
0x1009E476 cmp edx, 0x3B
0x1009E479 jnz switch_statement
switch_statement:
0x1009E591 movzx ecx, byte [indirect_table+edx]
0x1009E598 jmp dword [table1+ecx*4]
indirect_table:
0x1009E7AB db 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
db 0x07, 0x07, 0x06, 0x8B, 0xFF
table1:
0x1009E7B8 dd ptr code1
dd ptr code2
dd ptr code3
dd ptr code4
dd ptr code5
dd ptr code6
dd 0x00000000
0x1009E7D4 dd 0x01060600, 0x06020606, 0x06060306, 0x06060606 ; Note: nothing directly references this data.
dd 0x06040606, 0x06060606, 0x06060606, 0x06060606
dd 0x06060606, 0x06060606, 0x06060606, 0x06060606
dd 0x06060606, 0x06060606, 0x06060606, 0x06060606
dd 0x06060606
中的任何索引都indirect_table
不会引用 中的 6 个指针中的任何一个table1
。索引 6 将取消引用空指针,索引 7 将取消引用0x01060600
和索引0x8B
并0xFF
最终取消引用垃圾。因此,一切最终都会违反访问权限。
所以这也许是编译器的优化,table1的数据跟在6个代码指针和1个空指针后面,看起来像一个间接表,巧合的是所有的索引都适合这个switch语句(0-6)。虽然二进制文件没有对此数据的引用,但如果EBX
已知是0x29
或向上,它将引用此数据。编译器可能已经决定EBX
不会0
-0x29
因此将间接表位置向后移动以正确排列。那么cmp edx, 0x3B
在这当中扮演什么角色呢?
这是编译器代码生成问题,编译器优化,还是我严重误解了代码?
如果优化,任何支持阅读材料将不胜感激。