Wednesday, March 13, 2013

Backdoor CTF - Crypto 400

We have access to the code used for encryption function. With this we have to find the plain text value for the given cipher text:
168 232 100 162 135 179 112 100 173 206 106 123 106 195 179 157 123 173
Encryption function:
for ($i = 0; $i<strlen($str); $i++)
   $dec_array[] = ord($str{$i});
$ar = $dec_array;
$max = max($ar);

$key = rand(10,$max);
$key = 101*$key;

for($i=0;$i<strlen($str);$i++){
    $x = $ar[$i];
    $am = ($key+$x)/2;
    $gm = sqrt($key*$x);
    $enc = $am + $gm;
    $encrypt = floor($enc)%255; 
    echo $encrypt.' ';
}
Bruteforce seemed to be the easiest solution for the problem. Here is the approach
[*] Key value is choosen from rand(10,$max), where $max to range from 32 to 127 ie ascii printables. So we can bruteforce key value between 10 to 127
[*] Choose plain text values between 32 to 127 and perform encryption function upto the length of cipher text
[*] Check if any of key value results in count(plain text) == count(cipher text). In that case, the string we got might be the possible plain text

Here is the code to do that:
<?php

$cipher = array(168, 232, 100 ,162, 135, 179, 112, 100, 173, 206, 106, 123, 106, 195, 179, 157, 123, 173);

for($key=10; $key<=127; $key++){
    $plain = array();
    $key_new = $key * 101;
    for($i=0; $i<count($cipher); $i++){  
        for($p=32; $p<=127; $p++){
            $x = $p;
            $am = ($key_new+$x)/2;
            $gm = sqrt($key_new*$x);
            $enc = $am + $gm;
            $encrypt = floor($enc)%255;
            if($encrypt == $cipher[$i])
                array_push($plain,$p);    
        }
    }
    if(count($plain) == count($cipher)){
        $text = '';
        foreach($plain as $t)
            $text = $text.chr($t);
        echo $text."\n";
    }    
}

?>
[ctf@renorobert backdoor]# php sol.php
, f&." -i!W!Wo.*-i
myalgocantbebroken
Running the code we get two plain texts. The real plain text value is myalgocantbebroken

No comments :

Post a Comment