【问题标题】:Overflowing Buffer by specific integer特定整数溢出缓冲区
【发布时间】:2015-11-07 20:55:37
【问题描述】:

如果我有这个代码:

int main() {
    char buff[20];
    int x = 0;
    gets(buff);
    if (x==1337) {
        print("Congrats");
    }
    printf("%d\n", x);
    return 0;
}

知道这是用 C 语言编写的(不是很重要),如何将 char[] 正好溢出 1337? 而且,我不太了解我得到的输出。例如,如果我运行这段代码并输入:

12345678901234567890a

输出是:

0

事实上,在数据泄漏到 X 的值之前,我必须使我的 char[] 超出我的数组大小额外的 8 个字符。我不知道为什么会这样,并且会如果有人理解这一点,真的很想得到一些帮助。但是,它并不止于此。

如果我的输入是:

1234567890123456789012345678aa

我的输出是:

24929

这让我很纠结。因为我预计它会溢出a+a 的字符值,甚至可能是a*a,可惜两者都不是。 (a的char值为97)。

总结一下,因为我现在可能会感到困惑。我想知道如何将缓冲区(在 C 中)溢出到 int 中,从而使 int 成为一个非常具体的值(在本例中为 1337)。此外,如果您能解释这些数字是如何得出的,我将不胜感激!顺便提一下,代码是在 Linux shell 上执行的。

【问题讨论】:

  • 您不是在打印x 的值,而是在打印指针 "Wrong: " + x。将整数添加到指针会给您另一个指针。其实做"Wrong: " + x和做&("Wrong: "[x])是一样的
  • x 的类型更改为unsigned int,并将print("Wrong: " + x)(这不可能是您的实际代码,但没关系)更改为printf("Wrong: %08x\n", x)。输出现在将与输入有更明显的联系。
  • 我不得不承认,我从来没有真正使用过 C。我已经用代码中使用的确切 printf 语句更新了问题,这是否满足指针事故?
  • @zwol 请再次阅读代码,因为我向您保证,如果缓冲区溢出,我已经更改了 X 的值(或者至少我已经更改了正在打印的值)。
  • 这里的一个问题是您溢出缓冲区的数据是 characters,并且以十进制形式在 int 中查看它们并不能以简单的方式告诉您x 中有哪些字符。将其打印为十六进制,并将整数的单个字节与an ASCII table 进行比较。这应该准确地告诉您输入的哪一部分覆盖了x 以及字节顺序。然后,您只需将输入中的这些字节替换为以十进制显示为 1337 的一些字符(并且不要忘记字节顺序!)

标签: c buffer-overflow


【解决方案1】:

由于这可能是家庭作业,而不是给你一个直接的答案,我要做的是向你展示执行你认为你的程序会做的事情的 C 程序,以及它是如何做到的当输入超长输入时的行为。

#include <stdio.h>
int main(void)
{
  struct {
    char buff[20];
    volatile unsigned int x;
  } S;
  S.x = 0;
  gets(S.buff);
  if (S.x == 1337)
    puts("Congrats");
  else
    printf("Wrong: %08x\n", S.x);
  return 0;
}

主要区别在于我强制编译器以特定方式布置堆栈帧。我还以十六进制打印x 的值。这使得输出更容易预测,也更容易解释。

$ printf 'xxxxxxxxxxxxxxxxxxxxABCD' | ./a.out
Wrong: 44434241

$ printf 'xxxxxxxxxxxxxxxxxxxxABC' | ./a.out
Wrong: 00434241

$ printf 'xxxxxxxxxxxxxxxxxxxxAB' | ./a.out
Wrong: 00004241

$ printf 'xxxxxxxxxxxxxxxxxxxxA' | ./a.out
Wrong: 00000041

所有让您感到困惑的事情都是由以下一项或多项造成的:编译器不是按照您预期的方式布置堆栈帧,int 中的字节顺序不是您预期的,以及从二进制到十进制的转换,使 RAM 中的数据变得模糊。

为你练习:在-S 模式下编译我的程序和你的原始程序,这会转储出生成的汇编语言。并排阅读它们。弄清楚差异意味着什么。这应该告诉你什么输入(如果有的话——它可能不可能!)会让你的程序打印“恭喜”。

【讨论】:

  • 澄清一下,这不是家庭作业,它是我在别人的 shell 上执行的程序。我有点希望我不必完全了解 C 来完成这项任务。所以如果您不介意更深入,我们将不胜感激。
  • @JaredMassa 很抱歉,您将不得不了解 C,了解 C 对您隐藏的一堆低级细节。阅读“Smashing the Stack for Fun and Profit”,并列出所有你不知道 Aleph One 在说什么的地方。研究所有这些东西。重复直到你完全理解整篇文章。然后您应该能够回答自己的问题。
猜你喜欢
  • 2015-12-16
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 2013-07-19
  • 2013-11-06
  • 2013-04-11
  • 2015-07-07
  • 2012-02-05
相关资源
最近更新 更多