Table and files compressed by blocks with custom algo. Each block = max decompressed size is 0x8000
Code:
struct PKGHeader
{
DWORD dwTableOffset;
};
goto dwTableOffset
struct PKGTableHeader
{
DWORD dwTableSize;
DWORD dwTableBlockCount;
};
struct PKGTableBlockEntry
{
DWORD dwBlockPosition;
WORD dwBlockTableZSize;
WORD dwBlockTableSize;
};
File data compressed too and have custom header
struct PKGFileDataHeader
{
DWORD dwBlockCount;
};
struct PKGFileDataEntry
{
DWORD dwBlockOffset;
WORD dwBlockZSize; //can be 0 , don't know how avoid it
WORD dwBlockSize;
};
// for Table
struct PKGDataEntry
{
DWORD dwNameLength;
String pFileName; // Unicode
DWORD dwOffset;
DWORD dwSize;
};
Decompress algo:
Code:
int __cdecl System__Compression__Decompress(unsigned int pScrBuffer, int pScrSize, unsigned int pDstBuffer, int pDstSize)
{
unsigned int v4; // eax@1
unsigned int v5; // ebx@1
unsigned int v6; // edi@1
unsigned int v7; // edx@2
int v8; // edx@3
int v9; // edx@6
int v10; // esi@6
unsigned int v11; // esi@6
int v12; // ecx@8
int v13; // ecx@10
int v15; // [sp+14h] [bp+8h]@1
unsigned int v16; // [sp+1Ch] [bp+10h]@1
v5 = pDstBuffer;
v6 = pScrBuffer;
v16 = pScrBuffer + pScrSize;
v4 = v5;
v15 = v5 + pDstSize;
while ( 1 )
{
v7 = *(BYTE *)v6++;
if ( v7 >= 0x20 )
break;
v8 = v7 + 1;
if ( v8 + v4 > v15 )
return 0;
do
{
*(BYTE *)v4++ = *(BYTE *)v6++;
--v8;
}
while ( v8 );
LABEL_12:
if ( v6 >= v16 )
return v4 - v5;
}
v11 = v7;
v9 = (v7 & 0x1F) << 8;
v10 = v11 >> 5;
if ( v10 == 7 )
v10 = *(BYTE *)v6++ + 7;
v12 = v4 - v9 - 1 - *(BYTE *)v6++;
if ( v10 + v4 + 2 <= v15 && v12 >= v5 )
{
*(BYTE *)v4 = *(BYTE *)v12;
*(BYTE *)(v4 + 1) = *(BYTE *)(v12 + 1);
v4 += 2;
v13 = v12 + 2;
do
{
*(BYTE *)v4++ = *(BYTE *)v13++;
--v10;
}
while ( v10 );
goto LABEL_12;
}
return 0;
}
I make unpacker but i don't know how avoid this: Entry number > 54 > file have entry where PKGFileDataEntry.dwBlockZSize equal 0 for all blocks.