SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

Rompiendo el ARJ

      4475

Autor: Falken
-[ 0x0A ]--------------------------------------------------------------------
-[ ROMPIENDO EL ARJ ]--------------------------------------------------------
-[ by Falken ]--------------------------------------------------------SET-14-


                                  ROMPIENDO   EL

                           .o.       ooooooooo.      oooo
                          .888.      `888   `Y88.    `888 
                         .8"888.      888   .d88'     888 
                        .8' `888.     888ooo88P'      888 
                       .88ooo8888.    888`88b.        888 
                      .8'     `888.   888  `88b.      888 
                     o88o     o8888o o888o  o888o .o. 88P 
                                                  `Y888P  



    En SET 13 un lector nos comentaba que tenia problemas, pues habia copiado
en unos CDs algunos programas y juegos, compriendolos con el ARJ. A estos
archivos les habia puesto una password, y posteriormente se habia olvidado
de cual era. Asi que os escribia para preguntarnos como podia obtener la
clave.

    Puestos manos a la obra, vamos a desvelar cual es el metodo que usa
ARJ para encriptar los archivos, de forma que podais realizar por vosotros
mismos un programa capaz de romper el sistema.

    En esta aventura criptoanalitica contaremos tan solo con el ARJ en su
version 2.50, la documentacion que incluye, y un editor hexadecimal
cualquiera. Baste decir que para el caso que nos ocupa se uso el Hacker's
View por comodidad, y el debug del MS-DOS para realizar los volcados.


ENTENDIENDO EL ARJ
=-=-=-=-=-=-=-=-=-

    Lo primero, es leer la documentacion. Aqui vemos una referencia tecnica
en la que se nos explica cual es la estructura del archivo ARJ. Veamosla
con mas calma, aplicando un ejemplo que luego nos sera de utilidad a la hora
de realizar el criptoanalisis.

    Como ejemplo, generamos un archivo llamado CLARO.ARJ, en el que solo
incluimos un fichero, el UNO.TXT, cuyo contenido es la cadena "SET working on
ARJ". El metodo de compresion sera simplemente el almacenamiento, para
mayor comodidad a la hora del analisis.

    Ahora veamos la estructura del archivo ARJ, aplicada al caso particular
de CLARO.ARJ. Para ello, tenemos el siguiente volcado hexadecimal del mismo:


1BE8:0100  60 EA 29 00 1E 07 01 00-10 00 02 47 47 BF 8D 24   `.)........GG..$
1BE8:0110  47 BF 8D 24 00 00 00 00-00 00 00 00 00 00 00 00   G..$............
1BE8:0120  00 00 43 4C 41 52 4F 2E-41 52 4A 00 00 3F 2F 04   ..CLARO.ARJ..?/.
1BE8:0130  1B 00 00 60 EA 27 00 1E-07 01 00 10 00 00 47 FA   ...`.'........G.
1BE8:0140  BE 8D 24 12 00 00 00 12-00 00 00 2B 5B DD 85 00   ..$........+[...
1BE8:0150  00 20 00 00 00 55 4E 4F-2E 54 58 54 00 00 F4 3B   . ...UNO.TXT...;
1BE8:0160  39 D8 00 00 53 45 54 20-77 6F 72 6B 69 6E 67 20   9...SET working 
1BE8:0170  6F 6E 20 41 52 4A 60 EA-00 00                     on ARJ`...


    Bien, comencemos. La estructura de un archivo ARJ se compone de dos
partes fundamentales:

        - La cabecera principal del archivo.
        - La cabecera del fichero local.

    La cabecera del fichero local aparecera tantas veces como ficheros hayan
en el archivo. Asi, si hay dos ficheros comprimidos en el archivo, habra dos
cabeceras de fichero local, una por cada fichero.

    Pues para empezar, veamos la cabecera principal del archivo.

 .---------------------.
 | Bytes | Descripcion |
 |--------------------------------------------------------------------------.
 |   2   | ID de la cabecera (principal y local) = 0x60 0xEA                |
 |   2   | Tama€o de la cabecera basica:                                    |
 |       |   first_hdr_size + strlen (nombre) + 1 + strlen (comentario) + 1 |
 |       |   0 -> Si es el final del archivo                                |
 |       |   Tama€o maximo -> 2600                                          |
 |   1   | first_hdr_size                                                   |
 |   1   | Numero de version del archivador                                 |
 |   1   | Version minima del archivador a extraer                          |
 |   1   | OS [0 = MSDOS.1 = PRIMOS....2 = UNIX......3 = AMIGA..4 = MAC-OS] |
 |       |    [5 = OS/2..6 = APPLE GS..7 = ATARI ST..8 = NEXT..9 = VAX VMS] |
 |   1   | Indicadores ARJ:                                                 |
 |       |    [0x01 = NO USADO]                                             |
 |       |    [0x02 = OLD_SECURED_FLAG]                                     |
 |       |    [0x04 = VOLUME_FLAG]  Indica la existencia de otro volumen    |
 |       |    [0x08 = NO USADO]                                             |
 |       |    [0x10 = PATHSYM_FLAG] Indica cambio de \ a / en el path       |
 |       |    [0x20 = BACKUP_FLAG]  Indica que se trata de un backup        |
 |       |    [0x40 = SECURED_FLAG]                                         |
 |   1   | Version de seguridad (2 = actual)                                |
 |   1   | Tipo de fichero. Igual a 2 siempre.                              |
 |   1   | Reservado                                                        |
 |   4   | Fecha y hora del archivo original.                               |
 |   4   | Fecha y hora de la ultima modificacion.                          |
 |   4   | Tama€o del archivo.                                              |
 |   4   | Posicion de la envuelta de seguridad.                            |
 |   2   | ???                                                              |
 |   2   | Longitud en bytes de la envuelta de seguridad.                   |
 |   2   | No usado actualmente                                             |
 |   ?   | Actualmente nada.                                                |
 |   ?   | Nombre del archivo cuando se creo, terminado en null (0x00)      |
 |   ?   | Comentario del archivo, terminado en null (0x00)                 |
 |   4   | CRC de la cabecera.                                              |
 |   2   | Tama€o de la primera cabecera extendida (0 si no hay)            |
 |   ?   | Primera cabecera extendida                                       |
 |   4   | CRC de la primera cabecera extendida.                            |
 |       | No presente si no hay cabecera extendida.                        |
 `--------------------------------------------------------------------------'


    En nuestro ejemplo, esto se corresponde con:

1BE8:0100  60 EA 29 00 1E 07 01 00-10 00 02 47 47 BF 8D 24   `.)........GG..$
1BE8:0110  47 BF 8D 24 00 00 00 00-00 00 00 00 00 00 00 00   G..$............
1BE8:0120  00 00 43 4C 41 52 4F 2E-41 52 4A 00 00 3F 2F 04   ..CLARO.ARJ..?/.
1BE8:0130  1B 00 00                                          ...

    Para los que tengais curiosidad, la fecha y hora se almacena en el
siguiente formato:

           .-----------------------------------------------------.
           | 31 30 29 28 27 26 25 | 24 23 22 21 | 20 19 18 17 16 |
           | <--- a€o - 1980 ---> | <-- mes --> | <--- dia ----> |
           |-----------------------------------------------------|
           | 15 14 13 12 11 | 10 09 08 07 06 05 | 04 03 02 01 00 |
           | <--- hora ---> | <--- minutos ---> | <-- segs/2 --> |
           `-----------------------------------------------------'

    Asi que para detalle, la fecha de creacion del archivo es 0x248DBF47
(recordad que se invierte el orden al almacenarlo), o lo que es lo mismo:

0010010 -> 18 + 1980 -> 1998  \
0100    -> 4 -> Abril          |
01101   -> 13                  \   Creado el 13 de Abril de 1998
10111   -> 23                  /   a las 23h 58m 14s
111010  -> 58                  |   P'a que luego digan que no trabajamos
00111   -> 7 * 2 -> 14        /    hasta el cierre de edicion ;)


    Sigamos ahora con la cabecera del fichero local:

 .---------------------.
 | Bytes | Descripcion |
 |--------------------------------------------------------------------------.
 |   2   | ID de la cabecera (principal y local) = 0x60 0xEA                |
 |   2   | Tama€o de la cabecera basica:                                    |
 |       |   first_hdr_size + strlen (nombre) + 1 + strlen (comentario) + 1 |
 |       |   0 -> Si es el final del archivo                                |
 |       |   Tama€o maximo -> 2600                                          |
 |   1   | first_hdr_size                                                   |
 |   1   | Numero de version del archivador                                 |
 |   1   | Version minima del archivador a extraer                          |
 |   1   | OS [0 = MSDOS.1 = PRIMOS....2 = UNIX......3 = AMIGA..4 = MAC-OS] |
 |       |    [5 = OS/2..6 = APPLE GS..7 = ATARI ST..8 = NEXT..9 = VAX VMS] |
 |   1   | Indicadores ARJ:                                                 |
 |       |    [0x01 = GARBLED_FLAG] Indica un fichero encriptado.           |
 |       |    [0x02 = NO USADO]                                             |
 |       |    [0x04 = VOLUME_FLAG]  Indica la que el fihero esta cortado.   |
 |       |    [0x08 = EXTFILE_FLAG] Indica la posicion de continuacion en   |
 |       |                          ficheros cortados.                      |
 |       |    [0x10 = PATHSYM_FLAG] Indica cambio de \ a / en el path       |
 |       |    [0x20 = BACKUP_FLAG]  Indica que se trata de un backup        |
 |   1   | Metodo de compresion:  0 = almacenado.                           |
 |       |                        1 = Maxima compresion                     |
 |       |                        ...                                       |
 |       |                        4 = Compresion rapida.                    |
 |   1   | Tipo de fichero: 0 = Binario                                     |
 |       |                  1 = Texto en 7 bits                             |
 |       |                  2 = Directorio                                  |
 |       |                  3 = Etiqueta de volumen                         |
 |   1   | Reservado                                                        |
 |   4   | Fecha y hora de la ultima modificacion.                          |
 |   4   | Tama€o del archivo comprimido.                                   |
 |   4   | Tama€o del archivo original.                                     |
 |   4   | CRC del archivo original.                                        |
 |   2   | ???                                                              |
 |   2   | Modo de acceso al fichero.                                       |
 |   2   | Datos de la maquina (no usado actualmente)                       |
 |   ?   | Datos extra.                                                     |
 |       |    4 bytes para el punto de comienzo de los ficheros extendidos  |
 |       |    cuando se requiere (EXTFILE_FLAG)                             |
 |       |    0 bytes en cualquier otro caso.                               |
 |   ?   | Nombre del archivo cuando se creo, terminado en null (0x00)      |
 |   ?   | Comentario del archivo, terminado en null (0x00)                 |
 |   4   | CRC de la cabecera.                                              |
 |   2   | Tama€o de la primera cabecera extendida (0 si no hay)            |
 |   ?   | Primera cabecera extendida                                       |
 |   4   | CRC de la primera cabecera extendida.                            |
 |       | No presente si no hay cabecera extendida.                        |
 |  ...  | ...                                                              |
 |   ?   | Fichero comprimido                                               |
 `--------------------------------------------------------------------------'

   
    Y para el ejemplo que estamos siguiendo, sera:

1BE8:0130           60 EA 27 00 1E-07 01 00 10 00 00 47 FA      `.'........G.
1BE8:0140  BE 8D 24 12 00 00 00 12-00 00 00 2B 5B DD 85 00   ..$........+[...
1BE8:0150  00 20 00 00 00 55 4E 4F-2E 54 58 54 00 00 F4 3B   . ...UNO.TXT...;
1BE8:0160  39 D8 00 00 53 45 54 20-77 6F 72 6B 69 6E 67 20   9...SET working 
1BE8:0170  6F 6E 20 41 52 4A                                 on ARJ    

    Despues, aparece 0x60 0xEA 0x00 0x00, que indica el final del archivo.
Vemos aqui claramente donde comienza el fichero archivado. Asi, Lo que
encriptaremos, ira desde la posicion 0x163 a la posicion 0x175.

    Nos falta algo por leer en la documentacion que acompa€a al ARJ. Y es que
nos dice textualmente:

     ARJ does NOT use DES encryption algorithms.  It uses a combination of
     simple exclusive-or operations.

    He dicho que era textual, no? ;)

    Vale, sere bueno y lo traducire. Dice que el ARJ no usa DES como metodo
de encriptacion. Que solo usa una combinacion de simples XOR.

    A ver, alguno no sabe lo que es una operacion XOR? Pues no es ni mas
ni menos que un OR-eXclusivo. (Y me he quedado tan ancho ;) ).

    Bueno, una operacion XOR consiste, como ya he dicho, en una o logica
exclusiva, o lo que se puede leer de la siguiente manera: "O uno u otro, pero
no ambos a la vez". En logica binaria, tenemos la siguiente tabla de la
verdad para una operacion XOR, representado como en lenguaje C (^): 

            0 ^ 0 = 0     0 ^ 1 = 1     1 ^ 0 = 1     1 ^ 1 = 0

    Ha quedado claro ya? Como alguien me diga que esto es de un nivel alto,
lo hago del club de fans de Bill Gates. Lo juro por el pinguino de Linux.

    Creo que ya estamos en condiciones de afrontar el reto.


CRIPTOANALIZANDO ARJ
=-=-=-=-=-=-=-=-=-=-

    Pues para comenzar el criptoanalisis, y ver que metodo usa el ARJ,
debemos tener un archivo encriptado. Vamos, creo yo, no? ;)

    Asi que vamos a coger el archivo CLARO.ARJ, y lo vamos a copiar como
TEST1.ARJ, encriptando este ultimo con la clave: CLAVE. Despues de todo esto,
obtenemos un archivo tal que asi:

1BE8:0100  60 EA 29 00 1E 07 01 00-10 00 02 47 47 BF 8D 24   `.)........GG..$
1BE8:0110  78 BF 8D 24 00 00 00 00-00 00 00 00 00 00 00 00   x..$............
1BE8:0120  00 00 43 4C 41 52 4F 2E-41 52 4A 00 00 6E 72 96   ..CLARO.ARJ..nr.
1BE8:0130  17 00 00 60 EA 27 00 1E-07 01 00 11 00 00 78 FA   ...`.'........x.
1BE8:0140  BE 8D 24 12 00 00 00 12-00 00 00 2B 5B DD 85 00   ..$........+[...
1BE8:0150  00 20 00 00 00 55 4E 4F-2E 54 58 54 00 00 C6 B9   . ...UNO.TXT....
1BE8:0160  CD 6B 00 00 E8 81 ED EE-CA D4 B6 D2 A7 D3 DC E4   .k..............
1BE8:0170  D6 A0 9D FA 96 F3 60 EA-00 00                     ......`...


    Antes de pasar a la accion, conviene ver que valores han cambiado en el
archivo encriptado respecto al archivo en claro. Es evidente, que la clave, o
lo que sea que almacena el ARJ como clave, estara en alguno de estos bytes.

1BE8:0100
1BE8:0110  78                                                x
1BE8:0120                                         6E 72 96                nr.
1BE8:0130  17                               11       78      .          .  x
1BE8:0140
1BE8:0150                                            C6 B9                 ..
1BE8:0160  CD 6B       E8 81 ED EE-CA D4 B6 D2 A7 D3 DC E4   .k  ............
1BE8:0170  D6 A0 9D FA 96 F3                                 ......


    Veamos que es cada byte del archivo TEST1.ARJ que difiere del CLARO.ARJ:

   .---------------------------------------------------------------------.
   |          78 | Pertenece a la Fecha y hora de ultima modificacion:   |
   |             |      78 BF 8D 24                                      |
   | 6E 72 96 17 | Se trata del CRC de la cabecera.                      |
   |          11 | Son los flags ARJ. Indican que se trata de un archivo |
   |             | encriptado.                                           |
   |          78 | Reservado (Uhmmm! Interesante)                        |
   | C6 B9 CD 6B | El CRC de la cabecera del fichero local.              |
   |   E8 81 ... | El fichero encriptado.                                |
   `---------------------------------------------------------------------'

    Ya podemos ponernos a trabajar con el archivo.

    En la documentacion del ARJ, se nos avisaba de que el proceso de cifrado
era una simple combinacion de operaciones XOR. Pues por si no lo recordais,
o no lo sabiais, para la operacion XOR, se cumple:

                        A ^ B = C  --->  B ^ C = A

    Y como tenemos el texto en claro (arhivo sin codificar), y el encriptado,
pues puede que si lo XOReamos obtengamos la clave, no? Y como ya tenemos la
clave, pues sera facil comprobar si es este el metodo usado por el ARJ. Por
cierto, un metodo bastante absurdo.

    
  Texto cifrado  :  E8 81 ED EE CA D4 B6 D2 A7 D3 DC E4 D6 A0 9D FA 96 F3
  Texto en claro :  53 45 54 20 77 6F 72 6B 69 6E 67 20 6F 6E 20 41 52 4A ^
                   -------------------------------------------------------
  Resultado      :  BB C4 B9 CE BD BB C4 B9 CE BD BB C4 B9 CE BD BB C4 B9

    Pues no, parece que no es tan simple... Resulta que nuestra clave (CLAVE)
es 43 4C 41 56 45. Aunque algo curioso si se ve... No parece extra€o que en
el resultado se repita la cadena BB C4 B9 CE BD? Ademas, tiene la misma
longitud que la clave.

    Hagamos una hipotesis. Se hace alguna operacion con la clave original, y
despues, se XORea el resultado con el archivo original. Esa operacion puede
que sea un XOR de la clave con alguna constante. Ademas, resulta que esa
cadena (BB C4 B9 CE BD) no se ve en ninguna parte del archivo cifrado. Y
menos en los bytes que difieren de un archivo a otro, que son los que
interesan.

    De acuerdo, hagamos un XOR de la clave con lo que nos ha salido, a ver
que sale:

        Clave original   : 43 4C 41 56 45
        Clave de cifrado : BB C4 B9 CE BD ^
                          ----------------
        Resultado        : F8 88 F8 98 F8

    Vaya, vaya. Parece que se repite mucho el byte F8, eh? Pero no aparece
en el archivo cifrado. Quizas sea una cadena interna del ARJ, no? Pues para
probar, utilizaremos otro archivo cifrado nuevo: TEST2.ARJ. Usaremos la
misma clave, pues si sale el mismo archivo, sabremos que se trata de un
valor constante, o de que los valores dependen de la clave:

1BE8:0100  60 EA 29 00 1E 07 01 00-10 00 02 47 47 BF 8D 24   `.)........GG..$
1BE8:0110  7A BF 8D 24 00 00 00 00-00 00 00 00 00 00 00 00   z..$............
1BE8:0120  00 00 43 4C 41 52 4F 2E-41 52 4A 00 00 26 C0 99   ..CLARO.ARJ..&..
1BE8:0130  D1 00 00 60 EA 27 00 1E-07 01 00 11 00 00 7A FA   ...`.'........z.
1BE8:0140  BE 8D 24 12 00 00 00 12-00 00 00 2B 5B DD 85 00   ..$........+[...
1BE8:0150  00 20 00 00 00 55 4E 4F-2E 54 58 54 00 00 D3 B4   . ...UNO.TXT....
1BE8:0160  08 53 00 00 EE 83 EF F0-C8 D2 B4 D0 B9 D1 DA E6   .S..............
1BE8:0170  D4 BE 9F FC 94 F1 60 EA-00 00                     ......`...


    Fijandonos bien, nos damos cuenta de que nos es igual al TEST1.ARJ, por
que parece que alguno de los valores usados para camuflar la clave dependen
del momento en que se cifra, o son aleatorios (que para el caso, pues es
casi lo mismo). Y por ende, estos valores debieran almacenarse en el archivo,
verdad. Resulta que analizando TEST2.ARJ, vemos que los bytes que varian de
un archivo a otro ocupan las mismas posiciones que en TEST1.ARJ, asi que
no hara falta separarlos para que los veais, verdad?

    Bien, pues vamos ahora a realizar la misma operacion anterior, es decir
XORear, el texto en claro con el cifrado


  Texto cifrado  :  EE 83 EF F0 C8 D2 B4 D0 B9 D1 DA E6 D4 BE 9F FC 94 F1
  Texto en claro :  53 45 54 20 77 6F 72 6B 69 6E 67 20 6F 6E 20 41 52 4A ^
                   -------------------------------------------------------
  Resultado      :  BD C6 BB D0 BF BD C6 BB D0 BF BD C6 BB D0 BF BD C6 BB

    Ondia. Resulta que tambien se repite una misma cadena de 5 bytes, la
misma longitud que la clave. Pues XOReemos esta cadena con la clave tambien:
    
        Clave original   : 43 4C 41 56 45
        Clave de cifrado : BD C6 BB D0 BF ^
                          ----------------
        Resultado        : FE 8A FA 86 FA

    Pues vaya. Resulta que no da lo mismo. O sea, que tengo el mismo archivo
encriptado dos veces con la misma clave, en momentos diferentes (Siempre
sera un momento diferente). Y nos da un resultado que no es el mismo. Es
decir. La clave se modifica en funcion de algo aleatorio. Algo que quizas
dependa del tiempo. Y para mas recochineo, ninguno de los bytes resultado de
XORear las dos claves aparece en el archivo correspondiente. Me parece que
esto ya lo he dicho antes, no? ;)

    Aunque... si nos fijamos bien... las claves de cifrado usadas en ambos
casos se parecen, no?

    Visto que nuestra primera hipotesis no se cumple, hipoteticemos de nuevo.
(Que bien suena. Si hasta parece politico y todo ;) )

    Supongamos en esta ocasion que la clave se oculta en funcion del tiempo.
Si nos damos cuenta, TEST2.ARJ fue creado despues que TEST1.ARJ. Pongamos
las dos claves de cifrado juntas, a ver si salta algo por casualidad.

        Clave de cifrado TEST1.ARJ : BB C4 B9 CE BD
        Clave de cifrado TEST2.ARJ : BD C6 BB D0 BF

    Espera, no puede ser. Creo que lo estoy viendo. Joers, si es que despues
de todo, me vino bien aprenderme aquellas tablas de multiplicacion, division,
suma y resta en hexadecimal. Todo, para que luego te llegue un profesor, y
te diga que no se puede multiplicar en hexadecimal... Bueno, que yo recuerde
de mis clases de matematicas, los calculos se pueden hacer en cualquier base
numerica. Solo hay que saberse las tablas basicas de la base. A ver, todos
juntos: 1 * 1 es 1, 1 * 2, 2... 2 * F, es 1E...

    Me parece que estoy desvariando un poquito... A lo que ibamos. Si mirais
atentamente, os dareis cuenta que la clave de cifrado usada en TEST2.ARJ es
igual a la clave usada en TEST1.ARJ, mas 0x02, y si no, mirad:

                               BB C4 B9 CE BD
                               02 02 02 02 02 +
                              ----------------
                               BD C6 BB D0 BF

    Asi que puede que lo que estemos buscando, sea algo cuyo valor sea
diferente en 0x02 entre TEST2.ARJ y TEST1.ARJ. Y ademas, debe ser uno de esos
bytes que son diferentes respecto a CLARO.ARJ. Veamos el volcado de
TEST2.ARJ - TEST1.ARJ:

1BE8:0100
1BE8:0110  02                                                .
1BE8:0120                                         F8 4E 03                .N.
1BE8:0130  BA                               00       02      .          .  z
1BE8:0140
1BE8:0150                                            0D FD                 ..
1BE8:0160  3B E8       .. .. .. .. .. .. .. .. .. .. .. ..   ;...............
1BE8:0170  .. .. .. .. .. ..                                 ......

    Uhmm! Aparece dos veces. Una en el campo de de la fecha y hora de la
ultima modificacion... Y la otra en un byte marcado como... reservado. Me
parece que lo tengo... Asi que en ese byte se almacena como con que ocultar
la clave. Ahora nos falta saber el como. Y quizas, si ponemos la clave
original, la clave de cifrado y este dichoso byte juntos, se nos ocurra algo.
Vamos a verlo para TEST1.ARJ:

        Clave de cifrado : BB C4 B9 CE BD
        Clave original   : 43 4C 41 56 45
        Mardito byte     : 78 78 78 78 78

    Alguien lo ha descubierto ya. Me parece que no habeis hecho vuestros
deberes. Y aquellas tablas numericas que habia que aprenderse para hoy?
Repasemos todos juntos... BB - 78 = 43; C4 - 78 = 4C...

    Creo que no hacen falta mas explicaciones. Pero por si todavia no os
habeis dado cuenta, lo contare por palabros.

    De la fecha de ultima modificacion, o para ser exactos, en el momento en
el que incluye la clave, se toma un byte que se almacena en la posicion
reservada esa. Ademas, es el byte correpondiente al menos significativo de
la fecha y hora de encriptado.

    Ahora, el usuario normalito y corriente, introduce una password, a la que
se le suma este byte. Y con ello, obtenemos la clave con la que se cifrara
el fichero original. Tan simple como esto.


Y EL ARJ, COMO SABE QUE DESCIFRA BIEN?
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    Tan sencillo como descrifrar aplicando el mismo procedimiento que para
cifrar. O sea, el usuario introduce la password que cree que es, y el fichero
se encripta siguiendo el procedimiento anterior. Como A ^ B ^ A = B, entonces
solo si la clave es correcta, obtendremos el fichero original.

    Vale, todo esto es muy bonito. Pero... Como diantres se las apa€a el
ARJ para saber que la clave es correcta.

    Pues el propio ARJ nos da una muy buena pista. Si le metemos una password
erronea, que hace? Decirnos que se ha producido un error de CRC. Asi que si
pensamos un poco, nos daremos cuenta de que lo unico que tiene que hacer es
comprobar el CRC del fichero que se obtiene con el CRC del fichero original,
que va almacenado en el archivo, tal y como ya hemos visto.


Y SI TENGO MAS DE UN FICHERO EN EL ARJ?
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

    Veamoslo con un ejemplo practico. Esta vez tenemos el archivo sin cifrar
CLARO2.ARJ, y el archivo cifrado TEST21.ARJ, encriptado con la clave: SET

    El archivo CLAR2.ARJ es como sigue:

1BE8:0100  60 EA 2A 00 1E 07 01 00-10 00 02 05 05 00 8E 24   `.*............$
1BE8:0110  05 00 8E 24 00 00 00 00-00 00 00 00 00 00 00 00   ...$............
1BE8:0120  00 00 43 4C 41 52 4F 32-2E 41 52 4A 00 00 BE 81   ..CLARO2.ARJ....
1BE8:0130  82 E2 00 00 60 EA 27 00-1E 07 01 00 10 00 00 05   ....`.'.........
1BE8:0140  FA BE 8D 24 12 00 00 00-12 00 00 00 2B 5B DD 85   ...$........+[..
1BE8:0150  00 00 20 00 00 00 55 4E-4F 2E 54 58 54 00 00 45   .. ...UNO.TXT..E
1BE8:0160  8D 99 95 00 00 53 45 54-20 77 6F 72 6B 69 6E 67   .....SET working
1BE8:0170  20 6F 6E 20 41 52 4A 60-EA 27 00 1E 07 01 00 10    on ARJ`.'......
1BE8:0180  00 00 05 14 BF 8D 24 06-00 00 00 06 00 00 00 0D   ......$.........
1BE8:0190  15 A7 1B 00 00 20 00 00-00 44 4F 53 2E 54 58 54   ..... ...DOS.TXT
1BE8:01A0  00 00 D8 63 7E D3 00 00-45 55 52 45 4B 41 60 EA   ...c~...EUREKA`.
1BE8:01B0  00 00                                             ..

    Aqui vemos que hay dos ficheros almacenados: UNO.TXT y DOS.TXT

    Y ahora vamos con el aspecto del archivo encriptado:

1BE8:0100  60 EA 2A 00 1E 07 01 00-10 00 02 05 05 00 8E 24   `.*............$
1BE8:0110  49 00 8E 24 00 00 00 00-00 00 00 00 00 00 00 00   I..$............
1BE8:0120  00 00 43 4C 41 52 4F 32-2E 41 52 4A 00 00 D6 E5   ..CLARO2.ARJ....
1BE8:0130  B6 33 00 00 60 EA 27 00-1E 07 01 00 11 00 00 49   .3..`.'........I
1BE8:0140  FA BE 8D 24 12 00 00 00-12 00 00 00 2B 5B DD 85   ...$........+[..
1BE8:0150  00 00 20 00 00 00 55 4E-4F 2E 54 58 54 00 00 57   .. ...UNO.TXT..W
1BE8:0160  0F FC BD 00 00 CF CB C9-BC F9 F2 EE E5 F4 F2 E9   ................
1BE8:0170  BD F3 E0 BD DD DC D7 60-EA 27 00 1E 07 01 00 11   .......`.'......
1BE8:0180  00 00 49 14 BF 8D 24 06-00 00 00 06 00 00 00 0D   ..I...$.........
1BE8:0190  15 A7 1B 00 00 20 00 00-00 44 4F 53 2E 54 58 54   ..... ...DOS.TXT
1BE8:01A0  00 00 CA E1 1B FB 00 00-D9 DB CF D9 C5 DC 60 EA   ..............`.
1BE8:01B0  00 00                                             ..

    Si hacemos la comprobacion, veremos que la clave de cifrado es 53 45 54
(SET) + 49, o sea 9C 8E 9D. Y ademas ha resultado que es la misma para los
dos ficheros.

    Lo que si que nos queda claro despues de todo este rollo, es que ya
sabemos como encripta el ARJ, como romperlo, y que no es nada seguro.


Y ESO DEL CRC, QUE ES?
=-=-=-=-=-=-=-=--=-=-=

    Bueno, pues el CRC no es ni mas ni menos que el Codigo de Redundancia
Ciclica. A que suena bonito, eh? ;)

    CRCs hay de muchos tipos. El que nos interesa en esta ocasion, es el
CRC de 32 bits, pues es el que usa el ARJ.

    En si, es un valor, resultado de una funcion, usado para comprobar la
integridad de unos datos, como puede ser un fichero. Con esto nos comprobamos
casi con total seguridad que los datos estan tal y como se crearon. Tambien
se usa en las lineas de comunicacion de datos.

    Para calcular el CRC, se usa un polinomio, que en el caso del ARJ, es
el 0xEDB88320, que casualmente es el mismo que el usado en el PKZIP y otras
aplicaciones.

    Lo del polinomio, es para indicar que bits de la secuencia se usan en la
funcion. Asi el polinomio X^5 + x^3, es lo mismo que 0x14, ya que el bit 0
o menos significativo es en esta ocasion el bit 1.

    La forma mas rapida de calcular el CRC de un fichero, es usar este
peque€o programa que os doy a continuacion:

<++> set_014/arj/crc32.c
/*  CRC-32b version 1.03 by Craig Bruce, 27-Jan-94
**
**  Based on "File Verification Using CRC" by Mark R. Nelson in Dr. Dobb's
**  Journal, May 1992, pp. 64-67.  This program DOES generate the same CRC
**  values as ZMODEM and PKZIP
**
**  v1.00: original release.
**  v1.01: fixed printf formats.
**  v1.02: fixed something else.
**  v1.03: replaced CRC constant table by generator function.
*/

#include <stdio.h>

int main();
unsigned long getcrc();
void crcgen();

unsigned long crcTable[256];

/****************************************************************************/
int main( argc, argv )
	int argc;
	char *argv[];
{
	int	i;
	FILE   *fp;
	unsigned long crc;

	crcgen();
	if (argc < 2) {
		crc = getcrc( stdin );
		printf("crc32 = %08lx for <stdin>\n", crc);
	} else {
		for (i=1; i<argc; i++) {
			if ( (fp=fopen(argv[i],"rb")) == NULL ) {
				printf("error opening file \"%s\"!\n",argv[i]);
			} else {
				crc = getcrc( fp );
				printf("crc32 = %08lx for \"%s\"\n",
					crc, argv[i]);
				fclose( fp );
			}
		}
	}
	return( 0 );
}

/****************************************************************************/
unsigned long getcrc( fp )
	FILE *fp;
{
	register unsigned long crc;
	int c;

	crc = 0xFFFFFFFF;
	while( (c=getc(fp)) != EOF ) {
		crc = ((crc>>8) & 0x00FFFFFF) ^ crcTable[ (crc^c) & 0xFF ];
	}
	return( crc^0xFFFFFFFF );
}

/****************************************************************************/
void crcgen( )
{
	unsigned long	crc, poly;
	int	i, j;

	poly = 0xEDB88320L;
	for (i=0; i<256; i++) {
		crc = i;
		for (j=8; j>0; j--) {
			if (crc&1) {
				crc = (crc >> 1) ^ poly;
			} else {
				crc >>= 1;
			}
		}
		crcTable[i] = crc;
	}
}
<-->

    Con el podreis calcular el CRC de un fichero, y si sois avispados,
vuestro propio programa que obtenga claves de archivos ARJ. (Si, se que se
llaman crackeadores, pero no me gusta ese nombre)


PUES YO USO ZIP
=-=-=-=-=-=-=-=

    Pues vale, pues me alegro. Puer mira que bien. Si te crees que por eso
tienes mas seguridad... me temo que estas equivocado. Como regalito, aqui
va un esquema rapido de como encripta el PKZIP (version 2.04g).

    Primeramente, usa tres claves, inicializadas a los siguientes valores:

                - K0 = 0x12345678
                - K1 = 0x23456789
                - K2 = 0x34567890

    Andaaaa! Que integilentes, esto gintelitentes, es decir, ingelitentes.
No, no era asi. Era... inteligenetes... uhmm... Ah! Inteligentes

    Pero su inteligencia no queda ahi.

    El proceso de cifrado supera al del ARJ. Eso tenemos que reconocerselo.
Claro. PKWare es una empresa mas o menos potente. Y como es logico, han
usado un poco mas sus neuronas. Pero solo un poco, que luego les duele la
cabeza ;)

    Veamos el procedimiento, tal y como si fuera codigo fuente en C:

            Ci = Pi ^ K3
            K0 = crc32 (K0, Pi)
            K1 = K1 + (K0 & 0x000000FF)
            K1 = K1 * 0x8088405 + 1
            K2 = crc32 (K2, K1 >> 24)
            K3 = ((K2 | 2) * ((K2 | 2) ^ 1)) >> 8

    Aqui, Ci es el byte cifrado, y Pi el correspondiente byte antes de cifrar.
El proceso cuando se mete una clave es pasar la clave por el algoritmo de
cifrado como si de algo a encriptar se tratara. De esta forma se actualizan
K0, K1, K2 y K3. Evidentemente, el resultado de este cifrado se descarta.

    Ademas, se le a€aden 12 bytes aleatorios a la cabecera de cada fichero.
Pero esto no da mayor seguridad, verdad?

    Asi pues, solo tenemos que presuponer de 40 a 200 bytes del archivo
original, lo que segun los expertos es una complejidad de 2^27.

    Para desencriptar, pues se pasa el archivo de nuevo por el cifrador, y
como con el ARJ, se comprueba el CRC. Si coincide, la clave es correcta.

    Creo que se ve que es bastante facil romper la criptografia tanto del
ARJ como del PKZIP. Alguien afronta el reto?


DESPEDIDA
=-=-=-=-=

    Pues nada, que eso ha sido todo. Que ya se ve como de la propia
documentacion de un programa, con algo de ganas, mas paciencia todavia, y
tiempo, podemos descubrir cualquier cosa. Y por muy basica que parezca, lo
unico que teneis que pensar es que lo habeis hecho con vuestros propios
medios.

    Asi, cuando alguien vaya de cool porque sabe manejar un nuke (un boink,
etc.) vosotros podreis decir que sabeis como funciona, e incluso podreis
llegar a realizar vuestras propias modificaciones y mejoras.

    Bueno, nada mas por el momento. Y como diria el autor del programa que
os he ofrecido (el del CRC):


Keep on hackin'
Falken <falken@latinmail.com>