2024年4月21日发(作者:)

Windows格式化字符串漏洞利用

作者:mr_me /blog/

译者:StudyRush(老钟古) /StudyRush/

老钟古序:

本来是打算翻译作者的另外一篇文章(/blog/?p=71)的,但

是由于在实战分析过程中遇到了一些问题自己暂时无法解决,等技术掌握更深入

一些之后再去想办法解决之后再进行翻译(实在不想让它胎死腹中)。因为没有

实战分析过的文章对自己产生的价值会小很多,没有实践过就等于把文章最精华

的部分给浪费了,不能够为了翻译而翻译。在翻译的过程中加了很多自己的心得

体会。

正文:

这经常让我感到很奇怪怎么样才能够从一个格式化字符串的bug中来执行代码。

我知道在这样的一种情况下我们能够用C类型的说明符进行漏洞利用,在一个

X86平台上我们不能够直接指向EIP寄存器或者结构化异常处理。当大部分格式

化字符串bugs几乎不存在时,我仍然感到对于任何一个安全分析师来说这是一

个值得去理解的概念。(即什么是格式化溢出漏洞)

基本步骤:

1.通过说明符%x来找到我们的缓冲区攻击字符串的起始位置。

2.使用%n将这个值写入到EAX寄存器中。

3.将一个指向我们的shellcode的地址放入到ECX/EDX寄存器中(为什么呢?)

4.通过%x来重新计算EAX寄存器的偏移并用一个有效的返回值来覆写它

(译注:补充点小知识:在格式化字符串的输出中

(1)s—这个参数被视为指向字符串的指针,将以字符串的形式输出参数;

(2)n—这个参数被视为指向整数的指针,在这个参数之前输出的字符的数量将

被保存到这个参数指向的地址里。这个可以自己动手实践一下)

举个例子来验证一下%n的实际输出结果。

命令1:

E:编程练习C专家编程第一章>

AAAAAAAAAA%x%x%x%x%x%x%x

在没有使用%n说明符的输出结果看下图

AAAAAAAAAAAAAAAAAAAAAAAAAAADDDDDe3b2f 这个里一个32个字符

用上面的输入则可以看出输出的字符数是为32的,现在我们再次输入上面的命

令并把一个%x用%n进行替换,

命令2:

E:编程练习C专家编程第一章>

AAAAAAAAAA%x%x%x%x%x%x%n

这时候的结果就为,参看下图:

从上面的得到的结果我们就可以知道,%n格式符把它的参数作为内存地址,把

前面输出的字符的数量写到那个地址去,这一操作结果也就意味着我们有机会改

写某个内存地址的数据,从而控制程序的执行,是不是感到有点迷糊呢?继续看

接下来的分析)。

继续前进时,请确认你有在教程中需要的工具:

Immunity debugger (用Ollydbg也可以)

pywin32 (应该是Python的解释器)

一个编译器(Dev C++或lcc32也行) (我在实战中用CodeBlock编译器)

让我们从vuln.c开始

#include

#include

void parser(char *string)

{

char buff[256];

memset(buff, 0, sizeof(buff));

strncpy(buff, string, sizeof(buff) - 1);

printf(buff); //here is format string vulnerability

}

int main(int argc, char *argv[])

{

parser(argv[1]);