Users browsing this thread: 3 Guest(s)
32 byte PGMMV key
#1
Hi there,

I'm developing a game ripping tool for Windows and Linux.

So far works smooth, but the latest Pixel Game Maker MV switched from 16 bytes key to 32 bytes key (unfortunately the link points to the FOSS repo, which lacks the source for the decryption part).

The key is stored in Resources/data/info.json by the key "key", and it is base64 encoded. Once decoded, it needs some bitshuffling to get the actual Twofish encryption key used with decrypting the assets. For the 16 bytes long key, that shuffling goes like this, see decrypt_key.

Now as far as I can tell, the 32 bytes long key just uses a different bitshuffling, but otherwise it also results in a 16 bytes long Twofish key (because it still ciphers in 16 bytes blocks and the iv is the same for sure). I might be wrong about this, because it is possible to use twofish with a 32 bytes long encryption key.

I already support the legacy XOR encryption and the Twofish encryption with 16 bytes long keys for PGMMV, it would be great if I could add support for the latest variant too.

I attach a ZIP with the decrypted PNG, a PNG encrypted with the 16 bytes key, and the same PNG encrypted with the 32 bytes key. If it helps, I can also attach the executables for disassembly. The key is in the filename, decode it using base64. The source code for the 16 bytes long variant can be found here (look for case 2), and the Twofish iv is 0xA0,0x47,0xE9,0x3D,0x23,0x0A,0x4C,0x62,0xA7,0x44,0xB1,0xA4,0xEE,0x85,0x7F,0xBA. Note that the encrypted files have a 4 bytes long header and they are padded to be multiple of 16 bytes.

If anybody has any info on these new 32 bytes long info.json keys, that would be much appreciated! So far no matter how much I searched, I come up empty handed.

(FYI the tool supports a lot of other game engines as well, with key autodetection of course, for example Godot, RPG Maker MZ, WolfRPG, Ren'Py, etc.)


Attached Files
.zip   pgmmv_files.zip (Size: 33.53 KB / Downloads: 32)
Reply
Thanked by:
#2
Ok, here's what I've found out so far. Unforutnately I'm not familiar with Windows ABI, nor with MSVC generated code, nor with IDA (I'm a UNIX guy) so I'm not sure and I'm flying pretty much blind here.

Data

I was looking for the IV bytes in the data segment, see data_A03FC8.png It says this data is used in two functions: sub_49B510 and sub_49B750.

Decrypting the key?

If I'm guessing right, sub_49B510 is the one that reads in the key from the json. In sub_49B510.png we can see that after the IV is loaded, it is passed to another function, sub_49CA40.

I believe sub_49CA40 is the function that does the key bitshuffling and XORing with the IV, because it has a considerable amount of ROR, SHR and XOR instructions, see sub_49CA40.png. This could also be the Twofish initialialization maybe?

It looks like it is XORing with the IV key, which makes me assuem this is the key decryption.

Decrypting assets?

Similarly I'm assuming that sub_49B750 does the asset decryption. This calls sub_49D850 after it loads the IV.

Again, sub_49D850 could be a Twofish initialization or maybe one round of Twofish decryption? Not sure. See sub_49D850.png.

The similarity between sub_49CA40 and sub_49D850 are uncanny which makes me wonder if I've found the Twofish routines instead and I'm completely off-track. However sub_49D850 does call sub_49CA40, meaning sub_49D850 can't be Twofish initialization for sure.

Any help from someone more familar with these would be very much appreciated!


Attached Files
.zip   debug.zip (Size: 767.83 KB / Downloads: 43)
Reply
Thanked by:
#3
I would really appreciate some help with this!

A pastebin link, a blogpost about it, a github gist, etc. anything that helps understanding how 32 bytes long enckey works. No matter if it's not in English or if it's Python script or a Java class, etc. any help would do!
Reply
Thanked by:
#4
Anyone help?
Reply
Thanked by:
#5
Problem solved.

GAME RIPPER can now automatically decrypt PGMMV games with:
- the legacy byte shuffling and XORing encryption (key is autodetected from PNG files)
- 16 bytes long encryption keys with Twofish and XORing (key read from info.json), and
- 32 bytes long encryption keys with Twofish and XORing (key read from info.json)

Since my first post, it also became capable to decrypt the latest Godot encryption if someone interested.
Reply
Thanked by:


Forum Jump: