Attack-lab 总结
Attack lab 的第二个部分。其实本来没想写的思来想去还是补完吧。
曾沿着雪路浪游 为何为好事泪流
谁能凭爱意要富士山私有
第二部分
增强版的第一部分,只要做 2、3 两问。现在栈随机化,而且加了金丝雀导致不能直接改栈,好像还有栈保护机制。面向返回编程:既然栈上的内容不能运行而且连地址都不固定,那就直接利用内存中已经存在的代码段拼凑出破解的方法。(这个想法真的厉害)好比 “哈基米南北绿豆 “七个字每个单独拉出来都没什么问题连在一起就糖丸辣。
x86-64 适用于这种攻击的特点是机器码不定长,一段机器码从中间截取一段就可能是完全不同的意思,而且很可能运行。
题目好心造了一个 “代码农场”,rtarget 运行的时候会加载里面的代码,可以直接利用。
第一关,在代码农场找了这个:
1 | 00000000004019ca <getval_280>: |
利用缓冲区溢出加载一段跳到 pop rax 的地方,然后把放在栈顶的 cookie 顺水推舟到 rax 上,随着 ret 继续退栈转到下一个地址,也就是 movq % rax,% rdi 的位置,把 rax 加载到第一个参数,继续 ret 到 touch2。利用 ret 跳一跳就是 ROP 面向返回。载荷如下:
1 | 90 90 90 90 90 90 90 90 |
第二关,csapp 官方只给了很少的分数,据他们说比较难,为了防卷特意降分,建议国内大学学习这种优良品质。我给了一个一定概率过不掉的载荷,但事实上我试了五次都成功了。
需要参照上面的代码段,有复用。说实话我自己记不太清了。
1 | 00000000004019d6 <add_xy>: |
把栈顶指针给 rax,然后 al(低 8 位)+0x37,也就是往前移动,把这个地址喂给 rdi 当第一个参数,呼 touch3 结束。至于有可能跑不通是因为 al 加法不进位,一旦 al + 0x37 溢出了地址计算会少 255,我藏在栈里的字符串就给不到 touch3 了。
载荷,字符串以 0 结尾。
1 | 90 90 90 90 90 90 90 90 |
官方解答确实很可以。摘自 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 |
将最终算好的字符串绝对地址放入 %rdi(touch3 的参数)。 |
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,在我完全忘记之前。