3

I have been playing with some wargames and I ported some of then on my Linux machine as well. I noticed that when not using -mpreferred-stack-boundary=2, gcc might compile "main" with an interesting prologue/epilogue: effectively "relying on $ecx (which relies on $ebp-4) for $esp value before ret". Has anyone else come across this observation?

This means you can not overwrite normal ret address staying at $ebp+4, but instead you have to overwrite $ebp-4 (that is ecx) and reposition the stack pointer and your return address (effectively using a stack pivot) to further the exploitation.

Kindly find an example code and related assembly below:

$ cat stack4.c
/* stack4-stdin.c                               *
 * specially crafted to feed your brain by gera */

#include <stdio.h>

int main() {
    int cookie;
    char buf[80];

    printf("buf: %08x cookie: %08x\n", &buf, &cookie);
    gets(buf);

    if (cookie == 0x000d0a00)
        printf("you win!\n");
}

$ objdump -D ./stack4_normal | grep -A31 main.:
0804845b <main>:
 804845b:   8d 4c 24 04             lea    0x4(%esp),%ecx
 804845f:   83 e4 f0                and    $0xfffffff0,%esp
 8048462:   ff 71 fc                pushl  -0x4(%ecx)
 8048465:   55                      push   %ebp
 8048466:   89 e5                   mov    %esp,%ebp
 8048468:   51                      push   %ecx
 8048469:   83 ec 64                sub    $0x64,%esp
 804846c:   83 ec 04                sub    $0x4,%esp
 804846f:   8d 45 f4                lea    -0xc(%ebp),%eax
 8048472:   50                      push   %eax
 8048473:   8d 45 a4                lea    -0x5c(%ebp),%eax
 8048476:   50                      push   %eax
 8048477:   68 50 85 04 08          push   $0x8048550
 804847c:   e8 8f fe ff ff          call   8048310 <printf@plt>
 8048481:   83 c4 10                add    $0x10,%esp
 8048484:   83 ec 0c                sub    $0xc,%esp
 8048487:   8d 45 a4                lea    -0x5c(%ebp),%eax
 804848a:   50                      push   %eax
 804848b:   e8 90 fe ff ff          call   8048320 <gets@plt>
 8048490:   83 c4 10                add    $0x10,%esp
 8048493:   8b 45 f4                mov    -0xc(%ebp),%eax
 8048496:   3d 00 0a 0d 00          cmp    $0xd0a00,%eax
 804849b:   75 10                   jne    80484ad <main+0x52>
 804849d:   83 ec 0c                sub    $0xc,%esp
 80484a0:   68 68 85 04 08          push   $0x8048568
 80484a5:   e8 86 fe ff ff          call   8048330 <puts@plt>
 80484aa:   83 c4 10                add    $0x10,%esp
 80484ad:   8b 4d fc                mov    -0x4(%ebp),%ecx
 80484b0:   c9                      leave
 80484b1:   8d 61 fc                lea    -0x4(%ecx),%esp
 80484b4:   c3                      ret

I have found several StackExchange topics and explanation about why this happens. Nevertheless, I am looking for a guide/tutorial that specifically deals with the exploitation part. Perhaps someone smarter than me has standardised this exploitation in a much better way than I do.

It seems that most people, in tutorials, just use -mpreferred-stack-boundary=2 to avoid this problem and continue normally with the exploitation tutorial.

I find it hard to believe that no-one has mentioned this in a tutorial as new versions of gcc compile like this by default (at least at my machine).

In any case, the question is:

  • Is this the optimal way to exploit this (using a stack pivot)?

  • If no, can someone please point me to a tutorial or explanation of a better way?

nilminus
  • 31
  • 2

0 Answers0