compression reverse-engineering decompression unpack firmware
http://www.behringerdownload.de/X32/X32_Firmware_2.10.zip

compression - Analizando archivo empaquetado de formato desconocido, ¿cómo continuar?



reverse-engineering decompression (1)

Estoy interesado en profundizar en el firmware de mi mesa de mezclas Behringer X32, así que descargué el archivo real de ( http://www.behringerdownload.de/X32/X32_Firmware_2.10.zip ) e inicié IDA pro. El archivo .update contenido contenido en el interior comienza con algún tipo de marca de tiempo y la siguiente cadena de caracteres se parece bastante a una lista de directorios, asumo que esos son los archivos que de alguna manera se concatenaron en el archivo de actualización del firmware. Por ejemplo, hay la cadena

seg000:00005480: logo/X32RACK.bmp

pero como no hay una estructura similar a un mapa de bits, asumo que se trata de datos comprimidos. ¿Cómo puedo continuar desde aquí? ¿Hay una manera de interpretar diversos formatos de archivo empaquetados y / o concatenados adivinando y tratando / error del formato?

O, mejor aún, ¿alguien conoce a un empaquetador que usa este tipo de estructura que se encuentra aquí?

64 bytes c-string 24 bytes zero, probably reserved DWORD with some index, increasing thru the file but not always +1 DWORD of files Size 32 bytes additional data

Lo que he descubierto hasta ahora:

00000000 db ''"2.10 23db64e4672e (Thu, 20 Nov 2014 14:50:29 +0100) (clean)"'',0,0,0; UpdateID 00000000 dd 6 dup(0) ; reserved 00000000 dd 181 ; NumberOfContainedFiles 00000000 dd 12380 ; SomeUnknownValue 00000000 dd 44B026A4h, 0BA3708DBh, 4DD38F6Eh, 0F7C30159h, 31D6B225h; Data 00000000 dd 0DAA98CD6h, 26BF22F1h, 0BD9644B1h; Data 00000080 db ''binary/cheditC_C.bin'', 45 dup(0); fileName 00000080 dd 6 dup(0) ; reserved 00000080 dd 46 ; someValue 00000080 dd 4704 ; fileSize 00000080 dd 0DF3241E4h, 89FA54F6h, 12151762h; Data 00000080 dd 5D8FCCCAh, 19A58A36h, 0C47912D5h; Data 00000080 dd 0A629BC65h, 0C8706863h; Data 00000100 db ''binary/cheditP_P.bin'', 45 dup(0); fileName 00000100 dd 6 dup(0) ; reserved 00000100 dd 56 ; someValue 00000100 dd 4896 ; fileSize 00000100 dd 7567F90Fh, 94027A93h, 131CEDFCh; Data 00000100 dd 6D712A26h, 8CD5722Bh, 35D860h; Data 00000100 dd 3BF0E937h, 8BDAFFE2h; Data 00000180 db ''binary/cheditR_R.bin'', 45 dup(0); fileName 00000180 dd 6 dup(0) ; reserved 00000180 dd 66 ; someValue 00000180 dd 5024 ; fileSize 00000180 dd 97B9D746h, 6FF72013h, 6FC5761Bh; Data 00000180 dd 333181A9h, 0EF312D82h, 0CD39570Bh; Data 00000180 dd 0DE1D71F7h, 4B6047DAh; Data

(... datos similares ...)

00005A80 db ''styles/ablesque.rsrc.z'', 42 dup(0); fileName 00005A80 dd 6 dup(0) ; reserved 00005A80 dd 7111 ; someValue 00005A80 dd 2697635 ; fileSize 00005A80 dd 2B368721h, 929F40Eh, 0DE923A1Bh; Data 00005A80 dd 152F06D2h, 86D758BBh, 0B73DC55h; Data 00005A80 dd 0F418E36Ah, 0D03D2C4Ah; Data

Luego sigue los datos comprimidos.

Este pequeño programa ayuda a analizarlo:

struct descriptor { char zName[64]; // filename or update name UINT32 reserved[6]; // unused UINT32 lIndex; // kind of index? // size of file, in update: // datastart + chunksize / chunk_block_size // = file_size in blocks á 512 bytes UINT32 lFileSize; // unknown but shared between some files // it seems to be infact a 128-bit structure, as // those data records sharing the first sig have the // 2nd sig also equal. UINT64 signature[2]; // unknown but probably also a "UINT128" // for some records, sig and data are completely the same UINT64 data[2]; }; int _tmain(int argc, _TCHAR* argv[]) { descriptor dsc; if (argc < 2) { printf("ERROR: missing filename."); return 0; } std::ifstream fin; fin.open(argv[1], std::ios::binary); if (fin.fail()) { printf("ERROR: cannot open file/n%S", argv[1]); return 0; } fin.read((char*)&dsc, 128); printf("firmware update version/n%s/n", dsc.zName); int iFiles = dsc.lIndex; long lSize = 0; printf("containing %d files./n/n", iFiles); printf("index/t size/tname/t/n"); printf("------------------------------------------------/n"); while (iFiles-->0) { fin.read((char*)&dsc, 128); if (fin.fail()) { printf("ERROR: read-error/n"); return 0; } printf("%5d/t%8d/t%s/n", dsc.lIndex, dsc.lFileSize, dsc.zName); lSize += dsc.lFileSize; } fin.close(); printf("------------------------------------------------/n"); printf("%8d bytes in total.", lSize); return 0; }


Encontré alguna forma de continuar, aunque no lograra descifrar los datos, ahora estoy menos seguro de que tiene que estar cifrado / comprimido, porque tiene una entropía muy alta.

Escribí una herramienta que crea cuatro mapas de bits a partir de los archivos de bloques de datos. Analicé el archivo en palabras y en bytes, contando todas las apariciones de ciertos bytes / palabras y obtuve esos dos histogramas, el más pequeño es Σ (b) = h (x + y * 16) y el más grande es Σ (w) = h (x + y * 256). Esas son las firmas histográficas:

El byte más frecuente es 0x62 (Σ = 25136), el menor es 0x33 (Σ = 24176), la palabra que aparece más es 0x80b7 (Σ = 81) y el menor es 0x77a5 (Σ = 22).

Los otros dos archivos son la histografía de los datos, que son demasiado grandes para publicarlos aquí, pero no tienen ninguna estructura visible en ellos.