RUSTY HEARTS GAME PROTECTION:
The game protection on this game is weak:
- MPatcher.exe contains the keys to decrypt f00X.dat, and this program doesn't have any PE packing. Just hook up a debugger and watch it unpack the MIP files that it receives while patching to figure out how to do f00X.dat.
- The CRC table is also available from MPatcher.exe.
- XTrap can be seen from the Task Manager and Process Explorer.
- IDA Pro can continue to run while XTrap is running
- No PE Protection on RustyHearts.exe
- Very non-random AES key.
- The AESIV used for decryption is located right next to the Rijndael SBox in the executable which makes it very easy to find.
I would strongly encourage the development team at Perfect World Entertainment to beef up their security.
RUSTY HEARTS UNPACKING:
All of the files which I refer to are available in the ZIP file in this post.
The file directory is stored in f00X.dat. The encryption on f00x.dat is an extremely simple static stream cipher. The stream cipher is attached in the file called "RustyHearts.keys".
There is a crc32 also implemented to check file integrity. Although I have not included the calculation in the python scripts attached, I have included the CRC Table in "RustyHearts.crc".
Once you've decrypted f00X.dat by XORing it with the RustyHearts.keys, decompress it with zlib. Then you can fetch the directoryTree:
Code:
directoryTreeFile
{
fileName (UTF-16 string)
packFileNumber (byte)
fileLength (int32)
fileChecksum (int32)
fileOffset (int32)
nulls (int32)
}
Now that you have the directory tree, simply open up the PCK file represented by directoryTreeFile.packFileNumber, seek to the directoryTreeFile.fileOffset, and then read directoryTreeFile.fileLength bytes and write out to the file given by directoryTreeFile.fileName.
WARNING: There are some fileNames which are in asian languages. This may not play nicely with English on Windows 7. It didn't for me!
After you get the files unpacked, then you'll want to unpack the Rusty Hearts tables (located in "/table/" with suffix ".rh"). These are encrypted with AES-256.
AESKey = gkw3iurpamv;kj20984;asdkfjat1af\0
AESIV = 0xDB0F4940
AESMode = ECB
For the AESKey, that's 31 characters followed by a null terminator. The null terminator is required for the AES cipher to function. Decrypt the ".rh" files.
The tables are fairly simple:
Code:
rhFile
{
numRows (int32)
numColumns (int32)
columnNames (array of strings)
columnTypes (array of int32)
rowData
}
Code:
ENUM columnTypes
{
int32 = 0
float32 = 1
string = 3
int64 = 4
}
I haven't found anywhere that uses a columnType of 2.
From this point in the file, it's just a matter of reading all of the row data which should be extremely straightforward.
For the unpacker, you will need the following:
Python 2.6 (
You must be registered to see links
)
NumPy (
You must be registered to see links
)
PyCrypto (
You must be registered to see links
)
There is a hash that's used in Service.dat. That would be SHA-1. I don't know what it's hashing at the moment.