SECCON 2016 – Vigenere Cripto (100)

Siguiendo con los writeups de la SECCON ahora os traigo una prueba de criptografía.

Nos dan el siguiente enunciado:

Vigenere

k: ????????????
p: SECCON{???????????????????????????????????}
c: LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ

k=key, p=plain, c=cipher, md5(p)=f528a6ab914c1ecf856a1d93103948fe

 |ABCDEFGHIJKLMNOPQRSTUVWXYZ{}
-+----------------------------
A|ABCDEFGHIJKLMNOPQRSTUVWXYZ{}
B|BCDEFGHIJKLMNOPQRSTUVWXYZ{}A
C|CDEFGHIJKLMNOPQRSTUVWXYZ{}AB
D|DEFGHIJKLMNOPQRSTUVWXYZ{}ABC
E|EFGHIJKLMNOPQRSTUVWXYZ{}ABCD
F|FGHIJKLMNOPQRSTUVWXYZ{}ABCDE
G|GHIJKLMNOPQRSTUVWXYZ{}ABCDEF
H|HIJKLMNOPQRSTUVWXYZ{}ABCDEFG
I|IJKLMNOPQRSTUVWXYZ{}ABCDEFGH
J|JKLMNOPQRSTUVWXYZ{}ABCDEFGHI
K|KLMNOPQRSTUVWXYZ{}ABCDEFGHIJ
L|LMNOPQRSTUVWXYZ{}ABCDEFGHIJK
M|MNOPQRSTUVWXYZ{}ABCDEFGHIJKL
N|NOPQRSTUVWXYZ{}ABCDEFGHIJKLM
O|OPQRSTUVWXYZ{}ABCDEFGHIJKLMN
P|PQRSTUVWXYZ{}ABCDEFGHIJKLMNO
Q|QRSTUVWXYZ{}ABCDEFGHIJKLMNOP
R|RSTUVWXYZ{}ABCDEFGHIJKLMNOPQ
S|STUVWXYZ{}ABCDEFGHIJKLMNOPQR
T|TUVWXYZ{}ABCDEFGHIJKLMNOPQRS
U|UVWXYZ{}ABCDEFGHIJKLMNOPQRST
V|VWXYZ{}ABCDEFGHIJKLMNOPQRSTU
W|WXYZ{}ABCDEFGHIJKLMNOPQRSTUV
X|XYZ{}ABCDEFGHIJKLMNOPQRSTUVW
Y|YZ{}ABCDEFGHIJKLMNOPQRSTUVWX
Z|Z{}ABCDEFGHIJKLMNOPQRSTUVWXY
{|{}ABCDEFGHIJKLMNOPQRSTUVWXYZ
}|}ABCDEFGHIJKLMNOPQRSTUVWXYZ{

Vigenere cipher
https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher

Otra vez nos dan una pista enorme con el título de la prueba e incluso un link a la wikipedia. La verdad es que muy difícil no lo estaban poniendo.

Si no llegase con lo anteriormente mencionado además nos dan el charset y el md5 de la respuesta con lo cual el gran maestro Patatas construyo los siguientes scripts para resolver la prueba, primero se realiza un ataque de texto conocido utilizando el texto que conocemos de la flag:

<?php
function vigenere_decrypt_customcharset($txt, $clave, $charset) {
 $lentxt = strlen($charset);
 $lenkey = strlen($clave);

 $txt2 = '';
 for($i=0; $i<strlen($txt); $i++) {
 $c = strpos($charset, $txt[$i]); // caracter texto
 $x = strpos($charset, $clave[$i%$lenkey]); // caracter clave
 if($x!==FALSE and $c!==FALSE) {
 $txt2 .= $charset[($c - $x + $lentxt) % $lentxt]; // aplicar vigenere
 } else {
 $txt2 .= '?'; // aplicar vigenere
 //echo "X";
 }
 }
 return $txt2;
}
$charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ{}';

$p = 'SECCON{???????????????????????????????????}';
$c = 'LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ';

// PRIMERA PARTE

$key1 = vigenere_decrypt_customcharset($c, $p, $charset);
echo "KEY1: $key1\n\n";
?>

Lo cual nos da el siguiente resultado:

php vigenere_part1.php 
 SECCON{???????????????????????????????????}
KEY1: VIGENER???????????????????????????????????R

Como solo conocemos los 7 primeros caracteres podemos ver que la primera parte de la clave es “VIGENERE”. Con esto, sabiendo la longitud de la clave y el md5 podemos realizar un ataque de fuerza bruta contra el resto de la clave:

<?php
/* ---------------------------------------------------
 	VIGENERE
--------------------------------------------------- */
function vigenere_decrypt_customcharset($txt, $clave, $charset) {
 $lentxt = strlen($charset);
 $lenkey = strlen($clave);

 $txt2 = '';
 for($i=0; $i<strlen($txt); $i++) {
 $c = strpos($charset, $txt[$i]); // caracter texto
 $x = strpos($charset, $clave[$i%$lenkey]); // caracter clave
 if($x!==FALSE and $c!==FALSE) {
 $txt2 .= $charset[($c - $x + $lentxt) % $lentxt]; // aplicar vigenere
 } else {
 $txt2 .= '?'; // aplicar vigenere
 //echo "X";
 }
 }
 return $txt2;
}
$charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ{}';

$p = 'SECCON{???????????????????????????????????}';
$c = 'LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ';

$keyx = 'VIGENERE';

for($i=0; $i<strlen($charset); $i++) {
for($j=0; $j<strlen($charset); $j++) {
for($k=0; $k<strlen($charset); $k++) {
for($l=0; $l<strlen($charset); $l++) {

	$key = $keyx . $charset[$i]. $charset[$j] . $charset[$k] . $charset[$l];
	$p2 = vigenere_decrypt_customcharset($c, $key, $charset);
	echo "PLAIN: $p2\n\n";
	$md5 = md5($p2);
	if($md5=='f528a6ab914c1ecf856a1d93103948fe') {
		echo "FOUND!! $key $p2\n";
		exit;
	}
}}}}

?>

Ejecutamos el script y en menos de 2 segundos tenemos la flag:

php vigenere_part2.php
CLAVE: VIGENEREAAAA
PLAIN: SECCON{ADOEEBCDEDEFGJWMNKLMNOPQRUFWYVWXYYZ}

CLAVE: VIGENEREAAAB
PLAIN: SECCON{ADOEDBCDEDEFGJWMMKLMNOPQRUFWXVWXYYZ}

CLAVE: VIGENEREAAAC
PLAIN: SECCON{ADOECBCDEDEFGJWMLKLMNOPQRUFWWVWXYYZ}

CLAVE: VIGENEREAAAD
PLAIN: SECCON{ADOEBBCDEDEFGJWMKKLMNOPQRUFWVVWXYYZ}
.....
CLAVE: VIGENERECODC
PLAIN: SECCON{ABABCBCDEDEFGHIJLKLMNOPQRSTTWVWXYYZ}

CLAVE: VIGENERECODD
PLAIN: SECCON{ABABBBCDEDEFGHIJKKLMNOPQRSTTVVWXYYZ}

CLAVE: VIGENERECODE
PLAIN: SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}

FOUND!! VIGENERECODE SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}

Y ahí tenemos la pass “VIGENERECODE” y la flag:

SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}

Otra vez las pistas nos han facilitado la parte de investigación y nos hemos podido limitar a resolver el reto.

Espero os haya gustado, un saludo!

Esta entrada fue publicada en cripto, ctf, seccon, writeups. Guarda el enlace permanente.

Deja un comentario