一、 *实验目标*

%x查看栈内容

%s查看指定地址内容

è 复习缓冲区溢出覆写返回地址跳转shellcode的操作流程

è 了解sprintf()函数缺陷所在

è 分析shellcode的构造原理

è 实际操作对格式化输出函数漏洞进行利用

二、 *测试步骤与结果*

(一)通过%x来查看栈内容,重建栈内存,获得该frame的返回地址;

  1. 代码如下

img
如上所示,执行printf时第四个%x没有提供对应的参数,因此会显示本应该是参数所在位置的栈内容

  1. 运行至CALL test._printf处,可以看到显示了本应该是参数所在位置的栈内容。

img

  1. 通过更多的%x可以重建更多的栈内存:

img
img

(二)通过%s查看指定地址内容;

  1. 分析源代码

img

  1. 在OllyDbg中打开程序,并执行printf函数:

img
1,2,3是提供3个参数。利用%x步进,将%s的参数对应到77E61010,因此可以输出77E61010开始的字符串直到遇到截断符。0x0012FF58为format字符串起始地址,前四个字节即我们想要查看的内存地址77E61010:

(三)对sprintf函数及shellcode做解释分析;
img
作为向字符数组中写入数据的格式化输出函数,sprintf会假定存在任意长度的缓冲区。此处将字符数组user作为由用户构造的输入,其中出现了非常规字符%497d,是此次实验成功的关键。\x39\x4a\x42\x00是shellcode的起始地址,用来覆盖返回地址。\x90…\x33…\xD0…\x90为此次的弹框的shellcode:
img

(四)通过格式化字符串造成的缓冲区溢出覆盖返回地址,执行shellcode;

  1. 运行ollidbg,打下两处断点

img

  1. 运行至第一个 sprintf 处步过,观察缓冲区,可见存储位置从0012FB2C开始。由于后续被\x00截断,不在复制user后续内容

img

继续运行到第二个断点后,运行结果指向0012FD2C
img
可以看到第二个存储栈的内容
img
为满足%497d,中间使用\x20填充。最后写入\x39\x4a\x42\x00的十进制格式
img

  1. 由于“ERR Wrong command:”+若干个补充字符’\x20’+1245056D+0x00424A39=516字节,大于存储结构定义时的512,多余的四个字节会将返回地址覆盖淹没。返回地址转跳到shellcode代码地址。

img

三、 *测试结论*

格式化字符串漏洞是由于程序员在使用诸如printf这类的格式化输出函数时未能正确验证输入,导致攻击者可以通过构造特定的输入来控制格式化字符串的行为。如果格式化函数如sprintf或printf使用了用户控制的输入作为格式化参数,攻击者可能会插入恶意格式化指令,这些指令可以读取或写入内存,导致缓冲区溢出或其他安全问题,例如执行任意代码。这种类型的漏洞在软件安全中是严重且常见的,因为它允许攻击者绕过正常的权限检查来危害系统。

本次实验中了解到了格式化字符串造成缓冲区溢出的具体原理,并对其危害和效果进行了尝试。

四、 *思考题*

*破解foo.exe程序,在不改变源代码的情况下,要求通过命令行输入,利用格式化字符串漏洞n%的方式,调用隐藏的foo函数,并尝试调用一个shellcode。*

  1. 使用ollydbg启动程序,并在输出函数打断点。

img

  1. 尝试输入%x做参数,查看输出效果

img

  1. 查看输出结果

img

  1. 查看栈空间

img
可见存储从0012FD18开始,由于设定 char buf[512]因此会一直存储到0012FF18。但是_snprintf(buf, sizeof(buf)-1, “Can’tFind%s”, file);所以无法实现对0012FF18的直接写入。

  1. 查看%x的指针调用位置。

img
可见,指针是从0012FCCC开始调用的。

  1. 因此进行分析:如果想调用foo函数,需要在返回地址,即0012FF18写入foo函数地址00401014,而现有转跳是00401005。

img
因此可以使用%hn替换其低四位内容,即%hn输出前字符串输出1014。并且使指针通过%x遍历,最后停止在0012FF18的地址上。
参数格式应为%x%x%x%x……%x%x%x%x%hn \x00 \x12 \xFF \x18

  1. 计算%x个数。1014转换为10进制为4116,由此构造输出位数,结果如下。

img

  1. 尝试运行,运行成功

imgimg

  1. 同理构造shellcode。由于shellcode构造在参数部分,即0012FD20。因此在转跳时需要转跳此处,需要把0012FF18处内容00401005全部替换。构造如下:

img

  1. 运行结果

img