浏览器存储密码离线解密

一、任务目标

从Windows取证镜像中提取浏览器保存的网站 www.xxxxxxxx.top 账号 lulan 的密码。

二、最终结果

浏览器 网站 用户名 密码
Chrome https://www.xxxxxxxx.top/ admin111 98uhy675e
Edge https://www.xxxxxxxx.top/ lulan a8sa9syai
Chrome https://www.xxxxxxxx.top/ admin998 admin998156
Edge https://www.xxxxxxxx.top/ admin998 admin998156

**答案:账号 lulan 的密码为 a8sa9syai**(保存在Edge浏览器中)


三、加密原理

Chrome/Edge(v80+)均基于Chromium,密码加密采用两层结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
      Windows用户密码


┌─────────────────────┐
│ DPAPI Master Key │ ← 存储在 Protect\{SID}\{GUID}
│ (用户密码派生解密) │
└─────────┬───────────┘


┌─────────────────────┐
│ 浏览器 AES-256 Key │ ← 存储在 Local State(DPAPI加密)
└─────────┬───────────┘


┌─────────────────────┐
│ AES-256-GCM 解密 │ ← 密码密文存储在 Login Data
└─────────┬───────────┘


密码明文

密码密文格式(Login Data中的password_value字段):

1
2
[v10] [nonce: 12字节] [ciphertext] [tag: 16字节]
3字节 AES-GCM随机数 密文 认证标签

四、所需取证文件

从镜像中导出以下文件(用户名 chenchen):

Chrome

文件 镜像路径
Login Data C:\Users\chenchen\AppData\Local\Google\Chrome\User Data\Default\Login Data
Local State C:\Users\chenchen\AppData\Local\Google\Chrome\User Data\Local State

Edge

文件 镜像路径
Login Data C:\Users\chenchen\AppData\Local\Microsoft\Edge\User Data\Default\Login Data
Local State C:\Users\chenchen\AppData\Local\Microsoft\Edge\User Data\Local State

DPAPI(Chrome和Edge共用)

文件 镜像路径
Master Key C:\Users\chenchen\AppData\Roaming\Microsoft\Protect\S-1-5-21-17485621-1970499508-3307361946-1001\ad9b27cd-405e-44c5-9eb5-67e1f7c89def

Master Key的GUID可从Local State中的DPAPI Blob解析得到。


五、解密步骤详解

步骤1:读取Login Data查看加密记录

Login Data是SQLite数据库,查询logins表:

1
2
3
4
5
6
7
import sqlite3

conn = sqlite3.connect('Login Data')
cursor = conn.cursor()
cursor.execute('SELECT origin_url, username_value, password_value FROM logins')
for url, username, pwd in cursor.fetchall():
print(f'{url} | {username} | {pwd.hex()}')

输出(以Edge为例):

1
https://www.xxxxxxxx.top/ | lulan | 763130...(加密数据)

密码字段以 763130(ASCII “v10”)开头,确认为Chrome v80+加密格式。

步骤2:从Local State提取DPAPI加密的浏览器密钥

1
2
3
4
5
6
7
import json, base64

with open('Local State', 'r', encoding='utf-8') as f:
local_state = json.load(f)

encrypted_key = base64.b64decode(local_state['os_crypt']['encrypted_key'])
dpapi_blob = encrypted_key[5:] # 去掉 "DPAPI" 前缀(5字节)

解析DPAPI Blob可得到所需Master Key的GUID:AD9B27CD-405E-44C5-9EB5-67E1F7C89DEF

步骤3:使用Windows密码解密DPAPI Master Key

DPAPI密钥派生过程:

1
2
3
4
5
6
7
8
9
10
11
from hashlib import sha1
from Cryptodome.Hash import HMAC, SHA1

password = 'qwer123'
user_sid = 'S-1-5-21-17485621-1970499508-3307361946-1001'

# 1) 计算密码的SHA1
sha1_hash = sha1(password.encode('utf-16le')).digest()

# 2) HMAC-SHA1(SHA1(password), UTF16LE(SID + '\0')) 派生预密钥
prekey = HMAC.new(sha1_hash, (user_sid + '\0').encode('utf-16le'), SHA1).digest()

用预密钥解密Master Key文件:

1
2
3
4
5
6
7
8
9
10
11
from impacket.dpapi import MasterKeyFile, MasterKey

with open('ad9b27cd-405e-44c5-9eb5-67e1f7c89def', 'rb') as f:
mk_data = f.read()

mk_file = MasterKeyFile(mk_data)
mk = MasterKey(mk_data[len(mk_file.getData()):])

# impacket内部执行 PBKDF2-SHA512(prekey, salt, 8000次迭代)
# 派生AES-256密钥解密Master Key,并通过HMAC-SHA512验证完整性
master_key = mk.decrypt(prekey)

解密得到64字节的Master Key:

1
2
3
9555714bc67d3988852b2bb41dfec14d3d8cc9a2c7f0c577
0814c315ff391fc82405b46a190ce423e1b631e2848f30bf
bc15b3133550629c11f54ca6aa86dfe4

步骤4:解密浏览器AES Key

1
2
3
4
from impacket.dpapi import DPAPI_BLOB

blob = DPAPI_BLOB(dpapi_blob)
browser_key = blob.decrypt(master_key)
浏览器 AES-256 Key
Chrome 18b27bd82bfa6b739bb6f2149135dac512585599be00028f496ba91b81c407c2
Edge 717a8873ffa72c532e7378c3932ffa5ac0ee1b367e1a42a972b7647101ca44a9

步骤5:AES-256-GCM解密密码

1
2
3
4
5
6
7
8
9
10
from Cryptodome.Cipher import AES

encrypted_pwd = ... # 从Login Data读取的password_value

nonce = encrypted_pwd[3:15] # 跳过"v10",取12字节nonce
ciphertext = encrypted_pwd[15:-16] # 密文
tag = encrypted_pwd[-16:] # 认证标签

cipher = AES.new(browser_key, AES.MODE_GCM, nonce=nonce)
password = cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8')

六、完整解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env python3
"""浏览器密码离线解密工具(Chrome/Edge)"""

import json, base64, sqlite3
from hashlib import sha1
from Cryptodome.Hash import HMAC, SHA1
from Cryptodome.Cipher import AES
from impacket.dpapi import MasterKeyFile, MasterKey, DPAPI_BLOB

def decrypt_browser_passwords(login_data_path, local_state_path,
masterkey_path, user_sid, win_password):
# === 阶段1:解密DPAPI Master Key ===
sha1_hash = sha1(win_password.encode('utf-16le')).digest()
prekey = HMAC.new(sha1_hash, (user_sid + '\0').encode('utf-16le'), SHA1).digest()

with open(masterkey_path, 'rb') as f:
mk_data = f.read()
mk_file = MasterKeyFile(mk_data)
mk = MasterKey(mk_data[len(mk_file.getData()):])
master_key = mk.decrypt(prekey)
if not master_key:
raise Exception("Master Key解密失败,Windows密码可能错误")

# === 阶段2:解密浏览器AES Key ===
with open(local_state_path, 'r', encoding='utf-8') as f:
local_state = json.load(f)
encrypted_key = base64.b64decode(local_state['os_crypt']['encrypted_key'])
blob = DPAPI_BLOB(encrypted_key[5:])
browser_key = blob.decrypt(master_key)

# === 阶段3:解密所有密码 ===
conn = sqlite3.connect(login_data_path)
cursor = conn.cursor()
cursor.execute('SELECT origin_url, username_value, password_value FROM logins')

results = []
for url, username, enc_pwd in cursor.fetchall():
if enc_pwd and len(enc_pwd) > 3 and enc_pwd[:3] == b'v10':
nonce = enc_pwd[3:15]
ct_tag = enc_pwd[15:]
cipher = AES.new(browser_key, AES.MODE_GCM, nonce=nonce)
pwd = cipher.decrypt_and_verify(ct_tag[:-16], ct_tag[-16:]).decode('utf-8')
results.append((url, username, pwd))
conn.close()
return results


if __name__ == '__main__':
SID = 'S-1-5-21-17485621-1970499508-3307361946-1001'
WIN_PWD = 'qwer123'
MK_PATH = 'ad9b27cd-405e-44c5-9eb5-67e1f7c89def'

# Chrome
print("=== Chrome ===")
for url, user, pwd in decrypt_browser_passwords(
'Chrome_Login Data', 'Chrome_Local State', MK_PATH, SID, WIN_PWD):
print(f'{url} | {user} | {pwd}')

# Edge
print("\n=== Edge ===")
for url, user, pwd in decrypt_browser_passwords(
'Edge_Login Data', 'Edge_Local State', MK_PATH, SID, WIN_PWD):
print(f'{url} | {user} | {pwd}')

七、总结

  1. Chrome/Edge共用DPAPI体系:同一用户下Chrome和Edge使用相同的DPAPI Master Key,但各自有独立的AES Key
  2. Master Key GUID定位:DPAPI Blob内嵌了所需Master Key的GUID,对应 Protect\{SID}\ 下的文件名
  3. 密钥派生链Windows密码 → SHA1 → HMAC-SHA1(+SID) → PBKDF2-SHA512(+salt, 8000轮) → 解密Master Key
  4. 离线解密必要条件:Windows用户密码 + Master Key文件 + 用户SID + Login Data + Local State
  5. 依赖库impacket(DPAPI解析)、pycryptodome(AES-GCM解密)