public string ReadCookieValue(string browserName, string browserCompanyName, string cookieName, string cookieHost, string username = null)
{
SQLitePCL.Batteries.Init();
var localAppData = username == null ?
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) :
Path.Combine(RegistryUtils.GetUserHomeDir(username), "AppData", "Local");
var localState = File.ReadAllText(localAppData + $@"\{browserCompanyName}\{browserName}\User Data\Local State");
var dbPath = localAppData + $@"\{browserCompanyName}\{browserName}\User Data\Default\Network\Cookies";
if (!File.Exists(dbPath))
{
throw new FileNotFoundException($"Cant find cookie store {dbPath}");
}
var connString = $"Data Source={dbPath};Mode=ReadOnly;";
string cookieValue = null;
using (var conn = new SqliteConnection(connString))
{
var query = $"SELECT name,encrypted_value FROM cookies where host_key = '{cookieHost}';";
using (var cmd = new SqliteCommand(query, conn))
{
conn.Open();
try
{
using (SqliteDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
var name = dr.GetValue(0).ToString(); // name
if (name != cookieName)
{
continue;
}
// Get & decrypt a browser cookie encryption key
var encKey = JObject.Parse(localState)["os_crypt"]["encrypted_key"].ToString();
var decodedKey = ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, DataProtectionScope.LocalMachine);
// Decrypt cookie encrypted value by a browser cookie key
var val = (byte[])dr.GetValue(1);
try
{
cookieValue = DecryptWithKey(val, decodedKey, 3);
break;
}
catch (Exception ex)
{
conn.Close();
throw new Exception($"Failed decrypt {cookieName} cookie", ex);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
}
}
return cookieValue;
}
private string DecryptWithKey(byte[] message, byte[] key, int nonSecretPayloadLength)
{
const int KEY_BIT_SIZE = 256;
const int MAC_BIT_SIZE = 128;
const int NONCE_BIT_SIZE = 96;
if (key == null || key.Length != KEY_BIT_SIZE / 8)
{
throw new ArgumentException(string.Format("Key needs to be {0} bit!", KEY_BIT_SIZE), "key");
}
if (message == null || message.Length == 0)
{
throw new ArgumentException("Message required!", "message");
}
using (var cipherStream = new MemoryStream(message))
using (var cipherReader = new BinaryReader(cipherStream))
{
var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength);
var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8);
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), MAC_BIT_SIZE, nonce);
cipher.Init(false, parameters);
var cipherText = cipherReader.ReadBytes(message.Length);
var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
try
{
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
}
catch (InvalidCipherTextException)
{
return null;
}
return Encoding.Default.GetString(plainText);
}
}
Но у них обоих это перестало работать. Насколько я понял, они перешли на файлы cookie версии 20.
Теперь я начал использовать этот код для расшифровки файлов cookie Chrome, и у меня он отлично работает.
import os
import json
import sys
import binascii
from pypsexec.client import Client
from Crypto.Cipher import AES
import sqlite3
import pathlib
user_profile = os.environ['USERPROFILE']
local_state_path = rf"{user_profile}\AppData\Local\Google\Chrome\User Data\Local State"
cookie_db_path = rf"{user_profile}\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies"
with open(local_state_path, "r") as f:
local_state = json.load(f)
app_bound_encrypted_key = local_state["os_crypt"]["app_bound_encrypted_key"]
arguments = "-c \"" + """import win32crypt
import binascii
encrypted_key = win32crypt.CryptUnprotectData(binascii.a2b_base64('{}'), None, None, None, 0)
print(binascii.b2a_base64(encrypted_key[1]).decode())
""".replace("\n", ";") + "\""
c = Client("localhost")
c.connect()
try:
c.create_service()
assert(binascii.a2b_base64(app_bound_encrypted_key)[:4] == b"APPB")
app_bound_encrypted_key_b64 = binascii.b2a_base64(
binascii.a2b_base64(app_bound_encrypted_key)[4:]).decode().strip()
# decrypt with SYSTEM DPAPI
encrypted_key_b64, stderr, rc = c.run_executable(
sys.executable,
arguments=arguments.format(app_bound_encrypted_key_b64),
use_system_account=True
)
# decrypt with user DPAPI
decrypted_key_b64, stderr, rc = c.run_executable(
sys.executable,
arguments=arguments.format(encrypted_key_b64.decode().strip()),
use_system_account=False
)
decrypted_key = binascii.a2b_base64(decrypted_key_b64)[-61:]
assert(decrypted_key[0] == 1)
finally:
c.remove_service()
c.disconnect()
# decrypt key with AES256GCM
# aes key from elevation_service.exe
aes_key = binascii.a2b_base64("sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=")
# [flag|iv|ciphertext|tag] decrypted_key
# [1byte|12bytes|variable|16bytes]
iv = decrypted_key[1:1+12]
ciphertext = decrypted_key[1+12:1+12+32]
tag = decrypted_key[1+12+32:]
cipher = AES.new(aes_key, AES.MODE_GCM, nonce=iv)
key = cipher.decrypt_and_verify(ciphertext, tag)
print(binascii.b2a_base64(key))
# fetch all v20 cookies
con = sqlite3.connect(pathlib.Path(cookie_db_path).as_uri() + "?mode=ro", uri=True)
cur = con.cursor()
r = cur.execute("SELECT host_key, name, CAST(encrypted_value AS BLOB) from cookies;")
cookies = cur.fetchall()
cookies_v20 = [c for c in cookies if c[2][:3] == b"v20"]
con.close()
# decrypt v20 cookie with AES256GCM
# [flag|iv|ciphertext|tag] encrypted_value
# [3bytes|12bytes|variable|16bytes]
def decrypt_cookie_v20(encrypted_value):
cookie_iv = encrypted_value[3:3+12]
encrypted_cookie = encrypted_value[3+12:-16]
cookie_tag = encrypted_value[-16:]
cookie_cipher = AES.new(key, AES.MODE_GCM, nonce=cookie_iv)
decrypted_cookie = cookie_cipher.decrypt_and_verify(encrypted_cookie, cookie_tag)
return decrypted_cookie[32:].decode('utf-8')
for c in cookies_v20:
print(c[0], c[1], decrypt_cookie_v20(c[2]))
Но это не работает для Microsoft Edge, оно работает для Edge, но возвращает мусорное значение.
Что следует добавить/удалить из этого кода за исправление для расшифровки файлов cookie Microsoft Edge?
P.S. Я знаю, что это два разных языка, я только что перешел с C# на Python.
До сих пор я использовал этот код для Microsoft Edge и Google Chrome. [code]public string ReadCookieValue(string browserName, string browserCompanyName, string cookieName, string cookieHost, string username = null) { SQLitePCL.Batteries.Init();
var localState = File.ReadAllText(localAppData + $@"\{browserCompanyName}\{browserName}\User Data\Local State"); var dbPath = localAppData + $@"\{browserCompanyName}\{browserName}\User Data\Default\Network\Cookies";
if (!File.Exists(dbPath)) { throw new FileNotFoundException($"Cant find cookie store {dbPath}"); }
var connString = $"Data Source={dbPath};Mode=ReadOnly;"; string cookieValue = null;
using (var conn = new SqliteConnection(connString)) { var query = $"SELECT name,encrypted_value FROM cookies where host_key = '{cookieHost}';";
using (var cmd = new SqliteCommand(query, conn)) { conn.Open(); try { using (SqliteDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { var name = dr.GetValue(0).ToString(); // name
if (name != cookieName) { continue; }
// Get & decrypt a browser cookie encryption key var encKey = JObject.Parse(localState)["os_crypt"]["encrypted_key"].ToString(); var decodedKey = ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, DataProtectionScope.LocalMachine);
// Decrypt cookie encrypted value by a browser cookie key var val = (byte[])dr.GetValue(1); try { cookieValue = DecryptWithKey(val, decodedKey, 3);
private string DecryptWithKey(byte[] message, byte[] key, int nonSecretPayloadLength) { const int KEY_BIT_SIZE = 256; const int MAC_BIT_SIZE = 128; const int NONCE_BIT_SIZE = 96;
if (key == null || key.Length != KEY_BIT_SIZE / 8) { throw new ArgumentException(string.Format("Key needs to be {0} bit!", KEY_BIT_SIZE), "key"); }
if (message == null || message.Length == 0) { throw new ArgumentException("Message required!", "message"); }
using (var cipherStream = new MemoryStream(message)) using (var cipherReader = new BinaryReader(cipherStream)) { var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength); var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8); var cipher = new GcmBlockCipher(new AesEngine()); var parameters = new AeadParameters(new KeyParameter(key), MAC_BIT_SIZE, nonce); cipher.Init(false, parameters); var cipherText = cipherReader.ReadBytes(message.Length); var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
try { var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0); cipher.DoFinal(plainText, len); } catch (InvalidCipherTextException) { return null; }
return Encoding.Default.GetString(plainText); } } [/code] Но у них обоих это перестало работать. Насколько я понял, они перешли на файлы cookie версии 20. Теперь я начал использовать этот код для расшифровки файлов cookie Chrome, и у меня он отлично работает. [code]import os import json import sys import binascii from pypsexec.client import Client from Crypto.Cipher import AES import sqlite3 import pathlib
# fetch all v20 cookies con = sqlite3.connect(pathlib.Path(cookie_db_path).as_uri() + "?mode=ro", uri=True) cur = con.cursor() r = cur.execute("SELECT host_key, name, CAST(encrypted_value AS BLOB) from cookies;") cookies = cur.fetchall() cookies_v20 = [c for c in cookies if c[2][:3] == b"v20"] con.close()
for c in cookies_v20: print(c[0], c[1], decrypt_cookie_v20(c[2])) [/code] Но это не работает для Microsoft Edge, оно работает для Edge, но возвращает мусорное значение. Что следует добавить/удалить из этого кода за исправление для расшифровки файлов cookie Microsoft Edge? P.S. Я знаю, что это два разных языка, я только что перешел с C# на Python.