按特定整数溢出缓冲区

时间:2015-11-07 20:55:37

标签: c buffer-overflow

所以如果我有这个代码:

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的值之前,我必须通过我的数组大小的额外 8 字符溢出char[]。我不知道为什么会这样,如果有人理解这一点,我真的会想要一些帮助。但是,它并不止于此。

如果我输入的是:

1234567890123456789012345678aa

我的输出是:

24929

这引起了我的反响。由于我希望它可以通过a+a的char值或甚至a*a溢出,唉它既不是。 (a的char值为97)。

总而言之,因为我现在可能会感到困惑。我想知道如何将缓冲区(在C中)溢出到int中,使int保持一个非常具体的值(在本例中为1337)。此外,如果您能解释这些数字是如何出现的,我将非常感激!顺便说一句,可能有助于提及代码正在Linux shell上执行。

1 个答案:

答案 0 :(得分:4)

由于这可能是家庭作业,而不是给你一个直接的答案,我要做的就是告诉你 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模式下编译我的程序和原始程序,这会转储生成的汇编语言。并排阅读它们。弄清楚差异意味着什么。这应该告诉你什么输入(如果有的话 - 可能不可能!)将让你的程序打印出来#Congrats&#39;。