however this does not work remotely, this is becuase _stack_chk_fail calls __fortify_fail which calls __lib_message which does this:

void__libc_message(intdo_abort,constchar*fmt,...){va_listap;intfd=-1;va_start(ap,fmt);/* Open a descriptor for /dev/tty unless the user explicitly requests errors on standard error. */constchar*on_2=__libc_secure_getenv("LIBC_FATAL_STDERR_");if(on_2==NULL||*on_2=='\0')fd=open_not_cancel_2(_PATH_TTY,O_RDWR|O_NOCTTY|O_NDELAY);if(fd==-1)fd=STDERR_FILENO;// then prints stuff and crashes}

which means that we only need to set LIBC_FATAL_STDERR_ and the flag will get printed over stderr instead of /dev/tty.

In the 3 point challenge in the OMGACM ("guerilla programming") track, we were given a server to connect to. Connecting to this service, it quickly became clear, that the point of the challenge was to write a program to maneuver a car through a simple ASCII racing track, while avoiding obstacles on the road (zebras, cars, ...).

To do this, we simply started at the location of our own car and did a depth-first search up to the top of the screen. As soon as we had a viable path, we drive 5 spaces along this path, and process the next board.

In order to make it a bit more interesting and fun, we also added some pretty colors to make it more interesting to watch on rather slow servers.

First the length of what was about to be received should be sent, with the added requirement that the length could not exceed 0x1000 bytes.

Then a buffer of that size was malloc'ed and received into.

mmap was used to make room for a buffer twice the size of the input and the received input was copied into the mmap'ed memory.

This was however just a decoy, as both buffers were passed on to a function located at 0x40124c, which copied each byte from the malloced into every second position of the mmapped buffer. The spaces were filled with null bytes, so if 41414141 was sent to the server, the mmap'ed buffer would contain 4100410041004100.

Two cases would stop this copying:

1. if one of the bytes were less than 0x1f (with the exception of '\n'). This was a hard restriction because it would cause the function to return -1 and stop running.
2. if a null byte was encountered or if the buffer was filled the copying would stop, but the rest of the program would continue running.

If the function returns correctly, the program will call the mmap'ed buffer.

So first there is a need to craft shellcode, in which each second byte is a null byte and no byte value is less than 0x1f or larger than 7f (signed compare).

There is however some good news, as the stack contained goodies. A pointer to the forgotten lands (the malloc'ed buffer) is located on the stack, free has been called on it, but the later portions of the received data is still there.

<?php$value=time();$filename=$_GET["filename"];$accesscode=$_GET["accesscode"];if(md5($filename)==$accesscode){echo"Acces granted to $filename!<br><br>";srand($value);if(in_array($filename,array('getfile.php','index.html','key.txt','login.php','passwords.txt','usernames.txt'))==TRUE){$data=file_get_contents($filename);if($data!==FALSE){if($filename=="key.txt"){$key=rand();$cyphertext=mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_CBC);echobase64_encode($cyphertext);}else{echonl2br($data);}}else{echo"File does not exist";}}else{echo"File does not exist";}}else{echo"Invalid access code";}?></body></html>

Here we see, that the key must be stored in key.txt, and that it is encrypted with a random number, seeded based on the timestamp.

We then downloaded the key, as well as the approximate local timestamp, using the following command:

On the list, one secret in particular stands out; the one titled "key", posted by "admin". Attempting to access it, however, reveals a runtime error with a stack trace. In the stack trace, one can see, that the only the user that posted a secret can view it.

A bit of a read through the error page shows, that the page runs on Rack. The page also shows, that the cookie contains, among other things, the username of the current user. (In fact, anything stored in the rack.session variable, see the relevant implementation) However, this cookie is signed based on a site secret.

Luckily, the runtime error was also nice enough to leak this for us. This allowed us to write the following script, which takes a valid cookie, and rewrites it to have username admin.