CSAPP-AttackLab

WriteUp:http://csapp.cs.cmu.edu/3e/attacklab.pdf

题目要求

第一部分:代码注入攻击 对于前三个阶段,您的漏洞利用字符串将攻击 CTARGET。 该程序的设置方式使堆栈位置从一次运行到下一次运行保持一致,因此可以将堆栈上的数据视为可执行代码。 这些功能使程序容易受到攻击,其中漏洞利用字符串包含可执行代码的字节编码。

第二部分:面向返回的编程
对程序 RTARGET 执行代码注入攻击比 CTARGET 困难得多,因为它使用两种技术来阻止此类攻击。

使用 HEX2RAW

HEX2RAW 将十六进制格式的字符串作为输入。 在这种格式中,每个字节值由两个十六进制数字表示。 例如,字符串“012345”可以以十六进制格式输入为“30 31 32 33 34 35 00”。 (回想一下十进制数字 x 的 ASCII 码是 0x3x,并且字符串的结尾由空字节表示。) 您传递给 HEX2RAW 的十六进制字符应由空格(空格或换行符)分隔。 我们建议您在处理漏洞时用换行符分隔漏洞利用字符串的不同部分。 HEX2RAW 支持 C 风格的块注释,因此您可以标记出漏洞利用字符串的部分。 例如:

48 c7 c1 f0 11 40 00 /* mov $0x40011f0,%rcx */

确保在开始和结束注释字符串(“/”、“/”)周围都留有空格,以便正确忽略注释。

ADVICE: Include the -q flag which prevents program from contacting non-existent grading server in addition to the above

Phase1

For Phase 1, you will not inject new code. Instead, your exploit string will redirect the program to execute an existing procedure.

这一部分仅利用缓冲区溢出,getbuf函数要求输入一行字符串,要让这行字符串溢出到上一个栈帧的返回地址区域,就能使得本该返回 main 的程序跳转到 touch1 的代码。

主要有两个知识点:

  • 栈的结构
  • hex 与 字符串 的相互转化
栈的结构:

字符串以倒着的顺序,从栈顶往栈底存储.字符占用1byte空间,也就是8个bit位。在栈中,地址指的是byte,每个地址有8bit的存储空间,两个16进制数表示一个byte的状态。

1
两个16进制数 = 8bit = 1byte = 一个地址空间

一个地址占用 8 byte 空间,这也解释了为什么有些函数并没有向栈中暂存数据,但也要申请至少8字节的栈空间。

查了一下google,这个专业名词叫栈的8字节对齐,能够提高程序运行效率

hex2raw:

栈中存储的是16进制数(hex),但是函数输入是字符串形式,这时候就需要找到两者之间的映射关系。比如这一题里需要覆写的hex为40 17 c0,40好办,因为hex to raw的逻辑与ascii码相容,0x40的ascii码是@。

但是17就比较难办了,因为ascii码中17没有显式的字符与之对应,也就是说键盘输入hex为17的字符是不现实的。这个时候只能用lab中自带的hex2raw来完成这个工作。虽然17的字符不能显式表达,但是它确实存在。

命令行输入

cat hex.txt | ./hex2raw | ./ctarget -q(-q是指不给csapp的服务器发送信息)

就能把hex.txt中的16进制数通过hex2raw转化成字符串形式输入进ctarget程序。

⚠️注意字符串的存储是倒着来的(至少这一题中是的),所以地址也要倒着写。hex.txt内容如下:

✅phase1通过:

Phase2

Phase 2 involves injecting a small amount of code as part of your exploit string.

phase2是phase1的进阶版,要在重定向的基础上,实现一个数据注入。

思路是在两个函数中加插入一个函数,这个函数的bin代码放在栈上(此题中实际是堆),

⚠️注意%rip以地址递增读取,返回值以地址递减读取(想象pop出栈),同一个地址内从左到右。

内存栈入口位置:0x5561dc78

Phase3

和Phase2大同小异,只不过是吧参数换成字符串形式存储在栈上,rdi寄存器里面放着个字符串的地址,

要注意的是getbuf函数的栈帧在释放之后,可能会有后续的栈帧来覆盖这一部分。经过试验如果在缓冲区的40个字节里面放字符串,会被覆盖掉。

Phase4

事情开始变得有意思起来了,这一部分开始,就要用到面向返回编程(ROP)的思想进行攻击了。先来看一个例子:

1
2
4019b5:    c7 07 48 89 c7 90    movl  $0x90c78949,(%rdi)
4019c9: c3 ret

单凭这一句汇编来讲,好像没有什么值得利用的地方,但是注意movl这一句这里:48 89 c7,如果放在movl这一句里面表示的仅仅是一个立即数而已,但是如果把48 89 c7看作是操作指令的话,它代表的意思就是:mov %rax,%rdi。仔细想想,如果利用这一点,是不是感觉操作空间很大了呢?(只能说,舞台很大

至于一些常见指令的二进制表达,在writeUp里面也有提到,如下图:

既然是面向返回编程,就要对汇编中出现的c3(ret) 90(nop)敏感,这些往往是思路的切入点。

题解就不放了,知道了这些很简单。

⚠️另外要注意:大端序和小端序,这题里面的数据都是小端序摆放的,且占8个字节,多余的用00填充

Phase5

不想写了,就这吧

这一部分也是ROP攻击,思路和Phase4一样,但是因为要传字符串,难度会比Phase4高不少,so,不写了,摸鱼了🐟

下次一定下次一定😅