Monday, June 3, 2013

Codegate 2013 :: Misc #2 (200 points)

This was the second challenge under the misc category which was worth 200 points. Two files were provided, an encoded key and a source php file. The challenge was to write a decoder function to decode the encoded key.

Contents of source.php:
<?
function encode( $input )
{
$enc_tab = array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
'%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
'>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
);
for( $index = 0 ; $index < strlen($input) ; $index++ ) {
$var1 |= ord($input{$index}) << $var2; $var2 += 8;
if( $var2 > 13 ) {
$var3 = $var1 & 8191;
if( $var3 > 88 ) { $var1 >>= 13; $var2 -= 13; }
else { $var3 = $var1 & 16383; $var1 >>= 14; $var2 -= 14; }
$output .= $enc_tab[$var3 % 91] . $enc_tab[$var3 / 91];
}
}
if( $var2 ) {
$output .= $enc_tab[$var1 % 91];
if( $var2 > 7 || $var1 > 90 ) $output .= $enc_tab[$var1 / 91];
}
return $output;
}
?>
Several points were gathered from the encoder function:
  1. $enc_tab, an array, comprised of 91 items.
  2. $var1 contained the (shifted) ASCII value of the input character being processed.
  3. $var2 contained the number of bits to be processed.
  4. $var3 contained the working value of $var1.
  5. If $var1 was between 89 and 8191, and $var2 was more than 13, its value would be shifted right by 13 places, otherwise its value would be shifted right by 14 places. 2 characters would be picked from $enc_tab based on the quotient and remainder from the division operation.
With these points in mind, the decoder function was written to be:
<?php
function decode($data) {
$enc_tab = array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
'%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
'>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
);
$var1 = $var2 = $var3 = 0;
$output = "";
for ( $i = 0; $i < strlen($data); $i += 2 ) {
$char1 = -1;
for ( $j = 0; $j < count($enc_tab); $j++ ) {
if ( $enc_tab[$j] == $data{$i} ) {
$char1 = $j;
break;
}
}
if ( $char1 == -1 ) continue; // Ignore ASCII CR+LF ('\r\n', 0x0D 0x0A)
for ( $k = 0; $k < count($enc_tab); $k++ ) {
if ( $enc_tab[$k] == $data{$i+1} ) {
$char2 = $k;
break;
}
}
$var3 = $char1 + $char2 * 91;
$shift = $var2;
$var2 += ( ($var3 & 8191) > 88 ) ? 13 : 14;
$var1 |= ( $var3 << $shift );
while ($var2 > 8) {
$var2 -= 8;
$output .= chr( $var1 & 255 );
$var1 >>= 8;
}
}
return $output;
}
$filename = "encoded.key";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
echo decode($contents);
?>
Flag captured! 200 points in the bag!! Yay!!!


Cheers,
Braeburn Ladny

No comments:

Post a Comment