设为首页 加入收藏

TOP

5.5 难以构成跳转表的switch(3)
2013-10-07 14:30:07 来源: 作者: 【 】 浏览:64
Tags:5.5 难以 构成 switch

5.5 难以构成跳转表的switch(3)

图5-7中的第0项为数值0,在图5-8的地址表中查询第0项,取4字节数据作为case语句块首地址—0x0040DFAA,对应代码清单5-16中的“case 1”的首地址(还记得之前的减1调整吗?见代码清单5-16中的0040DF89地址处)。在表中,标号相同的为switch的结束地址标号(有default块则是default块的地址)。然后在地址表中第6项找到switch的结束地址,图5-8中地址表的第6项对应的地址为0x0040E02B。该地址中保存的数据按照地址方式解释为:0x0040E002对应着代码清单5-16中switch的结束地址。

 
图5-8 非线性地址表—Debug版

已知case语句数及每个case语句块的地址,如何还原每个case的标号值呢?需要将两表相结合,分析出每个case语句的标号值。将索引表看做一个数组,参考反汇编代码中将索引表对齐到0下标的操作,代码清单5-16中对齐到0下标的数值为-1,因此地址表所对应的索引表的下标加1就是case语句的标号值。

例如,索引表中的第0项内容为0(索引表以0为起始下标),在表中是一个独立的数据,说明其不是switch结尾地址下标。它对应于地址表中第0项,地址0x0040DFAA这条case语句的标号值就是(0+1=1)1。地址表中的最后一项0x0040E002是表中的第6项,这个值在索引表中重复出现,可以断定其是switch的结束地址或者是default语句块的首地址。地址表第5项0x0040DFF5对应索引表中的下标值254,将其加1就是地址0x0040DFF5的case语句标号值。

在case语句块中没有任何代码的情况下,索引表中也会出现相同标号。由于case中没有任何代码,当执行到它时,则会顺序向下,直到发现下一个case语句不为空为止。这时所有没有代码的case属于一段多个case值共用的代码。索引表中这些case的对应位置处所保存的都是这段共用代码在地址表中的下标值,因此出现了索引表中标号相同的情况。

总结:

  1. mov     reg, mem                    ; 取出switch变量  
  2. sub     reg,1                       ; 调整对齐到索引表的下标0  
  3. mov     mem, reg  
  4. ; 影响标记位的指令  
  5. jxx     xxxx                    ; 超出范围跳转到switch结尾或default  
  6. mov     reg, [mem]              ; 取出switch变量  
  7. ; eax不是必须使用的,但之后的数组查询用到的寄存器一定是此处使用到的寄存器  
  8. xor     eax,eax  
  9. mov     al,byte ptr  (xxxx)[reg]    ; 查询索引表,得到地址表的下标  
  10. jmp     dword ptr [eax*4+xxxx]      ; 查询地址表,得到对应的case块的首地址 

如果遇到以上代码块,可判定其是添加了索引表的switch结构。这里有两次查找地址表的过程,先分析第一次查表代码,byte ptr指明了表中的元素类型为byte;然后分析是否使用在第一次查表中获取的单字节数据作为下标,从而决定是否使用相对比例因子的寻址方式进行第二次查表;最后检查基址是否指向了地址表。有了这些特征后,即可参考索引表中保存的下标值来恢复索引表形式的switch结构中的每一句case原型。
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇5.7 do/while/for的比较(1) 下一篇5.5 难以构成跳转表的switch(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: