Reputation: 1
import os
import json
import base64
import win32crypt
from Crypto.Cipher import AES
path = r'%LocalAppData%\Google\Chrome\User Data\Local State'
path = os.path.expandvars(path)
with open(path, 'r') as file:
encrypted_key = json.loads(file.read())['os_crypt']['encrypted_key']
encrypted_key = base64.b64decode(encrypted_key) # Base64 decoding
encrypted_key = encrypted_key[5:] # Remove DPAPI
decrypted_key = win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1] # Decrypt key
data = bytes.fromhex('763130...') # the encrypted cookie
nonce = data[3:3+12]
ciphertext = data[3+12:-16]
tag = data[-16:]
cipher = AES.new(decrypted_key, AES.MODE_GCM, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag) # the decrypted cookie
This code works so great , But I need this code with powershell , I have trouble with decoding
Add-Type -Assembly System.Security
$ExtensionFile = "$($env:LOCALAPPDATA)\Google\Chrome\User Data\Local State"
$jsondata = Get-Content -Raw -Path $ExtensionFile | ConvertFrom-Json
$enckey = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($jsondata.os_crypt.encrypted_key)).Substring(5)
$deckey = [Security.Cryptography.ProtectedData]::Unprotect($enckey, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
What is the problem ?
Upvotes: 0
Views: 2014
Reputation: 93
I have done this recently. Firstly you should decrypt the key using DPAPI and then decrypt the cookie using AES-GCM.
Thanks for the python solution - I have used it as a reference. That's my PowerShell solution
Add-Type -Assembly System.Security
$ExtensionFile = "$($env:LOCALAPPDATA)\Google\Chrome SxS\User Data\Local State"
$protectedDataPath = "$($env:HOMEPATH)\Downloads\enc.cookie.bin"
$jsondata = Get-Content -Raw -Path $ExtensionFile | ConvertFrom-Json
$encKey = [System.Convert]::FromBase64String($jsondata.os_crypt.encrypted_key.ToString());
$encKey= $encKey[5..$encKey.Length];
$decryptedKey = [Security.Cryptography.ProtectedData]::Unprotect($enckey,$null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
$encodedCookieData=[System.IO.File]::ReadAllBytes($protectedDataPath)
[byte[]]$nonce = $encodedCookieData[3..14]
[byte[]]$ciphertext = $encodedCookieData[15..($encodedCookieData.Length-1-16)]
[byte[]]$tag = $encodedCookieData[($encodedCookieData.Length-16)..($encodedCookieData.Length-1)]
Write-Host "nonce: [$(($nonce|ForEach-Object ToString X2) -join '')]"
Write-Host "tag: [$(($tag|ForEach-Object ToString X2) -join '')]"
Write-Host "decryptedKey: [$(($decryptedKey|ForEach-Object ToString X2) -join '')]"
Write-Host "ciphertext: [$(($ciphertext|ForEach-Object ToString X2) -join '')]"
[byte[]]$plainText=new-object byte[] $ciphertext.Length
[System.Security.Cryptography.AesGcm] $oAESGcm = new-object System.Security.Cryptography.AesGcm (,$decryptedKey)
$oAESGcm.Decrypt($nonce, $ciphertext, $tag, $plainText, $null)
Write-Host "plainText: [$([System.Text.Encoding]::ASCII.GetString($plainText))]"
Tested on a Chrome Canary v98 / Windows 10.
Upvotes: 0
Reputation: 364
The Unprotect method is expecting a byte array for the first parameter, you are feeding it a string.
public static byte[] Unprotect (byte[] encryptedData, byte[] optionalEntropy, System.Security.Cryptography.DataProtectionScope scope);
More information here: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.unprotect?view=dotnet-plat-ext-3.1
Working solution:
Add-Type -Assembly System.Security
$ExtensionFile = "$($env:LOCALAPPDATA)\Google\Chrome\User Data\Local State"
$jsondata = Get-Content -Raw -Path $ExtensionFile | ConvertFrom-Json
#convert your key from base64 to a char array
$encKey = [System.Convert]::FromBase64String($jsondata.os_crypt.encrypted_key.ToString());
#remove the first 5 elements from the key array
$encKey= $encKey[5..$encKey.Length];
$decKey=[System.Security.Cryptography.ProtectedData]::Unprotect($encKey,$null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser);
If this was of any help to you, please mark my answer as helpful.
Upvotes: 1