Skip to content

V_CODEs

Robert Jordan edited this page Mar 16, 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.

Code Sample

string DecryptVCode(byte[] vcode, byte[] keyCode) {
    // This assumes the keyCode buffer passed in will not be used after this.
    // If you want to reuse the keyCode buffer, either perform the XOR once
    // beforehand outside of the method, or perform the same XOR again at
    // the end of the method before returning.
    for (int i = 0; i < keyCode.Length; i++)
        keyCode[i] ^= 0xCD;

    // Key does not need to be a multiple of 8.
    Blowfish blowfish = new Blowfish(keyCode);

    // Decryption buffer needs to be rounded up to the next multiple of 8.
    // & ~7 is equivalent to `(int) / 8 * 8`.
    byte[] vcodeBuffer = new byte[(vcode.Length + 7) & ~7];
    Array.Copy(vcodeData, vcodeBuffer, vcode.Length);

    blowfish.Decrypt(vcodeBuffer);

    // Shorten the string if there is a null-character.
    int index = Array.IndexOf(vcodeBuffer, 0);
    int length = (index != -1 ? index : vcodeBuffer.Length);
    return Encoding.ASCII.GetString(vcodeBuffer, 0, length);
}
Clone this wiki locally