My rusty corner on the Web.
by EchoStone
2023 Fall Semester
Due Time: 10.24
Deadline: 10.26
在这个 Lab 中,你会尝试对一些程序进行缓冲区溢出攻击。基本的逻辑是,目标程序会向你要求一个字符串输入;你需要尝试让这个字符串触发缓冲区溢出,并控制之后的控制流变化(这可能需要你在字符串中编入一些适当的代码或地址)。以下是几个着手点:
脆弱函数:对于ctarget和rtarget,getbuf()
这个函数存在缓冲区溢出漏洞,可以被你利用;对于starget,脆弱的函数则是getbuf_with_canary()
。这两个函数的源代码可以在Writeup中找到;同时你可能还需要使用objdump来观察具体的栈内存排布,以进行缓冲区溢出攻击。
目标:目标分为3类:调用特定函数;用指定整数值作为参数调用特定函数;用指定字符串作为参数调用特定函数。
实际上的6个phase即是在ctarget,rtarget和starget上分别重复进行这些目标。
你可能会用到的其他工具有:
hex2raw
handout中附带的二进制程序.它读取用空格分割的十六进制字节,输出一串对应的字符串。这在你的攻击中很可能是必要的,因为你需要在输入的字符串中放入一些特定的字节,它们并不能通过键盘输入。
Writeup中有介绍hex2raw
的各种使用方法,你可以借此熟悉重定向功能。推荐的工作流程是这样的:
对于phase_n,新建一个key_n.txt,将你的字符串的十六进制表示输入进去;为了你自己方便,可以每8个字节一换行,比如:
00 00 00 00 00 00 00 00
01 02 03 04 05 06 07 08
然后你可以通过以下命令,直接攻击相应的程序:
./hex2raw < key_n.txt | ./ctarget # 或者换成别的target
这是让hex2raw
读取你的十六进制表示,然后通过管道(|
字符)把生成的字符串作为目标程序的输入。
注意:hex2raw
可以识别并忽略C风格的注释;这或许也能帮助你设计字符串,比如你的key_n.txt可能长成这样:
00 00 00 00 00 00 00 00 /* padding */
01 02 03 04 05 06 07 08 /* code: mov %rax, %rsp */
12 34 56 78 00 00 00 00 /* addr of func1 */
此时仍然可以直接调用hex2raw
输出正确的字符串(不包含注释部分)。
gdb
和objdump
你仍然可能需要通过objdump观察缓冲区大小,或者通过gdb得到特定的内存地址,来编入你的攻击字符串。
gcc -c
你可以在一个文件中写入任何汇编代码(注意格式要正确,最后一行应该为空行),然后调用gcc -c
完成汇编;如果你的汇编格式无误,便会生成对应的.o文件。再通过objdump,就可以看到你写入的汇编代码的字节表示。你可能需要把一些这样的字节表示放入攻击字符串。
man ascii
查看字符的 ascii 编码。
请在 class machine 上完成攻击,否则服务器不能正确记录分数!
攻击的目标程序在和服务器交流的过程中,其中一些函数使用了对栈指针有特殊对齐要求的指令。要求的对齐是16字节,而每个返回地址只占8个字节。
其结果是,在一些phase里,你可能会看到程序提示你攻击成功,然后又报告segmentation fault。这种情况正说明你的栈指针错开了8个字节。你需要想办法在攻击成功的同时,让栈指针也对齐;可能的方法是额外进行一次ret,或者直接修改%rsp到合适的值。
ROP部分的gadget只能来自start_farm到end_farm函数之间;评分程序和助教都会检查你的攻击是否符合这个规则。