Descomprimir archivos de configuración lzw

Descomprimir lzw

Algunos routers usan archivos de configuración comprimidos por lzw.

No existe demasiada información en la web para poder descomprimirlos, pero algo hay, en particular:

https://www.ip-phone-forum.de/threads/o2-homebox-6641-daten-auslesen.273298/page-4

Se usa la librería lzw en python, y con unos sencillos pasos se descomprime.

El comienzo de este tipo de archivos es del tipo:

<compresed alg=lzw len=xxxxx> ... <crc=0xXXXXXX>

En la siguiente imagen puede verse:

Hay que recortar todo el comienzo del archivo hasta el byte que comienza con 80 (cualquier editor hex nos valdrá)

Se guarda el archivo y se descomprime con python (instalamos primero el módulo lzw)

y ejecutamos el código para descomprimir, sencillo, indicamos un archivo de salida. El error hay que obviarlo, todo se genera bien.

Y el archivo descomprimido:

Volver a comprimir lzw

Ahora lo ideal sería cambiar cualquier parámetro del archivo descomprimido, recomprimirlo y subirlo al router, sin embargo he encontrado alguna dificultad (no lo he conseguido). Tenemos que calcular el crc y la longitud del archivo. La longitud del archivo indicada en ‘len=’ es justo la del archivo recortado, pero el crc es calculado de alguna manera que desconozco por ahora.

Comprobación de que el valor «len» del archivo original del router, coincide con el calculado por el comando «cksum» con el archivo original del router al quitarle los bytes iniciales hasta el byte «80», el CRC no coincide

 

Para volver a comprimir hay que hacer algo parecido a la descompresión [morebytes=lzw.compres(mybytes) ]

Nos crea un archivo, donde puede inferirse unos bytes de cabecera comunes (comprimiendo distintos archivos se repiten) antes del byte «80». Recortando y añadiendo los bytes «<compressed….  >» podría valer, pero el crc hay que calcularlo como lo hace el router (ver en el siguiente apartado).

Sin embargo, este algoritmo de compresión produce un resultado distinto al original del router (en binario), es decir, la misma configuración (xml) es resultado de dos compresiones distintas, la del router y la de la librería lzw de python.

Profundizando en buscar el por qué, imprimiendo los «codepoint» del algoritmo lzw, vemos que la diferencia es producida por un orden distinto en un único codepoint del diccionario creado (más o menos, al descomprimir se va creando un diccionario con unos codepoints y unos clearbytes, los diccionarios son los mismos en ambos casos)

Archivo original del router (recortando la cabecera), vemos los codepoints al usar el lzw.decompress, donde el primero es el byte 256 (parámetro tamaño del algoritmo lzw)

Sin, embargo, al usar como fuente de lzw.decompress el mismo archivo xml, pero comprimido con python lzw.compress , vemos que los codepoints coinciden uno a uno, con la excepción que el 256 está ahora el último.

Por eso los binarios son distintos.

Buscando en internet sobre firmware de routers zyxel, uno puede encontrar alguno, donde existe una carpeta con utilidades (hostTools), y entre ellas una utilidad (32 bits) compressConfig, que resulta que genera exactamente el mismo archivo de configuración (binario) que el router (eso sí, desde el byte 80).

Adjunto la utilidad en zip: CompressConfig

Por tanto ya tenemos todo.

Calcular el CRC

Más investigaciones y búsquedas por internet, permiten saber cuál es el algoritmo usado para calcular el CRC del archivo binario con la configuración (ojo, desde el byte 80 )

En https://nada-labs.net/2018/crc-algorithm-finder/ tenemos una pequeña utilidad en python que usa la librería crcmod  ( https://pypi.org/project/crcmod/ ), y hace un recorrido por todos los algoritmos que tiene disponibles para poder mostrar el algortimo crc usado:

Nota: pip install me falló, por lo que tuve que compilar los fuentes para poder usar crcmod:

Usando este script con el archivo de configuración sin la cabecera, obtenemos por fin el algoritmo crc usado, que es jamcrc.

The «JAMCRC» is simply the bitwise-not of the standard CRC-32. A quick search turned up this, and I am sure you can find many implementations of CRC-32. Then you just take the not (~) of the result to get the JAMCRC.

Por tanto, ya podemos componer nuestro archivo de configuración modificado.

Una pequeña modificación del script en python nos permite calcular el crc de nuestra configuración (siempre desde el byte 80)

#!/usr/bin/python2
# Finds a CRC algorithm based on data and known CRC
# Requires crcmod
import crcmod
def find_crc(data, expected_crc):
    crc = crcmod.predefined.mkCrcFun('jamcrc')
    return crc(data)
if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Find CRC algorithm')
    parser.add_argument('infile', help='File containing the data (in binary) to CRC. ')
    args = parser.parse_args()
    data = None
    with open(args.infile, 'rb') as f:
       data = f.read()
    #excrc = int(args.crc, 0)
    crc = find_crc(data, 1)
    if crc:
        print('crcmod predefined algorithm produced %X from the provided data' % crc)
    else:
        print('crcmod predefined algorithm not found')

Bastará copiar la cabecera inicial de nuestro archivo descargado desde el router, pegarla al inicio del nuestro archivo de configuración modificado y comprimido con lzw, y modificar los correspondientes valores de len (obtenido con el comando cksum) y de crc (obtenido con el algoritmo jamcrc)

 

Consideraciones y Notas adicionales

Por desgracia, los routers de los operadores tienen un firmware muy capado y limitado, y lo que uno puede pensar que se puede cambiar al modificar el archivo de configuración, resulta que los cambios no se trasladan al comportamiento del router, es decir, no vale para nada, por ejemplo, he tratado de activar telnet, pero no funciona…(otro sí, por supuesto)

 

También, es posible que el router admita el archivo en xml para subírselo como configuración, sin necesidad de comprimirlo ni calcular longitud ni crc.

 

Algunos routers muestran con páginas web ocultas la configuración directamente en el navegador (en xml)

Algunos enlaces con páginas ocultas del router (accesibles, una vez hecho el login usual)

https://adrenaline.uol.com.br/forum/threads/banda-larga-vivo-xdsl-vdsl-fibra-optica-hfc.594503/page-141

https://www.cristianoronan.com.br/alteracao-das-configuracoes-bloqueadas-pelo-firmware-da-vivo/

http://community.plus.net/aptgm87544/attachments/aptgm87544/TechHelp/64716/1/2704n-plusnet-hack-DIY.pdf

https://pastebin.com/YwweWuna

Pero, como ya he visto, si el router está muy capado, muchas de las cosas que cambiemos no van a tener efecto ninguno… (incluso el interface web del router casca y hay que reinicialo).

Por ejemplo, modificando los valores de Telnet (estaba en DENY_ALL) no se consigue nada, y al reiniciar el router vuelve a cargar el valor DENY_ALL

 

 

Leave a Reply

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.