-
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);
// Shorten the string if there is a null-terminator.
int index = Array.IndexOf(vcodeBuffer, 0);
return Encoding.ASCII.GetString(vcodeBuffer, 0, (index != -1 ? index : vcodeBuffer.Length));
}