无法理解反汇编中的 C-switch 语句

逆向工程 拆卸 二元分析 C 静态分析 反汇编者
2021-07-03 20:21:49

当我试图反汇编我自己的 C 代码时,我陷入了一个不理解这个 Switch 语句是如何在汇编代码中实现的问题。任何人都可以帮忙弄清楚吗?这是开关组件。不明白为什么要使用这么多寄存器,加上最后一行写着“jmp dword ptr [eax 4+0A110E8h]”。这个 eax 4 是组装中的开关所必需的还是由拆卸器自己完成的? 在此处输入图片说明

我的 C 代码:

main() {
  int a;
  printf("Please enter a no between 1 and 5: ");
  scanf("%d", & a);
  switch (a) {
  case 1:
    printf("You chose One");
    break;
  case 2:
    printf("You chose Two");
    break;
  case 3:
    printf("You chose Three");
    break;
  case 4:
    printf("You chose Four");
    break;
  case 5:
    printf("You chose Five.");
    break;
  default:
    printf("Invalid Choice. Enter a no between 1 and 5");
    break;
  }
}
1个回答

这被编译为简单的跳转表。首先它从a变量中减去 1 ,所以现在你的 switch-case 是 <0;4> 范围内的值(而不是 <1;5>)。接下来检查是否a> 4,如果是,则跳转到default标签处0A1109F请注意,该JA指令适用于无符号值,因此default如果您的值为a,它将跳转到标签

现在奇迹发生了。它跳转到jump-table里面的地址,jump-table长5个元素(因为你的switch有5个case),每个元素长4个字节(因为你编译的是32位架构,sizeof指针那里是 32 位,这就是为什么它是 eax*4)。跳转表从 开始0A110E8

因此,如果您取消引用指针处,0A110E8您将获得“您选择了一个”块的地址。因为对于这种情况eax=0(刚刚递减),[eax*4+0A110E8] = [0A110E8]现在。

如果你输入2标准输入,那么eax=1,那么[eax*4+0A110E8] = [1*4+0A110E8] = [0A110EC]. 现在您可以取消引用指针 0A110EC,您将获得第二个开关块的地址,JMP在这种情况下指令将重定向程序流的地址相同的规则适用于所有块。