【问题标题】:Tim Newsham format string exploitTim Newsham 格式字符串漏洞利用
【发布时间】:2019-09-04 04:35:03
【问题描述】:

我正在阅读Tim Newsham's white paper 的格式字符串漏洞利用,发现一开始有些部分难以理解。

正在讨论以下计划。

/*
 * fmtme.c
 *       Format a value into a fixed-size buffer
 */

#include <stdio.h>

int
main(int argc, char **argv)
{
    char buf[100];
    int x;
    if(argc != 2)
        exit(1);
    x = 1;
    snprintf(buf, sizeof buf, argv[1]);
    buf[sizeof buf - 1] = 0;
    printf("buffer (%d): %s\n", strlen(buf), buf);
    printf("x is %d/%#x (@ %p)\n", x, x, &x);
    return 0;
}

作者说“本文档中的所有示例实际上都是在 x86 BSD/OS 4.1 上执行的”,这是一个 little-endian 机器。

程序是这样执行的

% ./fmtme "%x %x %x %x"
buffer (15): 1 f31 1031 3133
x is 1/0x1 (@ 0x804745c)

论文说:

"A quick analysis of the program will reveal that the stack layout of the
program when the snprintf function is called is:

    Address  Contents       Description
    fp+8     Buffer         pointer 4-byte address
    fp+12    Buffer         length 4-byte integer
    fp+16    Format         string 4-byte address
    fp+20    Variable x     4-byte integer
    fp+24    Variable buf   100 characters

The four values output in the previous test were the next four arguments on
the stack after the format string: the variable x, then three 4-byte
integers
taken from the uninitialized buf variable."

这里的fp 是什么?文件指针?

为什么它从 fp+8 而不是 fp+4 开始,而其他任何地方(4 字节地址)的增量都是 4?

这里,更大的地址意味着值在堆栈的上层还是下层?

“内容”下的名称是什么意思?


当我运行上面的程序时,x 的值,即1,没有被打印出来。可能是因为架构不同?

我是这样的

./fmtme "%x %x %x %x"
buffer (34): cd512860 b3356d80 b3356d80 8247ee8
x is 1/0x1 (@ 0x7ffc08247d8c)

谁能帮忙?

【问题讨论】:

  • @user3386109 我们能以某种方式将旧架构与新架构联系起来吗?如果这有什么不同?

标签: c security exploit format-string


【解决方案1】:
  • fp 代表“帧指针”。

  • 参数从fp+8开始,因为fp+4是返回地址,fp+0是保存的帧指针。

  • 在 x86 使用的传统向下增长堆栈中,更高的地址在堆栈中更深(较早推送的项目)。

Contents 有点不清楚 - 它试图描述堆栈槽中的内容,但其中一些没有名称。这可能更清楚:

Address  Contents                  Description
fp+8     First snprintf argument   pointer 4-byte address
fp+12    Second snprintf argument  length 4-byte integer
fp+16    Third snprintf argument   string 4-byte address
fp+20    Variable x in main        4-byte integer
fp+24    Variable buf in main      100 characters

您看不到相同的结果,因为这些类型的东西 - 形式上是未定义的行为 - 对您正在使用的架构、编译器和编译器版本高度敏感。从用%p 打印的指针值看来,您使用的是 64 位架构 - 如果您使用的是 x86-64,那么函数的前 6 个整数参数将在寄存器中传递,而不是在堆栈中,所以这就是你的虚假%x 格式开始寻找的地方。您可以尝试使用 -m32 编译器选项为 x86 编译,但不能保证。

【讨论】:

  • 我是架构概念的新手。您是如何从印有%p 的地址中找出我使用的是 64 位架构机器的?
  • 我觉得snprintf() 的参数是从右向左推送有点奇怪。如果给出更多参数,它们将通过该行为出现在“格式”和“变量 x”之间。但是为什么snprintf() 会读取“缓冲区”并跟随?那不匹配。我怀疑这里是作者的错误。
  • @J...S:因为打印的指针值超过 32 位(而且我也认识到它在 Linux x86-64 上的典型堆栈地址范围内)。
  • @thebusybee:从右到左推送参数非常常见。这意味着您可以访问 varargs 函数中的所有参数,而不必知道它们有多少(因为第一个参数始终位于函数入口处堆栈指针的已知偏移量处,就在返回地址之后)。跨度>
  • @thebusybee:This example 非常清楚地展示了从右到左推动论点。
猜你喜欢
  • 2020-10-26
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-05
  • 2011-12-01
相关资源
最近更新 更多