Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

analysing packed file of unknown format, how to continue?

Tags:

Im interested in taking a deeper look into the firmware of my Behringer X32 mixing console, so i downloaded the actual file from (http://www.behringerdownload.de/X32/X32_Firmware_2.10.zip) and started IDA pro. The contained .update-file inside starts with some kind of timestamp and the following stringtable pretty much looks line a directory listing, I assume those to be the files that got somehow concatenated into the firmware update file. For example, there is the string

seg000:00005480: logo/X32RACK.bmp

but as there is no bitmap-like structure, i assume this to be compressed data. How can I continue from here on? Is there a way to interpret diverse packed and/or concatenated file formats guessing and trying/erroring the format.

Or – even better – does someone know a packer that uses this kind of structure found here?

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

What i've found out so far:

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

(…similar data…)

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

Then follows the compressed data.

This little programm helps analysing it:

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;
}
like image 755
rhavin Avatar asked May 04 '15 10:05

rhavin


People also ask

How is binary file format calculated?

In order to identify a file type not only by its file name extension many file formats start with a unique byte sequence. The UNIX file command is able to detect the format of files mostly depending on magic numbers. Most binary file formats start with some structure called file header.


1 Answers

I found some way to continue, even if I didn't manage to decrypt the data, I'm now a least sure that it has to be encrypted/compressed, because it has a very high entropy.

I wrote a tool that creates four bitmaps from the files data-block. I analysed the file on word and on byte basis, counting all occurances of certain bytes/words and got those two histogrammes, the smaller is Σ(b) = h(x + y*16) and the larger is Σ(w) = h(x + y*256). Those are the histographic signatures:

Histographic signature in bytes

Histographic signature in word

The most occuring byte is 0x62 (Σ=25136), the least is 0x33 (Σ=24176), the most occuring word is 0x80b7 (Σ=81), the least is 0x77a5 (Σ=22).

The other two files are the histography of the data, which are far to big to post them here, but they dont have any noticable structure in it.

like image 56
rhavin Avatar answered Oct 29 '22 16:10

rhavin