XianOL (.pak)

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
happyend
Posts: 157
Joined: Sun Aug 24, 2014 8:54 am

XianOL (.pak)

Post by happyend »

aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

http://aluigi.org/papers/bms/others/xianol.bms

It uses a work-around to extract the files because the index table in the archive is encrypted/obfuscated.
For 8.pak I added a work-around to extract an mp3 file, because the script works only with compressed files (they are splitted in chunks).

So you will probably have problems with other archives.
happyend
Posts: 157
Joined: Sun Aug 24, 2014 8:54 am

Re: XianOL (.pak)

Post by happyend »

very cool,but,unpack 7.pak get some error
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

It looks like you have reached the end of the archive, so don't worry.
Check the extracted files, their total size should be bigger than the input archive.
happyend
Posts: 157
Joined: Sun Aug 24, 2014 8:54 am

Re: XianOL (.pak)

Post by happyend »

Thanks :)
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Small info

Code: Select all

struct PAKHeader
{
   DWORD dwID; // esl\x1A
   SHORT sNulls;
   DWORD dwHeaderSize;
   DWORD dwArchiveSize;
   DWORD dwHashTableOffset;
   SHORT sVersion; // 3
   DWORD dwEntryTableOffset;
   DWORD dwEntryTableSize; // shl 4
   DWORD dwHashTableSize; // shl 4
};


It's 100% modified MoPAQ. Algo and more info in attach :)
Last edited by Ekey on Tue Sep 09, 2014 6:11 pm, edited 1 time in total.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

Do you know that your pseudo code is slightly different than the assembly code?

Code: Select all

   SHL EDI,0x15
   ADD EDI,0x7F98679
and

Code: Select all

<< 19) - 0x55E0129A
Anyway doesn't give a correct result.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Olly code is slightly different from the code IDA. from IDA

Code: Select all

      shl   edi, 13h
      sub   edi, 55E0129Ah
      shr   esi, 0Bh


Here my works code. One problem with decrypting entry table

Edited: See below
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Done! s***t algo :geek:
CriticalError
Posts: 204
Joined: Thu Aug 14, 2014 8:52 pm

Re: XianOL (.pak)

Post by CriticalError »

wow thanks for that Ekey and alugi, thats great

@happyend

so can you provide which format use this game for 3D Models?
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

The entry table is still invalid, do you think it's the password to be wrong?
I tried also using 21 and 0x7F98679 but still wrong.

I compiled it with both Gcc and VS and I noticed that the output changes and it's ever wrong.
Tried also to call pPAK_Init() and handling the entry before the hash but nothing, still wrong.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

aluigi wrote:The entry table is still invalid

Why?

aluigi wrote:Tried also to call pPAK_Init() and handling the entry before the hash but nothing, still wrong.

pPAK_Init() used for initializing tables and they are always the same so that the function is not used.

aluigi wrote:do you think it's the password to be wrong?

Password need only for generate dwSeed1 and i replaced this code to already generated dwSeed1 for each table.

aluigi wrote:I compiled it with both Gcc and VS and I noticed that the output changes and it's ever wrong.
Tried also to call pPAK_Init() and handling the entry before the hash but nothing, still wrong.


For me works perfect. All tables dumped without any problems. See attach.

First you need to read the table of hashes to get the index that contains the records of the file offset, compressed size, real size, and ect.
Skip first 0x30 bytes.

Code: Select all

struct HashTable
{
   DWORD dwHashA;
   DWORD dwHashB;
   DWORD dwNull;
   DWORD dwIndex; // dwIndex * 16 & 0xFFFFFFFF
};


Now reading entry

Code: Select all

goto dwIndex;


Code: Select all

struct EntryTable
{
   DWORD dwOffset;
   DWORD dwZSize;
   DWORD dwSize;
   DWORD dwFlag;
};


Flags

Code: Select all

FILE_IMPLODE = 0x00000100 (File is compressed using PKWARE)
FILE_COMPRESS = 0x00000200 (File is compressed using combination of compression methods)
FILE_ENCRYPTED = 0x00010000 (The file is encrypted)
FILE_EXISTS = 0x80000000 (File exists)


Example flag from 0.pak

Code: Select all

Flag: 0x80010100 -> FILE_IMPLODE + FILE_ENCRYPTED + FILE_EXISTS
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

Ok, great.
Apparently I got one of the first versions of your attachment (without exe) and so it didn't work.

I have updated the script, now everything seems to work perfectly:
http://aluigi.org/papers/bms/others/xianol.bms

The following is the dll as reference:
http://aluigi.org/papers/bms/others/xolpak.c

Well done Ekey
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Good job! :)
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Continued..... In MoPAQ count tables 5.

1) (attributes) - attributes for files inside pak (not used in this game)
2) (blocktable) - for us it is entry table
3) (hashtable) - table with hashes
4) (listfile) - table with filenames (encrypted and compressed by Zlib) dwIndex for this file = 0, and of course in the entry table = first record
5) (version) - :)

(listfile) for 0.pak

Code: Select all

Offset: 707801 (7370753.)
ZSize: 2E5 (741.)
Size: 7D9 (2009.)


Decryption algo (dwSeed = 0xC16D37E2)

Code: Select all

int pPAK_Decrypt_FileData(unsigned int dwSize, int dwSeed, int pBuffer)
{
  unsigned int pSize1;
  bool pSize2; // zf@1
  int Buffer; // esi@1
  int result; // eax@1
  int dwTemp1; // eax@2
  int dwTemp2; // ecx@2

  pSize1 = dwSize >> 2;
  pSize2 = dwSize >> 2 == 0;
  Buffer = pBuffer;
  result = 0xEEEEEEEEu;
  if ( !dwSize >> 2 == 0 )
  {
    do
    {
      dwTemp1 = *(DWORD *)&pTable_e[4 * (unsigned __int8)dwSeed] + result;
      dwTemp2 = *(DWORD *)Buffer ^ (dwTemp1 + dwSeed);
      *(DWORD *)Buffer = dwTemp2;
      dwSeed = ((~dwSeed << 19) - 0x211E86D4) | ((unsigned int)dwSeed >> 11);
      Buffer += 4;
      --pSize1;
      result = 33 * dwTemp1 + dwTemp2 + 3;
    }
    while ( pSize1 );
  }
  return result;
}
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

ok so the algorithm is just the same, what changes is the password and the 2 numbers used for "<< A + B".
Do you have the password used to generate that dwSeed 0xC16D37E2?
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

He has already has been generated.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

But don't you have the original password?
It would be useful for other games that use different passwords.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: XianOL (.pak)

Post by aluigi »

Tested now, it looks like that dwSeed doesn't work for 8.pak. The first file decrypts incorrectly.

Anyway I have updated the script.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: XianOL (.pak)

Post by Ekey »

Well i guess this dwSeed only for listfile. I have no idea how it generate :/