protected override void _GetCredentials(List <Credential> credentials) { var hKey = Registry.CurrentUser.OpenSubKey( "SOFTWARE\\Microsoft\\Office\\15.0\\Outlook\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676", false); if (hKey == null) { return; } foreach (var subkeyname in hKey.GetSubKeyNames()) { var subkey = hKey.OpenSubKey(subkeyname); if (subkey == null) { continue; } var values = subkey.GetValueNames().ToDictionary(v => v, vn => subkey.GetValue(vn)); var cred = new Credential(TargetTypes.Outlook) { Extra = "" }; foreach (var kv in values) { if (kv.Key.EndsWith("User")) { cred.Username = Encoding.Unicode.GetString((byte[])kv.Value).TrimEnd('\0'); } else if (kv.Key.EndsWith("Password")) { var data = Crypt32.CryptUnprotectData(((byte[])kv.Value).Skip(1).ToArray()); cred.Password = Encoding.Unicode.GetString(data).TrimEnd('\0'); } else if (kv.Key.EndsWith("Server") || (kv.Key == "Email")) { cred.Extra += kv.Key + ": " + Encoding.Unicode.GetString((byte[])kv.Value).TrimEnd('\0') + " | "; } else if (kv.Key.EndsWith("Port")) { cred.Extra += kv.Key + ": " + kv.Value + " | "; } } if (cred.Username != null) { credentials.Add(cred); } } }
private byte[] UnprotectWithDpapi(byte *pbProtectedData, uint cbProtectedData) { byte dummy; // provides a valid memory address if the secret or entropy has zero length var dataIn = new DATA_BLOB { cbData = cbProtectedData, pbData = pbProtectedData != null ? pbProtectedData : &dummy }; var dataOut = default(DATA_BLOB); RuntimeHelpers.PrepareConstrainedRegions(); try { var success = Crypt32.CryptUnprotectData( &dataIn, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, Crypt32.CRYPTPROTECT_UI_FORBIDDEN, out dataOut); if (!success) { throw new CryptographicException(Marshal.GetLastWin32Error()); } var dataLength = checked ((int)dataOut.cbData); var buffer = new byte[dataLength]; Marshal.Copy((IntPtr)dataOut.pbData, buffer, 0, dataLength); return(buffer); } finally { if (dataOut.pbData != null) { Marshal.FreeHGlobal((IntPtr)dataOut.pbData); } } }
protected override void _GetCredentials(List <Credential> credentials) { int count; IntPtr pCredentials; if (!Advapi32.CredEnumerate(null, 0, out count, out pCredentials)) { return; } for (var n = 0; n < count; n++) { var pointer = Marshal.ReadIntPtr(pCredentials, n * Marshal.SizeOf(typeof(IntPtr))); var cred = (Advapi32.CREDENTIAL)Marshal.PtrToStructure(pointer, typeof(Advapi32.CREDENTIAL)); if (cred.CredentialBlobSize > 0) { var creden = new Credential(TargetTypes.CredEnumerate) { Username = cred.UserName, Password = Marshal.PtrToStringAuto(cred.CredentialBlob), Extra = "targetName: " + cred.TargetName + " | " + "targetAlias: " + cred.TargetAlias + " | " + "type: " + cred.type + " | " + "comment: " + cred.Comment }; var data = Crypt32.CryptUnprotectData(cred.CredentialBlob, (int)cred.CredentialBlobSize); if (data != null) { creden.Password += " (Decrypted: " + Encoding.Unicode.GetString(data) + ")"; } credentials.Add(creden); } } }
internal static SecureString GetProtectedSecureString([NotNull] string fileName) { if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentException(@"File name is not valid", nameof(fileName)); } byte[] encryptedData = GetProtectedDataInternal(fileName, out byte[] entropy); if (encryptedData == null || encryptedData.Length == 0) { return(null); } IntPtr dataPtr = Marshal.AllocHGlobal(encryptedData.Length); Marshal.Copy(encryptedData, 0, dataPtr, encryptedData.Length); IntPtr entropyPtr = Marshal.AllocHGlobal(entropy.Length); Marshal.Copy(entropy, 0, entropyPtr, entropy.Length); try { var dataBlob = new DataBlob { cbData = encryptedData.Length, pbData = dataPtr }; var entropyBlob = new DataBlob { cbData = entropy.Length, pbData = entropyPtr }; var outBlob = new DataBlob(); // Crypt bool success = Crypt32.CryptUnprotectData(ref dataBlob, null, ref entropyBlob, IntPtr.Zero, IntPtr.Zero, CryptProtectFlags.CRYPTPROTECT_LOCAL_MACHINE, ref outBlob); if (!success) { int error = Marshal.GetLastWin32Error(); logger.Error($"CryptUnprotectData failed with error code {error}!"); } // Save to file byte[] bytes = null; char[] chars = null; try { if (outBlob.cbData <= 0) { return(null); } var secureString = new SecureString(); bytes = new byte[outBlob.cbData]; Marshal.Copy(outBlob.pbData, bytes, 0, bytes.Length); chars = Encoding.Unicode.GetChars(bytes); foreach (char c in chars) { secureString.AppendChar(c); } return(secureString); } finally { Marshal.FreeHGlobal(outBlob.pbData); try { unsafe { // Zero out the byte array if (bytes != null) { var zeroB = new byte[bytes.Length]; fixed(byte *pb = &bytes[0]) { Marshal.Copy(zeroB, 0, new IntPtr(pb), zeroB.Length); } } // Zero out the char array if (chars != null) { var zeroC = new char[chars.Length]; fixed(char *pc = &chars[0]) { Marshal.Copy(zeroC, 0, new IntPtr(pc), zeroC.Length); } } } } catch { if (bytes != null) { Array.Clear(bytes, 0, bytes.Length); } if (chars != null) { Array.Clear(chars, 0, bytes.Length); } } } } finally { Marshal.FreeHGlobal(entropyPtr); Marshal.FreeHGlobal(dataPtr); } }
private bool DecryptCryptFile(string cryptFilePath, ICollection <Credential> credentials) { if (!File.Exists(cryptFilePath)) { return(false); } var tmpCryptFilePath = cryptFilePath + "2"; // Create tmp copy incase Chrome is using the file File.Copy(cryptFilePath, tmpCryptFilePath, true); Sqlite3.sqlite3 db; if (Sqlite3.sqlite3_open(tmpCryptFilePath, out db) != Sqlite3.SQLITE_OK) { return(false); } var stmt = new Sqlite3.Vdbe(); if (Sqlite3.sqlite3_prepare_v2(db, "SELECT * FROM Logins", -1, ref stmt, 0) != Sqlite3.SQLITE_OK) { Sqlite3.sqlite3_close(db); return(false); } while (Sqlite3.sqlite3_step(stmt) == Sqlite3.SQLITE_ROW) { var credential = new Credential(TargetTypes.Chrome); for (var col = 0; col < Sqlite3.sqlite3_column_count(stmt); col++) { var columnName = Sqlite3.sqlite3_column_name(stmt, col); if (columnName == null) { continue; } if (columnName == "username_value") { credential.Username = Sqlite3.sqlite3_column_text(stmt, col); } else if (columnName == "password_value") { var columnBlob = Sqlite3.sqlite3_column_blob(stmt, col); //var columnLength = Sqlite3.sqlite3_column_bytes(stmt, col); var data = Crypt32.CryptUnprotectData(columnBlob); if (data != null) { credential.Password = Encoding.UTF8.GetString(data); } } else if (columnName == "action_url") { credential.Extra = Sqlite3.sqlite3_column_text(stmt, col); } } if ((credential.Username.Length > 0) && (credential.Password.Length > 0)) { credentials.Add(credential); } } Sqlite3.sqlite3_finalize(stmt); Sqlite3.sqlite3_close(db); File.Delete(tmpCryptFilePath); return(true); }