asaix/mozdmp

GitHub: asaix/mozdmp

mozdmp 是一款 Firefox 配置数据离线解密工具,能够从 NSS 数据库提取密钥并解密 logins.json 中的用户密码,支持主密码字典破解。

Stars: 0 | Forks: 0

# mozdmp mozdmp 是一款用于 Mozilla Firefox 浏览器的离线配置解密工具。它通过从 NSS 数据库(`key4.db`)中提取密钥,能够对包含用户密码的 `logins.json` 文件进行解密。 **重要功能:** - 支持最新版本的 Firefox,这些版本使用 SHA384 来派生 PBKDF2 输入。工具会自动选择正确的哈希类型。 - 支持使用字典进行多核主密码破解。*\*在 Windows 和 MacOS 上,破解将仅限于单核。* **快速开始** 下载并解压最新的二进制发布版本。然后运行: ``` mozdmp ``` 该二进制文件仅在 Linux 上运行。如果你想 Windows/Mac 上运行该程序,请克隆源代码,从 `requirements.txt` 安装所需的依赖包,并使用 Python 3 运行脚本。 **许可证与免责声明** 本代码基于 MIT 许可证发布。请注意,本工具仅限在法律允许的范围内进行授权使用,开发者对任何非法或有害的使用行为不承担任何责任。 ## 演示 ``` ≻ ./mozdmp data/psw_1looove/key4.db data/psw_1looove/logins.json [*] Checking Master Password... >> Check Master Password == '' ... NO [*] Attempting to crack master password... [+] Multi-Core Enabled [?] Enter wordlist path: rockyou.txt [?] Workers (default 20): [*] Loading wordlist... W0: ▎ | 2407/717220 [00:11<56:18, 211.60pwd/s] W15: ▎ | 2325/717220 [00:11<56:54, 209.39pwd/s] W8: ▎ | 2278/717220 [00:11<58:55, 202.20pwd/s] W10: ▎ | 2389/717220 [00:11<55:57, 212.89pwd/s] W14: ▎ | 2222/717220 [00:11<59:41, 199.66pwd/s] W11: ▎ | 2186/717220 [00:11<1:01:03, 195.17pwd/s] W6: ▎ | 2425/717220 [00:11<55:29, 214.69pwd/s] W1: ▎ | 2314/717220 [00:11<58:31, 203.61pwd/s] W18: ▎ | 2203/717220 [00:11<59:40, 199.70pwd/s] W19: ▎ | 2217/717203 [00:11<59:11, 201.32pwd/s] W7: ▎ | 2295/717220 [00:11<58:35, 203.38pwd/s] W3: ▎ | 2608/717220 [00:11<51:47, 229.99pwd/s] W4: ▎ | 2444/717220 [00:11<55:12, 215.79pwd/s] W16: ▎ | 2501/717220 [00:11<52:47, 225.66pwd/s] W13: ▎ | 2440/717220 [00:11<54:28, 218.70pwd/s] W9: ▎ | 2377/717220 [00:11<56:23, 211.30pwd/s] W5: ▎ | 2280/717220 [00:11<59:07, 201.54pwd/s] W2: ▎ | 2506/717220 [00:11<53:58, 220.70pwd/s] W12: ▏ | 2159/717220 [00:11<1:01:43, 193.08pwd/s] W17: ▎ | 2290/717220 [00:11<57:34, 206.96pwd/s] [+] FOUND MASTER KEY: 1looove [*] ASN.1 Structure: { "0": { "0": "1.2.840.113549.1.5.13", "1": { "0": { "0": "1.2.840.113549.1.5.12", "1": { "0": "2a24f5f8ec2fc74eccd6fa396f11aa34f1c8d3de269af38ca1324539ec5a4894", "1": 10000, "2": 32, "3": { "0": "1.2.840.113549.2.9" } } }, "1": { "0": "2.16.840.1.101.3.4.1.42", "1": "d33681631562b28ee4494725e9bc" } } }, "1": "1012c08ee92981434c59134564e2684df5188b3aac4e7ade234c0accc853d31a40c7d2a3373c5e4af7b7f6835042df57" } [*] KDF Parameters: { "salt": "2a24f5f8ec2fc74eccd6fa396f11aa34f1c8d3de269af38ca1324539ec5a4894", "iterations": 10000, "keylen": 32 } [*] AES Parameters: { "iv": "040ed33681631562b28ee4494725e9bc" } [*] Global salt: 733f22304895df339a778680cbda652191f0b46fd240f1340b81e79c4997dcac11b25b897bc779cdbad0eb6cbe1696e5 [*] Ciphertext: 1012c08ee92981434c59134564e2684df5188b3aac4e7ade234c0accc853d31a40c7d2a3373c5e4af7b7f6835042df57 [*] KDF input (SHA384(global_salt + password)): aa5bf320258a8f9c10dc1a23dc415e3143d258c36c3218018672f0df1a6b9edb3174198700bf463201e8017d7f42767e [*] KDF Output (Wrapped AES Key): 3dd4e31d292fd8ee4bbaf995074a28e98365c8466cab24f84e75c2e843b97234 [+] Decrypted AES key: 462f7891ab8e708c1a93122a3b2857a5b016472b9d58cb40b52449db64e4a68a [*] Decrypting passwords from logins... ╭────────────────────────────┬────────────────────────────┬────────────┬────────────┬────────────────────┬────────────────────┬────────────────────┬──────────╮ │ Hostname │ Form Submit URL │ Username │ Password │ Created At │ Last Used │ Last Changed │ # uses │ ├────────────────────────────┼────────────────────────────┼────────────┼────────────┼────────────────────┼────────────────────┼────────────────────┼──────────┤ │ https://auth.wikimedia.org │ https://auth.wikimedia.org │ joog │ boog │ 08 June 2026 11:40 │ 08 June 2026 11:40 │ 08 June 2026 11:40 │ 1 │ ╰────────────────────────────┴────────────────────────────┴────────────┴────────────┴────────────────────┴────────────────────┴────────────────────┴──────────╯ ``` ## 解密过程详解 本部分解释了 Firefox 中的配置文件解密是如何运作的。这并非使用本程序的必需前提,但如果你打算贡献代码,了解这些是非常有价值的。 与基于 Chromium 的浏览器(它们使用诸如 keyring 和 DPAPI 密钥等操作系统级别的身份验证工具来保护敏感文件)不同,Firefox 没有采取此类额外措施,这可能是考虑到此类保护机制终究会被绕过。 也就是说,`logins.json` 中的所有登录数据都可以使用 `key4.db` 文件中提供的 NSS 密钥进行解密,而无需依赖任何*不包含在这些文件中*的信息(例如 NTLM 哈希等)来解密这些密钥。 现在,用于解密密码的 AES 密钥并不是以明文形式存在的。它必须通过派生出另一个密钥(以下称为 **wrapper key**)来解密。 本指南将带你详细了解在哪里找到所需的参数,如何使用它们派生 wrapper key,并最终使用解密后的 AES 登录密钥来解密实际数据。 ### 1. 提取 Global Salt 与 Password Check ASN.1 Blob Global Salt 存储在 `metadata` 表中,可以通过查询 `id="password"` 时的 `item1` 列来提取。 | id (UNIQUE) | item1 | item2 | | ----------- | ------------- | --------------------------- | | password | *global salt* | *Password Check ASN.1 Blob* | | ... | ... | ... | 为了快速测试输入的密码是否正确,Firefox 存储了一个 ASN.1 blob,其中包含使用主密钥加密的短语 `password-check`,以及用于生成加密该 `password-check` 短语的 AES 密钥的 PBKDF2 函数参数。 我们可以按如下方式索引该 blob,以获取 PBKDF2 的参数: - Salt: 0.1.0.1.0 - Iterations: 0.1.0.1.1 - Key length: 0.1.0.1.2 这些可用于生成 wrapper key。要解密密文,我们还需要两个字段: - Ciphertext: 1. - Initialization Vector (IV): 0.1.1.1 请注意,根据你使用的 ASN 解析库(如在 python.asn1crypto 中所见),解析器可能会在返回 IV 时去掉其 TLV 标头。这可以通过检查返回的 IV 长度来识别。如果长度小于 16,则说明 TLV 标头被去掉了。在这种情况下,可以在 IV 值前面加上字节序列 `0x04` 以及 IV 字节序列的长度。即 `IV = BYTES([0x04, len(IV)]) + IV`。 ### 2. 校验主密码 利用在第 1 步中获得的信息,我们现在可以通过使用上面获取的参数解密密文来测试主密码。默认情况下,Firefox 使用空字符串作为主密码,并且不会提示用户设置密码。 Firefox 使用 SHA1 或 SHA384 来派生 PBKDF2 函数的输入,如下所示: ``` KDF_INPUT = SHA*(global_salt + password) KDF_OUTPUT = PBKDF2("sha256", KDF_INPUT, salt, iterations, keylength) ``` **如果 global salt 的长度为 48,请使用 SHA384。如果不是,则使用 SHA1。** 现在,利用我们生成的密钥 `KDF_OUTPUT`,就可以解密密文了 ``` PLAINTEXT = AES-256-CBC-DECRYPT(ciphertext, KDF_OUTPUT, iv) ``` 如果获得的明文等于 `password-check`,则说明密码正确。如果不正确(通常 `AES-256-CBC-DECRYPT` 会因为无法剥离 PKCS#7 填充而报错),则说明用户设置了主密码,必须通过使用不同的 `password` 值运行此函数来对其进行破解。 ### 3. 获取真实密钥 有了主密码,我们现在可以继续派生 wrapper key,并最终获得真实密钥。 `nssPrivate` 数据库存储了大量信息,其中包含许多指向 NSS 协议不同部分的键。然而在我们的场景中,加密过程相当直接,我们只需要两列:`a0` 和 `a11`。 该表有多行。`a0` 列表示其存储的数据类型,这与 NSS 的机制是一致的。 带有 CKO_SECRET_KEY 的行是其 `a0` = `f8000000000000000000000000000004`(字节序列)的行。我们想要的行是唯一以 0x04 结尾的行,因此只需通过检查该值的最后一个字节即可将其筛选出来。 ``` res = db.run("SELECT a0, a11 from nssPrivate") for row in res: if row[0][-1] == 0x04: ... ``` a11 列中对应的值是一个 ASN.1 blob。 与第 1 步类似,我们可以提取有关加密和密钥生成算法的详细信息: PBKDF2: - Salt: 0.1.0.1.0 - Iterations: 0.1.0.1.1 - Key length: 0.1.0.1.2 AES: - IV: 0.1.1.1 - Ciphertext: 1. 由此,可以使用与第 2 步相同的步骤以及这些更新后的参数值来获取真实密钥。 ### 4. 解密 logins.json `logins.json` 文件中,每次登录只包含两个加密字段:"encryptedUsername" 和 "encryptedPassword"。 这两个都是经过 base64 编码的 ASN.1 blob。解密步骤如下所示。 1. 对这些值进行 Base64 解码。 2. 在 ASN blob 的 1.1 处获取 IV。 3. 在 2 处获取密文。 4. 使用在第 3 步中获取的真实密钥和 IV,通过 AES-256-CBC-DECRYPT 解密密文。
标签:DOS头擦除, Python, 凭证提取, 密码破解, 数据解密, 无后门, 逆向工具