Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Counter-Strike Online 2 (.VTF) Modified with LZMA

Featured Replies

  • Author
  • Localization

cra0, posted Fri Aug 08, 2014 5:11 am (34)


have yet to figure this out

Hey, I've been trying to figure this out but have had no luck at all I'm not sure if ekeys unpacker is at blame or something is going on weird but Counter-Strike Online 2's VTF textures just refuse to decompress. Well the VTF header all the mips do successfully decompress however the largest mip LZMA block fails

Here is what the files look like
Image

it uses LZMA in the format of
Code:
byte   LZMA[4]
uint32 size
uint32 zsize
byte   Lzmaprops[5]


So for example the first LZMA block decompresses to this and each MIP of the texture follows which is another LZMA block.
Image
Get to the last LZMA block and it just fails. I dump the buffer before the lzma bad data exception and the result is an image chopped up here is what i mean look.
The first 2 Mips are broken but the rest are fine
Image


The function which decompresses the lzma seems normal I don't understand whats going on why is it failing :(
Code:
vtf_lzma_header *__stdcall LzmaVtfDecode(vtf_lzma_header *lzmaHeader, unsigned __int8 *outputBuffer)
{
  vtf_lzma_header *lzmaHeader2; // ebx@1
  unsigned int uncompressedLength; // ebp@4
  unsigned int *probs; // esi@5
  signed int decodeResult; // edi@5
  vtf_lzma_header *result; // eax@6
  CLzmaDecoderState state; // [sp 10h] [bp-14h]@5

  lzmaHeader2 = lzmaHeader;
  if ( !lzmaHeader
    || !outputBuffer
    || lzmaHeader->lzmaMagic != 0x414D5A4C
    || (uncompressedLength = lzmaHeader->uncompressedLength) == 0 )
    goto LABEL_8;
  LzmaDecodeProperties(&state.Properties, lzmaHeader->decoderProperties);
  probs = (unsigned int *)(*(int (__thiscall **)(_DWORD, _DWORD))(**(_DWORD **)&byte_14F5E214[140] 4))(
                            *(_DWORD *)&byte_14F5E214[140],
                            4 * (768   state.Probs = probs;
  decodeResult = LzmaDecode(
                   &state,
                   lzmaHeader2->data,
                   lzmaHeader2->compressedLength,
                   (unsigned int *)&outputBuffer,
                   outputBuffer,
                   uncompressedLength,
                   (unsigned int *)&lzmaHeader);
  (*(void (__stdcall **)(_DWORD))(**(_DWORD **)&byte_14F5E214[140] 20))(probs);// freeFunc
  if ( decodeResult || (result = lzmaHeader, lzmaHeader != (vtf_lzma_header *)uncompressedLength) )
  {
    (*(void (**)(const char *, ...))&byte_14F5E214[24])("Decompress Fail. %d", decodeResult);
LABEL_8:
    result = 0;
  }
  return result;
}


Sample files (source engine shared files not only found in CSO2 but alienswarm/dota2/tf2 free2play game)
https://www.dropbox.com/sh/f8jmz3ppqefp ... wGUMF0LVJa

Here are more Samples (since CSO2 runs the Source Engine i found some files in CSS that are the same in CSO2)
https://dl.dropboxusercontent.com/u/107 ... samples.7z

PM me if you want the filesystem dll
  • Author
  • Localization

aluigi, posted Fri Aug 08, 2014 6:33 am (36)


The last LZMA chunk at offset 0xb66f of alyxmonitor_idle.vtf dumps correctly till the following offsets:
- compressed offset 0x6a9
- uncompressed offset 0x88d
I don't see strange code between 0x6a9 and 0x6b0.
  • Author
  • Localization

cra0, posted Fri Aug 08, 2014 8:11 am (41)


aluigi wrote:
The last LZMA chunk at offset 0xb66f of alyxmonitor_idle.vtf dumps correctly till the following offsets:
- compressed offset 0x6a9
- uncompressed offset 0x88d
I don't see strange code between 0x6a9 and 0x6b0.


Yeah it either the lzma chunk headers are wrong which might be likely because the ones in the CO2 header don't match the lzma header values
https://dl.dropboxusercontent.com/u/107 ... m_stdio.7z

here is the filesystem dll and IDA file I don't understand why this is happening. The map files from the game also seem to have lzma compressed blocks

Image
  • Author
  • Localization

cyanic, posted Wed Aug 13, 2014 2:00 am (130)


What's interesting is where the decompressed cuts off in your gif. Looks like they might cut off at the same byte position? Maybe after a while the decompressor is reset or something? Come to think of it, maybe it's like how in Evolution Engine the data is split into chunks then compressed. There probably aren't mixed compressed/non-compressed chunks, but maybe that's where that value in the CO2 header we never figured out comes in. I suggest finding a large enough texture that is mostly of uniform color, and one that is quite complex and compresses badly, and experimenting with dumping parts of the stream as uncompressed or resetting the LZMA decoder in the middle to test the theory.
Guest
This topic is now closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.