🌳1. CSAPP与AttackLab简介
🌼1.1 CSAPP
《CSAPP》是指计算机系统基础课程的经典教材《Computer Systems: A Programmer's Perspective》,由Randal E. Bryant和David R. O'Hallaron编写。该书的主要目标是帮助深入理解计算机系统的工作原理,包括硬件和软件的相互关系,其涵盖了计算机体系结构、汇编语言、操作系统、计算机网络等主题,旨在培养学生系统级编程和分析的能力。
🌼1.2 AttackLab
target1实验通常与CS:APP书中的“Buffer Overflow Attack”相关。这个实验旨在教授计算机系统的安全性,防止攻击者定位攻击和锻炼使用金丝雀防护,特别是关于缓冲区溢出漏洞的理解和利用。在这个实验中,尝试利用缓冲区溢出漏洞来修改程序的执行流程,从而实现未授权的操作,比如执行恶意代码或获取系统权限。要求深入了解程序内存布局、堆栈和函数调用等概念,并学会利用输入缓冲区溢出漏洞来修改程序行为,这有助于理解系统安全中的一些基本原则和漏洞。
资源获取:关注文末公众号回复 CSAPP AttackLab实验
🌳2. AttackLab
🌼2.1 实验环境
- VMware Workstation虚拟机环境下的Ubuntu 64位。
🌼2.2 实验过程
实验准备阶段:首先需要使用ubuntu联网环境跳转到链接下载实验所需的attacklab:attacklab源文件
下载target1压缩包并输入
tar –xvf target1.tar
进行解压缩,进入该目录所有文件如下所示:
当前提供材料包含一个攻击实验室实例的材料:
1.ctarget
带有代码注入漏洞的Linux二进制文件。用于作业的第1-3阶段。
2.rtarget
带有面向返回编程漏洞的Linux二进制文件。用于作业的第4-5阶段。
3.cookie.txt
包含此实验室实例所需的4字节签名的文本文件。(通过一些Phase需要用到的字符串)
4.farm.c
rtarget实例中出现的gadget场的源代码。您可以编译(使用标志-Og)并反汇编它来查找gadget。
5.hex2raw
生成字节序列的实用程序。参见实验讲义中的文档。(Lab提供给我们的把16进制数转二进制字符串的程序)
在终端处输入命令
tar -xvf target1.tar
将压缩包解压如下:
图3-2
实验过程阶段:
使用
objdump -d ctarget > ctarget.asm
objdump -d rtarget > rtarget.asm
对ctarget以及rtarget进行反汇编,得到ctarget.asm和rtarget.asm。
在官方文档的目标程序给出,CTARGET和RTARGET都从标准输入读取字符串。它们使用下面定义的函数getbuf来执行此操作:
函数Gets类似于标准库函数gets—它从标准输入中(从缓冲区)读取字符串 (以’ \n '或文件结束符结束) 并将其(连同空结束符)存储在指定的目的地。即空格/Tab/回车可以写入数组文本文件,不算作字符元素, 不占字节,直到文件结束, 如果是命令行输入的话,直到回车结束(区别getchar ():是在输入缓冲区顺序读入一个字符 (包括空格、回车和 Tab)结束,scanf:空格/Tab/回车都当作结束。函数Gets()无法确定它们的目标缓冲区是否足够大,以存储它们读取的字符串。它们只是复制字节序列,可能会超出在目的地分配的存储边界(缓冲区溢出)对应汇编代码:
因为Ctarget就是让我们通过缓冲区溢出来达到实验目的,所以可以推断sub $0x28,%rsp的40个字节数就等于输入字符串的最大空间,如果大于40个字节,则发生缓冲区溢出(超过40个字节的部分作为函数返回地址,如果不是确切对应指令的地址,则会误入未知区域,报错:
Type string:Ouch!: You caused a segmentation fault!段错误,可能访问了未知额内存)
🌼2.3 第二部分
解决完level1-level3后,进入到第二部分:面向返回的编程。对程序RTARGET执行代码注入攻击比CTARGET要困难得多,因为它使用两种技术来阻止这种攻击:
•使用随机化,以便堆栈位置在不同的运行中不同。这使得无法确定注入的代码将位于何处。
•将保存堆栈的内存部分标记为不可执行,因此即使将程序计数器设置为注入代码的开头,程序也会因分段错误而失败。
通过执行现有代码,而不是注入新代码,在程序中完成有用的事情。这种最通用的形式被称为面向返回编程(ROP)[1,2]。ROP的策略是识别现有程序中的字节序列,该序列由一条或多条指令组成,后面跟着指令ret.这样的段被称为gadget. 即Part II和PartI I的区别是:这里用栈随机性和禁止栈中使用命令:栈随机性导致栈的位置不再固定,也导致我们不能像Part I一样,运行命令直接用栈中的确切位置就返回;禁止栈中使用命令为如果我们的命令是在栈中的,即%rip(程序计数器)指向栈,则会报错(段错误)。
该图表示需要设置要执行的gadget序列,字节值0xc3对ret指令进行编码。说明了如何设置堆栈以执行一系列n个gadget。图中,堆栈包含一系列gadget地址。每个gadget都由一系列指令字节组成,最后一个字节是0xc3,用于编码ret指令。当程序从该配置开始执行ret指令时,它将启动一系列gadget执行,每个gadget末尾的ret指令会导致程序跳到下一个gadget的开头。gadget可以使用与编译器生成的汇编语言语句相对应的代码,尤其是函数末尾的代码。在实践中,可能有一些这种形式的有用gadget,但不足以实现许多重要的操作。例如,编译后的函数不太可能在返回之前将popq%rdi作为其最后一条指令。幸运的是,对于面向字节的指令集,如x86-64,通常可以通过从指令字节序列的其他部分提取模式来找到gadget。
例如,rtarget的一个版本包含为以下C函数生成的代码:
这个功能对攻击系统有用的可能性似乎很小。但是,这个函数的反汇编机器代码显示了一个有趣的字节序列:
字节序列48 89 c7对指令movq%rax,%rdi进行编码。此序列后面是字节值c3,它对ret指令进行编码。函数从地址0x400f15开始,序列从函数的第四个字节开始。因此,此代码包含一个gadget,其起始地址为0x400f18,它将把寄存器%rax中的64位值复制到寄存器%rdi。
RTARGET代码包含许多类似于上面显示的setval_210函数的函数,这些函数位于称为gadget farm的区域中(注意: 重要提示:gadget farm由rtarget副本中的函数start_farm和end_farm划分,不要试图从程序代码的其他部分构造gadget)。工作将是在gadget farm中识别有用的gadget,并使用这些gadget执行类似于第2阶段和第3阶段的攻击。
🌼2.4 level 2(第二部分)
这一关需要完成的部分还是touch2,只不过是rtarget部分。对于第4阶段,将重复第2阶段的攻击,但使用gadget farm中的gadget对程序RTARGET进行攻击。可以使用由以下指令类型组成的gadget构建解决方案,并且只使用前八个x86-64寄存器(%rax–%rdi)。
1.movq:将数据从一个位置复制到另一个位置。
2.popq:把数据弹出栈。
3.ret:此指令由单字节0xc3编码。
4.nop:此指令(发音为“no-op”,是“no-operation”的缩写)由单字节0x90编码。它唯一的作用是使程序计数器增加1。
🌻2.4.1 解决思路
在第一部分的Level 2中提到解法为:
定位需要注入的函数touch2的地址的字节表示,以便在getbuf的代码末尾的ret指令将控制权传递给它。第一个参数是在寄存器%rdi中传递的。注入的代码应该先将cookie保存在寄存器%rdi中,然后在使用ret指令将控制权传递给touch2。所以首先需要popq %rdi,把cookie存放到%rdi中,然后再利用retq返回到touch2。
为了完成上面的过程,需要查找工具部分机器码能不能直接提供相应的功能,如果不行,则需要分几个步骤来完成。
在反汇编文件rtarget.asm中查看farm部分汇编代码:
通过搜索48 89 (mov指令),还有对于popq对应的机器码,其中 0xc3 = retq ,0x90 = nop, 找到了两个对这个实验有用的指令且有效的指令(不唯一):popq %rax 58 0x4019a7和movq %rax,%rdi 0x4019c3
新建anwer3.s文件,内容如下所示:
popq %rax (%rax = 0x59b997fa) (location: 0x4019ab)
retq (jmp location: 0x4019c5)
movq %rax,%rdi (location: 0x4019c5)
retq (jmp location: touch2 4017ec)
其中popq %rax (%rax = 0x59b997fa) (location: 0x4019ab)是为了将栈元素存放到%rax中,而retq (jmp location: 0x4019c5)指令是为了将栈中值弹出,然后跳转到地址0x4019c5;movq %rax,%rdi (location: 0x4019c5)是为了将%rax数据取出存放至%rdi,而retq (jmp location: touch2 4017ec)指令是为了将栈中值弹出,然后跳转到地址touch2 4017ec。
新建level4.txt建立内容如下:
🌻2.4.2 问题验证
命令进行验证:./hex2raw < level4.txt | ./rtarget -q,显示结果为PASS(需要注意的是,这里的指向件应该为rtarget而非ctarget,否则显示仍然为Fail):
🌼2.5 实验结果
由于实验通关过程中是分阶段的,故展示通关过程中所需的创建文件如下:
🌼2.6 实验体会
- 深度理解系统底层原理: 在AttackLab实验中,深入理解了计算机系统底层的运行原理。通过逆向工程和分析二进制代码的过程,我对计算机系统中内存管理、指令执行等方面的细节有了更深刻的认识。这种深度理解不仅加强了我的系统编程技能,还提升了对计算机系统整体运作的把握能力。
- 实战锻炼安全编程技能: AttackLab实验是一次很好的实战机会,通过挑战性的任务,我得以实际应用课堂学到的知识。在攻防过程中,我锻炼了安全编程技能,学会了如何防范和应对潜在的安全威胁。这种实际应用的经验对于未来从事与计算机系统相关的工作至关重要。
- 团队协作与问题解决: 在实验中,我发现团队协作是解决问题的关键。与同学合作,共同思考和攻克实验中的难关,促使了我更好地理解课程内容。通过与同学的讨论,我学到了许多新的解决问题的方法,并培养了团队合作的能力。这种合作经验对于未来在技术团队中的工作将是非常宝贵的资产。
📝 总结
在计算机系统的广袤领域,仿佛是一片未被揭示的复杂网络,隐藏着深奥的密码,而CSAPP的AttackLab实验正是那一场引人入胜的冒险之旅。这实验不仅深入挖掘计算机系统的基本概念,更将目光投向底层的系统实现,逐步揭开计算机系统内核、汇编语言和数据结构这些层次的神秘面纱。
对于那些渴望挑战计算机系统安全学习路径,以及希望掌握底层系统编程技术的冒险者们,AttackLab提供了一个独特的机会。点击下方链接,你将能够深入研究计算机科学的奇迹,探讨安全编程技术的实际应用和创新。我们引领趋势的🌱计算机科学专栏《斯坦福大学之CSAPP》将为你展开一场精彩的学术冒险,带你穿越计算机系统的迷雾,解锁其中的奥秘。🌐🔍