一、实验目的
1、深入了解缓冲区溢出的隐患,了解如何利用缓冲区溢出这个漏洞对现有程序进行控制流劫持、执行非法程序代码,从而造成对程序进行攻击以及破坏的过程;
2、增强对程序机器级表示、汇编语言、调试器和逆向工程等理解。
二、实验内容
对目标程序实施缓冲区溢出攻击,通过造成缓冲区溢出来破坏目标程序的栈帧结构,继而执行一些原来程序中没有的行为。
本实验共完成以下2个实验小题:level1和level2。
1、准备工作
在所发目录中,一共3个和本实验相关的文件:
ctarget 代码注入攻击的目标文件
hex2row 将16进制数转化为攻击字符,因为有些字符在屏幕上面无法输入,所以输入该字符的16进制数,自动转化为该字符
cookie.txt 一个8为16进行数,作为攻击的特殊标志符(level2使用)
其中,ctarget为所要分析处理的文件。其中包含3个函数:getbuf( )和touch1、touch2。可用objdump工具反汇编查看其代码,并存入文件中方便查看。命令为:
objdump -d ctarget > ctarget.txt
2、level1的内容和要求
ctarget 的正常流程如下:
其中getbuf( )函数定义为:
Gets( )的功能是输入字符串到buf中,但没有检查字符串的长度是否在BUFFER_SIZE内。本题要求通过适当的输入,利用getbuf( )的漏洞使程序在test函数中重新定向到touch1函数。touch1函数定义如下:
3、level2的内容和要求
同level1的整体流程,即在getbuf中输入字符,拦截程序流,跳转到调用touch2函数。touch2函数定义如下:
这段程序验证传进来的参数val是否和cookie中值相等。本程序需要做的是在输入字符串中注入一小段代码,代码传入val参数到%rdi,其中val是和cookie一样的值,然后正确跳转到touch2。
三、实验工具和环境
软件工具:gdb调试器和objdump;
实验语言:C语言,AT&T汇编语言
实验环境: linux
四、过程分析
Level 1
1.用objdump工具反汇编查看其代码,并存入文件中方便查看。命令为:
objdump -d ctarget > ctarget.txt
2. 利用gdb 调试ctarget找到我们需要的信息
3. 反汇编getbuf函数,找到实际在栈上分配了多少字节
从第一行sub $0x28, %rsp中显示,在栈上为buf提供了0x28也就是40个字节的空间
4. 反汇编touch1函数,找到touch1函数的起始地址
从第一行中看出,touch1的返回地址是0x0000000000401934。
以上,我们已经到了我们需要的所有关键信息,现在构建我们输入字符,首先填充栈,可以使用任意字符,这里创建了一个文件输入16进制的0x00填充,然后填充touch1地址(通过在getbuf阶段输入特定的字符串,拦截程序流,跳转到touch1)。注意字节序的问题,大部分电脑应该都是little-endian字节序,即低位在低地址,高位在高地址。
5.使用如下命令进行结果验证:
cat 2009100031.l1 | ./hex2raw | ./ctarget -q
(hex2row 将16进制数转化为攻击字符,因为有些字符在屏幕上面无法输入,所以输入该字符的16进制数,自动转化为该字符; | 管道符号)
Level 2
1.查看touch2函数
这段程序就是验证传进来的参数val是否和cookie中值相等。本文中我的cookie值为:0x3952370c
2.建立inject.s文档,输入注入代码(第一个立即数是我的cookie,第二个是touch2的地址)
3. 利用gcc和objdump命令得到机器代码:
可以得到这三条指令序列如下:
48 c7 c7 0c 37 52 39 68 60 19 40 00 c3
4. 接下来就是寻找%rsp的地址,利用gdb进行调试,获取我们需要的信息:
地址为0x55650e08
如上所示,我们获取到了%rsp的地址,结合上文所讲,可以构造出如下字符串,在栈的开始位置为注入代码的指令序列,然后填充满至40个字节,在接下来的8个字节,也就是原来的返回地址,填充成注入代码的起始地址,也就是%rsp的地址,可以得到如下字符串:
5.验证通过