{"record":{"id":"b9d0df28b7a6bdc2","repo":"peass-ng/PEASS-ng","slug":"invalid-encryption-version-prefix","errorCode":null,"errorMessage":"Invalid encryption version prefix.","messagePattern":"Invalid encryption version prefix\\.","errorType":"exception","errorClass":"System.ArgumentException","httpStatus":null,"severity":"error","filePath":"winPEAS/winPEASexe/winPEAS/Info/CloudInfo/GWorkspaceInfo.cs","lineNumber":263,"sourceCode":"                Beaprint.PrintException(\"Error extracting refresh tokens (If Chrome is running the DB is probably locked but you could dump Chrome's procs and search it there or go around this lock): \" + ex.Message);\n                return refreshTokens.ToArray();\n            }\n        }\n        public static string DecryptWithAESGCM(byte[] ciphertext, byte[] key)\n        {\n            // Constants\n            int nonceLength = 12; // GCM standard nonce length\n            int macLength = 16;   // GCM authentication mac length\n            string versionPrefix = \"v10\"; // Matching kEncryptionVersionPrefix\n\n            // Convert prefix to byte array\n            byte[] versionPrefixBytes = Encoding.ASCII.GetBytes(versionPrefix);\n\n            // Check the prefix\n            if (ciphertext.Length < versionPrefixBytes.Length ||\n                !IsPrefixMatch(ciphertext, versionPrefixBytes))\n            {\n                throw new ArgumentException(\"Invalid encryption version prefix.\");\n            }\n\n            // Extract the nonce from the ciphertext (after the prefix)\n            byte[] nonce = new byte[nonceLength];\n            Array.Copy(ciphertext, versionPrefixBytes.Length, nonce, 0, nonceLength);\n\n            // Extract the actual encrypted data (after the prefix and nonce)\n            int encryptedDataStartIndex = versionPrefixBytes.Length + nonceLength;\n            byte[] encryptedData = new byte[ciphertext.Length - encryptedDataStartIndex];\n            Array.Copy(ciphertext, encryptedDataStartIndex, encryptedData, 0, encryptedData.Length);\n\n            // Split the mac and actual ciphertext\n            byte[] mac = new byte[macLength];\n            Array.Copy(encryptedData, encryptedData.Length - macLength, mac, 0, macLength);\n\n            byte[] actualCiphertext = new byte[encryptedData.Length - macLength];\n            Array.Copy(encryptedData, 0, actualCiphertext, 0, actualCiphertext.Length);\n","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/peass-ng/PEASS-ng/blob/53fb989abc2219826385683a6fee826bd6cd38d6/winPEAS/winPEASexe/winPEAS/Info/CloudInfo/GWorkspaceInfo.cs#L245-L281","documentation":"DecryptWithAESGCM expects Google Chrome app-bound encrypted tokens to start with a known ASCII version prefix (e.g. 'v10'/'v20'). If the ciphertext is shorter than the prefix or does not begin with it, decryption cannot proceed and ArgumentException is thrown. This prevents attempting AES-GCM decryption on data in an unexpected format.","triggerScenarios":"Calling decryptedToken with ciphertext whose first bytes are not the expected version prefix: the value was read from the wrong registry value/file, the prefix constant was changed, or the byte array was sliced incorrectly (e.g. off-by-one or including a BOM).","commonSituations":"Chrome changed its app-bound encryption format in newer versions; copying the wrong registry blob (DPAPI-encrypted instead of app-bound); reading the value with wrong offsets so the prefix is missing; handling Firefox or non-Chromium data with this routine.","solutions":["Inspect the first bytes of the ciphertext (hex dump) and confirm they match the expected versionPrefix","Re-read the correct source: the app-bound encrypted key from the right registry key/value for the installed browser version","Update the versionPrefix constant to match the browser version's actual format (e.g. v20 for newer Chrome app-bound encryption)","Add a length/format check and log a descriptive error distinguishing 'no prefix' from 'corrupt data'"],"exampleFix":"// before\nbyte[] plain = DecryptWithAESGCM(blob, key, \"v10\");\n// after\nif (blob == null || blob.Length < 3 || Encoding.ASCII.GetString(blob, 0, 3) != \"v20\")\n    throw new InvalidOperationException(\"Token blob does not carry v20 app-bound prefix; check browser version/source.\");\nbyte[] plain = DecryptWithAESGCM(blob, key, \"v20\");","handlingStrategy":"validation","validationCode":"static bool HasVersionPrefix(byte[] ct, string prefix)\n{\n    var p = Encoding.ASCII.GetBytes(prefix);\n    return ct != null && ct.Length >= p.Length &&\n           ct.AsSpan(0, p.Length).SequenceEqual(p);\n}","typeGuard":null,"tryCatchPattern":"try { return DecryptWithAESGCM(ct, key, prefix); }\ncatch (ArgumentException) { log.Error(\"Token blob missing expected version prefix; wrong source or browser format changed.\"); return null; }","preventionTips":["Hex-dump the first bytes of ciphertext and match against the prefix constant before decrypting","Keep versionPrefix in sync with the browser version's app-bound encryption format","Always preserve tokens as raw byte[]; never round-trip through string encodings that alter leading bytes","Read from the documented registry/file source for the specific Chromium flavor and version"],"tags":["csharp","cryptography","aes-gcm","format-mismatch"],"backgroundTag":"ciphertext-prefix-mismatch","analyzedSha":"53fb989abc2219826385683a6fee826bd6cd38d6","analyzedAt":"2026-09-02T04:25:09.259Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}