stack0
Nice refresher with regards to the volatile type qualifier. It is needed to prevent the compiler from optimizing it away, given that it’s “always” set to zero (it might remove the if condition altogether). This is specially true for signal handlers:
1 2 3 4 5 6 7 8 9 10 11 |
|
Given that the buffer is 64 bytes in size and the stack layout, writing one more will copy one over modified:
H +-------------+
| ... |
| modified |
| buffer[64] | /* Being power of two means that it's aligned. */
| ... |
L +-------------+
To trigger the condition, the following command can be issued:
1 2 |
|
stack1
Like the above, given that the address of modified is four bytes above the buffer and (like the exercise says) by taking into account that this is a little endian platform (i386):
1 2 3 4 |
|
stack2
The same as the last one but with an environment variable:
1 2 |
|
stack3
Disassembling, like the exercise says, with objdump and retrieving the address of the win() function yields the expected results:
1 2 |
|
1 2 3 |
|
stack4
A poor man’s fuzzer can be used to guess the EIP address (and while at it, to take advantage of the redirect operator in gdb, like the exercise says):
1 2 3 |
|
The offset should be incremented until (76) the program crashes with a segfault in the 0x42424242 address. Now that EIP is under control, the above can be used to obtain the address of win:
1 2 |
|
1 2 3 |
|
The padding, like the exercise says, is added by the compiler.
stack5
This was kind of tricky, since the stack isn’t in the same place inside and outside GDB. The environment and the arguments vector (ie argv) must be the same.
First, brute-forced the number of bytes needed to overwrite EIP (76 in this case) and obtained the address of the stack with GDB:
$ python -c 'print "A" * 76 + "B" * 4 + "C" * 32' >/tmp/boom
$ env - TERM=xterm PWD=$PWD gdb /opt/protostar/bin/stack5
(gdb) unset env LINES
(gdb) unset env COLUMNS
(gdb) show env
TERM=xterm
PWD=/tmp
(gdb) r </tmp/boom
(gdb) info registers
(gdb) x/x $esp
0xbffffe30: 0x43434343
Generated the shellcode with:
1 2 3 4 5 6 7 8 |
|
As for the exploit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Then, ensure that the environment is the same as the above (without changing directories due to $PWD):
1 2 3 4 5 |
|
stack6
With the usual methodology, it was noticed that EIP is under control when overwriting at least eighty characters. The traditional ret2libc with the system function and faking a stack frame works as expected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
The /bin/sh address might need the usual guessing and setting a regular environment inside and outside GDB:
1 2 3 4 5 6 |
|
As for the ROP one, I’ve opted by using a rather pointless open(2), read(2), write(2) and finally system(3) chain to play around a little. The gadgets addresses can be obtained by using objdump. Jumping to the middle of a multiple pop sequence might be needed and that’s okay.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Beware that the environment inherited from the parent may play tricks due to not being the same. Executing it through a clean environment all the time, such as the one below, solves this kind of issues:
1 2 3 4 5 6 |
|
The stack with the above ROP will look like:
H +---------------------+
| ret (the variable) |
| buffer [0x41 * 80] | <= 0xbffff73c
| open(2) | <= 0xb7f537a0
| POP POP RET | <= 0x08048452
| /etc/shadow | <= SHADOW variable.
| openflgs | <= O_RDONLY
| read(2) | <= 0xb7f53c00
| POP POP POP RET | <= 0x08048576
| 0x3 |
| buffer | <= 0xbffff73c
| 0x40 |
| write(2) | <= 0xb7f53c70
| POP POP POP RET | <= 0x08048576
| 0x2 |
| buffer | <= 0xbffff73c
| 0x40 |
| system(3) | <= 0xb7ecffb0
| FAKE |
| /bin/sh | <= SHELL variable.
L +---------------------+
stack7
Like the one above, this also places restrictions in the address that we are allowed to jump to. Therefore, like the exercise says we need to bypass this restriction by returning to a text section.
Decided with a straight ret opcode one, that pops the last value from the stack and updates EIP to that address (the system(3) function).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 |
|