-
Notifications
You must be signed in to change notification settings - Fork 9
V_CODEs
V_CODEs are two codes contained within the CatSystem2 executable resources that are used as keys for decryption and encryption.
| Type | Name | Language | Description |
|---|---|---|---|
| KEY_CODE | KEY | 0x0411 |
Key to decrypt V_CODEs |
| V_CODE | DATA | 0x0411 |
Unknown usage. Often present in config/startup.xml
|
| V_CODE2 | DATA | 0x0411 |
Used to decrypt KifintArchives |
V_CODEs can be extracted from the CatSystem2 executable using Windows API methods such as LoadLibraryEx, FindResource, LoadResource, LockResource, SizeofResource, and FreeLibrary. (These will not be linked to because Microsoft will change up their URLs and break these within a year's time)
Important Note: The executable used to launch the game may not be the CatSystem2 executable. Grisaia games often have a .bin file with the same name that is actually launched when running the executable. In this situation, the .bin file is the CatSystem2 executable with the V_CODE resource.
V_CODEs are decrypted using the KEY_CODE and a Blowfish cipher. First, take the KEY_CODE byte array, and XOR each byte by 0xCD. Then pass the modified KEY_CODE to the Blowfish cipher as the key. Because Blowfish requires buffers to be a multiple of 8 bytes, make sure your V_CODE byte array is a multiple of 8 bytes rounded up.
Important Note: Setting the key for a Blowfish cipher is much more expensive than the decryption process. It's highly recommend you keep a copy of your seeded Blowfish class handy so that you do not need to set the key every time.
string DecryptVCode(byte[] vcode, byte[] keyCode) {
for (int i = 0; i < keyCode.Length; i++)
keyCode[i] ^= 0xCD;
Blowfish blowfish = new Blowfish();
blowfish.SetKey(keyCode); // Key does not need to be a multiple of 8.
// Decryption buffer needs to be a multiple of 8.
byte[] vcodeBuffer = new byte[(vcode.Length + 7) / 8 * 8];
Array.Copy(vcodeData, vcodeBuffer, vcode.Length);
blowfish.Decrypt(vcodeBuffer);
int index = Array.IndexOf(vcodeBuffer, 0);
return Encoding.ASCII.GetString(vcodeBuffer, 0, (index != -1 ? index : vcodeBuffer.Length));
}