炸弹实验室作业第 5 阶段 - 编写其 C 等价物
Bomb Lab Assignment Phase 5 - Writing Its C Equivalent
我正在尝试为我的计算机架构解决一个稍微修改过的炸弹实验室问题 class。我应该为这些函数编写等效的 C 语言,但卡在了第 5 阶段。它与 非常相似,而且我确实已经弄清楚了函数的大部分功能。
105b: 56 push %esi
105c: 53 push %ebx
105d: 83 ec 10 sub [=10=]x10,%esp
1060: e8 6b fa ff ff call ad0 <__x86.get_pc_thunk.bx>
1065: 81 c3 fb 3e 00 00 add [=10=]x3efb,%ebx
106b: 8b 74 24 1c mov 0x1c(%esp),%esi
106f: 56 push %esi
1070: e8 bf 02 00 00 call 1334 <string_length>
1075: 83 c4 10 add [=10=]x10,%esp
1078: 83 f8 06 cmp [=10=]x6,%eax
107b: 75 2e jne 10ab <phase_5+0x50>
107d: 89 f0 mov %esi,%eax
107f: 83 c6 06 add [=10=]x6,%esi
1082: b9 00 00 00 00 mov [=10=]x0,%ecx
1087: 0f b6 10 movzbl (%eax),%edx
108a: 83 e2 0f and [=10=]xf,%edx
108d: 03 8c 93 00 da ff ff add -0x2600(%ebx,%edx,4),%ecx
1094: 83 c0 01 add [=10=]x1,%eax
1097: 39 f0 cmp %esi,%eax
1099: 75 ec jne 1087 <phase_5+0x2c>
109b: 83 f9 34 cmp [=10=]x34,%ecx
109e: 74 05 je 10a5 <phase_5+0x4a>
10a0: e8 38 05 00 00 call 15dd <explode_bomb>
10a5: 83 c4 04 add [=10=]x4,%esp
10a8: 5b pop %ebx
10a9: 5e pop %esi
10aa: c3 ret
10ab: e8 2d 05 00 00 call 15dd <explode_bomb>
10b0: eb cb jmp 107d <phase_5+0x22>
这是一个接受 6 个字符的字符串的函数(如果不接受,炸弹就会爆炸)并执行某种形式的循环算法来生成一个数字。最后,如果循环结果不等于 52 (0x34),则炸弹再次爆炸。但是,我无法理解代码的某个部分:
108d: 03 8c 93 00 da ff ff add -0x2600(%ebx,%edx,4),%ecx
显然,它抵消了您通过某种未知算法屏蔽字符串中每个字符的 ASCII 等价物而获得的数字。现在,我已经为每个字符创建了一个 table 的偏移量,并设法获得了一个可接受的字符串 aaaabb
,但我想知道代码的 C 等价物是什么样的。
就像 Jester 的回答一样,它正在索引一个数组。 ecx += table[edx]
,对于static int table[];
EDX索引在寻址方式下按4缩放,因为sizeof(int)
为4; asm 需要字节偏移量,C 索引使用元素偏移量。
-0x2600 + %ebx
是一个静态数组,与链接问题中的 0x804a4a0
相同。但是在静态反汇编中更难找到,因为 创建此 executable 的人烦人地将其编译为 32 位 PIE (position-independent executable)。
32 位 PIC / PIE 很糟糕,因为 PC-relative x86-64 的寻址是新的,因此逆向工程不必要地更复杂。
它将GOT(全局偏移量Table)地址获取到EBX中:首先call __x86.get_pc_thunk.bx
return它在EBX中的return地址,即0x1065
使用您从 objdump -d
获得的占位符地址。然后 add [=18=]x3efb,%ebx
将该位置的偏移量添加到 GOT。
然后静态数据相对于GOT base(在本例中为EBX)进行寻址。痛苦的屁股跟随那个与绝对地址。在内核的 program-loader 将代码映射到某个虚拟地址(0x1000
除外)之后,您可以在 运行 进程中的调试器中 single-step。
或手动执行:0x1065 + 0x3efb
= 0x4f60
的 GOT 基础 (EBX)。
0x4f60-0x2600
是查找 table 数组开始:0x2960
(如果您也使用 objdump -D
转储数据部分)。您可以在 GDB 中使用该地址(before start
或 run
),并使用 x
命令转储 table以一种方便的格式,而不是将数据伪装成来自 objdump 的代码。
运行 进程中的实际地址将是加上 4096 (0x1000) 的某个倍数。
我正在尝试为我的计算机架构解决一个稍微修改过的炸弹实验室问题 class。我应该为这些函数编写等效的 C 语言,但卡在了第 5 阶段。它与
105b: 56 push %esi
105c: 53 push %ebx
105d: 83 ec 10 sub [=10=]x10,%esp
1060: e8 6b fa ff ff call ad0 <__x86.get_pc_thunk.bx>
1065: 81 c3 fb 3e 00 00 add [=10=]x3efb,%ebx
106b: 8b 74 24 1c mov 0x1c(%esp),%esi
106f: 56 push %esi
1070: e8 bf 02 00 00 call 1334 <string_length>
1075: 83 c4 10 add [=10=]x10,%esp
1078: 83 f8 06 cmp [=10=]x6,%eax
107b: 75 2e jne 10ab <phase_5+0x50>
107d: 89 f0 mov %esi,%eax
107f: 83 c6 06 add [=10=]x6,%esi
1082: b9 00 00 00 00 mov [=10=]x0,%ecx
1087: 0f b6 10 movzbl (%eax),%edx
108a: 83 e2 0f and [=10=]xf,%edx
108d: 03 8c 93 00 da ff ff add -0x2600(%ebx,%edx,4),%ecx
1094: 83 c0 01 add [=10=]x1,%eax
1097: 39 f0 cmp %esi,%eax
1099: 75 ec jne 1087 <phase_5+0x2c>
109b: 83 f9 34 cmp [=10=]x34,%ecx
109e: 74 05 je 10a5 <phase_5+0x4a>
10a0: e8 38 05 00 00 call 15dd <explode_bomb>
10a5: 83 c4 04 add [=10=]x4,%esp
10a8: 5b pop %ebx
10a9: 5e pop %esi
10aa: c3 ret
10ab: e8 2d 05 00 00 call 15dd <explode_bomb>
10b0: eb cb jmp 107d <phase_5+0x22>
这是一个接受 6 个字符的字符串的函数(如果不接受,炸弹就会爆炸)并执行某种形式的循环算法来生成一个数字。最后,如果循环结果不等于 52 (0x34),则炸弹再次爆炸。但是,我无法理解代码的某个部分:
108d: 03 8c 93 00 da ff ff add -0x2600(%ebx,%edx,4),%ecx
显然,它抵消了您通过某种未知算法屏蔽字符串中每个字符的 ASCII 等价物而获得的数字。现在,我已经为每个字符创建了一个 table 的偏移量,并设法获得了一个可接受的字符串 aaaabb
,但我想知道代码的 C 等价物是什么样的。
就像 Jester 的回答一样,它正在索引一个数组。 ecx += table[edx]
,对于static int table[];
EDX索引在寻址方式下按4缩放,因为sizeof(int)
为4; asm 需要字节偏移量,C 索引使用元素偏移量。
-0x2600 + %ebx
是一个静态数组,与链接问题中的 0x804a4a0
相同。但是在静态反汇编中更难找到,因为 创建此 executable 的人烦人地将其编译为 32 位 PIE (position-independent executable)。
32 位 PIC / PIE 很糟糕,因为 PC-relative x86-64 的寻址是新的,因此逆向工程不必要地更复杂。
它将GOT(全局偏移量Table)地址获取到EBX中:首先call __x86.get_pc_thunk.bx
return它在EBX中的return地址,即0x1065
使用您从 objdump -d
获得的占位符地址。然后 add [=18=]x3efb,%ebx
将该位置的偏移量添加到 GOT。
然后静态数据相对于GOT base(在本例中为EBX)进行寻址。痛苦的屁股跟随那个与绝对地址。在内核的 program-loader 将代码映射到某个虚拟地址(0x1000
除外)之后,您可以在 运行 进程中的调试器中 single-step。
或手动执行:0x1065 + 0x3efb
= 0x4f60
的 GOT 基础 (EBX)。
0x4f60-0x2600
是查找 table 数组开始:0x2960
(如果您也使用 objdump -D
转储数据部分)。您可以在 GDB 中使用该地址(before start
或 run
),并使用 x
命令转储 table以一种方便的格式,而不是将数据伪装成来自 objdump 的代码。
运行 进程中的实际地址将是加上 4096 (0x1000) 的某个倍数。