From 647fe190ef40dc23bb0979cd952645fe1dd73bf5 Mon Sep 17 00:00:00 2001 From: makikvues Date: Mon, 8 Feb 2021 22:50:58 +0100 Subject: [PATCH] - added Brave browser credentials extraction - added PowerOnEvents - added PrintOutlookDownloads - added PrintAuditPoliciesInfo - added search keywords for keepass --- .../winPEASexe/winPEAS/Checks/BrowserInfo.cs | 2 + .../winPEASexe/winPEAS/Checks/EventsInfo.cs | 54 +++-- .../winPEASexe/winPEAS/Checks/FilesInfo.cs | 35 ++++ .../winPEASexe/winPEAS/Checks/SystemInfo.cs | 32 ++- .../winPEAS/Helpers/Search/Patterns.cs | 2 + .../winPEAS/Helpers/Search/SearchHelper.cs | 2 +- .../winPEAS/Info/EventsInfo/Power/Power.cs | 39 ++++ .../Info/EventsInfo/Power/PoweredEventInfo.cs | 10 + .../AuditPolicies/AuditEntryInfo.cs | 22 ++ .../SystemInfo/AuditPolicies/AuditPolicies.cs | 191 ++++++++++++++++++ .../AuditPolicies/AuditPolicyGPOInfo.cs | 27 +++ .../SystemInfo/AuditPolicies/AuditType.cs | 9 + .../KnownFileCreds/Browsers/Brave/Brave.cs | 16 ++ .../KnownFileCreds/Browsers/Chrome/Chrome.cs | 50 +---- .../KnownFileCreds/Browsers/ChromiumBase.cs | 58 ++++++ .../Browsers/Decryptor/GCDecryptor.cs | 13 +- .../KnownFileCreds/Browsers/Opera/Opera.cs | 54 +---- winPEAS/winPEASexe/winPEAS/Native/Kernel32.cs | 9 +- winPEAS/winPEASexe/winPEAS/winPEAS.csproj | 8 + 19 files changed, 497 insertions(+), 136 deletions(-) create mode 100644 winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/Power.cs create mode 100644 winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/PoweredEventInfo.cs create mode 100644 winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditEntryInfo.cs create mode 100644 winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicies.cs create mode 100644 winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicyGPOInfo.cs create mode 100644 winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditType.cs create mode 100644 winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Brave/Brave.cs create mode 100644 winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/ChromiumBase.cs diff --git a/winPEAS/winPEASexe/winPEAS/Checks/BrowserInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/BrowserInfo.cs index 25cbd99..0e7b2c3 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/BrowserInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/BrowserInfo.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using winPEAS.Helpers; using winPEAS.KnownFileCreds.Browsers; +using winPEAS.KnownFileCreds.Browsers.Brave; using winPEAS.KnownFileCreds.Browsers.Chrome; using winPEAS.KnownFileCreds.Browsers.Firefox; using winPEAS.KnownFileCreds.Browsers.Opera; @@ -18,6 +19,7 @@ namespace winPEAS.Checks new Firefox(), new Chrome(), new Opera(), + new Brave(), new InternetExplorer(), }.ForEach(browser => CheckRunner.Run(browser.PrintInfo, isDebug)); } diff --git a/winPEAS/winPEASexe/winPEAS/Checks/EventsInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/EventsInfo.cs index 09503f2..cd85b59 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/EventsInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/EventsInfo.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using winPEAS.Helpers; using winPEAS.Info.EventsInfo.Logon; +using winPEAS.Info.EventsInfo.Power; using winPEAS.Info.EventsInfo.PowerShell; using winPEAS.Info.EventsInfo.ProcessCreation; @@ -12,14 +13,15 @@ namespace winPEAS.Checks { public void PrintInfo(bool isDebug) { - Beaprint.GreatPrint("Interesting Events information"); + Beaprint.GreatPrint("Interesting Events information"); new List { PrintExplicitLogonEvents, PrintLogonEvents, PrintProcessCreationEvents, - PrintPowerShellEvents + PrintPowerShellEvents, + PowerOnEvents, }.ForEach(action => CheckRunner.Run(action, isDebug)); } @@ -30,23 +32,13 @@ namespace winPEAS.Checks Beaprint.MainPrint("PowerShell events - script block logs (EID 4104) - searching for sensitive data.\n"); var powerShellEventInfos = PowerShell.GetPowerShellEventInfos(); - // TODO - // add highlighting for interesting words - var colors = new Dictionary() - { - { "TODO", Beaprint.ansi_color_bad } - }; - foreach (var info in powerShellEventInfos) { - // TODO - // formatting - try horizontal? - Beaprint.AnsiPrint($" User Id : {info.UserId}\n" + + Beaprint.NoColorPrint($" User Id : {info.UserId}\n" + $" Event Id : {info.EventId}\n" + $" Context : {info.Context}\n" + $" Created At : {info.CreatedAt}\n" + - $" Command line : {info.Match}\n", - colors); + $" Command line : {info.Match}\n"); Beaprint.PrintLineSeparator(); } @@ -69,19 +61,15 @@ namespace winPEAS.Checks return; } - // TODO - // formatting / highlighting? - foreach (var eventInfo in ProcessCreation.GetProcessCreationEventInfos()) { - Beaprint.BadPrint($" Created (UTC) : {eventInfo.CreatedAtUtc}\n" + - $" Event Id : {eventInfo.EventId}\n" + - $" User : {eventInfo.User}\n" + - $" Command Line : {eventInfo.Match}\n"); + Beaprint.BadPrint($" Created (UTC) : {eventInfo.CreatedAtUtc}\n" + + $" Event Id : {eventInfo.EventId}\n" + + $" User : {eventInfo.User}\n" + + $" Command Line : {eventInfo.Match}\n"); Beaprint.PrintLineSeparator(); } - } catch (Exception ex) { @@ -203,5 +191,27 @@ namespace winPEAS.Checks Beaprint.BadPrint($" {user}"); } } + + private void PowerOnEvents() + { + try + { + var lastDays = 5; + + Beaprint.MainPrint($"Displaying Power off/on events for last {lastDays} days\n"); + + var infos = Power.GetPowerEventInfos(lastDays); + + foreach (var info in infos) + { + Beaprint.NoColorPrint($" {info.DateUtc.ToLocalTime(),-23} : {info.Description}"); + } + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } } } diff --git a/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs index d722398..a0ba16d 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs @@ -129,6 +129,7 @@ namespace winPEAS.Checks PrintUserCredsFiles, PrintOracleSQLDeveloperConfigFiles, Slack.PrintInfo, + PrintOutlookDownloads, PrintMachineAndUserCertificateFiles, PrintUsersInterestingFiles, PrintUsersDocsKeys, @@ -815,5 +816,39 @@ namespace winPEAS.Checks { } } + + private static void PrintOutlookDownloads() + { + Beaprint.MainPrint("Enumerating Outlook download files\n"); + + try + { + var userDirs = User.GetUsersFolders(); + + foreach (var userDir in userDirs) + { + try + { + var userOutlookBasePath = $"{userDir}\\AppData\\Local\\Microsoft\\Windows\\INetCache\\Content.Outlook\\"; + + if (Directory.Exists(userOutlookBasePath)) + { + var files = SearchHelper.GetFilesFast(userOutlookBasePath, "*"); + + foreach (var file in files) + { + Beaprint.BadPrint($" {file.FullPath}"); + } + } + } + catch (Exception e) + { + } + } + } + catch (Exception ex) + { + } + } } } diff --git a/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs index 2714ff0..7f4c4ec 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs @@ -14,6 +14,7 @@ using winPEAS.Info.SystemInfo; using winPEAS.Info.SystemInfo.SysMon; using winPEAS.Helpers.Extensions; using winPEAS.Helpers.Registry; +using winPEAS.Info.SystemInfo.AuditPolicies; using winPEAS.Info.SystemInfo.DotNet; using winPEAS.Info.SystemInfo.WindowsDefender; @@ -57,6 +58,7 @@ namespace winPEAS.Checks PrintUserEV, PrintSystemEV, PrintAuditInfo, + PrintAuditPoliciesInfo, PrintWEFInfo, PrintLAPSInfo, PrintWdigest, @@ -250,7 +252,7 @@ namespace winPEAS.Checks } } - static void PrintAuditInfo() + private static void PrintAuditInfo() { try { @@ -265,6 +267,34 @@ namespace winPEAS.Checks } } + private static void PrintAuditPoliciesInfo() + { + try + { + Beaprint.MainPrint("Audit Policy Settings - Classic & Advanced"); + + var policies = AuditPolicies.GetAuditPoliciesInfos(); + + foreach (var policy in policies) + { + Beaprint.NoColorPrint($" Domain : {policy.Domain}\n" + + $" GPO : {policy.GPO}\n" + + $" Type : {policy.Type}\n"); + + foreach (var entry in policy.Settings) + { + Beaprint.NoColorPrint($" {entry.Subcategory,50} : {entry.AuditType}"); + } + + Beaprint.PrintLineSeparator(); + } + } + catch (Exception ex) + { + Beaprint.PrintException(ex.Message); + } + } + static void PrintWEFInfo() { try diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/Search/Patterns.cs b/winPEAS/winPEASexe/winPEAS/Helpers/Search/Patterns.cs index 4d7ae1a..f7c16e8 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/Search/Patterns.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/Search/Patterns.cs @@ -48,6 +48,7 @@ namespace winPEAS.Helpers.Search "iis6.log", "index.dat", "keepass.config", + "keepass.config.xml", "my.cnf", "my.ini", "netsetup.log", @@ -56,6 +57,7 @@ namespace winPEAS.Helpers.Search "pagefile.sys", "php.ini", "printers.xml", + "protecteduserkey.bin", "rdcman.settings", "recentservers.xml", "sam", diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs index 2a7ea00..1a9878a 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs @@ -60,7 +60,7 @@ namespace winPEAS.Helpers.Search return files.ToList(); } - public static List GetFiles(string folder, string pattern = "*") + private static List GetFiles(string folder, string pattern = "*") { DirectoryInfo dirInfo; DirectoryInfo[] directories; diff --git a/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/Power.cs b/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/Power.cs new file mode 100644 index 0000000..6b038a5 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/Power.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using winPEAS.Helpers; + +namespace winPEAS.Info.EventsInfo.Power +{ + internal class Power + { + public static IEnumerable GetPowerEventInfos(int lastDays) + { + var startTime = DateTime.Now.AddDays(-lastDays); + var endTime = DateTime.Now; + + // eventID 1 == sleep + var query = $@"((*[System[(EventID=12 or EventID=13) and Provider[@Name='Microsoft-Windows-Kernel-General']]] or *[System/EventID=42]) or (*[System/EventID=6008]) or (*[System/EventID=1] and *[System[Provider[@Name='Microsoft-Windows-Power-Troubleshooter']]])) and *[System[TimeCreated[@SystemTime >= '{startTime.ToUniversalTime():o}']]] and *[System[TimeCreated[@SystemTime <= '{endTime.ToUniversalTime():o}']]]"; + + var logReader = MyUtils.GetEventLogReader("System", query); + + for (var eventDetail = logReader.ReadEvent(); eventDetail != null; eventDetail = logReader.ReadEvent()) + { + var action = eventDetail.Id switch + { + 1 => "Awake", + 12 => "Startup", + 13 => "Shutdown", + 42 => "Sleep", + 6008 => "Unexpected Shutdown", + _ => null + }; + + yield return new PowerEventInfo + { + DateUtc = (DateTime)eventDetail.TimeCreated?.ToUniversalTime(), + Description = action + }; + } + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/PoweredEventInfo.cs b/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/PoweredEventInfo.cs new file mode 100644 index 0000000..b705725 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/EventsInfo/Power/PoweredEventInfo.cs @@ -0,0 +1,10 @@ +using System; + +namespace winPEAS.Info.EventsInfo.Power +{ + internal class PowerEventInfo + { + public DateTime DateUtc { get; set; } + public string Description { get; set; } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditEntryInfo.cs b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditEntryInfo.cs new file mode 100644 index 0000000..e5f77e3 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditEntryInfo.cs @@ -0,0 +1,22 @@ +namespace winPEAS.Info.SystemInfo.AuditPolicies +{ + internal class AuditEntryInfo + { + public string Target { get; } + public string Subcategory { get; } + public string SubcategoryGuid { get; } + public AuditType AuditType { get; } + + public AuditEntryInfo( + string target, + string subcategory, + string subcategoryGuid, + AuditType auditType) + { + Target = target; + Subcategory = subcategory; + SubcategoryGuid = subcategoryGuid; + AuditType = auditType; + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicies.cs b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicies.cs new file mode 100644 index 0000000..9fd1ef8 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicies.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using winPEAS.Helpers.Search; +using winPEAS.Native; + +namespace winPEAS.Info.SystemInfo.AuditPolicies +{ + internal class AuditPolicies + { + private static readonly string SystemRoot = Environment.GetEnvironmentVariable("SystemRoot"); + + // https://code.msdn.microsoft.com/windowsdesktop/Reading-and-Writing-Values-85084b6a + private static int Capacity = 512; + + public static IEnumerable GetAuditPoliciesInfos() + { + var searchPath = $"{SystemRoot}\\System32\\GroupPolicy\\DataStore\\0\\sysvol\\"; + var files = SearchHelper.GetFilesFast(searchPath, "audit.csv"); + var classicFiles = SearchHelper.GetFilesFast(searchPath, "GptTmpl.inf"); + + foreach (var classicFilePath in classicFiles) + { + var fullFilePath = classicFilePath.FullPath; + var result = ParseGPOPath(fullFilePath); + var domain = result[0]; + var gpo = result[1]; + + //ParseClassicPolicy + var sections = ReadSections(fullFilePath); + + if (!sections.Contains("Event Audit")) + continue; + + var settings = ParseClassicPolicy(fullFilePath); + + yield return new AuditPolicyGPOInfo( + classicFilePath.FullPath, + domain, + gpo, + "classic", + settings + ); + } + + foreach (var filePath in files) + { + var result = ParseGPOPath(filePath.FullPath); + var domain = result[0]; + var gpo = result[1]; + + var settings = ParseAdvancedPolicy(filePath.FullPath); + + yield return new AuditPolicyGPOInfo( + filePath.FullPath, + domain, + gpo, + "advanced", + settings + ); + } + } + + private static string[] ParseGPOPath(string path) + { + // returns an array of the domain and GPO GUID from an audit.csv (or GptTmpl.inf) path + + var searchPath = $"{Environment.GetEnvironmentVariable("SystemRoot")}\\System32\\GroupPolicy\\DataStore\\0\\sysvol\\"; + var sysnativeSearchPath = $"{Environment.GetEnvironmentVariable("SystemRoot")}\\Sysnative\\GroupPolicy\\DataStore\\0\\sysvol\\"; + var actualSearchPath = Regex.IsMatch(path, "System32") ? searchPath : sysnativeSearchPath; + + var rest = path.Substring(actualSearchPath.Length, path.Length - actualSearchPath.Length); + var parts = rest.Split('\\'); + string[] result = { parts[0], parts[2] }; + return result; + } + + private static string[] ReadSections(string filePath) + { + // first line will not recognize if ini file is saved in UTF-8 with BOM + while (true) + { + var chars = new char[Capacity]; + var size = Kernel32.GetPrivateProfileString(null, null, "", chars, Capacity, filePath); + + if (size == 0) + return new string[] { }; + + if (size < Capacity - 2) + { + var result = new string(chars, 0, size); + var sections = result.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); + return sections; + } + + Capacity *= 2; + } + } + + private static List ParseAdvancedPolicy(string path) + { + // parses a "advanced" auditing policy (audit.csv), returning a list of AuditEntries + + var results = new List(); + + using (var reader = new StreamReader(path)) + { + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + var values = line.Split(','); + + if (values[0].Equals("Machine Name")) // skip the header + { + continue; + } + + // CSV lines: + // Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value + + var target = values[1]; + var subcategory = values[2]; + var subcategoryGuid = values[3]; + var auditType = (AuditType)int.Parse(values[6]); + + results.Add(new AuditEntryInfo( + target, + subcategory, + subcategoryGuid, + auditType + )); + } + } + + return results; + } + + private static List ParseClassicPolicy(string path) + { + // parses a "classic" auditing policy (GptTmpl.inf), returning a list of AuditEntries + + var results = new List(); + + var settings = ReadKeyValuePairs("Event Audit", path); + foreach (var setting in settings) + { + var parts = setting.Split('='); + + var result = new AuditEntryInfo( + string.Empty, + parts[0], + string.Empty, + (AuditType)Int32.Parse(parts[1]) + ); + + results.Add(result); + } + + return results; + } + + private static string[] ReadKeyValuePairs(string section, string filePath) + { + while (true) + { + var returnedString = Marshal.AllocCoTaskMem(Capacity * sizeof(char)); + var size = Kernel32.GetPrivateProfileSection(section, returnedString, Capacity, filePath); + + if (size == 0) + { + Marshal.FreeCoTaskMem(returnedString); + return new string[] { }; + } + + if (size < Capacity - 2) + { + var result = Marshal.PtrToStringAuto(returnedString, size - 1); + Marshal.FreeCoTaskMem(returnedString); + var keyValuePairs = result.Split('\0'); + return keyValuePairs; + } + + Marshal.FreeCoTaskMem(returnedString); + Capacity *= 2; + } + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicyGPOInfo.cs b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicyGPOInfo.cs new file mode 100644 index 0000000..cba9a2a --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditPolicyGPOInfo.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace winPEAS.Info.SystemInfo.AuditPolicies +{ + internal class AuditPolicyGPOInfo + { + public string Path { get; } + public string Domain { get; } + public string GPO { get; } + public string Type { get; } + public List Settings { get; } + + public AuditPolicyGPOInfo( + string path, + string domain, + string gpo, + string type, + List settings) + { + Path = path; + Domain = domain; + GPO = gpo; + Type = type; + Settings = settings ?? new List(); + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditType.cs b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditType.cs new file mode 100644 index 0000000..0485c23 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/AuditPolicies/AuditType.cs @@ -0,0 +1,9 @@ +namespace winPEAS.Info.SystemInfo.AuditPolicies +{ + internal enum AuditType + { + Success = 1, + Failure = 2, + SuccessAndFailure = 3 + } +} diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Brave/Brave.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Brave/Brave.cs new file mode 100644 index 0000000..ae7656f --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Brave/Brave.cs @@ -0,0 +1,16 @@ +using System.IO; + +namespace winPEAS.KnownFileCreds.Browsers.Brave +{ + internal class Brave : ChromiumBase, IBrowser + { + public override string Name => "Brave Browser"; + + public override string BaseAppDataPath => Path.Combine(AppDataPath, "..\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\"); + + public override void PrintInfo() + { + PrintSavedCredentials(); + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome/Chrome.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome/Chrome.cs index 896d8e1..4234791 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome/Chrome.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome/Chrome.cs @@ -1,22 +1,18 @@ using System; using System.Collections.Generic; -using System.Data; using System.IO; using System.Text.RegularExpressions; using System.Web.Script.Serialization; using winPEAS.Checks; using winPEAS.Helpers; -using winPEAS.KnownFileCreds.Browsers.Decryptor; -using winPEAS.KnownFileCreds.Browsers.Models; -using winPEAS._3rdParty.SQLite; namespace winPEAS.KnownFileCreds.Browsers.Chrome { - internal class Chrome : BrowserBase, IBrowser + internal class Chrome : ChromiumBase, IBrowser { public override string Name => "Chrome"; - private const string LOGIN_DATA_PATH = "\\..\\Local\\Google\\Chrome\\User Data\\Default\\Login Data"; + public override string BaseAppDataPath => Path.Combine(AppDataPath, "..\\Local\\Google\\Chrome\\User Data\\Default\\"); public override void PrintInfo() { @@ -274,47 +270,5 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome } return results; } - - public override IEnumerable GetSavedCredentials() - { - var result = new List(); - - var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);// APPDATA - var p = Path.GetFullPath(appdata + LOGIN_DATA_PATH); - - if (File.Exists(p)) - { - SQLiteDatabase database = new SQLiteDatabase(p); - string query = "SELECT action_url, username_value, password_value FROM logins"; - DataTable resultantQuery = database.ExecuteQuery(query); - - if (resultantQuery.Rows.Count > 0) - { - var key = GCDecryptor.GetChromeKey(); - - foreach (DataRow row in resultantQuery.Rows) - { - byte[] nonce, ciphertextTag; - byte[] encryptedData = Convert.FromBase64String((string)row["password_value"]); - GCDecryptor.Prepare(encryptedData, out nonce, out ciphertextTag); - var pass = GCDecryptor.Decrypt(ciphertextTag, key, nonce); - - string actionUrl = row["action_url"] is System.DBNull ? string.Empty : (string)row["action_url"]; - string usernameValue = row["username_value"] is System.DBNull ? string.Empty : (string)row["username_value"]; - - result.Add(new CredentialModel() - { - Url = actionUrl, - Username = usernameValue, - Password = pass - }); - } - - database.CloseDatabase(); - } - } - - return result; - } } } diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/ChromiumBase.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/ChromiumBase.cs new file mode 100644 index 0000000..47c022e --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/ChromiumBase.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using winPEAS._3rdParty.SQLite; +using winPEAS.KnownFileCreds.Browsers.Decryptor; +using winPEAS.KnownFileCreds.Browsers.Models; + +namespace winPEAS.KnownFileCreds.Browsers +{ + internal abstract class ChromiumBase : BrowserBase + { + public static string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + public abstract string BaseAppDataPath { get; } + + public override IEnumerable GetSavedCredentials() + { + var result = new List(); + + var p = Path.Combine(BaseAppDataPath, "Login Data"); + var keyPath = Path.Combine(BaseAppDataPath, "..\\Local State"); + + if (File.Exists(p)) + { + SQLiteDatabase database = new SQLiteDatabase(p); + string query = "SELECT action_url, username_value, password_value FROM logins"; + DataTable resultantQuery = database.ExecuteQuery(query); + + if (resultantQuery.Rows.Count > 0) + { + var key = GCDecryptor.GetKey(keyPath); + + foreach (DataRow row in resultantQuery.Rows) + { + byte[] encryptedData = Convert.FromBase64String((string)row["password_value"]); + GCDecryptor.Prepare(encryptedData, out var nonce, out var cipherTextTag); + var pass = GCDecryptor.Decrypt(cipherTextTag, key, nonce); + + string actionUrl = row["action_url"] is System.DBNull ? string.Empty : (string)row["action_url"]; + string usernameValue = row["username_value"] is System.DBNull ? string.Empty : (string)row["username_value"]; + + result.Add(new CredentialModel + { + Url = actionUrl, + Username = usernameValue, + Password = pass + }); + } + + database.CloseDatabase(); + } + } + + return result; + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Decryptor/GCDecryptor.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Decryptor/GCDecryptor.cs index 73c7856..df534ef 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Decryptor/GCDecryptor.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Decryptor/GCDecryptor.cs @@ -12,21 +12,10 @@ namespace winPEAS.KnownFileCreds.Browsers.Decryptor { public static class GCDecryptor { - public static byte[] GetChromeKey() - { - return GetKey("\\..\\Local\\Google\\Chrome\\User Data\\Local State"); - } - - public static byte[] GetOperaKey() - { - return GetKey("\\..\\Roaming\\Opera Software\\Opera Stable\\Local State"); - } - public static byte[] GetKey(string localStatePath) { var sR = string.Empty; - var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);// APPDATA - var path = Path.GetFullPath(appdata + localStatePath); + var path = Path.GetFullPath(localStatePath); var v = File.ReadAllText(path); var json = new JavaScriptSerializer().Deserialize(v); diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Opera/Opera.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Opera/Opera.cs index 8a86e3c..3ba9975 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Opera/Opera.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Opera/Opera.cs @@ -1,64 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using winPEAS.KnownFileCreds.Browsers.Decryptor; -using winPEAS.KnownFileCreds.Browsers.Models; -using winPEAS._3rdParty.SQLite; +using System.IO; namespace winPEAS.KnownFileCreds.Browsers.Opera { - internal class Opera : BrowserBase, IBrowser + internal class Opera : ChromiumBase, IBrowser { public override string Name => "Opera"; - private const string LOGIN_DATA_PATH = "\\..\\Roaming\\Opera Software\\Opera Stable\\Login Data"; - public override void PrintInfo() { PrintSavedCredentials(); } - public override IEnumerable GetSavedCredentials() - { - var result = new List(); - - var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);// APPDATA - var p = Path.GetFullPath(appdata + LOGIN_DATA_PATH); - - if (File.Exists(p)) - { - SQLiteDatabase database = new SQLiteDatabase(p); - string query = "SELECT action_url, username_value, password_value FROM logins"; - DataTable resultantQuery = database.ExecuteQuery(query); - - if (resultantQuery.Rows.Count > 0) - { - var key = GCDecryptor.GetOperaKey(); - - foreach (DataRow row in resultantQuery.Rows) - { - byte[] nonce, ciphertextTag; - byte[] encryptedData = Convert.FromBase64String((string)row["password_value"]); - GCDecryptor.Prepare(encryptedData, out nonce, out ciphertextTag); - var pass = GCDecryptor.Decrypt(ciphertextTag, key, nonce); - - string actionUrl = row["action_url"] is System.DBNull ? string.Empty : (string)row["action_url"]; - string usernameValue = row["username_value"] is System.DBNull ? string.Empty : (string)row["username_value"]; - - result.Add(new CredentialModel() - { - Url = actionUrl, - Username = usernameValue, - Password = pass - }); - } - - database.CloseDatabase(); - } - } - - return result; - } + public override string BaseAppDataPath => Path.Combine(AppDataPath, "..\\Roaming\\Opera Software\\Opera Stable"); } } diff --git a/winPEAS/winPEASexe/winPEAS/Native/Kernel32.cs b/winPEAS/winPEASexe/winPEAS/Native/Kernel32.cs index f35b1b8..09d0e12 100644 --- a/winPEAS/winPEASexe/winPEAS/Native/Kernel32.cs +++ b/winPEAS/winPEASexe/winPEAS/Native/Kernel32.cs @@ -60,5 +60,12 @@ namespace winPEAS.Native [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool FreeLibrary(IntPtr lib); - } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal static extern int GetPrivateProfileSection(string section, IntPtr keyValue, int size, string filePath); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal static extern int GetPrivateProfileString(string? section, string? key, string defaultValue, [In, Out] char[] value, int size, string filePath); + + } } diff --git a/winPEAS/winPEASexe/winPEAS/winPEAS.csproj b/winPEAS/winPEASexe/winPEAS/winPEAS.csproj index ec91849..c4e50fa 100755 --- a/winPEAS/winPEASexe/winPEAS/winPEAS.csproj +++ b/winPEAS/winPEASexe/winPEAS/winPEAS.csproj @@ -408,6 +408,8 @@ + + @@ -432,6 +434,10 @@ + + + + @@ -454,9 +460,11 @@ + +