4

I have some technical documentation which is supplied in the form of a generic Windows viewer and a database. The database contains different "books", which are represented by a bunch files:

  • book.bbi - book index i.e. what pages are in the book
  • a bunch of .bli's - text entries on the page, that's a guess
  • a bunch of .ilg's - media on the page, that's a guess too

All these files have a plaintext header and what's remaining is the data which is compressed or encrypted in some way:

upd: the data_header is actually the uncompressed length of the data enter image description here

I tried running binwalk and XorSearch, but with no success. I guess now I have to debug it, but I am very, very unfamiliar with it. I am using x32dbg with the xAnalyzer plugin. I tried setting a breakpoint on ReadFile and tracing from there, but it produces an enormously large log. However I can see that it uses crush32.dll - "old C/Win32 compression library" and runs some ors/xors and byte shifts(shr) which kinda reinforces my thought about compression/encryption usage. enter image description here

So my question is how do I approach it from here? How do I at least dump all strings with the correspoding instructions i.e. get to the point where this byte-mess becomes readable strings? I am absolutely stuck. Thanks in advance!

  • Not a real answer, but have you take look into the executable for cryptographic functions? (outside crush32.dll). I'm not familiar with crush32.dll, but you can also set a breakpoint on its exported functions and dump the input / output for each call. – wisk Mar 4 '19 at 14:02
  • @wisk thanks! I remember crush32 had some functions like cxOpen, might be worth looking into it. And how do I determine that a particular function is cryptographic? Look for various shifts etc.? Also my executable doesn't contain function names, all are just sub.*** :( – intelligentpotato Mar 4 '19 at 14:25
  • Did you manage to reverse engineer the file format? I am looking for the same :) It would be nice to have more information about the file format. – loluengo Sep 17 at 23:40
  • @loluengo I gave up halfway. There's a C# library to decompress crush32, you can find it here: github.com/cyberjunk/meridian59-dotnet/blob/master/Meridian59/… I'll drop the code I used into an answer. After decompression in my case there was some other proprietary file format which I wasn't able to reverse, so I approached it another way. – intelligentpotato Sep 30 at 18:10
2

I grabbed some crush32.dll from the Internet and it has some very interesting exports:

  • cxBufDecrypt
  • cxCompressFile
  • cxExpandFile
  • cxBuf2BufCompress
  • cxBuf2BufExpand

I'd set a breakpoint on all of them, let your program run, wait for a bp to hit, inspect the stack arguments to find input/output buffers, let the function run and then look for readable data.

| improve this answer | |
  • Thank you! I've placed breakpoints on crush32 functions and found out that it runs cxInit when the program starts and then runs cxBuf2BufInit and cxBuf2BufExpand after reading the data chunk of a file. Tracing execution of the cxBuf2BufExpand results in 324000 instructions being logged. I've also googled these instructions and found out that this thing is "Crusher! Data Compression Toolkit" created in the early 90s. Quite a few code implementations of how to unpack it can be found, but so far I am only getting memory allocation error from crush32.dll when trying to unpack. – intelligentpotato Mar 6 '19 at 22:50
  • 1
    Aight, I've managed to unpack .bbi and .bli. Will submit a detailed post once I also unpack .ilg. – intelligentpotato Mar 7 '19 at 2:18
1

This is the code I used for decompression. It uses Crush32.cs from https://github.com/cyberjunk/meridian59-dotnet/blob/c45a65552333509220b11b41ecc46d75023b5acd/Meridian59/Files/BGF/BgfBitmap.cs and Kaitai Struct (https://kaitai.io/) to slice the files. It should work for book.bbi and probably for other formats as well, it's been a long time so I don't exactly remember all the difficulties I ran into while decompressing and tinkering with these files.

foreach (string dir in Directory.EnumerateDirectories(@"F:\database\komatsu")) {
    foreach (string file in Directory.EnumerateFiles(dir, "book.bbi")) {
        Console.WriteLine("Decompressing " + file);
        Bbi03 page = Bbi03.FromFile(file);
        
        byte[] decompressedData = new byte[(int)page.UncompressedLength1];
        bool status = Crush32.Decompress(page.Data, 0, decompressedData, 0, (int)page.UncompressedLength1, (int)page.CompressedLength);
        Console.WriteLine(status);
        File.WriteAllBytes(@"saa6d1jc\" + Path.GetFileNameWithoutExtension(file) + ".bin", decompressedData);
    }
}

And here are the .ksy files:

book_bbi.ksy

meta:
  id: book_bbi
  endian: le
  encoding: ASCII
  
seq:
  - id: file_header
    type: str
    size: 22
  - id: date
    type: str
    size: 16
  - id: magic
    # bbi 03-04.030: [0xff, 0x7f, 0xff, 0x7f]
    # bbi 04.100: [0x88, 0x03, 0xca, 0x03]
    size: 4
  - id: data_header_start
    contents: [0x02, 0x00]
  - id: compressed_length_with_header
    type: u4
  - id: uncompressed_length
    type: u4
  - id: uncompressed_length_2
    type: u2
  - id: compressed_length
    type: u2
  - id: data_header_end
    contents: [0x00, 0x00]
  - id: data
    size: compressed_length
  

bli_03.ksy

meta:
  id: bli_03
  endian: le
  encoding: ASCII
seq:
  - id: file_header
    type: str
    size: 22
  - id: date
    type: str
    size: 16
  - id: data_header_start
    contents: [0x02, 0x00]
  - id: compressed_length_with_header
    type: u4
  - id: uncompressed_length_1
    type: u4
  - id: uncompressed_length_2
    type: u2
  - id: compressed_length
    type: u2
  - id: data_header_end
    contents: [0x00, 0x00]
  - id: data
    size: compressed_length

ilg_00.ksy

meta:
  id: ilg_00
  endian: le
  encoding: ASCII
seq:
  - id: header
    type: str
    size: 22
    size: 16
  - id: smth1
    size: 4
  - id: width
    type: u2
  - id: height
    type: u2
  - id: bits_per_pixel
    type: u2
  - id: dpi
    type: u2
  - id: smth2
    size: 12
  - id: data_length
    type: u4
  - id: smth3
    size: 12
  - id: data
    size: data_length

ilg_03.ksy

meta:
  id: ilg_03
  endian: le
  encoding: ASCII
seq:
  - id: header
    type: str
    size: 22
  - id: date
    type: str
    size: 16
  - id: smth1
    size: 4
  - id: width
    type: u2
  - id: height
    type: u2
  - id: bits_per_pixel
    type: u2
  - id: dpi
    type: u2
  - id: smth2
    size: 12
  - id: data_length
    type: u4
  - id: smth3
    size: 12
  - id: data
    size: data_length
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.