gdbbuffer-overflowmachine-codeeip

EIP doesn't get overwritten when perfoming a buffer overflow attack


I was watching this video on youtube: https://www.youtube.com/watch?v=1S0aBV-Waeo and i was trying to do the same steps shown in the video, but i can't seem to overwrite the EIP. I don't know if it's because the gdb may have changed during the years, or if anything else has. What i get when i try to overflow is the following

Program received signal SIGSEGV, Segmentation fault.
0x080491ac in main (
    argc=<error reading variable: Cannot access memory at address 0x41414141>, 
    argv=<error reading variable: Cannot access memory at address 0x41414145>)
    at example.c:9
9   }

I can't seem to overwrite the eip, no matter how large my input is. The code is the same as shown in the video with a smaller buffer size.

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

int main(int argc, char** argv){
    char buffer[10];
    strcpy(buffer, argv[1]);

    return 0;
}

I also get asked the following when running my program in gdb for the first time

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.archlinux.org>
Enable debuginfod for this session? (y or [n]) 

This is the register info in gdb

(gdb) info reg
eax            0x0                 0
ecx            0xffffd6b2          -10574
edx            0xffffd396          -11370
ebx            0x804bff4           134529012
esp            0xffffd390          0xffffd390
ebp            0xffffd3a8          0xffffd3a8
esi            0xffffd480          -11136
edi            0xf7ffcb60          -134231200
eip            0x80491a3           0x80491a3 <main+61>
eflags         0x286               [ PF SF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99
(gdb) x/20x $esp
0xffffd390: 0xffffffff  0x4141d3d4  0x41414141  0x41414141
0xffffd3a0: 0xffff0041  0xf7e1fe2c  0x00000000  0xf7c20af9
0xffffd3b0: 0x00000000  0x00000000  0x080482e7  0xf7c20af9
0xffffd3c0: 0x00000002  0xffffd474  0xffffd480  0xffffd3e0
0xffffd3d0: 0xf7e1fe2c  0x0804907d  0x00000002  0xffffd474

I'm compiling with the following flags

gcc -o example2 -fno-stack-protector -no-pie -m32 -g -z execstack example2.c -w

The whole interaction on gdb

(gdb) disassemble main
Dump of assembler code for function main:
   0x080497d5 <+0>: lea    0x4(%esp),%ecx
   0x080497d9 <+4>: and    $0xfffffff0,%esp
   0x080497dc <+7>: push   -0x4(%ecx)
   0x080497df <+10>:    push   %ebp
   0x080497e0 <+11>:    mov    %esp,%ebp
   0x080497e2 <+13>:    push   %ebx
   0x080497e3 <+14>:    push   %ecx
   0x080497e4 <+15>:    sub    $0x10,%esp
   0x080497e7 <+18>:    call   0x804981c <__x86.get_pc_thunk.ax>
   0x080497ec <+23>:    add    $0x9a808,%eax
   0x080497f1 <+28>:    mov    %ecx,%edx
   0x080497f3 <+30>:    mov    0x4(%edx),%edx
   0x080497f6 <+33>:    add    $0x4,%edx
   0x080497f9 <+36>:    mov    (%edx),%edx
   0x080497fb <+38>:    sub    $0x8,%esp
   0x080497fe <+41>:    push   %edx
   0x080497ff <+42>:    lea    -0x12(%ebp),%edx
   0x08049802 <+45>:    push   %edx
   0x08049803 <+46>:    mov    %eax,%ebx
   0x08049805 <+48>:    call   0x8049020
   0x0804980a <+53>:    add    $0x10,%esp
   0x0804980d <+56>:    mov    $0x0,%eax
--Type <RET> for more, q to quit, c to continue without paging--
   0x08049812 <+61>:    lea    -0x8(%ebp),%esp
   0x08049815 <+64>:    pop    %ecx
   0x08049816 <+65>:    pop    %ebx
   0x08049817 <+66>:    pop    %ebp
   0x08049818 <+67>:    lea    -0x4(%ecx),%esp
   0x0804981b <+70>:    ret
End of assembler dump.
(gdb) break *0x08049805
Breakpoint 1 at 0x8049805: file example.c, line 6.
(gdb) break *0x08049812
Breakpoint 2 at 0x8049812: file example.c, line 9.
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAA
Starting program: /home/r3/buffer-overflows/bo in memory example/example AAAAAAAAAAAAAAAAAAAAAAAAA

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.archlinux.org>
Enable debuginfod for this session? (y or [n]) 
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.

Breakpoint 1, 0x08049805 in main (argc=2, argv=0xffffd464) at example.c:6
6       strcpy(buffer, argv[1]);
(gdb) info reg
eax            0x80e3ff4           135151604
ecx            0xffffd330          -11472
edx            0xffffd306          -11514
ebx            0x80e3ff4           135151604
esp            0xffffd2f0          0xffffd2f0
ebp            0xffffd318          0xffffd318
esi            0x80e3ff4           135151604
edi            0x1                 1
eip            0x8049805           0x8049805 <main+48>
eflags         0x292               [ AF SF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99
(gdb) x/20x $esp
0xffffd2f0: 0xffffd306  0xffffd6a4  0x00000000  0x080497ec
0xffffd300: 0x080ade17  0x080e7c04  0x08049030  0x080ae037
0xffffd310: 0xffffd330  0x080e3ff4  0xffffd428  0x08049ceb
0xffffd320: 0x00000021  0xffffd338  0x00067e1c  0x08049ceb
0xffffd330: 0x00000002  0xffffd464  0xffffd470  0xffffd354
(gdb) c
Continuing.

Breakpoint 2, main (
    argc=<error reading variable: Cannot access memory at address 0x41414141>, 
    argv=<error reading variable: Cannot access memory at address 0x41414145>)
    at example.c:9
9   }
(gdb) info reg
eax            0x0                 0
ecx            0xffffd6b0          -10576
edx            0xffffd312          -11502
ebx            0x80e3ff4           135151604
esp            0xffffd300          0xffffd300
ebp            0xffffd318          0xffffd318
esi            0x80e3ff4           135151604
edi            0x1                 1
eip            0x8049812           0x8049812 <main+61>
eflags         0x286               [ PF SF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99
(gdb) x/20x $esp
0xffffd300: 0x080ade17  0x41417c04  0x41414141  0x41414141
0xffffd310: 0x41414141  0x41414141  0x41414141  0x00414141
0xffffd320: 0x00000021  0xffffd338  0x00067e1c  0x08049ceb
0xffffd330: 0x00000002  0xffffd464  0xffffd470  0xffffd354
0xffffd340: 0x080e3ff4  0x0804968d  0x00000002  0xffffd464
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0804981b in main (
    argc=<error reading variable: Cannot access memory at address 0x41414141>, 
    argv=<error reading variable: Cannot access memory at address 0x41414145>)
    at example.c:9
9   }
(gdb) info reg
eax            0x0                 0
ecx            0x41414141          1094795585
edx            0xffffd312          -11502
ebx            0x41414141          1094795585
esp            0x4141413d          0x4141413d
ebp            0x41414141          0x41414141
esi            0x80e3ff4           135151604
edi            0x1                 1
eip            0x804981b           0x804981b <main+70>
eflags         0x10286             [ PF SF IF RF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99
(gdb) x/20x $esp
0x4141413d: Cannot access memory at address 0x4141413d
(gdb) c
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Solution

  • This code

       0x08049815 <+64>:    pop    %ecx
       0x08049816 <+65>:    pop    %ebx
       0x08049817 <+66>:    pop    %ebp
       0x08049818 <+67>:    lea    -0x4(%ecx),%esp
       0x0804981b <+70>:    ret
    

    restores registers from their saved location on stack. However, you've overwritten the stack contents, so all the registers are now set to 0x4141... values. And that causes the lea -0x4(%ecx),%esp instruction to SIGSEGV, since ECX points to inaccessible memory.

    As ssbssa commented, this is happening due to stack realignment (which itself is needed to deal with 64-bit aligned (newer) AVX etc.).

    If I turn stack realignment off with -mpreferred-stack-boundary=2, the code becomes:

       0x08049176 <+0>:     push   %ebp
       0x08049177 <+1>:     mov    %esp,%ebp
       0x08049179 <+3>:     sub    $0xc,%esp
       0x0804917c <+6>:     mov    0xc(%ebp),%eax
       0x0804917f <+9>:     add    $0x4,%eax
       0x08049182 <+12>:    mov    (%eax),%eax
       0x08049184 <+14>:    push   %eax
       0x08049185 <+15>:    lea    -0xa(%ebp),%eax
       0x08049188 <+18>:    push   %eax
       0x08049189 <+19>:    call   0x8049050 <strcpy@plt>
       0x0804918e <+24>:    add    $0x8,%esp
       0x08049191 <+27>:    mov    $0x0,%eax
       0x08049196 <+32>:    leave
       0x08049197 <+33>:    ret
    

    and the RIP overwrite works:

    Program received signal SIGSEGV, Segmentation fault.
    0x41414141 in ?? ()
    (gdb) x/i $pc
    => 0x41414141:  Cannot access memory at address 0x41414141