格式化字符串漏洞 - 的printf [英] format string vulnerability - printf

查看:446
本文介绍了格式化字符串漏洞 - 的printf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这个打印的内存地址在0x08480110的价值?我不知道为什么会出现5%08X参数 - 那能够把你的堆栈?

Why does this print the value of the memory address at 0x08480110? I'm not sure why there are 5 %08x arguments - where does that take you up the stack?

address = 0x08480110
address (encoded as 32 bit le string): "\x10\x01\x48\x08"
printf ("\x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|");

这个例子是从本文的第11页<一所href=\"http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf\">http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf

This example is taken from page 11 of this paper http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf

推荐答案

我认为,该文件提供了一个有些混乱的方式及其的printf()的例子,因为例子使用字符串的格式字符串,而那些通常不允许被描述漏洞的类型。如这里所描述的格式字符串漏洞取决于用户输入所提供的格式字符串。

I think that the paper provides its printf() examples in a somewhat confusing way because the examples use string literals for format strings, and those don't generally permit the type of vulnerability being described. The format string vulnerability as described here depends on the format string being provided by user input.

因此​​,例如:

printf ("\x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|");

可以更好地被presented为:

Might better be presented as:

/* 
 * in a real program, some user input source would be copied 
 * into the `outstring` buffer 
 */
char outstring[80] = "\x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|";

printf(outstring);

由于 outstring 阵列是一个自动的,编译器将有可能把它压入堆栈。复制用户输入 outstring 阵列之后,它会看起来像作为'字堆栈中的下(假设小端):

Since the outstring array is an automatic, the compiler will likely put it on the stack. After copying the user input to the outstring array, it'll look like the following as 'words' on the stack (assuming little endian):

outstring[0c]               // etc...
outstring[08] 0x30252e78    // from "x.%0"
outstring[04] 0x3830255f    // from "_%08"
outstring[00] 0x08480110    // from the ""\x10\x01\x48\x08"

编译器将放在堆栈上其他项目,因为它认为合适的(其他的局部变量,保存的寄存器,等等)。

The compiler will put other items on the stack as it sees fit (other local variables, saved registers, whatever).

在该的printf()通话即将进行,堆栈可能类似于:

When the printf() call is about to be made, the stack might look like:

outstring[0c]               // etc...
outstring[08] 0x30252e78    // from "x.%0"
outstring[04] 0x3830255f    // from "_%08"
outstring[00] 0x08480110    // from the ""\x10\x01\x48\x08"
var1
var2
saved ECX
saved EDI

请注意,我完全使这些条目起来 - 每次编译器将使用以不同的方式堆栈(所以格式化字符串漏洞,可以定制制作的特定确切的情况。换句话说,你不会总是使用5假人格式说明就像这个例子 - 由于攻击你需要弄清楚的特别脆弱需要多少假人需要

Note that I'm completely making those entries up - each compiler will use the stack in different ways (so a format string vulnerability has to be custom crafted for a particular exact scenario. In other words, you won't always use 5 dummy format specifiers like in this example - as the attacker you'd need to figure out how many dummies the particular vulnerability would need.

现在叫的printf(),参数(地址 outstring )被压入堆栈和的printf()被调用,所以堆栈的参数区是这样的:

Now to call printf(), the argument (the address of outstring) is pushed on to the stack and printf() is called, so the argument area of the stack looks like:

outstring[0c]               // etc...
outstring[08] 0x30252e78    // from "x.%0"
outstring[04] 0x3830255f    // from "_%08"
outstring[00] 0x08480110    // from the ""\x10\x01\x48\x08"
var1
var2
var3
saved ECX
saved EDI
&outstring   // the one real argument to `printf()`

然而,printf的并不真正知道多少个参数被放在堆栈它什么 - 它的推移它发现格式字符串格式说明符(一个论据是不确定来获得)。因此,的printf()获取格式字符串参数,并开始处理它。当它到达1号%08X,将对应于我的例子中,救EDI',那么接下来的%08X将打印
保存ECX'等等。因此,%08X格式说明只是在堆栈上吃了数据,直到它回来的字符串攻击者能够输入。确定有多少,需要的是一些攻击者通过一种试错的做(这可能是通过测试运行具有的%08X格式的整体转换,直到他可以看到格式字符串开始的地方)。

However, printf doesn't really know anything about how many arguments have been placed on the stack for it - it goes by the format specifiers it finds in the format string (the one argument it's 'sure' to get). So printf() gets the format string argument and starts processing it. When it gets to the 1st "%08x" that will correspond to the 'saved EDI' in my example, then next "%08x" will print the saved ECX' and so on. So the "%08x" format specifiers are just eating up data on the stack until it gets back to the string the attacker was able to input. Determining how many of those are needed is something an attacker would do by a kind of trial and error (probably by a test run that has a whole slew of "%08x" formats until he can 'see' where the format string starts).

无论如何,当的printf()到达处理%S格式说明,它占用了所有的堆栈条目多达其中 outstring 缓存驻留。在%S说明对待自己的堆栈条目为指针,字符串用户已投入该缓冲区已被精心雕琢,具有 0x08480110 ,所以的printf()将打印出无论是在该地址为ASCIIZ字符串。

Anyway, when printf() gets to processing the "%s" format specifier, it has consumed all the stack entries up to where the outstring buffer resides. The "%s" specifier treats its stack entry as a pointer, and the string that the user has put into that buffer has been carefully crafted to have a binary representation of 0x08480110, so printf() will print out whatever is at that address as an ASCIIZ string.

这篇关于格式化字符串漏洞 - 的printf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆