Eternal magic/永恒魔法 .kfs

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
Drawing
Posts: 112
Joined: Fri Aug 05, 2016 6:17 pm

Eternal magic/永恒魔法 .kfs

Post by Drawing »

Hi guys.
Found this game with nice models and I would like to unpack the content that is stored in .kfs archive

Image

site: https://yh.duoyi.com/

Sample: https://www.mediafire.com/file/pmhu3apann6su89/Model.kfs/file
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: Eternal magic/永恒魔法 .kfs

Post by Ekey »

Seems data is xor'ed. Upload main executable with all modules.
Drawing
Posts: 112
Joined: Fri Aug 05, 2016 6:17 pm

Re: Eternal magic/永恒魔法 .kfs

Post by Drawing »

Drawing
Posts: 112
Joined: Fri Aug 05, 2016 6:17 pm

Re: Eternal magic/永恒魔法 .kfs

Post by Drawing »

any news ?
If you need other files just ask
atom0s
Posts: 250
Joined: Sat Dec 27, 2014 8:49 pm

Re: Eternal magic/永恒魔法 .kfs

Post by atom0s »

em_start.exe has some KFS file reading/referencing in it.

Key: Z.j^eihLui4e923@91WkBN19f_3x?Ubq
Key Size: 32

Decryption method is done via:

Code: Select all

sub_417880((int)off_4224B0, dword_4224B8, (int)v8, v9, 0);

Code: Select all

int __cdecl sub_417880(int a1, int a2, int a3, int a4, int a5)
{
  int v5; // edx
  int i; // eax

  v5 = a5 % a2;
  for ( i = 0; i < a4; ++i )
  {
    *(_BYTE *)(i + a3) -= *(_BYTE *)(v5++ + a1);
    if ( v5 >= a2 )
      v5 = 0;
  }
  return 0;
}


off_4224B0 points to the encryption key.
dword_4224B8 points to the encryption key size. (32)
v8 is a pointer to a buffer of the data to decrypt.
v9 is the size of the buffer.

Should be all the info needed to decrypt it.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: Eternal magic/永恒魔法 .kfs

Post by Ekey »

Ok, decryption is simple :)

Code: Select all

unsigned char lpKey[32] = {
    0x5A, 0x2E, 0x6A, 0x5E, 0x65, 0x69, 0x68, 0x4C, 0x75, 0x69, 0x34, 0x65, 0x39, 0x32, 0x33, 0x40,
    0x39, 0x31, 0x57, 0x6B, 0x42, 0x4E, 0x31, 0x39, 0x66, 0x5F, 0x33, 0x78, 0x3F, 0x55, 0x62, 0x71};
 
void iDecrypt(unsigned char* lpBuffer, int dwSize)
{
   for (int i = 0; i < dwSize; ++i)
   {
      lpBuffer[i] -= lpKey[i % 32];
   }
}


The header and entry table is at the end of the file.

Code: Select all

fseek(fi, -16, SEEK_END);


Code: Select all

struct KFSHeader
{
   uint32_t   dwID; //0xFF0D2C3A
   uint32_t   dwTotalFiles;
   uint32_t   dwTableSize;
   uint32_t   dwTableOffset;
};

struct KFSEntry
{
   uint16_t   wFileNameLength; //shl 1 or *2 = as you wish :)
   uint8_t    bUnknown1; //0
   uint32_t   dwUnknown1; //1
   uint32_t   dwSize;
   uint32_t   dwZSize;
   uint32_t   dwOffset; //???? -> IMUL ECX,DWORD PTR DS:[EAX],0x9E3779B1 , AND ECX,0x7FFFFFFF
};


Currently not clear with dwOffset field.
Drawing
Posts: 112
Joined: Fri Aug 05, 2016 6:17 pm

Re: Eternal magic/永恒魔法 .kfs

Post by Drawing »

waiting for aluigi's help :D
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: Eternal magic/永恒魔法 .kfs

Post by aluigi »

I made the script but I don't understand if the files are xored with some specific byte or not:
http://aluigi.org/bms/eternal_magic_kfs.bms