在 C 中导致缓冲区溢出以强制条件为真

标签 c input buffer-overflow

我正在尝试解决这个挑战,目标是让程序显示“你赢了!”为此,我必须找到正确的变量值,以使 if 条件和 assert 的计算结果均为 true。

本来我以为这个会比较简单。不过,似乎制作缓冲区溢出是一门需要高级编程技能的艺术(还有大端和小端的概念),但我在 C 编程方面没有太多经验。

任何帮助或建议将不胜感激。

#include<assert.h>
int
main(int argc, char*argv[]){
    int size = 0;
    int buf[1024];
    read(0,&size,sizeof(size));
    assert (size <= 1024);
    read(0,buf,size*sizeof(int));
    if (size > 0 && size < 100 && buf[999] == 'B')
        printf("YOU WIN!\n");
    return 0;
}

最佳答案

有趣的问题。

你必须了解你正在运行的机器,所以我做了 以下假设:

  1. 32 位机器,大端。

  2. 编译器执行“经典”堆栈布局,这将放置 size毗邻 buf 的末尾.

  3. 数据对齐到 4 个字节或更少,因此 buf 末尾之间没有填充。和size .

这台机器上的经典编译器按照变量在代码中出现的顺序在调用堆栈上分配变量,因此 size首先被推送,然后 buf 。您的堆栈将如下所示:

                   buf                byte
   top of stack   offset             offset
   +-----------+    0 * sizeof(int) =    0  
   | buf[   0] |   
   +-----------+    1 * sizeof(int) =    4
   |           |   
   ...
   |           |
   +-----------+ 1023 * sizeof(int) = 4092
   | buf[1023] |
   +-----------+ 1024 * sizeof(int) = 4096
   |   size    |
   +-----------+ 1025 * sizeof(int) = 4100
  bottom of stack

写信给buf[1024]会覆盖size 。如果我们写入原始字节, 那么字节 4096、4097、4098 和 4099 将对应于 size 中的字节.

我们知道我们希望大小为负数以通过 assert ,我们想要 size * sizeof(int) 计算结果为 4100。因为如果我们读取 4100 字节,最后 4 个字节将覆盖 size .

size * 4 = 4100.  Solving for size:
size = 1025 (or 0x401)

现在我们通过设置最高有效位将其设为负值。

0x80000401

因此将 size 设置为该值将通过 assert (size <= 1024) 。因为任何事 最高有效位设置为负数,并且所有负数都小于 1024。

当我们到达缓冲区读取时,它将像这样进行评估:

read(0, buf, 0x80000401 * sizeof(int));
read(0, buf, 0x80000401 * 4);
read(0, buf, 0x00001004) == read(0, buf, 4100)

是的,没错,因为 32 位模运算,我们只是告诉它读取 4100 字节。或者,如果有帮助的话,您可以将乘以 4 视为左移 2,因此将我们的魔法值左移 2 可以去掉最高有效位。

要打印“你赢了!”,你需要编写一个字节流,其中 buf[999] 是字节 3996 字节4096、4097、4098和4099是size的字节。关于这个假设 big-endian 机器,我们将这些字节分别设置为 0、0、0 和 1-99。

关于在 C 中导致缓冲区溢出以强制条件为真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24899535/

相关文章:

c++ - 是 。和 -> 在 C 和 C++ 中真的是运算符吗?

python - 为什么我的 C 模块会泄漏内存?

c - 利用缓冲区漏洞时从单独的函数返回地址

c - 有没有办法解决 "overload"或重新实现 __stack_chk_fail?

nhibernate - Oracle 托管驱动程序 ODP.NET 与 NHibernate 4.0 FLOAT (126) 到 C# DECIMAL/Double

c - 这段代码有什么问题?我无法从中获得 'welcome' 输出..使用代码块..我是初学者

c - 在 C 中使用指针将数组传递给函数?

php - 从另一个页面获取ID值

java - 使用带有提示和用户输入的扫描仪

c# - 在 System.ConsoleKey 值使用完毕后,如何使它无效(或分配另一个值)?