Skip to content

Instantly share code, notes, and snippets.

@newyear2006
Created March 3, 2018 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save newyear2006/d5f9560bd62f095fb6850da899d1034e to your computer and use it in GitHub Desktop.
Save newyear2006/d5f9560bd62f095fb6850da899d1034e to your computer and use it in GitHub Desktop.
Firefox oder Thunderbird Passwörter auslesen, hier C# aber als Grundlage für späteres Powershellscript. Bei Thunderbird sind die Passwörter im logins.json file im Profile-Verzeichnis.
using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
/// <summary>
/// A small class to recover Firefox Data
/// </summary>
public static class Firefox
{
private static IntPtr nssModule;
private static DirectoryInfo firefoxPath;
private static DirectoryInfo firefoxProfilePath;
private static FileInfo firefoxLoginFile;
private static FileInfo firefoxCookieFile;
static Firefox()
{
firefoxPath = GetFirefoxInstallPath();
if (firefoxPath == null)
throw new NullReferenceException("Firefox is not installed, or the install path could not be located");
firefoxProfilePath = GetProfilePath();
if (firefoxProfilePath == null)
throw new NullReferenceException("Firefox does not have any profiles, has it ever been launched?");
firefoxLoginFile = GetFile(firefoxProfilePath, "logins.json");
if (firefoxLoginFile == null)
throw new NullReferenceException("Firefox does not have any logins.json file");
firefoxCookieFile = GetFile(firefoxProfilePath, "cookies.sqlite");
if (firefoxCookieFile == null)
throw new NullReferenceException("Firefox does not have any cookie file");
}
#region Public Members
/// <summary>
/// Recover Firefox Passwords from logins.json
/// </summary>
/// <returns>List of Username/Password/Host</returns>
public static List<FirefoxPassword> Passwords()
{
List<FirefoxPassword> firefoxPasswords = new List<FirefoxPassword>();
// init libs
InitializeDelegates(firefoxProfilePath, firefoxPath);
JsonFFData ffLoginData = new JsonFFData();
using (StreamReader sr = new StreamReader(firefoxLoginFile.FullName))
{
string json = sr.ReadToEnd();
ffLoginData = JsonConvert.DeserializeObject<JsonFFData>(json);
}
foreach (LoginData data in ffLoginData.logins)
{
string username = Decrypt(data.encryptedUsername);
string password = Decrypt(data.encryptedPassword);
Uri host = new Uri(data.formSubmitURL);
firefoxPasswords.Add(new FirefoxPassword() { Host = host, Username = username, Password = password });
}
return firefoxPasswords;
}
/// <summary>
/// Recover Firefox Cookies from the SQLite3 Database
/// </summary>
/// <returns>List of Cookies found</returns>
#endregion
#region Functions
private static void InitializeDelegates(DirectoryInfo firefoxProfilePath, DirectoryInfo firefoxPath)
{
//LoadLibrary(firefoxPath.FullName + "\\msvcr100.dll");
//LoadLibrary(firefoxPath.FullName + "\\msvcp100.dll");
LoadLibrary(firefoxPath.FullName + "\\msvcp120.dll");
LoadLibrary(firefoxPath.FullName + "\\msvcr120.dll");
LoadLibrary(firefoxPath.FullName + "\\mozglue.dll");
nssModule = LoadLibrary(firefoxPath.FullName + "\\nss3.dll");
IntPtr pProc = GetProcAddress(nssModule, "NSS_Init");
NSS_InitPtr NSS_Init = (NSS_InitPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr));
NSS_Init(firefoxProfilePath.FullName);
}
private static DateTime FromUnixTime(long unixTime)
{
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
private static long ToUnixTime(DateTime value)
{
TimeSpan span = (value - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime());
return (long)span.TotalSeconds;
}
#endregion
#region File Handling
private static DirectoryInfo GetProfilePath()
{
string raw = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Mozilla\Firefox\Profiles";
if (!Directory.Exists(raw))
throw new Exception("Firefox Application Data folder does not exist!");
DirectoryInfo profileDir = new DirectoryInfo(raw);
DirectoryInfo[] profiles = profileDir.GetDirectories();
if (profiles.Length == 0)
throw new IndexOutOfRangeException("No Firefox profiles could be found");
// return first profile, fuck it.
return profiles[0];
}
private static FileInfo GetFile(DirectoryInfo profilePath, string searchTerm)
{
foreach (FileInfo file in profilePath.GetFiles(searchTerm))
{
return file;
}
throw new Exception("No Firefox logins.json was found");
}
private static DirectoryInfo GetFirefoxInstallPath()
{
string raw = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Mozilla Firefox";
if (!Directory.Exists(raw))
throw new Exception("Firefox not installed!");
DirectoryInfo firefoxPath = new DirectoryInfo(raw);
return firefoxPath;
}
#endregion
#region WinApi
// Credit: http://www.pinvoke.net/default.aspx/kernel32.loadlibrary
private static IntPtr LoadWin32Library(string libPath)
{
if (String.IsNullOrEmpty(libPath))
throw new ArgumentNullException("libPath");
IntPtr moduleHandle = LoadLibrary(libPath);
if (moduleHandle == IntPtr.Zero)
{
var lasterror = Marshal.GetLastWin32Error();
var innerEx = new Win32Exception(lasterror);
innerEx.Data.Add("LastWin32Error", lasterror);
throw new Exception("can't load DLL " + libPath, innerEx);
}
return moduleHandle;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate long NSS_InitPtr(string configdir);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int PK11SDR_DecryptPtr(ref TSECItem data, ref TSECItem result, int cx);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate long PK11_GetInternalKeySlotPtr();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate long PK11_AuthenticatePtr(long slot, bool loadCerts, long wincx);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int NSSBase64_DecodeBufferPtr(IntPtr arenaOpt, IntPtr outItemOpt, StringBuilder inStr, int inLen);
[StructLayout(LayoutKind.Sequential)]
private struct TSECItem
{
public int SECItemType;
public int SECItemData;
public int SECItemLen;
}
private enum SECStatus{
SECWouldBlock = -2,
SECFailure = -1,
SECSuccess = 0
}
#endregion
#region JSON
// json deserialize classes
private class JsonFFData
{
public long nextId;
public LoginData[] logins;
public string[] disabledHosts;
public int version;
}
private class LoginData
{
public long id;
public string hostname;
public string url;
public string httprealm;
public string formSubmitURL;
public string usernameField;
public string passwordField;
public string encryptedUsername;
public string encryptedPassword;
public string guid;
public int encType;
public long timeCreated;
public long timeLastUsed;
public long timePasswordChanged;
public long timesUsed;
}
#endregion
#region Delegate Handling
// Credit: http://www.codeforge.com/article/249225
private static long PK11_GetInternalKeySlot()
{
IntPtr pProc = GetProcAddress(nssModule, "PK11_GetInternalKeySlot");
PK11_GetInternalKeySlotPtr ptr = (PK11_GetInternalKeySlotPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_GetInternalKeySlotPtr));
return ptr();
}
private static long PK11_Authenticate(long slot, bool loadCerts, long wincx)
{
IntPtr pProc = GetProcAddress(nssModule, "PK11_Authenticate");
PK11_AuthenticatePtr ptr = (PK11_AuthenticatePtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_AuthenticatePtr));
return ptr(slot, loadCerts, wincx);
}
private static int NSSBase64_DecodeBuffer(IntPtr arenaOpt, IntPtr outItemOpt, StringBuilder inStr, int inLen)
{
IntPtr pProc = GetProcAddress(nssModule, "NSSBase64_DecodeBuffer");
NSSBase64_DecodeBufferPtr ptr = (NSSBase64_DecodeBufferPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSSBase64_DecodeBufferPtr));
return ptr(arenaOpt, outItemOpt, inStr, inLen);
}
private static int PK11SDR_Decrypt(ref TSECItem data, ref TSECItem result, int cx)
{
IntPtr pProc = GetProcAddress(nssModule, "PK11SDR_Decrypt");
PK11SDR_DecryptPtr ptr = (PK11SDR_DecryptPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11SDR_DecryptPtr));
return ptr(ref data, ref result, cx);
}
private static string Decrypt(string cypherText)
{
long keySlot = PK11_GetInternalKeySlot();
PK11_Authenticate(keySlot, true, 0);
StringBuilder sb = new StringBuilder(cypherText);
int hi2 = NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, sb, sb.Length);
TSECItem tSecDec = new TSECItem();
TSECItem item = (TSECItem)Marshal.PtrToStructure(new IntPtr(hi2), typeof(TSECItem));
if (PK11SDR_Decrypt(ref item, ref tSecDec, 0) == 0)
{
if (tSecDec.SECItemLen != 0)
{
byte[] bvRet = new byte[tSecDec.SECItemLen];
Marshal.Copy(new IntPtr(tSecDec.SECItemData), bvRet, 0, tSecDec.SECItemLen);
return Encoding.UTF8.GetString(bvRet);
}
}
return null;
}
#endregion
}
public class FirefoxPassword
{
public string Username { get; set; }
public string Password { get; set; }
public Uri Host { get; set; }
public override string ToString()
{
return string.Format("User: {0}{3}Pass: {1}{3}Host: {2}", Username, Password, Host.Host, Environment.NewLine);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment