fix: retrieve correct ABE master key when browser is running (#577)

* fix(windows): retrieve correct ABE master key when browser is running
This commit is contained in:
Roger
2026-04-19 20:07:51 +08:00
committed by GitHub
parent ae1ec66ccb
commit e50c623db0
7 changed files with 105 additions and 57 deletions
+4 -5
View File
@@ -6,9 +6,8 @@ import (
"github.com/moond4rk/hackbrowserdata/crypto"
)
// decryptValue decrypts a Chromium-encrypted value using the master key.
// It detects the cipher version from the ciphertext prefix and routes
// to the appropriate decryption function.
// decryptValue decrypts a Chromium-encrypted value using the master key. It detects the cipher version
// from the ciphertext prefix and routes to the appropriate decryption function.
func decryptValue(masterKey, ciphertext []byte) ([]byte, error) {
if len(ciphertext) == 0 {
return nil, nil
@@ -20,8 +19,8 @@ func decryptValue(masterKey, ciphertext []byte) ([]byte, error) {
// v11 is Linux-only and shares v10's AES-CBC path; only the key source differs.
return crypto.DecryptChromium(masterKey, ciphertext)
case crypto.CipherV20:
// v20 is cross-platform AES-GCM; routed through a dedicated function so
// Linux/macOS CI can exercise the same decryption path as Windows.
// v20 is cross-platform AES-GCM; routed through a dedicated function so Linux/macOS CI can
// exercise the same decryption path as Windows.
return crypto.DecryptChromiumV20(masterKey, ciphertext)
case crypto.CipherDPAPI:
return crypto.DecryptDPAPI(ciphertext)
+5 -6
View File
@@ -59,7 +59,7 @@ func extractCookies(masterKey []byte, path string) ([]types.CookieEntry, error)
return nil, err
}
if decryptFails > 0 {
log.Debugf("decrypt cookies: %d failed: %v", decryptFails, lastErr)
log.Warnf("cookies: total=%d decrypt_failed=%d last_err=%v", len(cookies), decryptFails, lastErr)
}
sort.Slice(cookies, func(i, j int) bool {
@@ -72,11 +72,10 @@ func countCookies(path string) (int, error) {
return sqliteutil.CountRows(path, false, countCookieQuery)
}
// stripCookieHash removes the SHA256(host_key) prefix from a decrypted cookie value.
// Chrome 130+ (Cookie DB schema version 24) prepends SHA256(domain) to the cookie
// value before encryption to prevent cross-domain cookie replay attacks.
// If the first 32 bytes don't match SHA256(hostKey), the value is returned unchanged,
// which handles both older Chrome versions and tampered data.
// stripCookieHash removes the SHA256(host_key) prefix from a decrypted cookie value. Chrome 130+
// (Cookie DB schema version 24) prepends SHA256(domain) to the cookie value before encryption to
// prevent cross-domain cookie replay attacks. If the first 32 bytes don't match SHA256(hostKey), the
// value is returned unchanged, which handles both older Chrome versions and tampered data.
func stripCookieHash(value []byte, hostKey string) []byte {
if len(value) < sha256.Size {
return value
+3 -3
View File
@@ -45,7 +45,7 @@ func extractPasswordsWithQuery(masterKey []byte, path, query string) ([]types.Lo
return nil, err
}
if decryptFails > 0 {
log.Debugf("decrypt passwords: %d failed: %v", decryptFails, lastErr)
log.Warnf("passwords: total=%d decrypt_failed=%d last_err=%v", len(logins), decryptFails, lastErr)
}
sort.Slice(logins, func(i, j int) bool {
@@ -54,8 +54,8 @@ func extractPasswordsWithQuery(masterKey []byte, path, query string) ([]types.Lo
return logins, nil
}
// extractYandexPasswords extracts passwords from Yandex's Ya Passman Data,
// which stores the URL in action_url instead of origin_url.
// extractYandexPasswords extracts passwords from Yandex's Ya Passman Data, which stores the URL in
// action_url instead of origin_url.
func extractYandexPasswords(masterKey []byte, path string) ([]types.LoginEntry, error) {
const yandexLoginQuery = `SELECT action_url, username_value, password_value, date_created FROM logins`
return extractPasswordsWithQuery(masterKey, path, yandexLoginQuery)