Skip to content

V_CODEs

Robert Jordan edited this page Mar 8, 2019 · 13 revisions

V_CODEs are two codes contained within the CatSystem2 executable resources that are used as keys for decryption and encryption.

Resources

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

Extracting

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.

Decrypting

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.

Example

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));
}
Clone this wiki locally