Leet More 2010 Strange Cipher writeup

Decrypt this “UPDYUFFRPY\TDDSUITF\R\FARTTITYGPPF\/YSGDFY
AAO:DF/TA\IAGR:A//DR/T”.

ctf.ifmo.ru:5555

If we connect to the service and try to encrypt \x00, \x01, \x02, \x03, \x04, we can notice that only first two bytes and the last one change:

[ GDOPU/SIIR\TDPAFYGDA/:S/EIT\\FS/OA:PRYS/DOIOTIS/GUPPYPS/GIGPUSS\ ]
[ GFOPU/SIIR\TDPAFYGDA/:S/EIT\\FS/OA:PRYS/DOIOTIS/GUPPYPS/GIGPUSSE ]
[ GGOPU/SIIR\TDPAFYGDA/:S/EIT\\FS/OA:PRYS/DOIOTIS/GUPPYPS/GIGPUSSR ]
[ ::OPU/SIIR\TDPAFYGDA/:S/EIT\\FS/OA:PRYS/DOIOTIS/GUPPYPS/GIGPUSST ]

There are 16 different chars, so a good idea is to replace them with [0-9a-f]. GD->GF->GG->::->:/ – looks like it’s increasing by 1 each step. That means, that ‘::’ is ’00’ ;) Make some more encryptions and we get a charset: “:/\ERTYUIOPASDFG” -> “0123456789abcdef”.

I wrote a simple decoder:

<?php
    $alpha = str_split(":/\\ERTYUIOPASDFG", 1);
    $replace = str_split("0123456789abcdef", 1);
    
    fgets(STDIN);
    fgets(STDIN);
    $s = fgets(STDIN);
    $s = str_replace($alpha, $replace, $s);
    
    echo $s;
?>
Use it like:
$ echo -e "\x04\x00\x00\x00" | nc ctf.ifmo.ru 5555 | php client.php
[ 009a71c88425dabe6fdb10c138522ec19b0a46c1d98958c1f7aa6ac1f8fa7cc5 ]
A fact that the byte is increased along with the input, points that it is a sum of input and some value. Let’s modify a client to get true values:
$ python -c 'print "\x00"*32;' | nc ctf.ifmo.ru 5555 | php client.php
[ fc9a71be7a25dabe6fdb10c138522ec19b0a46c1d98958c1f7aa6ac1f8fa7cc1 ]
<?php 
    $alpha = str_split(":/\\ERTYUIOPASDFG", 1);
    $replace = str_split("0123456789abcdef", 1);
    
    fgets(STDIN);
    fgets(STDIN);
    $s = fgets(STDIN);
    $s = str_replace($alpha, $replace, $s);
    $ss = str_split(substr($s, 2, -3), 2);
    $as = str_split("fc9a71be7a25dabe6fdb10c138522". \
             "ecba50a46c1d98958c1f7aa6ac1f8fa7cc1", 2);

    $s = '';
    foreach ($as as $index=>$add) {
        $char = hexdec($ss[$index])-hexdec($as[$index]);
        $t = dechex($char & 0xff);
        while (strlen($t)<2) $t = "0$t";
        $s .= $t;
    }
    
    echo "[ $s ]\n";
?>
Now, let’s play with encryption a bit more to understand it. Some tries and we understand that each byte is xored by next:
\xcc\x0c\x00\x00 -> \xc0\x0c\x00\x00
It’s time to write a decrypter:
<?php

    $s = "UPDYUFFRPY\\TDDSUITF\\R\\FARTTITYGPPF\\/Y". \
         "SGDFYAAO:DF/TA\\IAGR:A//DR/T";

    $alpha = str_split(":/\\ERTYUIOPASDFG", 1);
    $replace = str_split("0123456789abcdef", 1);
    $s = str_replace($alpha, $replace, $s);
    $ss = str_split( $s, 2);
    $as = str_split("fc9a71be7a25dabe6fdb10c13852". \
          "2ec19b0a46c1d98958c1f7aa6ac1f8fa7cc1", 2);
    
    $s = '';
    $ts = array();
    foreach ($as as $index=>$add) {
        $char = hexdec($ss[$index])-hexdec($as[$index]);
        $t = dechex($char & 0xff);
        while (strlen($t)<2) $t = "0$t";
        $ts[] = $t;
    }
    
    $rev = '';
    for ($i = count($ts); $i > 0; $i--) {
        $c = hexdec($ts[$i-1]);
        $c ^= hexdec($ts[$i % 32]);
        $t = dechex($c & 0xff);
        while (strlen($t)<2) $t = "0$t";
        $ts[$i-1] = $t;
        $rev = chr($c).$rev;
    }
    
    echo $rev."\n";

?>
$ php solve.php
*TheCoolestFlagOverTheWorldEver*
$ echo "*TheCoolestFlagOverTheWorldEver*" | nc ctf.ifmo.ru 5555
Enter the text to encrypt:
> Encryption successful:
[ UPDYUFFRPY\TDDSUITF\R\FARTTITYGPPF\/YSGDFYAAO:DF/TA\IAGR:A//DR/T ]
You can find the binary here.

Leave a Reply

Your email address will not be published.