这个实验要求在5个有不同安全漏洞的代码上进行攻击,攻击分为两部分:
Part 1:Code Injection Attacks(缓冲区溢出攻击)
Part 2:Return-Oriented Programming(ROP攻击)
做题之前一定要仔细阅读write up:http://csapp.cs.cmu.edu/3e/attacklab.pdf,跟着实验说明做会明朗很多。
文件说明
ctarget
:一个容易遭受code injection攻击的可执行程序。 rtarget
:一个容易遭受return-oriented programming攻击的可执行程序。 cookie.txt
:一个8位的十六进制码,用于验证身份的唯一标识符。 farm.c
:目标“gadget farm”的源代码,用于产生return-oriented programming攻击。 hex2raw
:一个生成攻击字符串的工具。
Part 1:Code Injection Attacks
Level 1
第一题是要我们攻击一个叫test的方法,这个方法中有个getbuf方法,要求从getbuf返回时不让它返回到test,而是返回到touch方法。
我们可以发现getbuf是一个输入字符串的方法,那么我们只要将此方法开辟的栈给填满,然后再填上touch方法的地址,那么就能实现跳转到touch的效果了!
所以我们要做两步:
首先确定getbuf方法的缓冲区大小,反汇编gets方法查看:
得到此方法的缓冲区为40个字节。
其次我们看下touch方法的地址:
地址是4017c0,那么我们需要输入的字符串就得到了:
前面的40个字节都是假的,随意填,关键在于最后8位,填的时候需要注意按照小端的排列顺序。
然后用hex2raw来生成字节码,成功入侵垃圾代码!
Level 2
根据题目指示,这一题我们要做的同样是跳转,这次我们跳转的是touch2函数,看下touch2函数长什么样,发现这里需要我们传入一个参数,根据实验说明我们知道这个参数的位置在%rdi。所以我们需要注入一段自己的入侵代码了。
这题我的思路是这样的:
1.写一段代码将参数(也就是每个人不同的cookie),放入寄存器%rip中,然后将touch2的地址压栈,为的是通过ret返回时可以跳转到ret。
2.然后通过第一题的方式如法炮制利用缓冲区溢出的漏洞将getbuf函数返回到上述的代码起始位置,也就是缓冲区的起始位置执行攻击代码。
我写的汇编,第一个立即数是我的cookie,第二个是touch2的地址:
利用gcc和objdump命令得到机器代码:
然后需要找到缓冲区的其实地址,我们需要gdb在getbuf打断点查看%rsp的值,但这里我碰到了个小问题,我前后两次执行程序查看%rsp的值是不一样的,导致我第一次实验始终不通过,没有能够理解这里为什么会变化,有读者如果知道可以留言给我。
这里用最新的rsp值即可再次入侵垃圾代码!
Level 3
这一题和上面一题很像,要求是跳转到touch3,同样需要传入一个参数,不过这次是传入一个地址,而不是直接的cookie:
可以看到touch3里又调用了hexmatch,这里需要注意了,我们存放cookie的地址,不能在缓冲区随便放,因为hexmatch里的数组还会把我们的cookie给覆盖掉,我的想法是可以讲cookie放到缓冲区之上,也就是返回地址再上面8个字节,也就是%rsp+30。
汇编代码:
字节码::
结果:
Part 2:Return-Oriented Programming
我们之前几题都是围绕着缓冲区溢出的话题,但是从这里开始,rtarget文件中对于上述攻击有了防御措施,比如栈地址随机化或者缓冲区的代码直接被设置成为不可执行,这样就断绝这种攻击的可能性,也是现在许多系统所采取的方式,但是攻击者并不会止步于此,于是ROP就诞生了。ROP攻击的大致意思就是利用现有的代码,通过不断的跳转,拼凑出自己想要的结果来进行攻击的方式。
下面是实验手册给出的部分指令所对应的字节码,我们需要在rtarget文件中挑选这些指令去执行之前level2和level3的攻击。
Level 2:
按照题目提示,第一题的代码可以在这段代码里找:
我的思路是先将cookie pop到rax,然后用mov指令将rax移动到rdi,最后通过覆盖返回地址来执行touch2。
通过观察我们要的命令在这里:
分别是58(pop %rax),48 89 c7(movq %rax,%rdi)
地址分别是0x4019ab,0x4019c5,touch2的地址是0x4017ec。
于是我们拼凑的代码就出来了:
Bingo!
Level 3:
这题略有难度,最近大病一场,等恢复后再挑战这一题。