Files
PEASS-ng/winPEAS/winPEASexe/winPEAS/Checks/SystemInfo.cs
T
GiveenandGitHub 115b7e60a7 MITRE ATT&CK Integration for LinPEAS and WinPEAS (#614)
* feat: MITRE ATT&CK integration for LinPEAS and WinPEAS

- Add -T T1234,T5678 flag to LinPEAS to filter checks by technique
- Add mitre=T1234,T5678 argument to WinPEAS for technique-based filtering
- Annotate every check title with MITRE technique ID(s) displayed in grey
- Add $_mitre_tag to Generated Global Variables in 0_variables_base.sh
- Add check_mitre_filter() shell function with prefix-match support
- Add MitreAttackIds property to ISystemCheck interface (C#)
- Update MainPrint/GreatPrint in Beaprint.cs to accept optional mitreIds
- Tag all 158 LinPEAS check modules with # Mitre: metadata
- Tag all 16 WinPEAS check classes with MitreAttackIds property
- Update linpeasModule.py to parse # Mitre: metadata field
- Update linpeasBaseBuilder.py to emit check_mitre_filter wrappers
- Add 3 MITRE argument parsing tests to ArgumentParsingTests.cs

* test: add MITRE filter coverage for LinPEAS builder and WinPEAS

LinPEAS (test_builder.py):
- test_mitre_flag_present_in_getopts: -T: must appear in getopts string
- test_mitre_flag_present_in_help_text: -T must appear in built help text
- test_mitre_filter_function_present: check_mitre_filter() must be in built script

WinPEAS (ArgumentParsingTests.cs):
- PassesMitreFilter_EmptyFilter_AllChecksPass: no filter -> all checks run
- PassesMitreFilter_ExactMatch_Passes: T1082 filter matches T1082 check
- PassesMitreFilter_NoMatch_Fails: T1082 filter rejects T1057 check
- PassesMitreFilter_PrefixMatch_Passes: T1552 filter matches T1552.001/T1552.005
- PassesMitreFilter_SubtechniqueDoesNotMatchDifferentBase_Fails: T1548 != T1552.001

* chore: ignore .github/instructions/ and untrack todos.instructions.md

* fix: complete and accurate MITRE ATT&CK mappings for LinPEAS and WinPEAS

gitignore:
- Add .github/instructions/ to .gitignore and untrack todos.instructions.md

LinPEAS — corrected mappings:
- 29_Interesting_environment_variables.sh: add missing T1552.007,T1082
- 3_USBCreator.sh: T1548 → T1548.003,T1068 (polkit bypass + CVE-class exploit)
- 9_Doas.sh: T1548 → T1548.003 (doas is a sudo/sudo-caching equivalent)
- 10_Pkexec.sh: T1548 → T1548.003,T1548.004,T1068 per-section specificity
- 2_Process_cred_in_memory.sh: T1003,T1055 → T1003.007 (Proc Filesystem, drop wrong T1055)
- 11_Superusers.sh: T1087.001,T1548 → T1087.001 (discovery only, no elevation abuse)
- 14/15/16 writable files: T1574 → T1574.009,T1574.010 (specific sub-techniques)

WinPEAS — corrected mappings:
- SystemInfo: class expanded to full technique union; WSUS T1195→T1072,T1068;
  KrbRelayUp T1558→T1187,T1558; Object Manager T1548→T1068;
  Named Pipes T1559.001→T1559; Low-priv pipes T1559.001→T1134.001,T1559
- EventsInfo: class expanded with T1078.003,T1552.001,T1059.001,T1082
- UserInfo: class expanded; Token privileges T1134→T1134.001
- ProcessInfo: Leaked Handlers T1134.003→T1134.001 (token impersonation, not make-token)
- ServicesInfo: class adds T1574.011,T1068
- ApplicationsInfo: class adds T1010,T1014
- NetworkInfo: class adds T1018,T1090
- ActiveDirectoryInfo: T1484→T1484.001; class adds T1003
- WindowsCreds: class sub-techniques T1552→T1552.001,T1552.002, T1555→T1555.003,T1555.004;
  SSClient T1059→T1552.001 (wrong technique entirely)
- FilesInfo: class expanded with T1552.002,T1552.004,T1552.006,T1564.001,T1574.001,
  T1059.004,T1114.001,T1218,T1649; Cloud Credentials T1552.005→T1552.001
- SoapClientInfo: T1059,T1071→T1559,T1071.001 (IPC/Web protocol, not scripting)

* fix: add missing T1613 and T1562.001 to SystemInfo class-level MitreAttackIds; label AD object enumeration with T1087.002 and T1018

* fix: correct linpeas mitre filter matching logic

* fix: MITRE code bugs — pass-through for untagged checks, remove dead OR in section gate

- PassesMitreFilter (Checks.cs): when MitreAttackIds is null or empty and a filter
  is active, return true (pass-through) instead of false.  Previously any future
  ISystemCheck added without MITRE IDs would be silently excluded by an active filter.
- linpeasBaseBuilder.py: remove redundant '|| [ -z "$MITRE_FILTER" ]' from the
  generated section-level gate.  check_mitre_filter already returns 0 immediately
  when MITRE_FILTER is empty, so the OR branch was unreachable and inconsistent with
  the check-level gate which uses the same function without the extra guard.
- ArgumentParsingTests.cs: add PassesMitreFilter_NullMitreAttackIds_PassesThrough
  and PassesMitreFilter_EmptyMitreAttackIds_PassesThrough regression tests.

* fix(mitre): 4 bugs — dead arg parser, wait logic, subprocess forks, cleanup race

Checks.cs: max-regex-file-size used string.Equals which requires exact match,
so 'max-regex-file-size=500000' could never match and MaxRegexFileSize was stuck
at 1000000 forever. Fixed to arg.StartsWith.

Checks.cs RunChecks: wait compared loop index i against
_systemCheckSelectedKeysHashSet.Count, which is 0 when all checks run (so
i < -1 is always false) and semantically wrong when a key subset is selected.
Replaced with a pre-count of checks that pass both filters and a running counter.

0_variables_base.sh check_mitre_filter: replaced two $(echo ... | tr ...)
subprocess forks per call with pure parameter-expansion while-loops. Zero
process forks, POSIX-compliant, ~632 fork()s saved per full filtered run.
Declares _mitre_tags_left and _mitre_filters_left in Generated Global Variables.

linpeas_builder.py: os.remove of the shared temp file raised FileNotFoundError
when multiple sequential builder invocations ran (the second saw the file
already deleted by the first). Wrapped in try/except FileNotFoundError.

Tests: Added PassesMitreFilter_SubtechniqueFilter_DoesNotMatchParentOnlyTag
and MaxRegexFileSize_ArgParsed_Correctly regression tests (16 total).

* ci: add manual build-artifacts workflow (winPEAS.exe + linpeas.sh)

* fix(linpeas): getopts silent mode — clear error when -T given without argument

Switch getopts to silent mode (leading ':') so the shell does not emit its
own terse 'No arg for -T option' message. Add explicit :) case that prints
  ERROR: -T requires an argument (e.g. -T T1082,T1552)
and then dumps the help text before exiting 1. Add *) case for unrecognised
flags with the same pattern. Behaviour for all valid flags is unchanged.

* chore: untrack build-artifacts workflow, add to .gitignore
2026-03-08 01:26:40 +01:00

1530 lines
68 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using winPEAS.Helpers;
using winPEAS.Helpers.AppLocker;
using winPEAS.Helpers.Extensions;
using winPEAS.Helpers.Registry;
using winPEAS.Info.SystemInfo;
using winPEAS.Info.SystemInfo.AuditPolicies;
using winPEAS.Info.SystemInfo.DotNet;
using winPEAS.Info.SystemInfo.GroupPolicy;
using winPEAS.Info.SystemInfo.NamedPipes;
using winPEAS.Info.SystemInfo.Ntlm;
using winPEAS.Info.SystemInfo.PowerShell;
using winPEAS.Info.SystemInfo.Printers;
using winPEAS.Info.SystemInfo.SysMon;
using winPEAS.Info.SystemInfo.WindowsDefender;
using winPEAS.Native.Enums;
namespace winPEAS.Checks
{
class SystemInfo : ISystemCheck
{
static string badUAC = "No prompting|PromptForNonWindowsBinaries";
static string goodUAC = "PromptPermitDenyOnSecureDesktop";
static string badLAPS = "LAPS not installed";
static Dictionary<string, string> _basicSystemInfo;
private static readonly Dictionary<string, string> _asrGuids = new Dictionary<string, string>
{
{ "01443614-cd74-433a-b99e-2ecdc07bfc25" , "Block executable files from running unless they meet a prevalence, age, or trusted list criteria"},
{ "c1db55ab-c21a-4637-bb3f-a12568109d35" , "Use advanced protection against ransomware"},
{ "9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2" , "Block credential stealing from the Windows local security authority subsystem (lsass.exe)"},
{ "d1e49aac-8f56-4280-b9ba-993a6d77406c" , "Block process creations originating from PSExec and WMI commands"},
{ "b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4" , "Block untrusted and unsigned processes that run from USB"},
{ "26190899-1602-49e8-8b27-eb1d0a1ce869" , "Block Office communication applications from creating child processes"},
{ "7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c" , "Block Adobe Reader from creating child processes"},
{ "e6db77e5-3df2-4cf1-b95a-636979351e5b" , "Block persistence through WMI event subscription"},
{ "d4f940ab-401b-4efc-aadc-ad5f3c50688a" , "Block all Office applications from creating child processes"},
{ "5beb7efe-fd9a-4556-801d-275e5ffc04cc" , "Block execution of potentially obfuscated scripts"},
{ "92e97fa1-2edf-4476-bdd6-9dd0b4dddc7b" , "Block Win32 API calls from Office macro "},
{ "3b576869-a4ec-4529-8536-b80a7769e899" , "Block Office applications from creating executable content "},
{ "75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84" , "Block Office applications from injecting code into other processes"},
{ "d3e037e1-3eb8-44c8-a917-57927947596d" , "Block JavaScript or VBScript from launching downloaded executable content"},
{ "be9ba2d9-53ea-4cdc-84e5-9b1eeee46550" , "Block executable content from email client and webmail"},
};
public string[] MitreAttackIds { get; } = new[] { "T1082", "T1068", "T1548.002", "T1003.001", "T1003.004", "T1003.005", "T1059.001", "T1552.001", "T1552.002", "T1562.001", "T1562.002", "T1518.001", "T1557.001", "T1558", "T1559", "T1134.001", "T1547.005", "T1484.001", "T1613", "T1654", "T1072", "T1187" };
public void PrintInfo(bool isDebug)
{
Beaprint.GreatPrint("System Information", "T1082,T1068,T1548.002,T1003.001,T1003.004,T1003.005,T1059.001,T1552.001,T1552.002,T1562.001,T1562.002,T1518.001,T1557.001,T1558,T1559,T1134.001,T1547.005,T1484.001,T1613,T1654,T1072,T1187");
new List<Action>
{
PrintBasicSystemInfo,
PrintWindowsVersionVulnerabilities,
PrintMicrosoftUpdatesCOM,
PrintSystemLastShutdownTime,
PrintUserEV,
PrintSystemEV,
PrintAuditInfo,
PrintAuditPoliciesInfo,
PrintWEFInfo,
PrintLAPSInfo,
PrintWdigest,
PrintLSAProtection,
PrintCredentialGuard,
PrintCachedCreds,
PrintRegistryCreds,
PrintAVInfo,
PrintWindowsDefenderInfo,
PrintUACInfo,
PrintPSInfo,
PrintPowerShellSessionSettings,
PrintTranscriptPS,
PrintInetInfo,
PrintDrivesInfo,
PrintWSUS,
PrintKrbRelayUp,
PrintInsideContainer,
PrintAlwaysInstallElevated,
PrintObjectManagerRaceAmplification,
PrintLSAInfo,
PrintNtlmSettings,
PrintLocalGroupPolicy,
PrintPotentialGPOAbuse,
AppLockerHelper.PrintAppLockerPolicy,
PrintPrintNightmarePointAndPrint,
PrintPrintersWMIInfo,
PrintNamedPipes,
PrintNamedPipeAbuseCandidates,
PrintAMSIProviders,
PrintSysmon,
PrintDotNetVersions
}.ForEach(action => CheckRunner.Run(action, isDebug));
}
private static void PrintBasicSystemInfo()
{
try
{
Beaprint.MainPrint("Basic System Information", "T1082");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#version-exploits", "Check if the Windows versions is vulnerable to some known exploit");
Dictionary<string, string> basicDictSystem = Info.SystemInfo.SystemInfo.GetBasicOSInfo();
_basicSystemInfo = new Dictionary<string, string>(basicDictSystem);
basicDictSystem["Hotfixes"] = Beaprint.ansi_color_good + basicDictSystem["Hotfixes"] + Beaprint.NOCOLOR;
Dictionary<string, string> colorsSI = new Dictionary<string, string>
{
{ Globals.StrTrue, Beaprint.ansi_color_bad },
};
Beaprint.DictPrint(basicDictSystem, colorsSI, false);
Console.WriteLine();
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintWindowsVersionVulnerabilities()
{
try
{
Beaprint.MainPrint("Windows Version Vulnerabilities", "T1082,T1068");
var basicInfo = _basicSystemInfo ?? Info.SystemInfo.SystemInfo.GetBasicOSInfo();
var report = WindowsVersionVulns.GetVulnerabilityReport(basicInfo);
if (report.CandidateProducts.Count == 0)
{
Beaprint.InfoPrint("Unable to map this OS to WES-NG product definitions.");
return;
}
Beaprint.InfoPrint("WES-NG product candidates: " + string.Join(" | ", report.CandidateProducts));
if (!string.IsNullOrEmpty(report.DefinitionsDate))
{
Beaprint.InfoPrint("Definitions date: " + report.DefinitionsDate);
}
Beaprint.InfoPrint("Installed hotfixes detected: " + report.InstalledHotfixesCount);
if (report.TotalMatchedBeforeFiltering > 0)
{
Beaprint.InfoPrint($"Pre-filter matches: {report.TotalMatchedBeforeFiltering}, filtered by installed/superseded KBs: {report.FilteredByPatches}");
}
if (report.Vulnerabilities.Count == 0)
{
Beaprint.GoodPrint("No known exploited vulnerabilities matched this running Windows version.");
return;
}
Beaprint.BadPrint($"Matched {report.Vulnerabilities.Count} known exploited vulnerabilities for this running Windows version.");
if (report.MatchedProducts.Count > 0)
{
Beaprint.BadPrint("Matched products: " + string.Join(" | ", report.MatchedProducts));
}
int maxToPrint = 20;
foreach (var vuln in report.Vulnerabilities.Take(maxToPrint))
{
string vulnId = string.IsNullOrWhiteSpace(vuln.cve) ? $"KB{vuln.kb}" : vuln.cve;
string kbInfo = string.IsNullOrWhiteSpace(vuln.kb) ? "" : $" KB{vuln.kb}";
string severityInfo = string.IsNullOrWhiteSpace(vuln.severity) ? "" : $" [{vuln.severity}]";
string impactInfo = string.IsNullOrWhiteSpace(vuln.impact) ? "" : $" {vuln.impact}";
Beaprint.BadPrint($" {vulnId}{kbInfo}{severityInfo}{impactInfo}");
}
if (report.Vulnerabilities.Count > maxToPrint)
{
Beaprint.InfoPrint($"Showing {maxToPrint}/{report.Vulnerabilities.Count} results.");
}
Beaprint.InfoPrint("This check applies version matching with installed/superseded KB filtering.");
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintMicrosoftUpdatesCOM()
{
try
{
Beaprint.MainPrint("Showing All Microsoft Updates", "T1082");
var searcher = Type.GetTypeFromProgID("Microsoft.Update.Searcher");
var searcherObj = Activator.CreateInstance(searcher);
// get the total number of updates
var count = (int)searcherObj.GetType().InvokeMember("GetTotalHistoryCount", BindingFlags.InvokeMethod, null, searcherObj, new object[] { });
// get the pointer to the update collection
var results = searcherObj.GetType().InvokeMember("QueryHistory", BindingFlags.InvokeMethod, null, searcherObj, new object[] { 0, count });
for (int i = 0; i < count; ++i)
{
// get the actual update item
var item = searcherObj.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, results, new object[] { i });
// get our properties
// ref - https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatehistoryentry
var title = searcherObj.GetType().InvokeMember("Title", BindingFlags.GetProperty, null, item, new object[] { })?.ToString() ?? string.Empty;
var date = searcherObj.GetType().InvokeMember("Date", BindingFlags.GetProperty, null, item, new object[] { });
var description = searcherObj.GetType().InvokeMember("Description", BindingFlags.GetProperty, null, item, new object[] { });
var clientApplicationID = searcherObj.GetType().InvokeMember("ClientApplicationID", BindingFlags.GetProperty, null, item, new object[] { });
string hotfixId = "";
Regex reg = new Regex(@"KB\d+");
var matches = reg.Matches(title);
if (matches.Count > 0)
{
hotfixId = matches[0].ToString();
}
Beaprint.NoColorPrint($" HotFix ID : {hotfixId}\n" +
$" Installed At (UTC) : {Convert.ToDateTime(date.ToString()).ToUniversalTime()}\n" +
$" Title : {title}\n" +
$" Client Application ID : {clientApplicationID}\n" +
$" Description : {description}\n");
Beaprint.PrintLineSeparator();
Marshal.ReleaseComObject(item);
}
Marshal.ReleaseComObject(results);
Marshal.ReleaseComObject(searcherObj);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintPSInfo()
{
try
{
Dictionary<string, string> colorsPSI = new Dictionary<string, string>()
{
{ "PS history file: .+", Beaprint.ansi_color_bad },
{ "PS history size: .+", Beaprint.ansi_color_bad }
};
Beaprint.MainPrint("PowerShell Settings", "T1059.001");
Dictionary<string, string> PSs = Info.SystemInfo.SystemInfo.GetPowerShellSettings();
Beaprint.DictPrint(PSs, colorsPSI, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintTranscriptPS()
{
try
{
Beaprint.MainPrint("PS default transcripts history", "T1552.001");
Beaprint.InfoPrint("Read the PS history inside these files (if any)");
string drive = Path.GetPathRoot(Environment.SystemDirectory);
string transcriptsPath = drive + @"transcripts\";
string usersPath = $"{drive}users";
var users = Directory.EnumerateDirectories(usersPath, "*", SearchOption.TopDirectoryOnly);
string powershellTranscriptFilter = "powershell_transcript*";
var colors = new Dictionary<string, string>()
{
{ "^.*", Beaprint.ansi_color_bad },
};
var results = new List<string>();
var dict = new Dictionary<string, string>()
{
// 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))
{
try
{
var files = Directory.EnumerateFiles(path, filter, SearchOption.TopDirectoryOnly).ToList();
foreach (var file in files)
{
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)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintAuditInfo()
{
try
{
Beaprint.MainPrint("Audit Settings", "T1562.002");
Beaprint.LinkPrint("", "Check what is being logged");
Dictionary<string, string> auditDict = Info.SystemInfo.SystemInfo.GetAuditSettings();
Beaprint.DictPrint(auditDict, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintAuditPoliciesInfo()
{
try
{
Beaprint.MainPrint("Audit Policy Settings - Classic & Advanced", "T1562.002");
var policies = AuditPolicies.GetAuditPoliciesInfos();
foreach (var policy in policies)
{
Beaprint.NoColorPrint($" Domain : {policy.Domain}\n" +
$" GPO : {policy.GPO}\n" +
$" Type : {policy.Type}\n");
foreach (var entry in policy.Settings)
{
Beaprint.NoColorPrint($" {entry.Subcategory,50} : {entry.AuditType}");
}
Beaprint.PrintLineSeparator();
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintWEFInfo()
{
try
{
Beaprint.MainPrint("WEF Settings", "T1562.002");
Beaprint.LinkPrint("", "Windows Event Forwarding, is interesting to know were are sent the logs");
Dictionary<string, string> weftDict = Info.SystemInfo.SystemInfo.GetWEFSettings();
Beaprint.DictPrint(weftDict, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
void PrintLAPSInfo()
{
try
{
Beaprint.MainPrint("LAPS Settings", "T1003.004");
Beaprint.LinkPrint("", "If installed, local administrator password is changed frequently and is restricted by ACL");
Dictionary<string, string> lapsDict = Info.SystemInfo.SystemInfo.GetLapsSettings();
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ badLAPS, Beaprint.ansi_color_bad }
};
Beaprint.DictPrint(lapsDict, colorsSI, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintWdigest()
{
Beaprint.MainPrint("Wdigest", "T1003.001");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#wdigest", "If enabled, plain-text crds could be stored in LSASS");
string useLogonCredential = RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest", "UseLogonCredential");
if (useLogonCredential == "1")
Beaprint.BadPrint(" Wdigest is active");
else
Beaprint.GoodPrint(" Wdigest is not enabled");
}
static void PrintLSAProtection()
{
Beaprint.MainPrint("LSA Protection", "T1003.001");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#lsa-protection", "If enabled, a driver is needed to read LSASS memory (If Secure Boot or UEFI, RunAsPPL cannot be disabled by deleting the registry key)");
string useLogonCredential = RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\LSA", "RunAsPPL");
if (useLogonCredential == "1")
Beaprint.GoodPrint(" LSA Protection is active");
else
Beaprint.BadPrint(" LSA Protection is not enabled");
}
static void PrintCredentialGuard()
{
Beaprint.MainPrint("Credentials Guard", "T1003.001");
Beaprint.LinkPrint("https://book.hacktricks.wiki/windows-hardening/stealing-credentials/credentials-protections#credentials-guard", "If enabled, a driver is needed to read LSASS memory");
string lsaCfgFlags = RegistryHelper.GetRegValue("HKLM", @"System\CurrentControlSet\Control\LSA", "LsaCfgFlags");
if (lsaCfgFlags == "1")
{
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Beaprint.GoodPrint(" CredentialGuard is active with UEFI lock");
}
else if (lsaCfgFlags == "2")
{
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Beaprint.GoodPrint(" CredentialGuard is active without UEFI lock");
}
else
{
Beaprint.BadPrint(" CredentialGuard is not enabled");
}
CredentialGuard.PrintInfo();
}
static void PrintCachedCreds()
{
try{
Beaprint.MainPrint("Cached Creds", "T1003.005");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#cached-credentials", "If > 0, credentials will be cached in the registry and accessible by SYSTEM user");
string cachedlogonscount = RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "CACHEDLOGONSCOUNT");
if (!string.IsNullOrEmpty(cachedlogonscount))
{
int clc = Int16.Parse(cachedlogonscount);
if (clc > 0)
{
Beaprint.BadPrint(" cachedlogonscount is " + cachedlogonscount);
}
else
{
Beaprint.BadPrint(" cachedlogonscount is " + cachedlogonscount);
}
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintUserEV()
{
try
{
Beaprint.MainPrint("User Environment Variables", "T1082");
Beaprint.LinkPrint("", "Check for some passwords or keys in the env variables");
Dictionary<string, string> userEnvDict = Info.SystemInfo.SystemInfo.GetUserEnvVariables();
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ Globals.PrintCredStringsLimited, Beaprint.ansi_color_bad }
};
Beaprint.DictPrint(userEnvDict, colorsSI, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintSystemEV()
{
try
{
Beaprint.MainPrint("System Environment Variables", "T1082");
Beaprint.LinkPrint("", "Check for some passwords or keys in the env variables");
Dictionary<string, string> sysEnvDict = Info.SystemInfo.SystemInfo.GetSystemEnvVariables();
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ Globals.PrintCredStringsLimited, Beaprint.ansi_color_bad }
};
Beaprint.DictPrint(sysEnvDict, colorsSI, false);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintInetInfo()
{
try
{
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ "ProxyServer.*", Beaprint.ansi_color_bad }
};
Beaprint.MainPrint("HKCU Internet Settings", "T1082");
Dictionary<string, string> HKCUDict = Info.SystemInfo.SystemInfo.GetInternetSettings("HKCU");
Beaprint.DictPrint(HKCUDict, colorsSI, true);
Beaprint.MainPrint("HKLM Internet Settings", "T1082");
Dictionary<string, string> HKMLDict = Info.SystemInfo.SystemInfo.GetInternetSettings("HKLM");
Beaprint.DictPrint(HKMLDict, colorsSI, true);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintDrivesInfo()
{
try
{
Beaprint.MainPrint("Drives Information", "T1082");
Beaprint.LinkPrint("", "Remember that you should search more info inside the other drives");
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ "Permissions.*", Beaprint.ansi_color_bad}
};
foreach (Dictionary<string, string> drive in Info.SystemInfo.SystemInfo.GetDrivesInfo())
{
string drive_permissions = string.Join(", ", PermissionsHelper.GetPermissionsFolder(drive["Name"], Checks.CurrentUserSiDs));
string dToPrint = string.Format(" {0} (Type: {1})", drive["Name"], drive["Type"]);
if (!string.IsNullOrEmpty(drive["Volume label"]))
dToPrint += "(Volume label: " + drive["Volume label"] + ")";
if (!string.IsNullOrEmpty(drive["Filesystem"]))
dToPrint += "(Filesystem: " + drive["Filesystem"] + ")";
if (!string.IsNullOrEmpty(drive["Available space"]))
dToPrint += "(Available space: " + (((Int64.Parse(drive["Available space"]) / 1024) / 1024) / 1024).ToString() + " GB)";
if (drive_permissions.Length > 0)
dToPrint += "(Permissions: " + drive_permissions + ")";
Beaprint.AnsiPrint(dToPrint, colorsSI);
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintAVInfo()
{
try
{
Beaprint.MainPrint("AV Information", "T1518.001");
Dictionary<string, string> AVInfo = Info.SystemInfo.SystemInfo.GetAVInfo();
if (AVInfo.ContainsKey("Name") && AVInfo["Name"].Length > 0)
Beaprint.GoodPrint(" Some AV was detected, search for bypasses");
else
Beaprint.BadPrint(" No AV was detected!!");
Beaprint.DictPrint(AVInfo, true);
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintUACInfo()
{
try
{
Beaprint.MainPrint("UAC Status", "T1548.002");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#from-administrator-medium-to-high-integrity-level--uac-bypasss", "If you are in the Administrators group check how to bypass the UAC");
Dictionary<string, string> uacDict = Info.SystemInfo.SystemInfo.GetUACSystemPolicies();
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
{
{ badUAC, Beaprint.ansi_color_bad },
{ goodUAC, Beaprint.ansi_color_good }
};
Beaprint.DictPrint(uacDict, colorsSI, false);
if ((uacDict["EnableLUA"] == "") || (uacDict["EnableLUA"] == "0"))
Beaprint.BadPrint(" [*] EnableLUA != 1, UAC policies disabled.\r\n [+] Any local account can be used for lateral movement.");
if ((uacDict["EnableLUA"] == "1") && (uacDict["LocalAccountTokenFilterPolicy"] == "1"))
Beaprint.BadPrint(" [*] LocalAccountTokenFilterPolicy set to 1.\r\n [+] Any local account can be used for lateral movement.");
if ((uacDict["EnableLUA"] == "1") && (uacDict["LocalAccountTokenFilterPolicy"] != "1") && (uacDict["FilterAdministratorToken"] != "1"))
Beaprint.GoodPrint(" [*] LocalAccountTokenFilterPolicy set to 0 and FilterAdministratorToken != 1.\r\n [-] Only the RID-500 local admin account can be used for lateral movement.");
if ((uacDict["EnableLUA"] == "1") && (uacDict["LocalAccountTokenFilterPolicy"] != "1") && (uacDict["FilterAdministratorToken"] == "1"))
Beaprint.GoodPrint(" [*] LocalAccountTokenFilterPolicy set to 0 and FilterAdministratorToken == 1.\r\n [-] No local accounts can be used for lateral movement.");
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintWSUS()
{
try
{
Beaprint.MainPrint("Checking WSUS", "T1072,T1068");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#wsus");
string policyPath = "Software\\Policies\\Microsoft\\Windows\\WindowsUpdate";
string policyAUPath = "Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU";
string wsusPolicyValue = RegistryHelper.GetRegValue("HKLM", policyPath, "WUServer");
string useWUServerValue = RegistryHelper.GetRegValue("HKLM", policyAUPath, "UseWUServer");
if (!string.IsNullOrEmpty(wsusPolicyValue) && wsusPolicyValue.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
{
Beaprint.BadPrint(" WSUS is using http: " + wsusPolicyValue);
Beaprint.InfoPrint("You can test https://github.com/pimps/wsuxploit to escalate privileges");
if (useWUServerValue == "1")
Beaprint.BadPrint(" And UseWUServer is equals to 1, so it is vulnerable!");
else if (useWUServerValue == "0")
Beaprint.GoodPrint(" But UseWUServer is equals to 0, so it is not vulnerable!");
else
Console.WriteLine(" But UseWUServer is equals to " + useWUServerValue + ", so it may work or not");
}
else
{
if (string.IsNullOrEmpty(wsusPolicyValue))
Beaprint.NotFoundPrint();
else
Beaprint.GoodPrint(" WSUS value: " + wsusPolicyValue);
}
if (!string.IsNullOrEmpty(wsusPolicyValue))
{
bool clientsForced = useWUServerValue == "1";
if (clientsForced)
{
Beaprint.BadPrint(" CVE-2025-59287: Clients talk to WSUS at " + wsusPolicyValue + " (UseWUServer=1). Unpatched WSUS allows unauthenticated deserialization to SYSTEM.");
}
else
{
Beaprint.InfoPrint(" CVE-2025-59287: WSUS endpoint discovered at " + wsusPolicyValue + ". Confirm patch level before attempting exploitation.");
if (!string.IsNullOrEmpty(useWUServerValue))
Beaprint.InfoPrint(" UseWUServer is set to " + useWUServerValue + ", clients may still reach Microsoft Update.");
}
}
string wsusSetupPath = @"SOFTWARE\Microsoft\Update Services\Server\Setup";
string wsusVersion = RegistryHelper.GetRegValue("HKLM", wsusSetupPath, "VersionString");
string wsusInstallPath = RegistryHelper.GetRegValue("HKLM", wsusSetupPath, "InstallPath");
bool wsusRoleDetected = !string.IsNullOrEmpty(wsusVersion) || !string.IsNullOrEmpty(wsusInstallPath);
if (TryGetServiceStateAndAccount("WSUSService", out string wsusServiceState, out string wsusServiceAccount))
{
wsusRoleDetected = true;
string serviceMsg = " WSUSService status: " + wsusServiceState;
if (!string.IsNullOrEmpty(wsusServiceAccount))
serviceMsg += " (runs as " + wsusServiceAccount + ")";
Beaprint.BadPrint(serviceMsg);
}
if (wsusRoleDetected)
{
if (!string.IsNullOrEmpty(wsusVersion))
Beaprint.BadPrint(" WSUS Server version: " + wsusVersion + " (verify patch level for CVE-2025-59287).");
if (!string.IsNullOrEmpty(wsusInstallPath))
Beaprint.InfoPrint(" WSUS install path: " + wsusInstallPath);
Beaprint.BadPrint(" CVE-2025-59287: Local WSUS server exposes an unauthenticated deserialization surface reachable over HTTP(S). Patch or restrict access.");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static bool TryGetServiceStateAndAccount(string serviceName, out string state, out string account)
{
state = string.Empty;
account = string.Empty;
try
{
string query = $"SELECT Name, State, StartName FROM Win32_Service WHERE Name='{serviceName.Replace("'", "''")}'";
using (var searcher = new ManagementObjectSearcher(@"root\cimv2", query))
{
foreach (ManagementObject service in searcher.Get())
{
state = service["State"]?.ToString() ?? string.Empty;
account = service["StartName"]?.ToString() ?? string.Empty;
return true;
}
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
return false;
}
static void PrintKrbRelayUp()
{
try
{
Beaprint.MainPrint("Checking KrbRelayUp", "T1187,T1558");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#krbrelayup");
if (Checks.CurrentAdDomainName.Length > 0)
{
Beaprint.BadPrint(" The system is inside a domain (" + Checks.CurrentAdDomainName + ") so it could be vulnerable.");
Beaprint.InfoPrint("You can try https://github.com/Dec0ne/KrbRelayUp to escalate privileges");
}
else
{
Beaprint.GoodPrint(" The system isn't inside a domain, so it isn't vulnerable");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintInsideContainer()
{
try
{
Beaprint.MainPrint("Checking If Inside Container", "T1613");
Beaprint.LinkPrint("", "If the binary cexecsvc.exe or associated service exists, you are inside Docker");
Dictionary<string, object> regVal = RegistryHelper.GetRegValues("HKLM", @"System\CurrentControlSet\Services\cexecsvc");
bool cexecsvcExist = File.Exists(Environment.SystemDirectory + @"\cexecsvc.exe");
if (regVal != null || cexecsvcExist)
{
Beaprint.BadPrint("You are inside a container");
}
else
{
Beaprint.GoodPrint("You are NOT inside a container");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintAlwaysInstallElevated()
{
try
{
Beaprint.MainPrint("Checking AlwaysInstallElevated", "T1548.002");
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#alwaysinstallelevated");
string path = "Software\\Policies\\Microsoft\\Windows\\Installer";
string HKLM_AIE = RegistryHelper.GetRegValue("HKLM", path, "AlwaysInstallElevated");
string HKCU_AIE = RegistryHelper.GetRegValue("HKCU", path, "AlwaysInstallElevated");
if (HKLM_AIE == "1")
{
Beaprint.BadPrint(" AlwaysInstallElevated set to 1 in HKLM!");
}
if (HKCU_AIE == "1")
{
Beaprint.BadPrint(" AlwaysInstallElevated set to 1 in HKCU!");
}
if (HKLM_AIE != "1" && HKCU_AIE != "1")
{
Beaprint.GoodPrint(" AlwaysInstallElevated isn't available");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
static void PrintObjectManagerRaceAmplification()
{
try
{
Beaprint.MainPrint("Object Manager race-window amplification primitives", "T1068");
Beaprint.LinkPrint("https://projectzero.google/2025/12/windows-exploitation-techniques.html", "Project Zero write-up:");
if (ObjectManagerHelper.TryCreateSessionEvent(out var objectName, out var error))
{
Beaprint.BadPrint($" Created a test named event ({objectName}) under \\BaseNamedObjects.");
Beaprint.InfoPrint(" -> Low-privileged users can slow NtOpen*/NtCreate* lookups using ~32k-character names or ~16k-level directory chains.");
Beaprint.InfoPrint(" -> Point attacker-controlled symbolic links to the slow path to stretch kernel race windows.");
Beaprint.InfoPrint(" -> Use this whenever a bug follows check -> NtOpenX -> privileged action patterns.");
}
else
{
Beaprint.InfoPrint($" Could not create a test event under \\BaseNamedObjects ({error}). The namespace might be locked down.");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintNtlmSettings()
{
Beaprint.MainPrint($"Enumerating NTLM Settings", "T1557.001");
try
{
var info = Ntlm.GetNtlmSettingsInfo();
string lmCompatibilityLevelColor = info.LanmanCompatibilityLevel >= 3 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad;
Beaprint.ColorPrint($" LanmanCompatibilityLevel : {info.LanmanCompatibilityLevel} ({info.LanmanCompatibilityLevelString})\n", lmCompatibilityLevelColor);
var ntlmSettingsColors = new Dictionary<string, string>
{
{ "True", Beaprint.ansi_color_good },
{ "False", Beaprint.ansi_color_bad },
{ "No signing", Beaprint.ansi_color_bad},
{ "null", Beaprint.ansi_color_bad},
{ "Require Signing", Beaprint.ansi_color_good},
{ "Negotiate signing", Beaprint.ansi_color_yellow},
{ "Unknown", Beaprint.ansi_color_bad},
};
Beaprint.ColorPrint("\n NTLM Signing Settings", Beaprint.LBLUE);
Beaprint.AnsiPrint($" ClientRequireSigning : {info.ClientRequireSigning}\n" +
$" ClientNegotiateSigning : {info.ClientNegotiateSigning}\n" +
$" ServerRequireSigning : {info.ServerRequireSigning}\n" +
$" ServerNegotiateSigning : {info.ServerNegotiateSigning}\n" +
$" LdapSigning : {(info.LdapSigning != null ? info.LdapSigningString : "null")} ({info.LdapSigningString})",
ntlmSettingsColors);
Beaprint.ColorPrint("\n Session Security", Beaprint.LBLUE);
if (info.NTLMMinClientSec != null)
{
var clientSessionSecurity = (SessionSecurity)info.NTLMMinClientSec;
var clientSessionSecurityDescription = clientSessionSecurity.GetDescription();
var color = !clientSessionSecurity.HasFlag(SessionSecurity.NTLMv2) && !clientSessionSecurity.HasFlag(SessionSecurity.Require128BitKey) ?
Beaprint.ansi_color_bad :
Beaprint.ansi_color_good;
Beaprint.ColorPrint($" NTLMMinClientSec : {info.NTLMMinClientSec} ({clientSessionSecurityDescription})", color);
if (info.LanmanCompatibilityLevel < 3 && !clientSessionSecurity.HasFlag(SessionSecurity.NTLMv2))
{
Beaprint.BadPrint(" [!] NTLM clients support NTLMv1!");
}
}
if (info.NTLMMinServerSec != null)
{
var serverSessionSecurity = (SessionSecurity)info.NTLMMinServerSec;
var serverSessionSecurityDescription = serverSessionSecurity.GetDescription();
var color = !serverSessionSecurity.HasFlag(SessionSecurity.NTLMv2) && !serverSessionSecurity.HasFlag(SessionSecurity.Require128BitKey) ?
Beaprint.ansi_color_bad :
Beaprint.ansi_color_good;
Beaprint.ColorPrint($" NTLMMinServerSec : {info.NTLMMinServerSec} ({serverSessionSecurityDescription})\n", color);
if (info.LanmanCompatibilityLevel < 3 && !serverSessionSecurity.HasFlag(SessionSecurity.NTLMv2))
{
Beaprint.BadPrint(" [!] NTLM services on this machine support NTLMv1!");
}
}
var ntlmOutboundRestrictionsColor = info.OutboundRestrictions == 2 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad;
Beaprint.ColorPrint("\n NTLM Auditing and Restrictions", Beaprint.LBLUE);
Beaprint.NoColorPrint($" InboundRestrictions : {info.InboundRestrictions} ({info.InboundRestrictionsString})");
Beaprint.ColorPrint($" OutboundRestrictions : {info.OutboundRestrictions} ({info.OutboundRestrictionsString})", ntlmOutboundRestrictionsColor);
Beaprint.NoColorPrint($" InboundAuditing : {info.InboundAuditing} ({info.InboundRestrictionsString})");
Beaprint.NoColorPrint($" OutboundExceptions : {info.OutboundExceptions}");
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintPrintNightmarePointAndPrint()
{
Beaprint.MainPrint("PrintNightmare PointAndPrint Policies", "T1068");
Beaprint.LinkPrint("https://itm4n.github.io/printnightmare-exploitation/", "Check PointAndPrint policy hardening");
try
{
string key = @"Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint";
var restrict = RegistryHelper.GetDwordValue("HKLM", key, "RestrictDriverInstallationToAdministrators");
var noWarn = RegistryHelper.GetDwordValue("HKLM", key, "NoWarningNoElevationOnInstall");
var updatePrompt = RegistryHelper.GetDwordValue("HKLM", key, "UpdatePromptSettings");
if (restrict == null && noWarn == null && updatePrompt == null)
{
Beaprint.NotFoundPrint();
return;
}
Beaprint.NoColorPrint($" RestrictDriverInstallationToAdministrators: {restrict}\n" +
$" NoWarningNoElevationOnInstall: {noWarn}\n" +
$" UpdatePromptSettings: {updatePrompt}");
if (restrict == 0 && noWarn == 1 && updatePrompt == 2)
{
Beaprint.BadPrint(" [!] Potentially vulnerable to PrintNightmare misconfiguration");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintPrintersWMIInfo()
{
Beaprint.MainPrint("Enumerating Printers (WMI)", "T1082");
try
{
foreach (var printer in Printers.GetPrinterWMIInfos())
{
Beaprint.NoColorPrint($" Name: {printer.Name}\n" +
$" Status: {printer.Status}\n" +
$" Sddl: {printer.Sddl}\n" +
$" Is default: {printer.IsDefault}\n" +
$" Is network printer: {printer.IsNetworkPrinter}\n");
Beaprint.PrintLineSeparator();
}
}
catch (Exception ex)
{
//Beaprint.PrintException(ex.Message);
}
}
private static void PrintNamedPipes()
{
Beaprint.MainPrint("Enumerating Named Pipes", "T1559");
try
{
string formatString = " {0,-100} {1,-70} {2}\n";
Beaprint.NoColorPrint(string.Format($"{formatString}", "Name", "CurrentUserPerms", "Sddl"));
foreach (var namedPipe in NamedPipes.GetNamedPipeInfos())
{
var colors = new Dictionary<string, string>
{
{namedPipe.CurrentUserPerms.Replace("[","\\[").Replace("]","\\]"), Beaprint.ansi_color_bad },
};
Beaprint.AnsiPrint(string.Format(formatString, namedPipe.Name, namedPipe.CurrentUserPerms, namedPipe.Sddl), colors);
}
}
catch (Exception ex)
{
//Beaprint.PrintException(ex.Message);
}
}
private static void PrintNamedPipeAbuseCandidates()
{
Beaprint.MainPrint("Named Pipes with Low-Priv Write Access to Privileged Servers", "T1134.001,T1559");
try
{
var candidates = NamedPipeSecurityAnalyzer.GetNamedPipeAbuseCandidates().ToList();
if (!candidates.Any())
{
Beaprint.NoColorPrint(" No risky named pipe ACLs were found.\n");
return;
}
foreach (var candidate in candidates)
{
var aclSummary = candidate.LowPrivilegeAces.Any()
? string.Join("; ", candidate.LowPrivilegeAces.Select(ace =>
$"{ace.Principal} [{ace.RightsDescription}]").Where(s => !string.IsNullOrEmpty(s)))
: "Unknown";
var serverSummary = candidate.Processes.Any()
? string.Join("; ", candidate.Processes.Select(proc =>
$"{proc.ProcessName} (PID {proc.Pid}, {proc.UserName ?? proc.UserSid})"))
: "No privileged handles observed (service idle or access denied)";
var color = candidate.HasPrivilegedServer ? Beaprint.ansi_color_bad : Beaprint.ansi_color_yellow;
Beaprint.ColorPrint($" \\\\.\\pipe\\{candidate.Name}", color);
Beaprint.NoColorPrint($" Low-priv ACLs : {aclSummary}");
Beaprint.NoColorPrint($" Observed owners: {serverSummary}");
Beaprint.NoColorPrint($" SDDL : {candidate.Sddl}");
Beaprint.PrintLineSeparator();
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private void PrintAMSIProviders()
{
Beaprint.MainPrint("Enumerating AMSI registered providers", "T1562.001");
try
{
var providers = RegistryHelper.GetRegSubkeys("HKLM", @"SOFTWARE\Microsoft\AMSI\Providers") ?? new string[] { };
foreach (var provider in providers)
{
var providerPath = RegistryHelper.GetRegValue("HKLM", $"SOFTWARE\\Classes\\CLSID\\{provider}\\InprocServer32", "");
Beaprint.NoColorPrint($" Provider: {provider}\n" +
$" Path: {providerPath}\n");
Beaprint.PrintLineSeparator();
}
}
catch (Exception)
{
}
}
private void PrintSysmon()
{
PrintSysmonConfiguration();
PrintSysmonEventLogs();
}
private void PrintSysmonConfiguration()
{
Beaprint.MainPrint("Enumerating Sysmon configuration", "T1518.001");
Dictionary<string, string> colors = new Dictionary<string, string>
{
{ SysMon.NotDefined, Beaprint.ansi_color_bad },
{ "False", Beaprint.ansi_color_bad },
};
try
{
if (!MyUtils.IsHighIntegrity())
{
Beaprint.NoColorPrint(" You must be an administrator to run this check");
return;
}
foreach (var item in SysMon.GetSysMonInfos())
{
Beaprint.AnsiPrint($" Installed: {item.Installed}\n" +
$" Hashing Algorithm: {item.HashingAlgorithm.GetDescription()}\n" +
$" Options: {item.Options.GetDescription()}\n" +
$" Rules: {item.Rules}\n",
colors);
Beaprint.PrintLineSeparator();
}
}
catch (Exception)
{
}
}
private void PrintSysmonEventLogs()
{
Beaprint.MainPrint("Enumerating Sysmon process creation logs (1)", "T1654");
try
{
if (!MyUtils.IsHighIntegrity())
{
Beaprint.NoColorPrint(" You must be an administrator to run this check");
return;
}
foreach (var item in SysMon.GetSysMonEventInfos())
{
Beaprint.BadPrint($" EventID: {item.EventID}\n" +
$" User Name: {item.UserName}\n" +
$" Time Created: {item.TimeCreated}\n");
Beaprint.PrintLineSeparator();
}
}
catch (Exception)
{
}
}
private static void PrintWindowsDefenderInfo()
{
Beaprint.MainPrint("Windows Defender configuration", "T1518.001");
void DisplayDefenderSettings(WindowsDefenderSettings settings)
{
var pathExclusions = settings.PathExclusions;
var processExclusions = settings.ProcessExclusions;
var extensionExclusions = settings.ExtensionExclusions;
var asrSettings = settings.AsrSettings;
if (pathExclusions.Count != 0)
{
Beaprint.NoColorPrint("\n Path Exclusions:");
foreach (var path in pathExclusions)
{
Beaprint.NoColorPrint($" {path}");
}
}
if (pathExclusions.Count != 0)
{
Beaprint.NoColorPrint("\n PolicyManagerPathExclusions:");
foreach (var path in pathExclusions)
{
Beaprint.NoColorPrint($" {path}");
}
}
if (processExclusions.Count != 0)
{
Beaprint.NoColorPrint("\n Process Exclusions");
foreach (var process in processExclusions)
{
Beaprint.NoColorPrint($" {process}");
}
}
if (extensionExclusions.Count != 0)
{
Beaprint.NoColorPrint("\n Extension Exclusions");
foreach (var ext in extensionExclusions)
{
Beaprint.NoColorPrint($" {ext}");
}
}
if (asrSettings.Enabled)
{
Beaprint.NoColorPrint("\n Attack Surface Reduction Rules:\n");
Beaprint.NoColorPrint($" {"State",-10} Rule\n");
foreach (var rule in asrSettings.Rules)
{
string state;
if (rule.State == 0)
state = "Disabled";
else if (rule.State == 1)
state = "Blocked";
else if (rule.State == 2)
state = "Audited";
else
state = $"{rule.State} - Unknown";
var asrRule = _asrGuids.ContainsKey(rule.Rule.ToString())
? _asrGuids[rule.Rule.ToString()]
: $"{rule.Rule} - Please report this";
Beaprint.NoColorPrint($" {state,-10} {asrRule}");
}
if (asrSettings.Exclusions.Count > 0)
{
Beaprint.NoColorPrint("\n ASR Exclusions:");
foreach (var exclusion in asrSettings.Exclusions)
{
Beaprint.NoColorPrint($" {exclusion}");
}
}
}
}
try
{
var info = WindowsDefender.GetDefenderSettingsInfo();
Beaprint.ColorPrint(" Local Settings", Beaprint.LBLUE);
DisplayDefenderSettings(info.LocalSettings);
Beaprint.ColorPrint(" Group Policy Settings", Beaprint.LBLUE);
DisplayDefenderSettings(info.GroupPolicySettings);
}
catch (Exception e)
{
}
}
private static void PrintDotNetVersions()
{
try
{
Beaprint.MainPrint("Installed .NET versions\n", "T1082");
var info = DotNet.GetDotNetInfo();
Beaprint.ColorPrint(" CLR Versions", Beaprint.LBLUE);
foreach (var version in info.ClrVersions)
{
Beaprint.NoColorPrint($" {version}");
}
Beaprint.ColorPrint("\n .NET Versions", Beaprint.LBLUE);
foreach (var version in info.DotNetVersions)
{
Beaprint.NoColorPrint($" {version}");
}
var colors = new Dictionary<string, string>
{
{ "True", Beaprint.ansi_color_good },
{ "False", Beaprint.ansi_color_bad },
};
Beaprint.ColorPrint("\n .NET & AMSI (Anti-Malware Scan Interface) support", Beaprint.LBLUE);
Beaprint.AnsiPrint($" .NET version supports AMSI : {info.IsAmsiSupportedByDotNet}\n" +
$" OS supports AMSI : {info.IsAmsiSupportedByOs}",
colors);
var highestVersion = info.HighestVersion;
var lowestVersion = info.LowestVersion;
if ((highestVersion.Major == DotNetInfo.AmsiSupportedByDotNetMinMajorVersion) && (highestVersion.Minor >= DotNetInfo.AmsiSupportedByDotNetMinMinorVersion))
{
Beaprint.NoColorPrint($" [!] The highest .NET version is enrolled in AMSI!");
}
if (
info.IsAmsiSupportedByOs &&
info.IsAmsiSupportedByDotNet &&
((
(lowestVersion.Major == DotNetInfo.AmsiSupportedByDotNetMinMajorVersion - 1)
) ||
((lowestVersion.Major == DotNetInfo.AmsiSupportedByDotNetMinMajorVersion) && (lowestVersion.Minor < DotNetInfo.AmsiSupportedByDotNetMinMinorVersion)))
)
{
Beaprint.NoColorPrint($" [-] You can invoke .NET version {lowestVersion.Major}.{lowestVersion.Minor} to bypass AMSI.");
}
}
catch (Exception e)
{
}
}
private static void PrintSystemLastShutdownTime()
{
try
{
Beaprint.MainPrint("System Last Shutdown Date/time (from Registry)\n", "T1082");
var shutdownBytes = RegistryHelper.GetRegValueBytes("HKLM", "SYSTEM\\ControlSet001\\Control\\Windows", "ShutdownTime");
if (shutdownBytes != null)
{
var shutdownInt = BitConverter.ToInt64(shutdownBytes, 0);
var shutdownTime = DateTime.FromFileTime(shutdownInt);
Beaprint.NoColorPrint($" Last Shutdown Date/time : {shutdownTime}");
}
}
catch (Exception ex)
{
}
}
private static void PrintLSAInfo()
{
try
{
Beaprint.MainPrint("Enumerate LSA settings - auth packages included\n", "T1547.005");
var settings = RegistryHelper.GetRegValues("HKLM", "SYSTEM\\CurrentControlSet\\Control\\Lsa");
if ((settings != null) && (settings.Count != 0))
{
foreach (var kvp in settings)
{
var val = string.Empty;
if (kvp.Value.GetType().IsArray && (kvp.Value.GetType().GetElementType().ToString() == "System.String"))
{
val = string.Join(",", (string[])kvp.Value);
}
else if (kvp.Value.GetType().IsArray && (kvp.Value.GetType().GetElementType().ToString() == "System.Byte"))
{
val = BitConverter.ToString((byte[])kvp.Value);
}
else
{
val = kvp.Value.ToString();
}
var key = kvp.Key;
Beaprint.NoColorPrint($" {key,-30} : {val}");
if (Regex.IsMatch(key, "Security Packages") && Regex.IsMatch(val, @".*wdigest.*"))
{
Beaprint.BadPrint(" [!] WDigest is enabled - plaintext password extraction is possible!");
}
if (key.Equals("RunAsPPL", StringComparison.InvariantCultureIgnoreCase) && val == "1")
{
Beaprint.BadPrint(" [!] LSASS Protected Mode is enabled! You will not be able to access lsass.exe's memory easily.");
}
if (key.Equals("DisableRestrictedAdmin", StringComparison.InvariantCultureIgnoreCase) && val == "0")
{
Beaprint.BadPrint(" [!] RDP Restricted Admin Mode is enabled! You can use pass-the-hash to access RDP on this system.");
}
}
}
}
catch (Exception ex)
{
}
}
private static void PrintLocalGroupPolicy()
{
try
{
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine", "T1082");
var infos = GroupPolicy.GetLocalGroupPolicyInfos();
foreach (var info in infos)
{
Beaprint.NoColorPrint($" Type : {info.GPOType}\n" +
$" Display Name : {info.DisplayName}\n" +
$" Name : {info.GPOName}\n" +
$" Extensions : {info.Extensions}\n" +
$" File Sys Path : {info.FileSysPath}\n" +
$" Link : {info.Link}\n" +
$" GPO Link : {info.GPOLink.GetDescription()}\n" +
$" Options : {info.Options.GetDescription()}\n");
Beaprint.PrintLineSeparator();
}
}
catch (Exception ex)
{
}
}
private static void PrintPotentialGPOAbuse()
{
try
{
Beaprint.MainPrint("Potential GPO abuse vectors (applied domain GPOs writable by current user)", "T1484.001");
if (!Checks.IsPartOfDomain)
{
Beaprint.NoColorPrint(" Host is not joined to a domain or domain info is unavailable.");
return;
}
// Build a friendly group list for the current user to quickly spot interesting memberships
var currentGroups = winPEAS.Info.UserInfo.User.GetUserGroups(Checks.CurrentUserName, Checks.CurrentUserDomainName) ?? new System.Collections.Generic.List<string>();
var hasGPCO = currentGroups.Any(g => string.Equals(g, "Group Policy Creator Owners", System.StringComparison.InvariantCultureIgnoreCase));
if (hasGPCO)
{
Beaprint.BadPrint(" [!] Current user is member of 'Group Policy Creator Owners' — can create/own new GPOs. If you can link a GPO to an OU that applies here, you can execute code as SYSTEM via scheduled task/startup script.");
}
var infos = GroupPolicy.GetLocalGroupPolicyInfos();
bool anyFinding = false;
foreach (var info in infos)
{
var fileSysPath = info.FileSysPath?.ToString();
if (string.IsNullOrEmpty(fileSysPath))
{
continue;
}
// Only look at domain GPOs stored in SYSVOL
var isSysvolPath = fileSysPath.StartsWith(@"\", System.StringComparison.InvariantCultureIgnoreCase) &&
fileSysPath.IndexOf(@"\SysVol\", System.StringComparison.InvariantCultureIgnoreCase) >= 0 &&
fileSysPath.IndexOf(@"\Policies\", System.StringComparison.InvariantCultureIgnoreCase) >= 0;
if (!isSysvolPath)
{
continue;
}
// Check write/equivalent permissions on common abuse locations inside the GPO
var pathsToCheck = new System.Collections.Generic.List<string>
{
fileSysPath,
System.IO.Path.Combine(fileSysPath, @"Machine\Scripts\Startup"),
System.IO.Path.Combine(fileSysPath, @"User\Scripts\Logon"),
System.IO.Path.Combine(fileSysPath, @"Machine\Preferences\ScheduledTasks")
};
foreach (var p in pathsToCheck)
{
var perms = PermissionsHelper.GetPermissionsFolder(p, Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
if (perms != null && perms.Count > 0)
{
if (!anyFinding)
{
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/gpo-abuse.html", "Why it matters");
}
anyFinding = true;
Beaprint.BadPrint($" [!] Writable applied GPO detected");
Beaprint.NoColorPrint($" GPO Display Name : {info.DisplayName}");
Beaprint.NoColorPrint($" GPO Name : {info.GPOName}");
Beaprint.NoColorPrint($" GPO Link : {info.Link}");
Beaprint.NoColorPrint($" Path : {p}");
foreach (var entry in perms)
{
Beaprint.NoColorPrint($" -> {entry}");
}
Beaprint.GrayPrint(" Hint: Abuse by adding an immediate Scheduled Task or Startup script to execute as SYSTEM on gpupdate.");
}
}
}
if (!anyFinding && !hasGPCO)
{
Beaprint.NoColorPrint(" No obvious GPO abuse via writable SYSVOL paths or GPCO membership detected.");
}
}
catch (Exception ex)
{
// Avoid noisy stack traces in normal runs
Beaprint.GrayPrint($" [!] Error while checking potential GPO abuse: {ex.Message}");
}
}
private static void PrintPowerShellSessionSettings()
{
try
{
Beaprint.MainPrint("Enumerating PowerShell Session Settings using the registry", "T1059.001");
if (!MyUtils.IsHighIntegrity())
{
Beaprint.NoColorPrint(" You must be an administrator to run this check");
return;
}
var infos = PowerShell.GetPowerShellSessionSettingsInfos();
foreach (var info in infos)
{
Beaprint.NoColorPrint($" {"Name",-38} {info.Plugin}");
foreach (var access in info.Permissions)
{
Beaprint.NoColorPrint($" {access.Principal,-35} {access.Permission,-22}");
}
Beaprint.PrintLineSeparator();
}
}
catch (Exception ex)
{
}
}
private static void PrintRegistryCreds()
{
try
{
Beaprint.MainPrint("Enumerating saved credentials in Registry (CurrentPass)", "T1552.002");
string currentPass = "CurrentPass";
var hive = "HKLM";
var path = "System";
var controlSet = "ControlSet";
var colors = new Dictionary<string, string>
{
{ currentPass, Beaprint.ansi_color_bad }
};
var subkeys = RegistryHelper.GetRegSubkeys(hive, path);
foreach (var subkey in subkeys.Where(i => i.Contains(controlSet)))
{
try
{
var subPath = @$"{path}\{subkey}\Control";
var key = $@"{hive}\{subPath}\{currentPass}";
var value = RegistryHelper.GetRegValue(hive, subPath, currentPass);
if (!string.IsNullOrWhiteSpace(value))
{
Beaprint.AnsiPrint($@" {key,-60} : {value}", colors);
}
}
catch (Exception)
{
}
}
}
catch (Exception ex)
{
}
}
}
}