0%

[CSAPP Lab]-II Bomb Lab

Phase 6

Phase 6 的汇编又臭又长,先把 Phase 6 反汇编出来

完整的代码就不放了,先来一段段分析

Section 1

这一段是函数调用相关的,不用过多的在意,不过注意最后一行调用了 read_six_numbers ,根据之前的练习中,这个函数会读取 6 个数字并放在 %rsp~%rsp+0x14 中(这里可以用 GDBx/d 打印检查)

Section 2

下面开始正文了,先上代码

最后一行的 401151 可以看出外层嵌套了一个大的循环,401117 中,将 eax 赋值为 r13 指向的地址,也就是第r12d个输入变量,然后 40111e 的比较确保了输入变量是小于 6 的

内层循环中,则是取出第 r12d 个输入变量后边的,依次与 eax 比较,确保每个变量都不相同

Section 3

rax 每次增加 4 个 Byte 来读取下一个 Int ,并且将 raxrsp+0x18 比较
每次用 0x7 减去

Section 4

这里就开始比较恶心了,先看里边有个 Magic Number 0x6032d0 ,用 GDB 打印出来发现是这样的:

1
2
3
4
5
6
7
(gdb) x/24 0x6032d0
0x6032d0 <node1>: 332 1 6304480 0
0x6032e0 <node2>: 168 2 6304496 0
0x6032f0 <node3>: 924 3 6304512 0
0x603300 <node4>: 691 4 6304528 0
0x603310 <node5>: 477 5 6304544 0
0x603320 <node6>: 443 6 0 0

说实话我也不懂这个是什么(???),一番百度 Google 后发现这是一个链表,结构大概是这样的

注意这里的Next地址是十进制表示的,要记得把它转换成十六进制

地址 序号 Next地址
0x6032d0 332 1 0x6032e0
0x6032e0 168 2 0x6032f0
0x6032f0 924 3 0x603300
0x603300 691 4 0x603310
0x603310 477 5 0x603320
0x603320 443 6 0

循环中, ecx 用来存取当前所读取的输入变量,最后一行跳转到 401176 ,因为链表的每个 Node 都是两个 Int 和一个 Pointer 组成的,所以 401176 中获得下一个 Node 的地址,并且用 eax 来做计数变量,可以看出这几行的作用就是使得 rdx 中存的是第 ecx 个链表元素

然后下边的就是在 0x20+rsp+rsi*2 后边添加上第 ecx 个 Node 的地址

举个例子,如果输入是 6 5 4 3 2 1 这一步就会把链表第六个 Node 的地址放到栈顶第一位,第五个放到第二位…

Section 5

这里的工作就像注释所说的:把新的链表重新连接起来

Section 6

这里比较的是新链接的链表的前一个元素的 Value 大于后一个元素的

Final

综上,这个逻辑总算是理清楚了:首先从输入读取 6 个数字,确保每个数字都是小于等于 6 并且只出现一次,然后将链表重新排序为按照输入的顺序,最后验证新的链表的前一项大于后一项

链表中的值分别是 332 168 924 691 477 433 ,所以输入就是 4 3 2 1 6 5

有时间把之前的 Phase 补齐吧(Flag)

EOF.