【问题标题】:Why does malloc overwrite previous allocation if pointer is passed in as size? [closed]如果指针作为大小传入,为什么 malloc 会覆盖先前的分配? [关闭]
【发布时间】:2021-01-02 14:11:01
【问题描述】:

我有以下 C 代码,在这里我不太明白malloc 的行为:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
        size_t* v3;
        char *message;
        size_t size;
        v3 = malloc(10uLL);
        *v3 = 1LL;
        printf("first address: %p\n", (void *)v3);
        size = 0;
        scanf("%lu", &size);
        message = malloc(size);
        read(0, message, size);
        message[size-1] = 0;
        write(1, message, size);
        if(!*v3) printf("you win");
        else printf("you didn't win");
        return 0;
}

所以程序分配了一些内存,然后我们打印地址。现在,如果我使用这个地址作为一个数字并将其加 1,然后将其作为下一个malloc 的大小提供,那么当message[size-1] = 0 发生时,它基本上会溢出并修改v3。它被设置为1LL,但之后它是0,并且打印了“you win”。

谁能解释一下这是怎么回事?

正如 cmets 中所建议的,这是我运行程序时发生的情况:

第一个输出是:first address: 0x5581cb0646b0 然后我只打开一个 python shell 并执行:int("0x5581cb0646b0", 16) + 1 将十六进制值转换为数字并将1 添加到它,得到94015945328305

我将此提供给scanf,然后read 运行,但此处的消息可以是任何内容,不会改变发生的情况。

最后,打印出消息,然后是“you win”。 (但请注意 *v3 应该是 1LL 而不是 0

【问题讨论】:

  • 我建议(void *)&amp;v3 应该是(void *)v3。我看不出“将地址作为数字并将其加 1,然后将其作为大小提供”有任何意义。
  • message[size-1] = 0 happens it basically overflows and modifies v3 您是否期望 malloc 的返回值是连续的?这是一个理论上的例子吗?你真的执行了这个程序吗? how this happens? 请发布程序执行的输出。
  • 我的猜测是scanf 失败,所以size 仍然为零,然后message[size-1] = 0 损坏内存,因为索引超出范围。
  • 这是一个足够短的程序,您应该能够逐行调试它,看看谁在更改*v3
  • malloc 不会覆盖以前的分配:问题出在这个非常奇怪的代码中,它不检查任何内容,也不报告“之前”和“之后”。

标签: c memory memory-management heap-memory


【解决方案1】:

v3 被分配了一个内存块,之后你分配了另一个内存块给消息。 很有可能它们是连续的内存块,并且消息是通过 v3 的 8 字节,但是您不应该依赖这种行为,因为 malloc 可以为您提供指向它认为合适的任何地址的地址,所以它绝对是未定义的应该发生什么 仅仅因为这是你得到的结果并不意味着它是你每次都应该依赖的结果。

要考虑的另一件事是,malloc 的指针可能包含哪些元数据,这取决于 malloc 的实现并且对“我们”用户隐藏,据我们所知,malloc 当然可以在分配的指针末尾保存元数据,如果你想真正测试 malloc 而不导致未定义的行为,你应该使用 vlg 运行它,以确保你没有做任何可能产生不可靠结果的事情。

你介意解释一下你在这段代码中究竟试图做什么以及你是如何做到的吗?

【讨论】:

  • 我正在尝试重现一个 ctf 挑战并了解用于完成这项工作的技巧。
【解决方案2】:

经过更多调试和研究,我找到了解决方案。因此,仅就上下文而言,这是我试图了解如何利用的 CTF 挑战。结果我错过的关键点是,如果您获取屏幕上打印的v3 的地址并将1 添加到其中并将其传递给scanf,然后将其用作第二个@ 的大小987654324@,太大了,malloc 会返回0。但是,message[size - 1] 基本上只是0 + size (这是v3 + 1 的地址)-1 这是v3 的确切地址,这使得可以将值更改为0 .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2018-01-05
    • 2021-03-11
    • 2011-01-29
    • 2012-10-12
    • 2015-02-04
    相关资源
    最近更新 更多