diff --git a/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs index 2abb2a2..60644e1 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/FilesInfo.cs @@ -101,7 +101,7 @@ namespace winPEAS.Checks "winscp.ini", "ws_ftp.ini", "wsl.exe", - }; + }; public void PrintInfo(bool isDebug) @@ -252,20 +252,27 @@ namespace winPEAS.Checks { try { - string[] pass_reg_hkcu = new string[] { @"Software\ORL\WinVNC3\Password", @"Software\TightVNC\Server", @"Software\SimonTatham\PuTTY\Sessions" }; - string[] pass_reg_hklm = new string[] { @"SYSTEM\CurrentControlSet\Services\SNMP" }; + string[] passRegHkcu = new string[] { @"Software\ORL\WinVNC3\Password", @"Software\TightVNC\Server", @"Software\SimonTatham\PuTTY\Sessions" }; + string[] passRegHklm = new string[] { @"SYSTEM\CurrentControlSet\Services\SNMP" }; Beaprint.MainPrint("Looking for possible regs with creds"); Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#inside-the-registry"); - string winVNC4 = RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\RealVNC\WinVNC4", "passwword"); - if (!string.IsNullOrEmpty(winVNC4.Trim())) - Beaprint.BadPrint(winVNC4); + string winVnc4 = RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\RealVNC\WinVNC4", "passwword"); + if (!string.IsNullOrEmpty(winVnc4.Trim())) + { + Beaprint.BadPrint(winVnc4); + } - foreach (string reg_hkcu in pass_reg_hkcu) - Beaprint.DictPrint(RegistryHelper.GetRegValues("HKLM", reg_hkcu), false); - foreach (string reg_hklm in pass_reg_hklm) - Beaprint.DictPrint(RegistryHelper.GetRegValues("HKLM", reg_hklm), false); + foreach (string regHkcu in passRegHkcu) + { + Beaprint.DictPrint(RegistryHelper.GetRegValues("HKLM", regHkcu), false); + } + + foreach (string regHklm in passRegHklm) + { + Beaprint.DictPrint(RegistryHelper.GetRegValues("HKLM", regHklm), false); + } } catch (Exception ex) { @@ -277,11 +284,7 @@ namespace winPEAS.Checks { try { - string patterns = "*credential*;*password*"; - string pattern_color = "[cC][rR][eE][dD][eE][nN][tT][iI][aA][lL]|[pP][aA][sS][sS][wW][oO][rR][dD]"; - - var valid_extensions = new List() { ".txt", ".conf", ".cnf", ".yml", ".yaml", ".doc", ".docx", ".xlsx", ".json", ".xml" }; - + string pattern_color = "[cC][rR][eE][dD][eE][nN][tT][iI][aA][lL]|[pP][aA][sS][sS][wW][oO][rR][dD]"; var validExtensions = new HashSet { ".cnf", @@ -302,13 +305,11 @@ namespace winPEAS.Checks }; Beaprint.MainPrint("Looking for possible password files in users homes"); - Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files"); - string searchPath = $"{Environment.GetEnvironmentVariable("SystemDrive") + "\\Users"}\\"; - List fileInfos = SearchHelper.SearchUserCredsFiles(); + Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files"); + var fileInfos = SearchHelper.SearchUserCredsFiles(); foreach (var fileInfo in fileInfos) { - // if (!Path.GetFileName(file_path).Contains(".")) if (!fileInfo.Filename.Contains(".")) { Beaprint.AnsiPrint(" " + fileInfo.FullPath, colorF); @@ -321,14 +322,6 @@ namespace winPEAS.Checks { Beaprint.AnsiPrint(" " + fileInfo.FullPath, colorF); } - - //foreach (string ext in valid_extensions) - //{ - // if (file_path.Contains(ext)) - // { - // Beaprint.AnsiPrint(" " + file_path, colorF); - // } - //} } } } @@ -345,7 +338,6 @@ namespace winPEAS.Checks //string pattern_bin = _patternsFileCreds + ";*password*;*credential*"; string pattern_bin = string.Join(";", patternsFileCreds) + ";*password*;*credential*"; - Dictionary colorF = new Dictionary() { { _patternsFileCredsColor + "|.*password.*|.*credential.*", Beaprint.ansi_color_bad }, @@ -405,8 +397,8 @@ namespace winPEAS.Checks try { Beaprint.MainPrint("Looking for documents --limit 100--"); - List doc_files = InterestingFiles.InterestingFiles.ListUsersDocs(); - Beaprint.ListPrint(doc_files.GetRange(0, doc_files.Count <= 100 ? doc_files.Count : 100)); + List docFiles = InterestingFiles.InterestingFiles.ListUsersDocs(); + Beaprint.ListPrint(docFiles.GetRange(0, docFiles.Count <= 100 ? docFiles.Count : 100)); } catch (Exception ex) { @@ -432,7 +424,6 @@ namespace winPEAS.Checks { Beaprint.AnsiPrint(" " + recF["Target"] + "(" + recF["Accessed"] + ")", colorF); } - } else { diff --git a/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs index 7a71a79..6f800e3 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs @@ -1,7 +1,10 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Runtime.InteropServices; using winPEAS.Helpers; +using winPEAS.Helpers.AppLocker; using winPEAS._3rdParty.Watson; namespace winPEAS.Checks @@ -36,6 +39,8 @@ namespace winPEAS.Checks PrintDrivesInfo, PrintWSUS, PrintAlwaysInstallElevated, + PrintLsaCompatiblityLevel, + PrintApplockerPolicy }.ForEach(action => CheckRunner.Run(action, isDebug)); } @@ -69,10 +74,10 @@ namespace winPEAS.Checks try { Dictionary colorsPSI = new Dictionary() - { - { "PS history file: .+", Beaprint.ansi_color_bad }, - { "PS history size: .+", Beaprint.ansi_color_bad } - }; + { + { "PS history file: .+", Beaprint.ansi_color_bad }, + { "PS history size: .+", Beaprint.ansi_color_bad } + }; Beaprint.MainPrint("PowerShell Settings"); Dictionary PSs = Info.SystemInfo.SystemInfo.GetPowerShellSettings(); Beaprint.DictPrint(PSs, colorsPSI, false); @@ -90,20 +95,61 @@ namespace winPEAS.Checks Beaprint.MainPrint("PS default transcripts history"); Beaprint.InfoPrint("Read the PS history inside these files (if any)"); string drive = Path.GetPathRoot(Environment.SystemDirectory); - string path = drive + @"transcripts\"; - if (Directory.Exists(path)) + string transcriptsPath = drive + @"transcripts\"; + string usersPath = $"{drive}users"; + + string[] users = Directory.GetDirectories(usersPath, "*", SearchOption.TopDirectoryOnly); + string powershellTranscriptFilter = "powershell_transcript*"; + + var colors = new Dictionary() { - string[] fileEntries = Directory.GetFiles(path); - List fileEntriesl = new List(fileEntries); - if (fileEntries.Length > 0) + { "^.*", Beaprint.ansi_color_bad }, + }; + + var results = new List(); + + var dict = new Dictionary() + { + // check \\transcripts\ folder + {transcriptsPath, "*"}, + }; + + foreach (var user in users) + { + // check the users directories + dict.Add($"{user}\\Documents", powershellTranscriptFilter); + } + + foreach (var kvp in dict) + { + var path = kvp.Key; + var filter = kvp.Value; + + if (Directory.Exists(path)) { - Dictionary colors = new Dictionary() + try + { + var files = Directory.GetFiles(path, filter, SearchOption.TopDirectoryOnly).ToList(); + + foreach (var file in files) { - { "^.*", Beaprint.ansi_color_bad }, - }; - Beaprint.ListPrint(fileEntriesl, colors); + var fileInfo = new FileInfo(file); + var humanReadableSize = MyUtils.ConvertBytesToHumanReadable(fileInfo.Length); + var item = $"[{humanReadableSize}] - {file}"; + + results.Add(item); + } + } + catch (UnauthorizedAccessException) { } + catch (PathTooLongException) { } + catch (DirectoryNotFoundException) { } } } + + if (results.Count > 0) + { + Beaprint.ListPrint(results, colors); + } } catch (Exception ex) { @@ -425,5 +471,88 @@ namespace winPEAS.Checks Beaprint.PrintException(ex.Message); } } + + private void PrintLsaCompatiblityLevel() + { + try + { + string hive = "HKLM"; + string path = "SYSTEM\\CurrentControlSet\\Control\\Lsa\\"; + string key = "LmCompatibilityLevel"; + + Beaprint.MainPrint($"Checking {hive}\\{path}{key}"); + + string lmCompatibilityLevelValue = RegistryHelper.GetRegValue(hive, path, key); + Dictionary dict = new Dictionary() + { + { 0, "Send LM & NTLM responses" }, + { 1, "Send LM & NTLM responses, use NTLMv2 session security if negotiated" }, + { 2, "Send NTLM response only" }, + { 3, "Send NTLMv2 response only" }, + { 4, "Send NTLMv2 response only, refuse LM" }, + { 5, "Send NTLMv2 response only, refuse LM & NTLM" }, + }; + + if (!string.IsNullOrEmpty(lmCompatibilityLevelValue)) + { + if (int.TryParse(lmCompatibilityLevelValue, out int lmCompatibilityLevel)) + { + string color = lmCompatibilityLevel == 5 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad; + + if (dict.TryGetValue(lmCompatibilityLevel, out string description)) + { + Beaprint.ColorPrint($" value: {lmCompatibilityLevel}, description: {description}", color); + } + else + { + throw new Exception($"Unable to get value description for value '{lmCompatibilityLevel}'"); + } + } + else + { + throw new Exception($"Unable to parse {key} value '{lmCompatibilityLevelValue}'"); + } + } + else + { + Beaprint.ColorPrint(" The registry key does not exist", Beaprint.ansi_color_yellow); + } + } + catch (Exception ex) + { + Beaprint.PrintException(ex.Message); + } + } + + private static void PrintApplockerPolicy() + { + Beaprint.MainPrint("Checking AppLocker effective policy"); + + try + { + string[] ruleTypes = new string[] { "All" }; + string ldapPath = ""; + bool allowOnly = false; + bool denyOnly = false; + + string applockerSettings = SharpAppLocker.GetAppLockerPolicy(SharpAppLocker.PolicyType.Effective, ruleTypes, ldapPath, allowOnly, denyOnly); + var colors = new Dictionary() + { + { "/>", Beaprint.DGRAY }, + { "<", Beaprint.DGRAY }, + { "NotConfigured", Beaprint.ansi_color_bad }, + }; + + Beaprint.AnsiPrint(applockerSettings, colors); + } + catch (COMException ex) + { + Beaprint.ColorPrint(" AppLocker unsupported on this Windows version.", Beaprint.ansi_color_yellow); + } + catch (Exception ex) + { + Beaprint.PrintException(ex.Message); + } + } } } diff --git a/winPEAS/winPEASexe/winPEAS/Checks/UserInfo.cs b/winPEAS/winPEASexe/winPEAS/Checks/UserInfo.cs index 64bccbc..a1ab997 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/UserInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/UserInfo.cs @@ -225,7 +225,7 @@ namespace winPEAS.Checks { Beaprint.MainPrint("Looking for AutoLogon credentials"); bool ban = false; - Dictionary autologon = Info.UserInfo.UserInfoHelper.GetAutoLogon(); + Dictionary autologon = UserInfoHelper.GetAutoLogon(); if (autologon.Count > 0) { foreach (KeyValuePair entry in autologon) @@ -234,7 +234,7 @@ namespace winPEAS.Checks { if (!ban) { - Beaprint.BadPrint(" Some AutoLogon credentials were found!!"); + Beaprint.BadPrint(" Some AutoLogon credentials were found"); ban = true; } Beaprint.AnsiPrint(string.Format(" {0,-30}: {1}", entry.Key, entry.Value), ColorsU()); diff --git a/winPEAS/winPEASexe/winPEAS/Checks/WindowsCreds.cs b/winPEAS/winPEASexe/winPEAS/Checks/WindowsCreds.cs index 6a28e47..5bde69e 100644 --- a/winPEAS/winPEASexe/winPEAS/Checks/WindowsCreds.cs +++ b/winPEAS/winPEASexe/winPEAS/Checks/WindowsCreds.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; using winPEAS.Helpers; +using winPEAS.Helpers.CredentialManager; using winPEAS.KnownFileCreds; using winPEAS.KnownFileCreds.Kerberos; using winPEAS.KnownFileCreds.Vault; @@ -70,15 +71,40 @@ namespace winPEAS.Checks } else { - Beaprint.GrayPrint(" This function is not yet implemented."); - Beaprint.InfoPrint("If you want to list credentials inside Credential Manager use 'cmdkey /list'"); + var colorsC = new Dictionary() + { + { "Warning:", Beaprint.YELLOW }, + }; + Beaprint.AnsiPrint(" [!] Warning: if password contains non-printable characters, it will be printed as unicode base64 encoded string\n\n", colorsC); + + var keywords = new HashSet + { + nameof(Credential.Password), + nameof(Credential.Username), + nameof(Credential.Target), + nameof(Credential.PersistenceType), + nameof(Credential.LastWriteTime), + }; + + colorsC = new Dictionary() + { + { CredentialManager.UnicodeInfoText, Beaprint.LBLUE } + }; + + foreach (var keyword in keywords) + { + colorsC.Add($"{keyword}:", Beaprint.ansi_color_bad); + } + + var credentials = CredentialManager.GetCredentials(); + + Beaprint.ListPrint(credentials, colorsC); } } catch (Exception ex) { Beaprint.PrintException(ex.Message); } - } static void PrintSavedRDPInfo() diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/AppLockerRules.cs b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/AppLockerRules.cs new file mode 100644 index 0000000..c506341 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/AppLockerRules.cs @@ -0,0 +1,676 @@ +using System.Collections.Generic; + +namespace winPEAS.Helpers.AppLocker +{ + // NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0. + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] + public partial class AppLockerPolicy + { + + private AppLockerPolicyRuleCollection[] ruleCollectionField; + + private byte versionField; + + /// + [System.Xml.Serialization.XmlElementAttribute("RuleCollection")] + public AppLockerPolicyRuleCollection[] RuleCollection + { + get + { + return this.ruleCollectionField; + } + set + { + this.ruleCollectionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte Version + { + get + { + return this.versionField; + } + set + { + this.versionField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollection + { + + private List fileHashRuleField; + + private List filePathRuleField; + + private List filePublisherRuleField; + + private string typeField; + + private string enforcementModeField; + + /// + [System.Xml.Serialization.XmlElementAttribute("FileHashRule")] + public List FileHashRule + { + get + { + return this.fileHashRuleField; + } + set + { + this.fileHashRuleField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("FilePathRule")] + public List FilePathRule + { + get + { + return this.filePathRuleField; + } + set + { + this.filePathRuleField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("FilePublisherRule")] + public List FilePublisherRule + { + get + { + return this.filePublisherRuleField; + } + set + { + this.filePublisherRuleField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type + { + get + { + return this.typeField; + } + set + { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string EnforcementMode + { + get + { + return this.enforcementModeField; + } + set + { + this.enforcementModeField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFileHashRule + { + + private AppLockerPolicyRuleCollectionFileHashRuleFileHashCondition[] conditionsField; + + private string idField; + + private string nameField; + + private string descriptionField; + + private string userOrGroupSidField; + + private string actionField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("FileHashCondition", IsNullable = false)] + public AppLockerPolicyRuleCollectionFileHashRuleFileHashCondition[] Conditions + { + get + { + return this.conditionsField; + } + set + { + this.conditionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Id + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description + { + get + { + return this.descriptionField; + } + set + { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string UserOrGroupSid + { + get + { + return this.userOrGroupSidField; + } + set + { + this.userOrGroupSidField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Action + { + get + { + return this.actionField; + } + set + { + this.actionField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFileHashRuleFileHashCondition + { + + private AppLockerPolicyRuleCollectionFileHashRuleFileHashConditionFileHash fileHashField; + + /// + public AppLockerPolicyRuleCollectionFileHashRuleFileHashConditionFileHash FileHash + { + get + { + return this.fileHashField; + } + set + { + this.fileHashField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFileHashRuleFileHashConditionFileHash + { + + private string typeField; + + private string dataField; + + private string sourceFileNameField; + + private uint sourceFileLengthField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type + { + get + { + return this.typeField; + } + set + { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Data + { + get + { + return this.dataField; + } + set + { + this.dataField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceFileName + { + get + { + return this.sourceFileNameField; + } + set + { + this.sourceFileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint SourceFileLength + { + get + { + return this.sourceFileLengthField; + } + set + { + this.sourceFileLengthField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFilePathRule + { + + private AppLockerPolicyRuleCollectionFilePathRuleFilePathCondition[] conditionsField; + + private string idField; + + private string nameField; + + private string descriptionField; + + private string userOrGroupSidField; + + private string actionField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("FilePathCondition", IsNullable = false)] + public AppLockerPolicyRuleCollectionFilePathRuleFilePathCondition[] Conditions + { + get + { + return this.conditionsField; + } + set + { + this.conditionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Id + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description + { + get + { + return this.descriptionField; + } + set + { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string UserOrGroupSid + { + get + { + return this.userOrGroupSidField; + } + set + { + this.userOrGroupSidField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Action + { + get + { + return this.actionField; + } + set + { + this.actionField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFilePathRuleFilePathCondition + { + + private string pathField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Path + { + get + { + return this.pathField; + } + set + { + this.pathField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFilePublisherRule + { + + private AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherCondition[] conditionsField; + + private string idField; + + private string nameField; + + private string descriptionField; + + private string userOrGroupSidField; + + private string actionField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("FilePublisherCondition", IsNullable = false)] + public AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherCondition[] Conditions + { + get + { + return this.conditionsField; + } + set + { + this.conditionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Id + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description + { + get + { + return this.descriptionField; + } + set + { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string UserOrGroupSid + { + get + { + return this.userOrGroupSidField; + } + set + { + this.userOrGroupSidField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Action + { + get + { + return this.actionField; + } + set + { + this.actionField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherCondition + { + + private AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherConditionBinaryVersionRange binaryVersionRangeField; + + private string publisherNameField; + + private string productNameField; + + private string binaryNameField; + + /// + public AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherConditionBinaryVersionRange BinaryVersionRange + { + get + { + return this.binaryVersionRangeField; + } + set + { + this.binaryVersionRangeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PublisherName + { + get + { + return this.publisherNameField; + } + set + { + this.publisherNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProductName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string BinaryName + { + get + { + return this.binaryNameField; + } + set + { + this.binaryNameField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class AppLockerPolicyRuleCollectionFilePublisherRuleFilePublisherConditionBinaryVersionRange + { + + private string lowSectionField; + + private string highSectionField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string LowSection + { + get + { + return this.lowSectionField; + } + set + { + this.lowSectionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string HighSection + { + get + { + return this.highSectionField; + } + set + { + this.highSectionField = value; + } + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/IAppIdPolicyHandler.cs b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/IAppIdPolicyHandler.cs new file mode 100644 index 0000000..ad7bbcc --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/IAppIdPolicyHandler.cs @@ -0,0 +1,83 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace winPEAS.Helpers.AppLocker +{ + [Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")] + [TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)] + [ComImport] + public interface IAppIdPolicyHandler + { + // Token: 0x06000001 RID: 1 + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy); + + // Token: 0x06000002 RID: 2 + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath); + + // Token: 0x06000003 RID: 3 + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + string GetEffectivePolicy(); + + // Token: 0x06000004 RID: 4 + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId); + + // Token: 0x06000005 RID: 5 + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId); + } + + // Token: 0x02000003 RID: 3 + [CoClass(typeof(AppIdPolicyHandlerClass))] + [Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")] + [ComImport] + public interface AppIdPolicyHandler : IAppIdPolicyHandler + { + } + + // Token: 0x02000004 RID: 4 + [Guid("F1ED7D4C-F863-4DE6-A1CA-7253EFDEE1F3")] + [ClassInterface(ClassInterfaceType.None)] + [TypeLibType(TypeLibTypeFlags.FCanCreate)] + [ComImport] + public class AppIdPolicyHandlerClass : IAppIdPolicyHandler, AppIdPolicyHandler + { + + // Token: 0x06000007 RID: 7 + [DispId(1)] + [MethodImpl(MethodImplOptions.InternalCall)] + public virtual extern void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy); + + // Token: 0x06000008 RID: 8 + [DispId(2)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + public virtual extern string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath); + + // Token: 0x06000009 RID: 9 + [DispId(3)] + [MethodImpl(MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.BStr)] + public virtual extern string GetEffectivePolicy(); + + // Token: 0x0600000A RID: 10 + [DispId(4)] + [MethodImpl(MethodImplOptions.InternalCall)] + public virtual extern int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId); + + // Token: 0x0600000B RID: 11 + [DispId(5)] + [MethodImpl(MethodImplOptions.InternalCall)] + public virtual extern int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId); + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/SharpAppLocker.cs b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/SharpAppLocker.cs new file mode 100644 index 0000000..3c7aa30 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/AppLocker/SharpAppLocker.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace winPEAS.Helpers.AppLocker +{ + // https://github.com/Flangvik/SharpAppLocker + + public class SharpAppLocker + { + public enum PolicyType + { + Local, + Domain, + Effective + } + + public static T DeserializeToObject(string xmlData) where T : class + { + System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T)); + + using (StreamReader sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(xmlData)))) + { + return (T)ser.Deserialize(sr); + } + } + + + public static string GetAppLockerPolicy(PolicyType policyType, string[] appLockerRuleTypes, string ldapPath = "", bool allowOnly = false, bool denyOnly = false) + { + + // Create IAppIdPolicyHandler COM interface + IAppIdPolicyHandler IAppHandler = new AppIdPolicyHandlerClass(); + string policies; + + switch (policyType) + { + case PolicyType.Local: + case PolicyType.Domain: + policies = IAppHandler.GetPolicy(ldapPath); + break; + + case PolicyType.Effective: + policies = IAppHandler.GetEffectivePolicy(); + break; + + default: + throw new InvalidOperationException(); + }; + + /* + var objectHolder = DeserializeToObject(policies); + AppLockerPolicy appLockerPolicyFiltered = DeserializeToObject(policies); + if (objectHolder?.RuleCollection?.Count() > 0) + { + + + //Null them all out to emtpy lists + for (int i = 0; i < appLockerPolicyFiltered.RuleCollection.Length; i++) + { + appLockerPolicyFiltered.RuleCollection[i].FileHashRule = new List() { }; + appLockerPolicyFiltered.RuleCollection[i].FilePathRule = new List() { }; + appLockerPolicyFiltered.RuleCollection[i].FilePublisherRule = new List() { }; + } + + for (int i = 0; i < objectHolder?.RuleCollection.Count(); i++) + { + if (objectHolder?.RuleCollection[i].FilePathRule != null) + { + if (appLockerRuleTypes.Contains("All", StringComparer.InvariantCultureIgnoreCase) || appLockerRuleTypes.Contains("FilePathRule", StringComparer.InvariantCultureIgnoreCase)) + { + foreach (var pathRule in objectHolder?.RuleCollection[i].FilePathRule) + { + if (allowOnly || denyOnly) + { + if (pathRule.Action.Equals(allowOnly ? "Allow" : "Deny")) + { + appLockerPolicyFiltered.RuleCollection[i].FilePathRule.Add(pathRule); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + else + { + appLockerPolicyFiltered.RuleCollection[i].FilePathRule.Add(pathRule); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + } + } + if (objectHolder?.RuleCollection[i].FileHashRule != null) + { + if (appLockerRuleTypes.Contains("All", StringComparer.InvariantCultureIgnoreCase) || appLockerRuleTypes.Contains("FileHashRule", StringComparer.InvariantCultureIgnoreCase)) + { + foreach (var hashRule in objectHolder?.RuleCollection[i].FileHashRule) + { + if (allowOnly || denyOnly) + { + if (hashRule.Action.Equals(allowOnly ? "Allow" : "Deny")) + { + appLockerPolicyFiltered.RuleCollection[i].FileHashRule.Add(hashRule); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + else + { + appLockerPolicyFiltered.RuleCollection[i].FileHashRule.Add(hashRule); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + } + } + if (objectHolder?.RuleCollection[i].FilePublisherRule != null) + { + if (appLockerRuleTypes.Contains("All", StringComparer.InvariantCultureIgnoreCase) || appLockerRuleTypes.Contains("FilePublisherRule", StringComparer.InvariantCultureIgnoreCase)) + { + foreach (var pubRile in objectHolder?.RuleCollection[i].FilePublisherRule.ToArray()) + { + if (allowOnly || denyOnly) + { + if (pubRile.Action.Equals(allowOnly ? "Allow" : "Deny")) + { + appLockerPolicyFiltered.RuleCollection[i].FilePublisherRule.Add(pubRile); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + else + { + appLockerPolicyFiltered.RuleCollection[i].FilePublisherRule.Add(pubRile); + //outputBuilder.Append(JsonConvert.SerializeObject(pathRule, Newtonsoft.Json.Formatting.Indented)); + } + } + } + } + } + + //Remove all the empty stuff + appLockerPolicyFiltered.RuleCollection = appLockerPolicyFiltered.RuleCollection.Where(x => + + x.FilePublisherRule.Count() > 0 || + x.FilePathRule.Count() > 0 || + x.FileHashRule.Count() > 0 + + ).ToArray(); + + return JsonConvert.SerializeObject(appLockerPolicyFiltered, Newtonsoft.Json.Formatting.Indented); + + + } + return JsonConvert.SerializeObject(objectHolder, Newtonsoft.Json.Formatting.Indented); + */ + + policies = policies.Replace("><", ">\n<"); + + return policies; + } + } + +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/Beaprint.cs b/winPEAS/winPEASexe/winPEAS/Helpers/Beaprint.cs index 95db8cc..59c6da8 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/Beaprint.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/Beaprint.cs @@ -43,7 +43,7 @@ namespace winPEAS.Helpers ///////////////////////////////// public static void PrintBanner() { - Console.WriteLine(BLUE + String.Format(@" + Console.WriteLine(BLUE + string.Format(@" {0}*((,.,/((((((((((((((((((((/, */ {0},/*,..*((((((((((((((((((((((((((((((((((, {0},*/((((((((((((((((((/, .*//((//**, .*(((((((* @@ -173,6 +173,11 @@ namespace winPEAS.Helpers Console.WriteLine(RED + to_print + NOCOLOR); } + public static void ColorPrint(string to_print, string color) + { + Console.WriteLine(color + to_print + NOCOLOR); + } + public static void GrayPrint(string to_print) { Console.WriteLine(DGRAY + to_print + NOCOLOR); @@ -203,7 +208,9 @@ namespace winPEAS.Helpers { string new_line = line; foreach (KeyValuePair color in ansi_colors_regexp) + { new_line = Regexansi(new_line, color.Value, color.Key); + } Console.WriteLine(new_line); } @@ -227,7 +234,7 @@ namespace winPEAS.Helpers { foreach (KeyValuePair entry in dicprint) { - if (delete_nulls && String.IsNullOrEmpty(entry.Value.Trim())) + if (delete_nulls && string.IsNullOrEmpty(entry.Value.Trim())) { continue; } @@ -259,7 +266,7 @@ namespace winPEAS.Helpers { foreach (KeyValuePair entry in dicprint) { - if (delete_nulls && String.IsNullOrEmpty(entry.Value)) + if (delete_nulls && string.IsNullOrEmpty(entry.Value)) { continue; } @@ -296,7 +303,7 @@ namespace winPEAS.Helpers Dictionary results = new Dictionary(); foreach (KeyValuePair entry in dicprint) { - results[entry.Key] = String.Format("{0}", entry.Value); + results[entry.Key] = string.Format("{0}", entry.Value); } DictPrint(results, delete_nulls); diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/Credential.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/Credential.cs new file mode 100644 index 0000000..72af64a --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/Credential.cs @@ -0,0 +1,397 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Text; + +namespace winPEAS.Helpers.CredentialManager +{ + /// + /// Class Credential, wrapper for native CREDENTIAL structure. + /// See CREDENTIAL structure + /// documentation. + /// See Credential Manager + /// documentation. + /// + internal class Credential : IDisposable + { + /// + /// The lock object + /// + private static readonly object LockObject = new object(); + + /// + /// The unmanaged code permission + /// + private static readonly SecurityPermission UnmanagedCodePermission; + + /// + /// The credential description + /// + private string description; + + /// + /// The disposed flag + /// + private bool disposed; + + /// + /// The last write time + /// + private DateTime lastWriteTime; + + /// + /// The password + /// + private SecureString password; + + /// + /// The persistence type + /// + private PersistenceType persistenceType; + + /// + /// The string that contains the name of the credential + /// + private string target; + + /// + /// The credential type + /// + private CredentialType type; + + /// + /// The username + /// + private string username; + + /// + /// Initializes UnmanagedCodePermission for the class. + /// + static Credential() + { + lock (LockObject) + { + UnmanagedCodePermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + } + } + + /// + /// Initializes a new instance of the class. + /// + public Credential() + : this(null) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The username. + public Credential(string username) + : this(username, null) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The username. + /// The password. + public Credential(string username, string password) + : this(username, password, null) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The username. + /// The password. + /// The string that contains the name of the credential. + public Credential(string username, string password, string target) + : this(username, password, target, CredentialType.Generic) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The username. + /// The password. + /// The string that contains the name of the credential. + /// The credential type. + public Credential(string username, string password, string target, CredentialType type) + { + Username = username; + Password = password; + Target = target; + Type = type; + PersistenceType = PersistenceType.Session; + lastWriteTime = DateTime.MinValue; + } + + /// + /// Gets or sets the username. + /// + /// The user name of the account used to connect to TargetName. + public string Username + { + get + { + CheckNotDisposed(); + return username; + } + set + { + CheckNotDisposed(); + username = value; + } + } + + /// + /// Gets or sets the password. + /// + /// The decoded secure string password. + public string Password + { + get { return SecureStringHelper.CreateString(SecurePassword); } + set + { + CheckNotDisposed(); + SecurePassword = + SecureStringHelper.CreateSecureString(string.IsNullOrEmpty(value) ? string.Empty : value); + } + } + + /// + /// Gets or sets the secure password. + /// + /// The secure password of the account used to connect to TargetName. + public SecureString SecurePassword + { + get + { + CheckNotDisposed(); + UnmanagedCodePermission.Demand(); + return null == password ? new SecureString() : password.Copy(); + } + set + { + CheckNotDisposed(); + if (null != password) + { + password.Clear(); + password.Dispose(); + } + password = null == value ? new SecureString() : value.Copy(); + } + } + + /// + /// Gets or sets the target. + /// + /// + /// The name of the credential. The TargetName and Type members uniquely identify the credential. This member cannot + /// be changed after the credential is created. Instead, the credential with the old name should be deleted and the + /// credential with the new name created. + /// + public string Target + { + get + { + CheckNotDisposed(); + return target; + } + set + { + CheckNotDisposed(); + target = value; + } + } + + /// + /// Gets or sets the description. + /// + /// + /// The string comment from the user that describes this credential. This member cannot be longer than + /// CRED_MAX_STRING_LENGTH (256) characters. + /// + public string Description + { + get + { + CheckNotDisposed(); + return description; + } + set + { + CheckNotDisposed(); + description = value; + } + } + + /// + /// Gets the last write time. + /// + /// The last write time. + public DateTime LastWriteTime + { + get { return LastWriteTimeUtc.ToLocalTime(); } + } + + /// + /// Gets the last write time UTC. + /// + /// The last write time UTC. + public DateTime LastWriteTimeUtc + { + get + { + CheckNotDisposed(); + return lastWriteTime; + } + private set { lastWriteTime = value; } + } + + /// + /// Gets or sets the type. + /// + /// The type of the credential. This member cannot be changed after the credential is created. + public CredentialType Type + { + get + { + CheckNotDisposed(); + return type; + } + set + { + CheckNotDisposed(); + type = value; + } + } + + /// + /// Gets or sets the type of the persistence. + /// + /// Defines the persistence of this credential. This member can be read and written. + public PersistenceType PersistenceType + { + get + { + CheckNotDisposed(); + return persistenceType; + } + set + { + CheckNotDisposed(); + persistenceType = value; + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + + // Prevent GC Collection since we have already disposed of this object + GC.SuppressFinalize(this); + } + + /// + /// Finalizes an instance of the class. + /// + ~Credential() + { + Dispose(false); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// + /// true to release both managed and unmanaged resources; false to release only + /// unmanaged resources. + /// + private void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + SecurePassword.Clear(); + SecurePassword.Dispose(); + } + } + disposed = true; + } + + /// + /// Ensures this instance is not disposed. + /// + /// Credential object is already disposed. + private void CheckNotDisposed() + { + if (disposed) + { + throw new ObjectDisposedException("Credential object is already disposed."); + } + } + + /// + /// Loads this instance. + /// + /// true if credential is load properly, false otherwise. + public bool Load() + { + CheckNotDisposed(); + UnmanagedCodePermission.Demand(); + + IntPtr credPointer; + + var result = NativeMethods.CredRead(Target, Type, 0, out credPointer); + if (!result) + return false; + + using (var credentialHandle = new NativeMethods.CriticalCredentialHandle(credPointer)) + { + LoadInternal(credentialHandle.GetCredential()); + } + + return true; + } + + /// + /// Loads all credentials + /// + public static IEnumerable LoadAll() + { + UnmanagedCodePermission.Demand(); + + return NativeMethods.CredEnumerate() + .Select(c => new Credential(c.UserName, null, c.TargetName)) + .Where(c => c.Load()); + } + + /// + /// Loads the internal. + /// + /// The credential. + internal void LoadInternal(NativeMethods.CREDENTIAL credential) + { + Username = credential.UserName; + + if (credential.CredentialBlobSize > 0) + { + Password = Marshal.PtrToStringUni(credential.CredentialBlob, credential.CredentialBlobSize / 2); + } + + Target = credential.TargetName; + Type = (CredentialType)credential.Type; + PersistenceType = (PersistenceType)credential.Persist; + Description = credential.Comment; + LastWriteTimeUtc = DateTime.FromFileTimeUtc(credential.LastWritten); + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialManager.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialManager.cs new file mode 100644 index 0000000..a619fa0 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialManager.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Text; + +namespace winPEAS.Helpers.CredentialManager +{ + internal static class CredentialManager + { + // thanks to + // https://github.com/spolnik/Simple.CredentialsManager + + public static string UnicodeInfoText = "(Unicode Base64 encoded)"; + + internal static List GetCredentials() + { + var result = new List(); + var credentials = Credential.LoadAll(); + + foreach (var credential in credentials) + { + var isUnicode = MyUtils.IsUnicode(credential.Password); + + string clearTextPassword = credential.Password; + string unicodeInfo = string.Empty; + if (isUnicode) + { + clearTextPassword = System.Convert.ToBase64String(Encoding.Unicode.GetBytes(credential.Password)); + unicodeInfo = UnicodeInfoText; + } + + string item = $"\nUsername: {credential.Username}\n" + + $"Password:{unicodeInfo} {clearTextPassword}\n" + + $"Target: {credential.Target}\n" + + $"PersistenceType: {credential.PersistenceType}\n" + + $"LastWriteTime: {credential.LastWriteTime}\n" + + "-------------------------------------------------------"; + + result.Add(item); + } + + return result; + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialType.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialType.cs new file mode 100644 index 0000000..6e9e0a6 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/CredentialType.cs @@ -0,0 +1,39 @@ +namespace winPEAS.Helpers.CredentialManager +{ + /// + /// Enum CredentialType + /// + /// The type of the credential. This member cannot be changed after the credential is created. + /// + public enum CredentialType : uint + { + /// + /// The lack of credential type + /// + None = 0, + + /// + /// Generic credential type + /// + /// The credential is a generic credential. The credential will not be used by any particular authentication package. + /// The credential will be stored securely but has no other significant characteristics. + /// + Generic = 1, + + /// + /// Domain password credential type + /// + /// The credential is a password credential and is specific to Microsoft's authentication packages. + /// The NTLM, Kerberos, and Negotiate authentication packages will automatically use this credential when connecting to the named target. + /// + DomainPassword = 2, + + /// + /// Domain certificate credential type + /// + /// The credential is a certificate credential and is specific to Microsoft's authentication packages. + /// The Kerberos, Negotiate, and Schannel authentication packages automatically use this credential when connecting to the named target. + /// + DomainCertificate = 3 + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/NativeMethods.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/NativeMethods.cs new file mode 100644 index 0000000..9e48c78 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/NativeMethods.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Win32.SafeHandles; + +namespace winPEAS.Helpers.CredentialManager +{ + /// + /// Wrapper for advapi32.dll library. + /// Advanced Services + /// Provide access to functionality additional to the kernel. + /// Included are things like the Windows registry, shutdown/restart the system (or abort), + /// start/stop/create a Windows service, manage user accounts. + /// These functions reside in advapi32.dll on 32-bit Windows. + /// + public class NativeMethods + { + /// + /// The CredRead function reads a credential from the user's credential set. + /// The credential set used is the one associated with the logon session of the current token. + /// The token must not have the user's SID disabled. + /// + /// + /// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is + /// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function can return only one + /// credential of the specified type. + /// + /// Pointer to a null-terminated string that contains the name of the credential to read. + /// Type of the credential to read. Type must be one of the CRED_TYPE_* defined types. + /// Currently reserved and must be zero. + /// + /// Pointer to a single allocated block buffer to return the credential. + /// Any pointers contained within the buffer are pointers to locations within this single allocated block. + /// The single returned buffer must be freed by calling CredFree. + /// + /// The function returns TRUE on success and FALSE on failure. + [DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool CredRead(string target, CredentialType type, int reservedFlag, + out IntPtr credentialPtr); + + /// + /// The CredWrite function creates a new credential or modifies an existing credential in the user's credential set. + /// The new credential is associated with the logon session of the current token. + /// The token must not have the user's security identifier (SID) disabled. + /// + /// + /// This function creates a credential if a credential with the specified TargetName and Type does not exist. If a + /// credential with the specified TargetName and Type exists, the new specified credential replaces the existing one. + /// When this function writes a CRED_TYPE_CERTIFICATE credential, the Credential->CredentialBlob member specifies the + /// PIN protecting the private key of the certificate specified by the Credential->UserName member. The credential + /// manager does not maintain the PIN. Rather, the PIN is passed to the cryptographic service provider (CSP) indicated + /// on the certificate for later use by the CSP and the authentication packages. The CSP defines the lifetime of the + /// PIN. Most CSPs flush the PIN when the smart card removal from the smart card reader. + /// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is + /// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function does not support writing + /// to target names that contain wildcards. + /// + /// A pointer to the CREDENTIAL structure to be written. + /// Flags that control the function's operation. The following flag is defined. + /// If the function succeeds, the function returns TRUE, if the function fails, it returns FALSE. + [DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool CredWrite([In] ref CREDENTIAL userCredential, [In] UInt32 flags); + + /// + /// The CredFree function frees a buffer returned by any of the credentials management functions. + /// + /// Pointer to the buffer to be freed. + [DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)] + internal static extern void CredFree([In] IntPtr cred); + + /// + /// The CredDelete function deletes a credential from the user's credential set. + /// The credential set used is the one associated with the logon session of the current token. + /// The token must not have the user's SID disabled. + /// + /// Pointer to a null-terminated string that contains the name of the credential to delete. + /// + /// Type of the credential to delete. Must be one of the CRED_TYPE_* defined types. + /// For a list of the defined types, see the Type member of the CREDENTIAL structure. + /// If the value of this parameter is CRED_TYPE_DOMAIN_EXTENDED, + /// this function can delete a credential that specifies a user name when there are multiple credentials for the same + /// target. The value of the TargetName parameter must specify the user name as Target|UserName. + /// + /// Reserved and must be zero. + /// The function returns TRUE on success and FALSE on failure. + [DllImport("Advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)] + internal static extern bool CredDelete(StringBuilder target, CredentialType type, int flags); + + /// + /// Enumerate credentials in the credential store + /// signature: BOOL CredEnumerate ( + /// _In_ LPCTSTR Filter, + /// _In_ DWORD Flags, + /// _Out_ DWORD *Count, + /// _Out_ PCREDENTIAL **Credentials + ///); + /// [in] + /// Pointer to a null-terminated string that contains the filter for the returned credentials.Only credentials with a TargetName matching the filter will be returned.The filter specifies a name prefix followed by an asterisk.For instance, the filter "FRED*" will return all credentials with a TargetName beginning with the string "FRED". + /// If NULL is specified, all credentials will be returned. + /// [in] + /// The value of this parameter can be zero or more of the following values combined with a bitwise-OR operation. + /// Value Meaning + /// CRED_ENUMERATE_ALL_CREDENTIALS 0x1 + /// This function enumerates all of the credentials in the user's credential set. The target name of each credential is returned in the "namespace:attribute=target" format. If this flag is set and the Filter parameter is not NULL, the function fails and returns ERROR_INVALID_FLAGS. + /// Windows Server 2003 and Windows XP: This flag is not supported. + /// + /// [out] Count of the credentials returned in the Credentials array. + /// [out] + /// Pointer to an array of pointers to credentials.The returned credential is a single allocated block. Any pointers contained within the buffer are pointers to locations within this single allocated block.The single returned buffer must be freed by calling CredFree. + /// Return value + /// + /// + /// The function returns TRUE on success and FALSE on failure. The GetLastError function can be called to get a more specific status code.The following status codes can be returned. + /// Return code/value Description + /// ERROR_NOT_FOUND + /// 1168 (0x490) + /// No credential exists matching the specified Filter. + /// ERROR_NO_SUCH_LOGON_SESSION + /// 1312 (0x520) + /// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not have an associated credential set. + /// ERROR_INVALID_FLAGS + /// 1004 (0x3EC) + /// A flag that is not valid was specified for the Flags parameter, or CRED_ENUMERATE_ALL_CREDENTIALS is specified for the Flags parameter and the Filter parameter is not NULL. + /// + /// + [DllImport("Advapi32.dll", EntryPoint = "CredEnumerate", SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr pCredentials); + + /// + /// The CREDENTIAL structure contains an individual credential. + /// + /// See CREDENTIAL structure documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct CREDENTIAL + { + 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; + } + + internal static IEnumerable CredEnumerate() + { + int count; + IntPtr pCredentials; + var ret = CredEnumerate(null, 0, out count, out pCredentials); + + if (ret == false) + throw new Exception("Failed to enumerate credentials"); + + var credentials = new IntPtr[count]; + for (var n = 0; n < count; n++) + credentials[n] = Marshal.ReadIntPtr(pCredentials, + n * Marshal.SizeOf(typeof(IntPtr))); + + return credentials.Select(ptr => (CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL))); + } + + internal sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid + { + // Set the handle. + internal CriticalCredentialHandle(IntPtr preexistingHandle) + { + SetHandle(preexistingHandle); + } + + internal CREDENTIAL GetCredential() + { + if (!IsInvalid) + { + // Get the Credential from the mem location + return (CREDENTIAL)Marshal.PtrToStructure(handle, typeof(CREDENTIAL)); + } + + throw new InvalidOperationException("Invalid CriticalHandle!"); + } + + // Perform any specific actions to release the handle in the ReleaseHandle method. + // Often, you need to use P/Invoke 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. + protected override bool ReleaseHandle() + { + // 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; + } + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/PersistenceType.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/PersistenceType.cs new file mode 100644 index 0000000..ee713c4 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/PersistenceType.cs @@ -0,0 +1,35 @@ +namespace winPEAS.Helpers.CredentialManager +{ + /// + /// Enum PersistenceType + /// Defines the persistence of this credential. This member can be read and written. + /// + public enum PersistenceType : uint + { + /// + /// The session persistence type + /// The credential persists for the life of the logon session. + /// It will not be visible to other logon sessions of this same user. + /// It will not exist after this user logs off and back on. + /// + Session = 1, + + /// + /// The local computer persistence type + /// The credential persists for all subsequent logon sessions on this same computer. + /// It is visible to other logon sessions of this same user on this same computer + /// and not visible to logon sessions for this user on other computers. + /// + LocalComputer = 2, + + /// + /// The enterprise persistence type + /// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon + /// sessions of this same user on this same computer and to logon sessions for this user on other computers. + /// this option can be implemented as locally persisted credential if the administrator or user configures the user + /// account to not have roam-able state. For instance, if the user has no roaming profile, the credential will only + /// persist locally. + /// + Enterprise = 3 + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/SecureStringHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/SecureStringHelper.cs new file mode 100644 index 0000000..0579302 --- /dev/null +++ b/winPEAS/winPEASexe/winPEAS/Helpers/CredentialManager/SecureStringHelper.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; +using System.Security; + +namespace winPEAS.Helpers.CredentialManager +{ + [SuppressUnmanagedCodeSecurity] + internal static class SecureStringHelper + { + internal static unsafe SecureString CreateSecureString(string plainString) + { + if (string.IsNullOrEmpty(plainString)) + return new SecureString(); + + SecureString str; + fixed (char* str2 = plainString) + { + var chPtr = str2; + str = new SecureString(chPtr, plainString.Length); + str.MakeReadOnly(); + } + + return str; + } + + internal static string CreateString(SecureString secureString) + { + if ((secureString == null) || (secureString.Length == 0)) + return string.Empty; + + string str; + var zero = IntPtr.Zero; + + try + { + zero = Marshal.SecureStringToBSTR(secureString); + str = Marshal.PtrToStringBSTR(zero); + } + finally + { + if (zero != IntPtr.Zero) + Marshal.ZeroFreeBSTR(zero); + } + + return str; + } + } +} diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/DomainHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/DomainHelper.cs index 8736591..01bac60 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/DomainHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/DomainHelper.cs @@ -54,7 +54,7 @@ namespace winPEAS.Helpers catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}\n Trying to check if domain is joined using WMI", ex.Message)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}\n Trying to check if domain is joined using WMI", ex.Message)); return IsDomainJoinedWmi(); } return ""; diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/MemoryHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/MemoryHelper.cs index d69534f..1e37dda 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/MemoryHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/MemoryHelper.cs @@ -15,31 +15,15 @@ namespace winPEAS.Helpers string memoryStats = $"{process.ProcessName} - Memory Stats\n" + $"-------------------------------------\n" + - $" Physical memory usage : {ToSize(process.WorkingSet64)}\n" + - $" Paged system memory size : {ToSize(process.PagedSystemMemorySize64)}\n" + - $" Paged memory size : {ToSize(process.PagedMemorySize64)}\n"; + $" Physical memory usage : {MyUtils.ConvertBytesToHumanReadable(process.WorkingSet64)}\n" + + $" Paged system memory size : {MyUtils.ConvertBytesToHumanReadable(process.PagedSystemMemorySize64)}\n" + + $" Paged memory size : {MyUtils.ConvertBytesToHumanReadable(process.PagedMemorySize64)}\n"; Beaprint.PrintDebugLine(memoryStats); } } } - private static string[] suffixes = new[] { " B", " KB", " MB", " GB", " TB", " PB" }; - private static string ToSize(double number, int precision = 2) - { - // unit's number of bytes - const double unit = 1024; - // suffix counter - int i = 0; - // as long as we're bigger than a unit, keep going - while (number > unit) - { - number /= unit; - i++; - } - // apply precision and current suffix - return Math.Round(number, precision) + suffixes[i]; - } } } diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/MyUtils.cs b/winPEAS/winPEASexe/winPEAS/Helpers/MyUtils.cs index c80c264..1a99d2e 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/MyUtils.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/MyUtils.cs @@ -5,16 +5,18 @@ using System.IO; using System.Linq; using System.Reflection; using System.Security.Principal; +using System.Text; using System.Text.RegularExpressions; namespace winPEAS.Helpers { public class MyUtils - { + { public static string GetCLSIDBinPath(string CLSID) { - return RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\Classes\CLSID\" + CLSID + @"\InprocServer32", ""); //To get the default object you need to use an empty string - } + return RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\Classes\CLSID\" + CLSID + @"\InprocServer32", + ""); //To get the default object you need to use an empty string + } //////////////////////////////////// /////// MISC - Files & Paths /////// @@ -24,7 +26,8 @@ namespace winPEAS.Helpers bool isDotNet = false; FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(path); string companyName = myFileVersionInfo.CompanyName; - if ((String.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) + if ((string.IsNullOrEmpty(companyName)) || + (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) { try { @@ -37,7 +40,9 @@ namespace winPEAS.Helpers } catch (System.BadImageFormatException exception) { - if (Regex.IsMatch(exception.Message, ".*This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.*", RegexOptions.IgnoreCase)) + if (Regex.IsMatch(exception.Message, + ".*This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.*", + RegexOptions.IgnoreCase)) { isDotNet = true; } @@ -47,15 +52,17 @@ namespace winPEAS.Helpers // System.Console.WriteLine("The assembly has already been loaded."); } } + return isDotNet; } public static string GetExecutableFromPath(string path) { string binaryPath = ""; - Match match_path = Regex.Match(path, @"^\W*([a-z]:\\.+?(\.exe|\.dll|\.sys))\W*", RegexOptions.RightToLeft | RegexOptions.IgnoreCase); + Match match_path = Regex.Match(path, @"^\W*([a-z]:\\.+?(\.exe|\.dll|\.sys))\W*", + RegexOptions.RightToLeft | RegexOptions.IgnoreCase); if (match_path.Groups.Count > 1) - { + { binaryPath = match_path.Groups[1].ToString(); } @@ -72,6 +79,7 @@ namespace winPEAS.Helpers { binaryPath = binaryPathdll32[1].Trim(); } + return binaryPath; } @@ -101,8 +109,9 @@ namespace winPEAS.Helpers } } } + return binaryPath; - } + } public static bool CheckQuoteAndSpace(string path) { @@ -111,9 +120,10 @@ namespace winPEAS.Helpers if (path.Contains(" ")) return true; } + return false; } - + ////////////////////// //////// MISC //////// @@ -125,7 +135,7 @@ namespace winPEAS.Helpers return dirs.ToList(); } - + //From Seatbelt public static bool IsHighIntegrity() { @@ -143,12 +153,13 @@ namespace winPEAS.Helpers if (Regex.Match(haystack, regex, RegexOptions.IgnoreCase).Success) return true; } + return false; } - + // From https://stackoverflow.com/questions/206323/how-to-execute-command-line-in-c-get-std-out-results - public static string ExecCMD(string args, string alternative_binary="") + public static string ExecCMD(string args, string alternative_binary = "") { //Create process Process pProcess = new Process(); @@ -157,10 +168,10 @@ namespace winPEAS.Helpers pProcess.StartInfo.CreateNoWindow = true; //strCommand is path and file name of command to run - pProcess.StartInfo.FileName = (String.IsNullOrEmpty(alternative_binary)) ? "cmd.exe" : alternative_binary; + pProcess.StartInfo.FileName = (string.IsNullOrEmpty(alternative_binary)) ? "cmd.exe" : alternative_binary; //strCommandParameters are parameters to pass to program - pProcess.StartInfo.Arguments = (String.IsNullOrEmpty(alternative_binary)) ? "/C " + args : args; + pProcess.StartInfo.Arguments = (string.IsNullOrEmpty(alternative_binary)) ? "/C " + args : args; pProcess.StartInfo.UseShellExecute = false; @@ -178,5 +189,31 @@ namespace winPEAS.Helpers return strOutput; } + + private static string[] suffixes = new[] {" B", " KB", " MB", " GB", " TB", " PB"}; + + public static string ConvertBytesToHumanReadable(double number, int precision = 2) + { + // unit's number of bytes + const double unit = 1024; + // suffix counter + int i = 0; + // as long as we're bigger than a unit, keep going + while (number > unit) + { + number /= unit; + i++; + } + + // apply precision and current suffix + return Math.Round(number, precision) + suffixes[i]; + } + + public static bool IsUnicode(string input) + { + var asciiBytesCount = Encoding.ASCII.GetByteCount(input); + var unicodBytesCount = Encoding.UTF8.GetByteCount(input); + return asciiBytesCount != unicodBytesCount; + } } } diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/PermissionsHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/PermissionsHelper.cs index a433dc9..f1a65ae 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/PermissionsHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/PermissionsHelper.cs @@ -53,14 +53,14 @@ namespace winPEAS.Helpers try { path = path.Trim(); - if (String.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) { return results; } path = GetFolderFromString(path); - if (String.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) { return results; } @@ -96,7 +96,7 @@ namespace winPEAS.Helpers // If the rule is interesting, check if any of my SIDs is in the rule if (rule.IdentityReference.Value.ToLower() == mySID.Key.ToLower()) { - string SID_name = String.IsNullOrEmpty(mySID.Value) ? mySID.Key : mySID.Value; + string SID_name = string.IsNullOrEmpty(mySID.Value) ? mySID.Key : mySID.Value; if (container.ContainsKey(SID_name)) { @@ -108,13 +108,13 @@ namespace winPEAS.Helpers else container[SID_name] = current_perm_str; - string to_add = String.Format("{0} [{1}]", SID_name, current_perm_str); + string to_add = string.Format("{0} [{1}]", SID_name, current_perm_str); } } } foreach (KeyValuePair SID_input in container) { - string to_add = String.Format("{0} [{1}]", SID_input.Key, SID_input.Value); + string to_add = string.Format("{0} [{1}]", SID_input.Key, SID_input.Value); results.Add(to_add); } return results; @@ -143,7 +143,7 @@ namespace winPEAS.Helpers // If the rule is interesting, check if any of my SIDs is in the rule if (rule.IdentityReference.Value.ToLower() == mySID.Key.ToLower()) { - string SID_name = String.IsNullOrEmpty(mySID.Value) ? mySID.Key : mySID.Value; + string SID_name = string.IsNullOrEmpty(mySID.Value) ? mySID.Key : mySID.Value; if (container.ContainsKey(SID_name)) { @@ -153,13 +153,13 @@ namespace winPEAS.Helpers else container[SID_name] = current_perm_str; - string to_add = String.Format("{0} [{1}]", SID_name, current_perm_str); + string to_add = string.Format("{0} [{1}]", SID_name, current_perm_str); } } } foreach (KeyValuePair SID_input in container) { - string to_add = String.Format("{0} [{1}]", SID_input.Key, SID_input.Value); + string to_add = string.Format("{0} [{1}]", SID_input.Key, SID_input.Value); results.Add(to_add); } } @@ -263,7 +263,7 @@ namespace winPEAS.Helpers try { results[path] = String.Join(", ", GetPermissionsFolder(path, Checks.Checks.CurrentUserSiDs)); - if (String.IsNullOrEmpty(results[path])) + if (string.IsNullOrEmpty(results[path])) { foreach (string d in Directory.GetDirectories(path)) { diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/RegistryHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/RegistryHelper.cs index bd7ca19..585efc9 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/RegistryHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/RegistryHelper.cs @@ -21,7 +21,7 @@ namespace winPEAS.Helpers var regKey = Registry.CurrentUser.OpenSubKey(path); if (regKey != null) { - regKeyValue = String.Format("{0}", regKey.GetValue(value)); + regKeyValue = string.Format("{0}", regKey.GetValue(value)); } return regKeyValue; } @@ -30,7 +30,7 @@ namespace winPEAS.Helpers var regKey = Registry.Users.OpenSubKey(path); if (regKey != null) { - regKeyValue = String.Format("{0}", regKey.GetValue(value)); + regKeyValue = string.Format("{0}", regKey.GetValue(value)); } return regKeyValue; } @@ -39,7 +39,7 @@ namespace winPEAS.Helpers var regKey = Registry.LocalMachine.OpenSubKey(path); if (regKey != null) { - regKeyValue = String.Format("{0}", regKey.GetValue(value)); + regKeyValue = string.Format("{0}", regKey.GetValue(value)); } return regKeyValue; } diff --git a/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs b/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs index 8b45050..ece04d6 100644 --- a/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Helpers/Search/SearchHelper.cs @@ -22,12 +22,7 @@ namespace winPEAS.Helpers.Search public static List GetFilesFast(string folder, string pattern = "*", HashSet excludedDirs = null) { ConcurrentBag files = new ConcurrentBag(); - // ConcurrentBag files = new ConcurrentBag(); - - //Beaprint.InfoPrint($"[*] folder 1: '{folder}'"); - IEnumerable startDirs = GetStartDirectories(folder, files, pattern); - IList startDirsExcluded = new List(); if (excludedDirs != null) @@ -41,16 +36,9 @@ namespace winPEAS.Helpers.Search { if (Regex.IsMatch(startDirLower, excludedDirPattern, RegexOptions.IgnoreCase)) { - //files2.Add(file + $" [pattern: '{pattern}']"); shouldAdd = false; break; } - - //if (startDirLower.StartsWith(excludedDir)) - //{ - // shouldAdd = false; - // break; - //} } if (shouldAdd) @@ -58,30 +46,18 @@ namespace winPEAS.Helpers.Search startDirsExcluded.Add(startDir); } } - - - //startDirsExcluded = - // (from startDir in startDirs - // from excludedDir in excludedDirs - // where !startDir.FullName.Contains(excludedDir) - // select startDir).ToList(); } else { startDirsExcluded = startDirs.ToList(); } - - // !!!! TODO - // probably we need to exclude the excluded dirs here - not in parallel processing - Parallel.ForEach(startDirsExcluded, (d) => { Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern), (dir) => { GetFiles(dir.FullName, pattern).ForEach( (f) => - //files.Add(f.FullName) files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName)) ); }); @@ -154,7 +130,6 @@ namespace winPEAS.Helpers.Search foreach (var f in dirInfo.GetFiles(pattern)) { - //files.Add(f.FullName); files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName)); } @@ -165,15 +140,15 @@ namespace winPEAS.Helpers.Search return new List(); } - catch (UnauthorizedAccessException ex) + catch (UnauthorizedAccessException) { return new List(); } - catch (PathTooLongException ex) + catch (PathTooLongException) { return new List(); } - catch (DirectoryNotFoundException ex) + catch (DirectoryNotFoundException) { return new List(); } diff --git a/winPEAS/winPEASexe/winPEAS/Info/ApplicationInfo/AutoRuns.cs b/winPEAS/winPEASexe/winPEAS/Info/ApplicationInfo/AutoRuns.cs index dc68be9..dc14ef7 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/ApplicationInfo/AutoRuns.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/ApplicationInfo/AutoRuns.cs @@ -6,7 +6,6 @@ using System.Management; using System.Text.RegularExpressions; using Microsoft.Win32; using winPEAS.Helpers; -using winPEAS.KnownFileCreds; namespace winPEAS.Info.ApplicationInfo { @@ -16,11 +15,13 @@ namespace winPEAS.Info.ApplicationInfo { var result = new List>(); var regAutoRuns = GetRegistryAutoRuns(NtAccountNames); - var fileAutoRuns = GetAutoRunsFolder(); + var folderAutoRuns = GetAutoRunsFolder(); + //var fileAutoRuns = GetAutoRunsFiles(); var wmicAutoRuns = GetAutoRunsWMIC(); result.AddRange(regAutoRuns); - result.AddRange(fileAutoRuns); + result.AddRange(folderAutoRuns); + //result.AddRange(fileAutoRuns); result.AddRange(wmicAutoRuns); return result; @@ -66,6 +67,10 @@ namespace winPEAS.Info.ApplicationInfo new List {"HKCU","Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx"}, new List {"HKCU","Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx"}, + //RunServicesOnce + new List {"HKCU","Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce"}, + new List {"HKLM","SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce"}, + //Startup Path new List {"HKCU", @"Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders", "Common Startup"}, new List {"HKCU", @"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "Common Startup"}, @@ -76,6 +81,8 @@ namespace winPEAS.Info.ApplicationInfo new List {"HKLM", @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "Userinit"}, new List {"HKLM", @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "Shell"}, + new List { "HKCU", @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows", "load"}, + //Policy Settings new List {"HKLM", @"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", "Run"}, new List {"HKCU", @"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", "Run"}, @@ -251,9 +258,31 @@ namespace winPEAS.Info.ApplicationInfo { List> results = new List>(); List autorunLocations = new List(); - autorunLocations.Add(Environment.ExpandEnvironmentVariables(@"%appdata%\Microsoft\Windows\Start Menu\Programs\Startup")); + // displays startup for current user + //autorunLocations.Add(Environment.ExpandEnvironmentVariables(@"%appdata%\Microsoft\Windows\Start Menu\Programs\Startup")); autorunLocations.Add(Environment.ExpandEnvironmentVariables(@"%programdata%\Microsoft\Windows\Start Menu\Programs\Startup")); + //string usersPath = Environment.GetEnvironmentVariable("USERPROFILE") + "\\..\\"; + string usersPath = Path.Combine(Environment.GetEnvironmentVariable(@"USERPROFILE")); + usersPath = Directory.GetParent(usersPath).FullName; + try + { + var userDirs = Directory.GetDirectories(usersPath); + + foreach (var userDir in userDirs) + { + string startupPath = $@"{userDir}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"; + + if (Directory.Exists(startupPath)) + { + autorunLocations.Add(startupPath); + } + } + } + catch (Exception e) + { + } + foreach (string path in autorunLocations) { foreach (string filepath in Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly)) @@ -316,6 +345,11 @@ namespace winPEAS.Info.ApplicationInfo Beaprint.GrayPrint("Error getting autoruns from WMIC: " + e); } return results; - } + } + + private static IEnumerable> GetAutoRunsFiles() + { + throw new NotImplementedException(); + } } } diff --git a/winPEAS/winPEASexe/winPEAS/Info/ProcessInfo/ProcessesInfo.cs b/winPEAS/winPEASexe/winPEAS/Info/ProcessInfo/ProcessesInfo.cs index 98897c1..6153a30 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/ProcessInfo/ProcessesInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/ProcessInfo/ProcessesInfo.cs @@ -77,7 +77,7 @@ namespace winPEAS.Info.ProcessInfo { // Not enough privileges } - if ((String.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) + if ((string.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) { Dictionary to_add = new Dictionary(); to_add["Name"] = itm.Proc.ProcessName; diff --git a/winPEAS/winPEASexe/winPEAS/Info/ServicesInfo/ServicesInfoHelper.cs b/winPEAS/winPEASexe/winPEAS/Info/ServicesInfo/ServicesInfoHelper.cs index a232a53..73e56d2 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/ServicesInfo/ServicesInfoHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/ServicesInfo/ServicesInfoHelper.cs @@ -46,18 +46,20 @@ namespace winPEAS.Info.ServicesInfo // Not enough privileges } - if (String.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) + if (string.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) { - Dictionary toadd = new Dictionary(); - toadd["Name"] = String.Format("{0}", result["Name"]); - toadd["DisplayName"] = String.Format("{0}", result["DisplayName"]); - toadd["CompanyName"] = companyName; - toadd["State"] = String.Format("{0}", result["State"]); - toadd["StartMode"] = String.Format("{0}", result["StartMode"]); - toadd["PathName"] = String.Format("{0}", result["PathName"]); - toadd["FilteredPath"] = binaryPath; - toadd["isDotNet"] = isDotNet; - toadd["Description"] = String.Format("{0}", result["Description"]); + Dictionary toadd = new Dictionary + { + ["Name"] = string.Format("{0}", result["Name"]), + ["DisplayName"] = string.Format("{0}", result["DisplayName"]), + ["CompanyName"] = companyName, + ["State"] = string.Format("{0}", result["State"]), + ["StartMode"] = string.Format("{0}", result["StartMode"]), + ["PathName"] = string.Format("{0}", result["PathName"]), + ["FilteredPath"] = binaryPath, + ["isDotNet"] = isDotNet, + ["Description"] = result["Description"].ToString() + }; results.Add(toadd); } } @@ -84,7 +86,7 @@ namespace winPEAS.Info.ServicesInfo { string companyName = ""; string isDotNet = ""; - string pathName = Environment.ExpandEnvironmentVariables(String.Format("{0}", key_values["ImagePath"]).Replace("\\SystemRoot\\", "%SystemRoot%\\")); + string pathName = Environment.ExpandEnvironmentVariables(string.Format("{0}", key_values["ImagePath"]).Replace("\\SystemRoot\\", "%SystemRoot%\\")); string binaryPath = MyUtils.ReconstructExecPath(pathName); if (binaryPath != "") { @@ -100,9 +102,9 @@ namespace winPEAS.Info.ServicesInfo } } - string displayName = String.Format("{0}", key_values["DisplayName"]); - string imagePath = String.Format("{0}", key_values["ImagePath"]); - string description = key_values.ContainsKey("Description") ? String.Format("{0}", key_values["Description"]) : ""; + string displayName = string.Format("{0}", key_values["DisplayName"]); + string imagePath = string.Format("{0}", key_values["ImagePath"]); + string description = key_values.ContainsKey("Description") ? string.Format("{0}", key_values["Description"]) : ""; string startMode = ""; if (key_values.ContainsKey("Start")) { @@ -128,18 +130,20 @@ namespace winPEAS.Info.ServicesInfo break; } } - if (String.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) + if (string.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase))) { - Dictionary toadd = new Dictionary(); - toadd["Name"] = String.Format("{0}", displayName); - toadd["DisplayName"] = String.Format("{0}", displayName); - toadd["CompanyName"] = companyName; - toadd["State"] = ""; - toadd["StartMode"] = startMode; - toadd["PathName"] = pathName; - toadd["FilteredPath"] = binaryPath; - toadd["isDotNet"] = isDotNet; - toadd["Description"] = description; + Dictionary toadd = new Dictionary + { + ["Name"] = displayName, + ["DisplayName"] = displayName, + ["CompanyName"] = companyName, + ["State"] = "", + ["StartMode"] = startMode, + ["PathName"] = pathName, + ["FilteredPath"] = binaryPath, + ["isDotNet"] = isDotNet, + ["Description"] = description + }; results.Add(toadd); } } @@ -181,8 +185,7 @@ namespace winPEAS.Info.ServicesInfo IntPtr handle = (IntPtr)GetServiceHandle.Invoke(sc, readRights); ServiceControllerStatus status = sc.Status; byte[] psd = new byte[0]; - uint bufSizeNeeded; - bool ok = QueryServiceObjectSecurity(handle, SecurityInfos.DiscretionaryAcl, psd, 0, out bufSizeNeeded); + bool ok = QueryServiceObjectSecurity(handle, SecurityInfos.DiscretionaryAcl, psd, 0, out uint bufSizeNeeded); if (!ok) { int err = Marshal.GetLastWin32Error(); @@ -218,7 +221,7 @@ namespace winPEAS.Info.ServicesInfo int serviceRights = ace.AccessMask; string current_perm_str = PermissionsHelper.PermInt2Str(serviceRights, true, true); - if (!String.IsNullOrEmpty(current_perm_str) && !permissions.Contains(current_perm_str)) + if (!string.IsNullOrEmpty(current_perm_str) && !permissions.Contains(current_perm_str)) permissions.Add(current_perm_str); } } @@ -281,7 +284,7 @@ namespace winPEAS.Info.ServicesInfo { // grabbed from the registry instead of System.Environment.GetEnvironmentVariable to prevent false positives string path = RegistryHelper.GetRegValue("HKLM", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "Path"); - if (String.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) path = Environment.GetEnvironmentVariable("PATH"); List folders = path.Split(';').ToList(); diff --git a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/SystemInfo.cs b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/SystemInfo.cs index 507acd8..457c5ed 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/SystemInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/SystemInfo/SystemInfo.cs @@ -151,22 +151,24 @@ namespace winPEAS.Info.SystemInfo try { whitelistpaths = String.Join("\n ", RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths").Keys); - ManagementObjectSearcher wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntiVirusProduct"); - ManagementObjectCollection data = wmiData.Get(); - - foreach (ManagementObject virusChecker in data) + using (ManagementObjectSearcher wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntiVirusProduct")) { - results["Name"] = (string)virusChecker["displayName"]; - results["ProductEXE"] = (string)virusChecker["pathToSignedProductExe"]; - results["pathToSignedReportingExe"] = (string)virusChecker["pathToSignedReportingExe"]; + foreach (ManagementObject virusChecker in wmiData.Get()) + { + results["Name"] = (string)virusChecker["displayName"]; + results["ProductEXE"] = (string)virusChecker["pathToSignedProductExe"]; + results["pathToSignedReportingExe"] = (string)virusChecker["pathToSignedReportingExe"]; + } } } catch (Exception ex) { Beaprint.PrintException(ex.Message); } - if (!String.IsNullOrEmpty(whitelistpaths)) + if (!string.IsNullOrEmpty(whitelistpaths)) + { results["whitelistpaths"] = " " + whitelistpaths; //Add this info the last + } return results; } @@ -179,35 +181,16 @@ namespace winPEAS.Info.SystemInfo try { string ConsentPromptBehaviorAdmin = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "ConsentPromptBehaviorAdmin"); - switch (ConsentPromptBehaviorAdmin) + results["ConsentPromptBehaviorAdmin"] = ConsentPromptBehaviorAdmin switch { - case "0": - results["ConsentPromptBehaviorAdmin"] = $"{ConsentPromptBehaviorAdmin} - No prompting"; - break; - case "1": - results["ConsentPromptBehaviorAdmin"] = $"{ConsentPromptBehaviorAdmin} - PromptOnSecureDesktop"; - break; - case "2": - results["ConsentPromptBehaviorAdmin"] = $"{ConsentPromptBehaviorAdmin} - PromptPermitDenyOnSecureDesktop"; - break; - case "3": - results["ConsentPromptBehaviorAdmin"] = - $"{ConsentPromptBehaviorAdmin} - PromptForCredsNotOnSecureDesktop"; - break; - case "4": - results["ConsentPromptBehaviorAdmin"] = - $"{ConsentPromptBehaviorAdmin} - PromptForPermitDenyNotOnSecureDesktop"; - break; - case "5": - results["ConsentPromptBehaviorAdmin"] = - $"{ConsentPromptBehaviorAdmin} - PromptForNonWindowsBinaries"; - break; - default: - results["ConsentPromptBehaviorAdmin"] = - $"{ConsentPromptBehaviorAdmin} - PromptForNonWindowsBinaries"; - break; - } - + "0" => $"{ConsentPromptBehaviorAdmin} - No prompting", + "1" => $"{ConsentPromptBehaviorAdmin} - PromptOnSecureDesktop", + "2" => $"{ConsentPromptBehaviorAdmin} - PromptPermitDenyOnSecureDesktop", + "3" => $"{ConsentPromptBehaviorAdmin} - PromptForCredsNotOnSecureDesktop", + "4" => $"{ConsentPromptBehaviorAdmin} - PromptForPermitDenyNotOnSecureDesktop", + "5" => $"{ConsentPromptBehaviorAdmin} - PromptForNonWindowsBinaries", + _ => $"{ConsentPromptBehaviorAdmin} - PromptForNonWindowsBinaries", + }; string EnableLUA = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "EnableLUA"); results["EnableLUA"] = EnableLUA; @@ -248,7 +231,7 @@ namespace winPEAS.Info.SystemInfo { foreach (KeyValuePair kvp in transcriptionSettingsCU) { - results["Transcription Settings CU"] += String.Format(" {0,30} : {1}\r\n", kvp.Key, kvp.Value); + results["Transcription Settings CU"] += string.Format(" {0,30} : {1}\r\n", kvp.Key, kvp.Value); } } diff --git a/winPEAS/winPEASexe/winPEAS/Info/UserInfo/SAM/SamServer.cs b/winPEAS/winPEASexe/winPEAS/Info/UserInfo/SAM/SamServer.cs index c72baef..d24f54f 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/UserInfo/SAM/SamServer.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/UserInfo/SAM/SamServer.cs @@ -133,7 +133,7 @@ namespace winPEAS.Info.UserInfo.SAM } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } Buffer = IntPtr.Zero; } diff --git a/winPEAS/winPEASexe/winPEAS/Info/UserInfo/UserInfoHelper.cs b/winPEAS/winPEASexe/winPEAS/Info/UserInfo/UserInfoHelper.cs index f1ae5fe..3c848f6 100644 --- a/winPEAS/winPEASexe/winPEAS/Info/UserInfo/UserInfoHelper.cs +++ b/winPEAS/winPEASexe/winPEAS/Info/UserInfo/UserInfoHelper.cs @@ -40,7 +40,7 @@ namespace winPEAS.Info.UserInfo catch (Exception ex) { //If error, check inside the other one - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}\n Checking using the other Principal Context", ex.Message)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}\n Checking using the other Principal Context", ex.Message)); try { groupName = GetSIDGroupName(SID, ct == ContextType.Machine ? ContextType.Domain : ContextType.Machine); @@ -53,7 +53,7 @@ namespace winPEAS.Info.UserInfo } //If nothing, check inside the other one - if (String.IsNullOrEmpty(groupName)) + if (string.IsNullOrEmpty(groupName)) { try { @@ -233,11 +233,11 @@ namespace winPEAS.Info.UserInfo if (si.pUserName == null || si.pUserName == "") continue; - rdp_session["SessionID"] = String.Format("{0}", si.SessionID); - rdp_session["pSessionName"] = String.Format("{0}", si.pSessionName); - rdp_session["pUserName"] = String.Format("{0}", si.pUserName); - rdp_session["pDomainName"] = String.Format("{0}", si.pDomainName); - rdp_session["State"] = String.Format("{0}", si.State); + rdp_session["SessionID"] = string.Format("{0}", si.SessionID); + rdp_session["pSessionName"] = string.Format("{0}", si.pSessionName); + rdp_session["pUserName"] = string.Format("{0}", si.pUserName); + rdp_session["pDomainName"] = string.Format("{0}", si.pDomainName); + rdp_session["State"] = string.Format("{0}", si.State); rdp_session["SourceIP"] = ""; // Now use WTSQuerySessionInformation to get the remote IP (if any) for the connection @@ -249,8 +249,8 @@ namespace winPEAS.Info.UserInfo if (address.Address[2] != 0) { - string sourceIP = String.Format("{0}.{1}.{2}.{3}", address.Address[2], address.Address[3], address.Address[4], address.Address[5]); - rdp_session["SourceIP"] = String.Format("{0}", sourceIP); + string sourceIP = string.Format("{0}.{1}.{2}.{3}", address.Address[2], address.Address[3], address.Address[4], address.Address[5]); + rdp_session["SourceIP"] = string.Format("{0}", sourceIP); } results.Add(rdp_session); } @@ -259,7 +259,7 @@ namespace winPEAS.Info.UserInfo } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } finally { @@ -284,19 +284,19 @@ namespace winPEAS.Info.UserInfo results.Add(new Dictionary() { { "Domain", domain }, - { "SID", String.Format("{0}", sid) }, - { "MaxPasswordAge", String.Format("{0}", pi.MaxPasswordAge) }, - { "MinPasswordAge", String.Format("{0}", pi.MinPasswordAge) }, - { "MinPasswordLength", String.Format("{0}", pi.MinPasswordLength) }, - { "PasswordHistoryLength", String.Format("{0}", pi.PasswordHistoryLength) }, - { "PasswordProperties", String.Format("{0}", pi.PasswordProperties) }, + { "SID", string.Format("{0}", sid) }, + { "MaxPasswordAge", string.Format("{0}", pi.MaxPasswordAge) }, + { "MinPasswordAge", string.Format("{0}", pi.MinPasswordAge) }, + { "MinPasswordLength", string.Format("{0}", pi.MinPasswordLength) }, + { "PasswordHistoryLength", string.Format("{0}", pi.PasswordHistoryLength) }, + { "PasswordProperties", string.Format("{0}", pi.PasswordProperties) }, }); } } } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return results; } @@ -333,11 +333,11 @@ namespace winPEAS.Info.UserInfo c = $"{Clipboard.GetFileDropList()}"; //else if (Clipboard.ContainsImage()) //No system.Drwing import - //c = String.Format("{0}", Clipboard.GetImage()); + //c = string.Format("{0}", Clipboard.GetImage()); } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return c; } diff --git a/winPEAS/winPEASexe/winPEAS/InterestingFiles/InterestingFiles.cs b/winPEAS/winPEASexe/winPEAS/InterestingFiles/InterestingFiles.cs index 3de5861..ee0f8e6 100644 --- a/winPEAS/winPEASexe/winPEAS/InterestingFiles/InterestingFiles.cs +++ b/winPEAS/winPEASexe/winPEAS/InterestingFiles/InterestingFiles.cs @@ -98,37 +98,12 @@ namespace winPEAS.InterestingFiles List results = new List(); try { - // returns files (w/ modification dates) that match the given pattern below - string patterns = "*diagram*;*.pdf;*.vsd;*.doc;*docx;*.xls;*.xlsx"; - if (MyUtils.IsHighIntegrity()) { - string searchPath = $"{Environment.GetEnvironmentVariable("SystemDrive")}\\Users\\"; - - //List files = SearchHelper.FindFiles(searchPath, patterns); - - //foreach (string file in files) - //{ - // //DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); - // //DateTime lastModified = System.IO.File.GetLastWriteTime(file); - // results.Add(file); - //} - - results = SearchHelper.SearchUsersDocs(); + results = SearchHelper.SearchUsersDocs(); } - else { - string searchPath = Environment.GetEnvironmentVariable("USERPROFILE"); - - //List files = SearchHelper.FindFiles(searchPath, patterns); - - //foreach (string file in files) - //{ - // //DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); - // //DateTime lastModified = System.IO.File.GetLastWriteTime(file); - // results.Add(file); - //} results = SearchHelper.SearchCurrentUserDocs(); } } diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome.cs index 80f8575..91df6ab 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Chrome.cs @@ -195,27 +195,27 @@ namespace winPEAS.KnownFileCreds.Browsers { Console.WriteLine("\r\n\r\n=== Chrome (All Users) ==="); - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { - string userChromeHistoryPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", dir); + string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", dir); results["history"] = ParseChromeHistory(userChromeHistoryPath); - string userChromeBookmarkPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", dir); + string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", dir); results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath); } } } else { - string userChromeHistoryPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE")); results["history"] = ParseChromeHistory(userChromeHistoryPath); - string userChromeBookmarkPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE")); results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath); } diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Firefox.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Firefox.cs index a747dda..c55ef3f 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Firefox.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/Firefox.cs @@ -190,7 +190,7 @@ namespace winPEAS.KnownFileCreds.Browsers string[] directories = Directory.GetDirectories(path); foreach (string directory in directories) { - string firefoxHistoryFile = String.Format("{0}\\{1}", directory, "places.sqlite"); + string firefoxHistoryFile = string.Format("{0}\\{1}", directory, "places.sqlite"); Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?"); try diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/InternetExplorer.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/InternetExplorer.cs index d806273..263b8f2 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/InternetExplorer.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Browsers/InternetExplorer.cs @@ -96,12 +96,12 @@ namespace winPEAS.KnownFileCreds.Browsers { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { - Dictionary settings = RegistryHelper.GetRegValues("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLs", SID)); + Dictionary settings = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLs", SID)); if ((settings != null) && (settings.Count > 1)) { foreach (KeyValuePair kvp in settings) { - byte[] timeBytes = RegistryHelper.GetRegValueBytes("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", SID), kvp.Key.ToString().Trim()); + byte[] timeBytes = RegistryHelper.GetRegValueBytes("HKU", string.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", SID), kvp.Key.ToString().Trim()); if (timeBytes != null) { long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0)); @@ -116,7 +116,7 @@ namespace winPEAS.KnownFileCreds.Browsers } } - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { @@ -124,7 +124,7 @@ namespace winPEAS.KnownFileCreds.Browsers string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { - string userIEBookmarkPath = String.Format("{0}\\Favorites\\", dir); + string userIEBookmarkPath = string.Format("{0}\\Favorites\\", dir); if (Directory.Exists(userIEBookmarkPath)) { @@ -174,7 +174,7 @@ namespace winPEAS.KnownFileCreds.Browsers } } - string userIEBookmarkPath = String.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string userIEBookmarkPath = string.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); string[] bookmarkPaths = Directory.GetFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories); @@ -200,7 +200,7 @@ namespace winPEAS.KnownFileCreds.Browsers } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return results; } @@ -240,7 +240,7 @@ namespace winPEAS.KnownFileCreds.Browsers // ensure we have a site address if (Regex.IsMatch(locationURL.ToString(), @"(^https?://.+)|(^ftp://)")) { - results.Add(String.Format("{0}", locationURL)); + results.Add(string.Format("{0}", locationURL)); } Marshal.ReleaseComObject(item); item = null; @@ -257,7 +257,7 @@ namespace winPEAS.KnownFileCreds.Browsers } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return results; } diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Kerberos/Kerberos.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Kerberos/Kerberos.cs index 798a803..4ed0b3e 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Kerberos/Kerberos.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Kerberos/Kerberos.cs @@ -150,9 +150,9 @@ namespace winPEAS.KnownFileCreds.Kerberos { "UserPrincipalName", upn }, { "serverName", serverName }, { "RealmName", realmName }, - { "StartTime", String.Format("{0}", startTime) }, - { "EndTime", String.Format("{0}", endTime) }, - { "RenewTime", String.Format("{0}", renewTime) }, + { "StartTime", string.Format("{0}", startTime) }, + { "EndTime", string.Format("{0}", endTime) }, + { "RenewTime", string.Format("{0}", renewTime) }, { "EncryptionType", encryptionType }, { "TicketFlags", ticketFlags }, }); @@ -247,9 +247,9 @@ namespace winPEAS.KnownFileCreds.Kerberos { { "serverName", serverName }, { "RealmName", realmName }, - { "StartTime", String.Format("{0}", startTime) }, - { "EndTime", String.Format("{0}", endTime) }, - { "RenewTime", String.Format("{0}", renewTime) }, + { "StartTime", string.Format("{0}", startTime) }, + { "EndTime", string.Format("{0}", endTime) }, + { "RenewTime", string.Format("{0}", renewTime) }, { "EncryptionType", encryptionType }, { "TicketFlags", ticketFlags }, }); @@ -423,15 +423,15 @@ namespace winPEAS.KnownFileCreds.Kerberos { "ClientName", clientName }, { "DomainName", domainName }, { "TargetDomainName", targetDomainName }, - { "SessionKeyType", String.Format("{0}", sessionKeyType) }, + { "SessionKeyType", string.Format("{0}", sessionKeyType) }, { "Base64SessionKey", base64SessionKey }, - { "KeyExpirationTime", String.Format("{0}", keyExpirationTime) }, + { "KeyExpirationTime", string.Format("{0}", keyExpirationTime) }, { "TicketFlags", ticketFlags }, - { "StartTime", String.Format("{0}", startTime) }, - { "EndTime", String.Format("{0}", endTime) }, - { "RenewUntil", String.Format("{0}", renewUntil) }, - { "TimeSkew", String.Format("{0}", timeSkew) }, - { "EncodedTicketSize", String.Format("{0}", encodedTicketSize) }, + { "StartTime", string.Format("{0}", startTime) }, + { "EndTime", string.Format("{0}", endTime) }, + { "RenewUntil", string.Format("{0}", renewUntil) }, + { "TimeSkew", string.Format("{0}", timeSkew) }, + { "EncodedTicketSize", string.Format("{0}", encodedTicketSize) }, { "Base64EncodedTicket", base64TGT }, }); totalTicketCount++; @@ -543,15 +543,15 @@ namespace winPEAS.KnownFileCreds.Kerberos { "ClientName", clientName }, { "DomainName", domainName }, { "TargetDomainName", targetDomainName }, - { "SessionKeyType", String.Format("{0}", sessionKeyType) }, + { "SessionKeyType", string.Format("{0}", sessionKeyType) }, { "Base64SessionKey", base64SessionKey }, - { "KeyExpirationTime", String.Format("{0}", keyExpirationTime) }, + { "KeyExpirationTime", string.Format("{0}", keyExpirationTime) }, { "TicketFlags", ticketFlags }, - { "StartTime", String.Format("{0}", startTime) }, - { "EndTime", String.Format("{0}", endTime) }, - { "RenewUntil", String.Format("{0}", renewUntil) }, - { "TimeSkew", String.Format("{0}", timeSkew) }, - { "EncodedTicketSize", String.Format("{0}", encodedTicketSize) }, + { "StartTime", string.Format("{0}", startTime) }, + { "EndTime", string.Format("{0}", endTime) }, + { "RenewUntil", string.Format("{0}", renewUntil) }, + { "TimeSkew", string.Format("{0}", timeSkew) }, + { "EncodedTicketSize", string.Format("{0}", encodedTicketSize) }, { "Base64EncodedTicket", base64TGT }, }); diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/KnownFileCredsInfo.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/KnownFileCredsInfo.cs index 42eb13a..fc36fa2 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/KnownFileCredsInfo.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/KnownFileCredsInfo.cs @@ -23,7 +23,7 @@ namespace winPEAS.KnownFileCreds { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { - results = RegistryHelper.GetRegValues("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", SID)); + results = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", SID)); } } } @@ -43,7 +43,7 @@ namespace winPEAS.KnownFileCreds { if (MyUtils.IsHighIntegrity()) { - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { @@ -51,7 +51,7 @@ namespace winPEAS.KnownFileCreds string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { - string awsKeyFile = String.Format("{0}\\.aws\\credentials", dir); + string awsKeyFile = string.Format("{0}\\.aws\\credentials", dir); if (System.IO.File.Exists(awsKeyFile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(awsKeyFile); @@ -60,12 +60,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", awsKeyFile }, { "Description", "AWS credentials file" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeCredsDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", dir); + string computeCredsDb = string.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", dir); if (System.IO.File.Exists(computeCredsDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeCredsDb); @@ -74,12 +74,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeCredsDb }, { "Description", "GC Compute creds" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeLegacyCreds = String.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", dir); + string computeLegacyCreds = string.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", dir); if (System.IO.File.Exists(computeLegacyCreds)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeLegacyCreds); @@ -88,12 +88,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeLegacyCreds }, { "Description", "GC Compute creds legacy" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeAccessTokensDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", dir); + string computeAccessTokensDb = string.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", dir); if (System.IO.File.Exists(computeAccessTokensDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeAccessTokensDb); @@ -102,12 +102,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeAccessTokensDb }, { "Description", "GC Compute tokens" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string azureTokens = String.Format("{0}\\.azure\\accessTokens.json", dir); + string azureTokens = string.Format("{0}\\.azure\\accessTokens.json", dir); if (System.IO.File.Exists(azureTokens)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureTokens); @@ -116,12 +116,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", azureTokens }, { "Description", "Azure tokens" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string azureProfile = String.Format("{0}\\.azure\\azureProfile.json", dir); + string azureProfile = string.Format("{0}\\.azure\\azureProfile.json", dir); if (System.IO.File.Exists(azureProfile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureProfile); @@ -130,9 +130,9 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", azureProfile }, { "Description", "Azure profile" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } } @@ -140,7 +140,7 @@ namespace winPEAS.KnownFileCreds } else { - string awsKeyFile = String.Format("{0}\\.aws\\credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string awsKeyFile = string.Format("{0}\\.aws\\credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(awsKeyFile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(awsKeyFile); @@ -149,12 +149,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", awsKeyFile }, { "Description", "AWS keys file" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeCredsDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string computeCredsDb = string.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeCredsDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeCredsDb); @@ -163,12 +163,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeCredsDb }, { "Description", "GC Compute creds" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeLegacyCreds = String.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string computeLegacyCreds = string.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeLegacyCreds)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeLegacyCreds); @@ -177,12 +177,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeLegacyCreds }, { "Description", "GC Compute creds legacy" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string computeAccessTokensDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string computeAccessTokensDb = string.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeAccessTokensDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeAccessTokensDb); @@ -191,12 +191,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", computeAccessTokensDb }, { "Description", "GC Compute tokens" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string azureTokens = String.Format("{0}\\.azure\\accessTokens.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string azureTokens = string.Format("{0}\\.azure\\accessTokens.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(azureTokens)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureTokens); @@ -205,12 +205,12 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", azureTokens }, { "Description", "Azure tokens" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } - string azureProfile = String.Format("{0}\\.azure\\azureProfile.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string azureProfile = string.Format("{0}\\.azure\\azureProfile.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(azureProfile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureProfile); @@ -219,16 +219,16 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "file", azureProfile }, { "Description", "Azure profile" }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) } + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) } }); } } } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return results; } @@ -249,7 +249,7 @@ namespace winPEAS.KnownFileCreds if (MyUtils.IsHighIntegrity()) { - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { @@ -258,7 +258,7 @@ namespace winPEAS.KnownFileCreds if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { - string recentPath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\", dir); + string recentPath = string.Format("{0}\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\", dir); try { string[] recentFiles = Directory.GetFiles(recentPath, "*.lnk", SearchOption.AllDirectories); @@ -281,7 +281,7 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "Target", TargetPath.ToString() }, - { "Accessed", String.Format("{0}", lastAccessed) } + { "Accessed", string.Format("{0}", lastAccessed) } }); } Marshal.ReleaseComObject(shortcut); @@ -296,7 +296,7 @@ namespace winPEAS.KnownFileCreds } else { - string recentPath = String.Format("{0}\\Microsoft\\Windows\\Recent\\", System.Environment.GetEnvironmentVariable("APPDATA")); + string recentPath = string.Format("{0}\\Microsoft\\Windows\\Recent\\", System.Environment.GetEnvironmentVariable("APPDATA")); string[] recentFiles = Directory.GetFiles(recentPath, "*.lnk", SearchOption.AllDirectories); @@ -318,7 +318,7 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "Target", TargetPath.ToString() }, - { "Accessed", String.Format("{0}", lastAccessed) } + { "Accessed", string.Format("{0}", lastAccessed) } }); } Marshal.ReleaseComObject(shortcut); @@ -332,7 +332,7 @@ namespace winPEAS.KnownFileCreds } catch (Exception ex) { - Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); + Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex)); } return results; } @@ -345,7 +345,7 @@ namespace winPEAS.KnownFileCreds { if (MyUtils.IsHighIntegrity()) { - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { @@ -354,8 +354,8 @@ namespace winPEAS.KnownFileCreds if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { List userDPAPIBasePaths = new List(); - userDPAPIBasePaths.Add(String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); - userDPAPIBasePaths.Add(String.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); foreach (string userDPAPIBasePath in userDPAPIBasePaths) { @@ -376,8 +376,8 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "MasterKey", file }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, }); } } @@ -391,8 +391,8 @@ namespace winPEAS.KnownFileCreds { string userName = Environment.GetEnvironmentVariable("USERNAME"); List userDPAPIBasePaths = new List(); - userDPAPIBasePaths.Add(String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); - userDPAPIBasePaths.Add(String.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); foreach (string userDPAPIBasePath in userDPAPIBasePaths) { @@ -413,8 +413,8 @@ namespace winPEAS.KnownFileCreds results.Add(new Dictionary() { { "MasterKey", file }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, }); } } @@ -438,7 +438,7 @@ namespace winPEAS.KnownFileCreds { if (MyUtils.IsHighIntegrity()) { - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) @@ -448,8 +448,8 @@ namespace winPEAS.KnownFileCreds if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { List userCredFilePaths = new List(); - userCredFilePaths.Add(String.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", dir)); - userCredFilePaths.Add(String.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", dir)); + userCredFilePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", dir)); + userCredFilePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", dir)); foreach (string userCredFilePath in userCredFilePaths) { @@ -484,10 +484,10 @@ namespace winPEAS.KnownFileCreds { { "CredFile", file }, { "Description", desc }, - { "MasterKey", String.Format("{0}", guidMasterKey) }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) }, + { "MasterKey", string.Format("{0}", guidMasterKey) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) }, }); } } @@ -496,7 +496,7 @@ namespace winPEAS.KnownFileCreds } } - string systemFolder = String.Format("{0}\\System32\\config\\systemprofile\\AppData\\Local\\Microsoft\\Credentials", Environment.GetEnvironmentVariable("SystemRoot")); + string systemFolder = string.Format("{0}\\System32\\config\\systemprofile\\AppData\\Local\\Microsoft\\Credentials", Environment.GetEnvironmentVariable("SystemRoot")); string[] files = Directory.GetFiles(systemFolder); if ((files != null) && (files.Length != 0)) { @@ -526,10 +526,10 @@ namespace winPEAS.KnownFileCreds { { "CredFile", file }, { "Description", desc }, - { "MasterKey", String.Format("{0}", guidMasterKey) }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) }, + { "MasterKey", string.Format("{0}", guidMasterKey) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) }, }); } } @@ -538,8 +538,8 @@ namespace winPEAS.KnownFileCreds { string userName = Environment.GetEnvironmentVariable("USERNAME"); List userCredFilePaths = new List(); - userCredFilePaths.Add(String.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); - userCredFilePaths.Add(String.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userCredFilePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); + userCredFilePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE"))); foreach (string userCredFilePath in userCredFilePaths) { @@ -573,10 +573,10 @@ namespace winPEAS.KnownFileCreds { { "CredFile", file }, { "Description", desc }, - { "MasterKey", String.Format("{0}", guidMasterKey) }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, - { "Size", String.Format("{0}", size) }, + { "MasterKey", string.Format("{0}", guidMasterKey) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, + { "Size", string.Format("{0}", size) }, }); } } diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Putty.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Putty.cs index 8fdf1dd..938a042 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Putty.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Putty.cs @@ -86,7 +86,7 @@ namespace winPEAS.KnownFileCreds { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { - string[] subKeys = RegistryHelper.GetRegSubkeys("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\", SID)); + string[] subKeys = RegistryHelper.GetRegSubkeys("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\", SID)); foreach (string sessionName in subKeys) { @@ -117,7 +117,7 @@ namespace winPEAS.KnownFileCreds }; foreach (string key in keys) - putty_sess[key] = RegistryHelper.GetRegValue("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\{1}", SID, sessionName), key); + putty_sess[key] = RegistryHelper.GetRegValue("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\{1}", SID, sessionName), key); results.Add(putty_sess); } @@ -155,7 +155,7 @@ namespace winPEAS.KnownFileCreds }; foreach (string key in keys) - putty_sess[key] = RegistryHelper.GetRegValue("HKCU", String.Format("Software\\SimonTatham\\PuTTY\\Sessions\\{0}", sessionName), key); + putty_sess[key] = RegistryHelper.GetRegValue("HKCU", string.Format("Software\\SimonTatham\\PuTTY\\Sessions\\{0}", sessionName), key); results.Add(putty_sess); } @@ -176,7 +176,7 @@ namespace winPEAS.KnownFileCreds { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { - Dictionary hostKeys = RegistryHelper.GetRegValues("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys\\", SID)); + Dictionary hostKeys = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys\\", SID)); if ((hostKeys != null) && (hostKeys.Count != 0)) { Dictionary putty_ssh = new Dictionary(); diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/RemoteDesktop.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/RemoteDesktop.cs index fcf091c..a660726 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/RemoteDesktop.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/RemoteDesktop.cs @@ -23,13 +23,13 @@ namespace winPEAS.KnownFileCreds { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { - string[] subkeys = RegistryHelper.GetRegSubkeys("HKU", String.Format("{0}\\Software\\Microsoft\\Terminal Server Client\\Servers", SID)); + string[] subkeys = RegistryHelper.GetRegSubkeys("HKU", string.Format("{0}\\Software\\Microsoft\\Terminal Server Client\\Servers", SID)); if (subkeys != null) { //Console.WriteLine("\r\n\r\n=== Saved RDP Connection Information ({0}) ===", SID); foreach (string host in subkeys) { - string usernameHint = RegistryHelper.GetRegValue("HKCU", String.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); + string usernameHint = RegistryHelper.GetRegValue("HKCU", string.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); Dictionary rdp_info = new Dictionary() { { "SID", SID }, { "Host", host }, @@ -48,7 +48,7 @@ namespace winPEAS.KnownFileCreds { foreach (string host in subkeys) { - string usernameHint = RegistryHelper.GetRegValue("HKCU", String.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); + string usernameHint = RegistryHelper.GetRegValue("HKCU", string.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); Dictionary rdp_info = new Dictionary() { { "SID", "" }, { "Host", host }, @@ -69,7 +69,7 @@ namespace winPEAS.KnownFileCreds { if (MyUtils.IsHighIntegrity()) { - string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); + string userFolder = string.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) @@ -78,7 +78,7 @@ namespace winPEAS.KnownFileCreds string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { - string userRDManFile = String.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", dir); + string userRDManFile = string.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", dir); if (System.IO.File.Exists(userRDManFile)) { XmlDocument xmlDoc = new XmlDocument(); @@ -93,8 +93,8 @@ namespace winPEAS.KnownFileCreds DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile); Dictionary rdg = new Dictionary(){ { "RDCManFile", userRDManFile }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, { ".RDG Files", "" }, }; @@ -109,7 +109,7 @@ namespace winPEAS.KnownFileCreds else { string userName = Environment.GetEnvironmentVariable("USERNAME"); - string userRDManFile = String.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", System.Environment.GetEnvironmentVariable("USERPROFILE")); + string userRDManFile = string.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(userRDManFile)) { @@ -125,8 +125,8 @@ namespace winPEAS.KnownFileCreds DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile); Dictionary rdg = new Dictionary(){ { "RDCManFile", userRDManFile }, - { "Accessed", String.Format("{0}", lastAccessed) }, - { "Modified", String.Format("{0}", lastModified) }, + { "Accessed", string.Format("{0}", lastAccessed) }, + { "Modified", string.Format("{0}", lastModified) }, { ".RDG Files", "" }, }; diff --git a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Vault/VaultCli.cs b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Vault/VaultCli.cs index 85ec04a..51ed395 100644 --- a/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Vault/VaultCli.cs +++ b/winPEAS/winPEASexe/winPEAS/KnownFileCreds/Vault/VaultCli.cs @@ -114,7 +114,7 @@ namespace winPEAS.KnownFileCreds.Vault for (int j = 1; j <= vaultItemCount; j++) { Dictionary vault_cred = new Dictionary() { - { "GUID", String.Format("{0}", vaultGuid) }, + { "GUID", string.Format("{0}", vaultGuid) }, { "Type", vaultType }, { "Resource", "" }, { "Identity", "" }, @@ -172,19 +172,19 @@ namespace winPEAS.KnownFileCreds.Vault object resource = GetVaultElementValue(pResourceElement); if (resource != null) { - vault_cred["Resource"] = String.Format("{0}", resource); + vault_cred["Resource"] = string.Format("{0}", resource); } object identity = GetVaultElementValue(pIdentityElement); if (identity != null) { - vault_cred["Identity"] = String.Format("{0}", identity); + vault_cred["Identity"] = string.Format("{0}", identity); } if (packageSid != null) { - vault_cred["PacakgeSid"] = String.Format("{0}", packageSid); + vault_cred["PacakgeSid"] = string.Format("{0}", packageSid); } - vault_cred["Credential"] = String.Format("{0}", cred); - vault_cred["Last Modified"] = String.Format("{0}", System.DateTime.FromFileTimeUtc((long)lastModified)); + vault_cred["Credential"] = string.Format("{0}", cred); + vault_cred["Last Modified"] = string.Format("{0}", System.DateTime.FromFileTimeUtc((long)lastModified)); results.Add(vault_cred); } } diff --git a/winPEAS/winPEASexe/winPEAS/TaskScheduler/TaskFolder.cs b/winPEAS/winPEASexe/winPEAS/TaskScheduler/TaskFolder.cs index d76864b..143bc15 100644 --- a/winPEAS/winPEASexe/winPEAS/TaskScheduler/TaskFolder.cs +++ b/winPEAS/winPEASexe/winPEAS/TaskScheduler/TaskFolder.cs @@ -331,7 +331,7 @@ namespace winPEAS.TaskScheduler break; case TaskLogonType.ServiceAccount: flags &= ~(TaskFlags.Interactive | TaskFlags.RunOnlyIfLoggedOn); - definition.v1Task.SetAccountInformation((String.IsNullOrEmpty(userId) || user.IsSystem) ? String.Empty : user.Name, IntPtr.Zero); + definition.v1Task.SetAccountInformation((string.IsNullOrEmpty(userId) || user.IsSystem) ? String.Empty : user.Name, IntPtr.Zero); break; case TaskLogonType.InteractiveTokenOrPassword: flags |= TaskFlags.Interactive; diff --git a/winPEAS/winPEASexe/winPEAS/winPEAS.csproj b/winPEAS/winPEASexe/winPEAS/winPEAS.csproj index 1202fa9..13b5a49 100755 --- a/winPEAS/winPEASexe/winPEAS/winPEAS.csproj +++ b/winPEAS/winPEASexe/winPEAS/winPEAS.csproj @@ -26,6 +26,7 @@ 4 false 8.0 + true AnyCPU @@ -116,6 +117,15 @@ + + + + + + + + +