It should work…

Cuando cualquier trasto es útil

It should work… header image 2

Descifrando un reto del FBI

April 18th, 2009 · 2 Comments · hacking, programming

Hace unos días TuXeD dejó propuesto un pequeño reto que propuso el FBI en 2008 para el entretenimiento del personal. Tal cual lo ví me puse manos a la obra.

Vamos a la web y nos encontramos con esto:

fbi

Code Cracking Challenge FBI 2008

¿Por dónde empezamos? Mmmm, así a primera vista vemos que el porcentaje de vocales es bajo, casi todo son consonantes seguidas así que el cifrado usado debería ser de sustitución y no de transposición (en ese caso como se hubiera realizado un cambio de lugar de las letras debería haber un porcentaje razonable de vocales, cercano al 45% como es el caso del español o al 40% como es el caso del inglés, de todas formas seguro que es inglés al ser un reto del FBI).

Enseguida nos damos cuenta que hay algo muy reconocible, algo tiene forma de URL:  YYY.AHB.MSK/NSCDC.OFZ
¿Sera sea www.fbi.gov/index.php ? A ver si vamos a terminar antes de empezar! Bueno, lo pruebo y no xD, la web no carga así que debe ser otra cosa.

Asumimos es un cifrado de sustitución y viendo ese ‘YYY’ vamos a suponer que son Ws y que seguro que la web es del dominio fbi.gov, con lo cual por ahora tenemos las siguientes correspondencias:

Y-W
A-F
H-B
B-I
M-G
S-O
K-V

TuXeD nos ha dado la pista de que “es un puzzle más bien” así que en lugar de darle mil vueltas al Cryptool casi mejor cogemos una hoja de papel. Nos escribimos el mensaje y cambiamos las letras que hemos supuesto a ver si vemos algo que nos suene para obtener más concordancias entre letras.

Una vez escrito está claro que es inglés (por si no estaba claro) porque aparece la conjunción “OF”.

Delante de la URL tenemos la palabra VI-I- así que parece claro que es la palabra VISIT ¿qué puedes hacer sino con una URL? Así que parece que nuestra suposición con las primeras concordancias eran buenas. Ya tenemos:

V-S
F-T

Nos ponemos a sustituir de nuevo. Una vez terminado vemos que el final de la URL es -T-. Yo de primeras he pensado que siendo de 3 letras podía ser HTM, PHP, JSP, ASP etc incluso un fichero PDF, pero ahora seguro que es HTM así que:

O-H
Z-M

Pero www.fbi.gov/index.htm no carga, sh*t! así que no asignamos las letras de la palabra INDEX.

Nos ponemos de nuevo con el texto y vemos que FOBV casa con THIS pero ya no hay más palabras obvias pero, era inglés, ¿no? Hay una palabra que acaba en I-G, ¿será un gerundio? En ese caso L-N.

Ahora vemos un -NOW que seguro es un KNOW, luego Q-K.

Y ahora viene una de cajón, como no, parece que la palabra ENCRYPTION aparece en forma de -N—-TION. Esto ya está resuelto ;)

Una vez sustituidas los nuevos pares de letras ya podemos reconocer muchas palabras: cracking, success, congratulate, you, el texto es nuestro :)

“Stupendous. We congratulate you on cracking this latest encryption. Visit www.fbi.gov/coded.htm to let us know of your success.”

Cuya web si carga ;)

Y ahora los más avispados dirán, baaaaaaah, eso es una mierda, ¿cómo lo haces en un texto donde no hay una manera de empezar tan clara como esa URL? Así que me puse a ello.

Vamos a suponer que en el texto no estuviera la URL, ¿qué hago? Por las mismas deducciones que antes suponemos que es un cifrado de sustitución simple y ahora viene el truco, todos los idiomas tienen ciertas palabras que por su estructura son menos comunes que otras debido a tener la misma letra seguida en varias partes de la palabra. Debido a este tipo de cifrado usado ¡esa estructura se conserva! Pues vamos a chequear las palabras que nos parezcan de estructura más adecuada contra un diccionario, vamos a buscar patrones. Así que pillamos un diccionario de palabras en inglés (yo tenía el de aspell ya instalado así que con un strings lo meto en un txt) y con la ayuda del siguiente programa en C que tenía guardado buscamos patrones que encajen con la palabra elegida (no recuerdo de donde salió, si alguien lo sabe que me pase la fuente). Además, despues de comprobarla contra el diccionario seguro que podemos descartar muchas por la longitud que debe tener.

¿palabra candidata? Sin duda “VWNNDVV”, por esas repeticiones. Es de la forma ABCCDAA.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ./pattern en-common.txt ABCCDAA
unsuccessful
unsuccessfully
falloff
falloffs
colossally
cappuccino
cappuccino's
cappuccinos
nonsuccessive
success
successor
success's
successive
successful
successfully
successively
successes
successor's
successors
succession
succession's
successions

Si nuestro diccionario es bueno hemos reducido el asunto a muy muy pocas palabras y gracias a que sabemos la longitud que tiene que tener la palabra sólo nos encajan 2. “falloff” y “success”. Tratándose de descifrar un código la palabra success tiene sentido, ¿no? Estaríamos dando de pleno en el clavo :) Ahora tendríamos ir operando como antes para ir sacando más palabras. Otra candidata para empezar podría haber sido la palabra cifrada que corresponde a “stupendous” pero el ataque contra diccionario no acota suficiente la solución.

Otro días más! Y aquí el programa en C:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void remove_nl(char *str)
{
   if(str[strlen(str)-1]=='\n')
      str[strlen(str)-1]=0;
}
 
int match_pattern(char *match, const char *pattern, size_t pattern_len)
{
   int i,j;
 
   for(i=0; i<pattern_len; i++)
   {
      for(j=i; j>pattern_len; j++)
      {
         if(pattern[i]==pattern[j])
            if(match[i]!=match[j])
               return 0;
 
         if(pattern[i]!=pattern[j])
            if(match[i]==match[j])
               return 0;
      }
   }
 
   return 1;
}
 
int main(int argc, char *argv[])
{
   char word[64];
   char *pattern = NULL;
   int pattern_len = 0;
 
   if(argc!=3)
   {
      printf("Usage: %s [word list] [crypto-pattern]\n\n", argv[0]);
      return 0;
   }
 
   pattern = argv[2];
   pattern_len = strlen(pattern);
 
   FILE *file = fopen(argv[1], "r");
   if(!file)
   {
      perror("fopen()");
      exit(0);
   }
 
   while(!feof(file))
   {
      fgets(word, sizeof(word), file);
      remove_nl(word);
 
      char *substr = word;
 
      while(strlen(substr)>=pattern_len)
      {
         if(strlen(substr)<pattern_len)
            break;
 
         char match[pattern_len];
         strncpy(match, substr, pattern_len);
         match[pattern_len]=0;
 
         if(match_pattern(match, pattern, pattern_len))
            printf("%s\n", word);
 
         substr++;
      }
   }
 
 
   fclose(file);
 
   return 0;
}




Fuente original en http://vierito.es/wordpress

Similar Posts:

VN:F [1.8.4_1055]
Rating: 5.0/5 (1 vote cast)
VN:F [1.8.4_1055]
Rating: 0 (from 0 votes)
Descifrando un reto del FBI5.051

Tags: ····

2 responses so far ↓

Leave a Comment