首发于 Computer Science学习笔记
CSAPP Lab -- Attack Lab

CSAPP Lab -- Attack Lab

准备

如同封面图片,这次Lab可以给你体验做一个"hacker"的感觉。


和 Bomb Lab一样,这个实验也是CSAPP中第三章的配套实验,前者主要是利用基础的汇编知识来读汇编代码并解决问题,而Attack Lab则需要弄明白控制过程在机器级代码中的表现形式和运行过程。

这个实验分为两个部分,分别是code injection attacks和ROP,这是攻击程序的两种方法。在开始实验之前,可以准备一些资料:

介绍一下,整个Lab的大致流程就是,你输入一个字符串,然后利用stack的buffer overflow,我们就可以修改stack中的数据,然后就可以改变程序的运行,达成我们的目的。具体到这个Lab,我们要完成的目标就是通过test()函数中的getbuf()这个入口,来完成对stack某些部分的覆盖,利用两种攻击程序的技术,让程序调用我们希望调用的函数。

为了能够方便地分析代码和debug,推荐一个GDB的衍生版 pwndbg。

Like this:



Part I : Code Injection Attacks


level 1

这个部分很简单,要求我们输入一个字符串,利用溢出来重写stack中的getbuf函数ret的地址,让程序调用函数touch1。先objdump -d ctarget.c > ctarget.d反汇编得到汇编代码。

根据这段代码可以确定,getbuf在栈中分配了0x28bytes的内存来存储输入的字符串。回想一下CSAPP中程序调用时栈的结构,我们会把返回地址存在栈中,然后再去调用函数。如果我们输入的字符串长度超过40,就可以覆盖掉getbuf的返回地址了,所以,我们只需要把输入的第40-47个字符填写为touch1函数的地址就OK了。

touch1的地址为00000000004017c0,按照前面的思路,填写字符串就好了:

这里需要注意的是,我们输入的字符应该用两位十六进制数来表示ascii码,然后通过./hex2raw来将其转换成字符串。另外,因为我使用的是ubuntu,数据都是用小端法来保存的,所以低位在前。


level 2

和level1相比,level2需要调用的touch2函数有一个unsighed型的参数,而这个参数就是lab提供的cookie。所以,这次我们在ret到touch2之前,需要先把cookie放在寄存器%rdi中(第一个参数通过%rdi传递)。

为了达到这个目的,我们需要在stack中植入指令movq $0x59b997fa, %rdi。所以,考虑在第一次ret的时候,将这个地址写为这条指令的地址,然后再ret到touch2

首先,通过

来把指令转换成十六进制的形式,然后放在字符串的开头。这个时候,我们需要得到这个指令在栈中的具体位置,可以用GDB来调试获得:

所以,将第一次ret的地址写为这个。然后,再把touch2的地址放在这后面就行了:

整个流程就是: getbuf => ret => 0x5561dc78 => movq $0x59b997fa, %rdi => ret => 0x4017ec


level 3

和level2一样,touch3也需要传入cookie,但是要求以字符串的形式传入。所以,我们要做的就是,把字符串形式的cookie放在stack中,然后再把它的地址放在%rdi中,再就和touch2中一样了。

但是,在这里有一个问题,我们不能够单纯地像level2中那样做,因为touch3中调用了hexmatch函数,而这个函数会在栈中申请110bytes的空间,这样有可能将我们在stack中放置的cookie给覆盖掉。

为了解决这样的问题,我们可以考虑将cookie放在更上面的位置,让hexmatch够不着,或者直接通过植入指令来修改%rsp栈指针的值。

这里采用了第二种方案:


Part II: Return-Oriented Programming


level 2

level2对应Part I中的level2,不同的是,在Part II:
- stack的地址会随机化
- 不能够ret到stack中来执行指令


在这样的限制下,我们不能使用代码注入的方式来进行攻击了,Write up中介绍了ROP这种方式,大致的思想就是我们把栈中放上很多地址,而每次ret都会到一个Gadget(小的代码片段,并且会ret),这样就可以形成一个程序链。通过将程序自身(./rtarget)的指令来完成我们的目的。

Write up提示可以用movq, popq等来完成这个任务。利用popq我们可以把数据从栈中转移到寄存器中,而这个恰好是我们所需要的(将cookie放到%rdi中)。

思路确定了,接下来只需要根据Write up提供的encoding table来查找popq对应encoding是否在程序中出现了。很容易找到popq %rdi对应的编码5f在这里出现,并且下一条就是ret:

所以答案就是:


level 3

最后一个题就比较麻烦了,因为它需要处理好cookie存放的位置,并且需要找到能够对%rsp进行运算,然后保存在%rdi中的一系列Gadget。

首先解决第一个问题,因为我们没有实现sub操作的可能性,所以cookie只能放到比较高的位置,而不能够通过修改%rsp来保护cookie不被覆盖。

然后处理第二个问题,我们必须找到一个能够实现加法或者减法运算的Gadget,这个函数带来了希望:

我们可以通过这个函数来实现加法,因为lea (%rdi,%rsi,1) %rax就是%rax = %rdi + %rsi。所以,只要能够让%rdi和%rsi其中一个保存%rsp,另一个保存从stack中pop出来的偏移值,就可以表示cookie存放的地址,然后把这个地址mov到%rdi就大功告成了。

对应Write up里面的encoding table会发现,从%rax并不能直接mov到%rsi,而只能通过%eax->%edx->%ecx->%esi来完成这个。所以,兵分两路:
- 1.把%rsp存放到%rdi
- 2.把偏移值(需要确定指令数后才能确定)存放到%rsi

然后,再用lea那条指令把这两个结果的和存放到%rax中,再movq%rdi中就完成了。

值得注意的是,上面两路完成任务的寄存器不能互换,因为从%eax%esi这条路线上面的mov都是4个byte的操作,如果对%rsp的值采用这条路线,%rsp的值会被截断掉,最后的结果就错了。但是偏移值不会,因为4个bytes足够表示了。


另外,在网上发现了一些其他做法,例如 这篇文章。在文章中,他的主要思路是利用在这里:

发现的04 37表示add $0x37, %al,利用这个直接对%rax的值进行修改。但是这种做法是不完全正确的,因为%al只表示2个bytes,如果出现溢出的情况,那样计算出来的cookie的地址就是错误的,所以这种方法会有fail的情况发生。

最后结果:


到这里,第三章对应的两个Lab就做完了。通过这两个Lab,感觉对GDB的使用更熟练了,也对程序的运行有了更深入的认识。这两个Lab很良心,从浅到深,循循善诱。根据Write up的提示,可以减少很多麻烦。

聚圣源起泡酒牌子排名卖厨卫电器起什么店名500g是多少斤补英语甜水园二手房生活处处有语文给我的启示起群聊名快递起什么名字比较好江苏短信群发易经起名字测打分曾起名字女孩姓名起名起名字大全诗经乡村爱情进行曲营养食品起名男孩子早晨生起名字一夜鱼龙舞抱团取暖起名三才五格方法合肥万科金域华府傅雷家书读书笔记摘抄及感悟世外桃源的主人公是谁特朗普称美国拥有世上最强武器给家起个有诗意的名字起个韩国服装店名字大全给女孩子起什么名好?西甲皇马赛程直播吧cctv5釮字起名代表什么意思怎么查起名字淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化