缓冲区溢出的例子?

Example of Buffer Overflow?

我在我的书中读到有关缓冲区溢出的内容并看到:

字符串加载到内存的顺序是否正确?在 little endian 中,我读到我们在较低地址的较低索引处加载位,但此示例显示相反的情况。

现在给定这段代码:

如何将 auth_flag 设置为 1? ascii 值为 1 的字符串不可打印,因此这似乎无法利用,对吗?

代码示例1:

In little endian I read that we load the bits at lower index in lower addresses but this example shows the opposite.

当使用简单的 C 风格字符串时,字节顺序不适用。 Endianess 与多字节值相关,但与 char 值无关。

代码示例2:

The string which has an ascii value of 1 isn't printable so this seems as impossible to exploit, am I right?

不对,你这里有一个基本的误解。您不需要将数值 1 放入 auth_flag。您只需要 非零 值。

记住

if (check_authentication(argv[1])) {

真的

if (check_authentication(argv[1]) != 0) {
                                  ^^^^

因此 if 条件对于任何非零 return 值都为真。

要破坏身份验证检查,想法是编译器将 auth_flag 放在内存中的某处 password_buffer 之后。在这种情况下,您可以为程序提供一个长度超过 16 个字符的开始参数,以便多余的字符溢出缓冲区并在 auth_flag.

的位置结束

这里是您的代码的重写。原理是一样的。我只是使用了更短的名称并删除了一些(不必要的)代码以使示例变得简单。我还打印了变量的位置。

int ca(char* pw)
{
    int af = 0;
    char pw_b[16];
    printf("af   location: %p\n", (void*)&af);
    printf("pw_b location: %p\n", (void*)pw_b);

    strcpy(pw_b, pw);
    return af;
}

int main(int argc, char *argv[])
{
  if (argc < 2)
  {
      printf("wrong usage\n");
      return 0;
  }
  if (ca(argv[1]))
  {
      printf("Did it...\n");
  }
  else
  {
      printf("Failed to break in\n");
  }
  return 0;
}

gcc -O0 编译 我在开始时得到这个输出 ./prog abc

af   location: 0x7ffd579e13cc
pw_b location: 0x7ffd579e13b0
Failed to break in

从这里我可以看到 af 位于 0x1c 字节(或 28 位十进制)after pw_b。所以如果我给程序一个超过 28 个字符的参数,它可能会覆盖 af(如果它没有因为其他原因崩溃....)。

所以我尝试了 ./prog 1234567890123456789012345678b(注意字符串中有 29 个字符),我得到:

af   location: 0x7ffc63312f8c
pw_b location: 0x7ffc63312f70
Did it...

所以我成功了...我破解了验证码。

但是请注意...在另一个系统上,使用另一个编译器,使用其他编译器选项等,情况可能会有所不同。所以你不能确定在你的系统上重现它。也许您需要不同的输入,也许在您的系统上什至不可能。首先检查变量所在的位置,然后计算所需的输入。