Auto-merge PR #786 (Chack Agent)

Co-authored-by: HackTricks News Bot <[email protected]>
This commit is contained in:
SirBroccoliandHackTricks News Bot authored and GitHub committed 2026-10-15 06:34:18 +00:00
1 parent 7d438b858a
commit 652ba220e4
3 files changed
+153

No files matched your search

+9
View File
@@ -77,6 +77,15 @@ Enroll ACEs for the current token. These are candidate paths, not proof of
effective access: CA-specific publication, enrollment-agent restrictions,
issuance policy, and certificate authentication still need manual verification.
The device-driver audit also reviews registered kernel-driver services whose image
is named `WinNotify.sys` or `msft.sys`. It reports service state, image path,
SHA-256, file version, and signature details. Only a SHA-256 match to the
[LocalStranger PoC driver](https://github.com/nbs32k/LocalStranger) confirms that
specific image; filename-only matches require manual review. The bounded,
read-only audit does not test the device interface or establish that the driver
can be loaded or exploited by the current user. It does not assess current
vulnerable-driver blocklist enforcement.
## Basic information
The goal of this project is to search for possible **Privilege Escalation Paths** in Windows environments.
@@ -982,6 +982,30 @@ namespace winPEAS.Checks
Beaprint.PrintLineSeparator();
}
}
bool candidateAuditIncomplete;
List<VulnerableDriverCandidate> candidates = DeviceDrivers.GetVulnerableDriverCandidates(out candidateAuditIncomplete);
if (candidates.Count > 0)
{
Beaprint.MainPrint("Known vulnerable driver indicators (BYOVD)", "T1068");
Beaprint.LinkPrint("https://github.com/nbs32k/LocalStranger", "WinNotify.sys / msft.sys LocalStranger proof of concept");
foreach (VulnerableDriverCandidate candidate in candidates)
{
string finding = candidate.KnownHash
? "Confirmed match to the published LocalStranger driver image"
: "Filename match only; driver identity not confirmed";
if (candidate.KnownHash) Beaprint.BadPrint(" " + finding);
else Beaprint.InfoPrint(" " + finding);
Beaprint.NoColorPrint(" Service/Image: " + candidate.ServiceName + " / " + candidate.Path);
Beaprint.NoColorPrint(" Service registered; image on disk: " + (candidate.ImagePresent ? "yes" : "not found or unresolved") +
"; SCM state: " + candidate.State + "; Start: " + (candidate.Start >= 0 ? candidate.Start.ToString() : "unknown"));
Beaprint.NoColorPrint(" SHA-256: " + candidate.Sha256);
Beaprint.NoColorPrint(" Version: " + candidate.Version + "; Signer: " + candidate.Signer);
Beaprint.NoColorPrint(" Authenticode: " + candidate.SignatureStatus);
}
Beaprint.GrayPrint(" Device access, service-load rights, and vulnerable-driver blocklist enforcement were not verified; a running service or matching image alone does not prove exploitability.");
}
if (candidateAuditIncomplete)
Beaprint.InfoPrint(" Known-driver indicator audit incomplete (registry access, 2-second or 4096-service limit, or 4-candidate limit).");
if (inventory.UnknownOrTruncated)
Beaprint.InfoPrint(" Driver inventory partial/unknown: " + inventory.Detail);
}
@@ -3,7 +3,12 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.Win32;
using System.ServiceProcess;
using winPEAS.Helpers;
using winPEAS.Native;
namespace winPEAS.Info.ApplicationInfo
@@ -26,8 +31,27 @@ namespace winPEAS.Info.ApplicationInfo
public string Detail;
}
internal sealed class VulnerableDriverCandidate
{
public string ServiceName;
public string Path;
public bool ImagePresent;
public string State = "unknown";
public int Start = -1;
public string Sha256 = "unavailable";
public bool KnownHash;
public string Version = "unavailable";
public string Signer = "unavailable";
public string SignatureStatus = "not checked";
}
internal static class DeviceDrivers
{
// SHA-256 of msft.sys in nbs32k/LocalStranger, commit 41fbecee2c9f928abb6306ccb481e715c80d8e8e.
private const string LocalStrangerSha256 = "4dc3a03a046c210a7c6cd37db8d6bd34bf3760a612232cc82acf941a9e508e0f";
private const int MaxDriverServiceKeys = 4096;
private const int MaxDriverCandidates = 4;
private const long MaxHashBytes = 8 * 1024 * 1024;
internal const int MaxPsapiDrivers = 1024;
internal const int MaxWmiDrivers = 1024;
internal const int MaxOutputDrivers = 256;
@@ -44,6 +68,102 @@ namespace winPEAS.Info.ApplicationInfo
return Merge(psapi, wmi, MaxOutputDrivers, string.Join("; ", details));
}
// Inspect only registered kernel-driver images with relevant names. Never contact a driver device.
public static List<VulnerableDriverCandidate> GetVulnerableDriverCandidates(out bool incomplete)
{
var candidates = new List<VulnerableDriverCandidate>();
incomplete = false;
try
{
using (RegistryKey services = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services"))
{
if (services == null) { incomplete = true; return candidates; }
string[] names = services.GetSubKeyNames();
int inspected = 0;
var timer = Stopwatch.StartNew();
foreach (string name in names)
{
if (++inspected > MaxDriverServiceKeys || timer.ElapsedMilliseconds >= 2000 ||
candidates.Count >= MaxDriverCandidates)
{
incomplete = true;
break;
}
try
{
using (RegistryKey key = services.OpenSubKey(name))
{
if (key == null) continue;
int type = Convert.ToInt32(key.GetValue("Type", 0));
if (type != 1 && type != 2) continue; // kernel and file-system driver services
string rawPath = key.GetValue("ImagePath") as string;
if (string.IsNullOrWhiteSpace(rawPath))
rawPath = @"System32\drivers\" + name + ".sys";
string path = NormalizePath(rawPath);
string fileName = Path.GetFileName(path);
if (!string.Equals(fileName, "WinNotify.sys", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(fileName, "msft.sys", StringComparison.OrdinalIgnoreCase)) continue;
var candidate = new VulnerableDriverCandidate { ServiceName = name, Path = path };
try { candidate.Start = Convert.ToInt32(key.GetValue("Start", -1)); }
catch { /* Keep start mode unknown. */ }
try
{
using (var controller = new ServiceController(name))
candidate.State = controller.Status.ToString();
}
catch { /* Loaded state remains unknown. */ }
ReadCandidateFile(candidate);
candidates.Add(candidate);
}
}
catch { incomplete = true; /* One unreadable service must not stop the audit. */ }
}
}
}
catch { incomplete = true; }
return candidates;
}
private static void ReadCandidateFile(VulnerableDriverCandidate candidate)
{
try
{
if (!IsLocalFilePath(candidate.Path) || !File.Exists(candidate.Path)) return;
candidate.ImagePresent = true;
var file = new FileInfo(candidate.Path);
if (file.Length > MaxHashBytes)
{
candidate.Sha256 = "not checked (image exceeds 8 MiB limit)";
candidate.Version = "not checked (image exceeds 8 MiB limit)";
candidate.SignatureStatus = "not checked (image exceeds 8 MiB limit)";
return;
}
try
{
using (var stream = new FileStream(candidate.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var sha = SHA256.Create())
candidate.Sha256 = BitConverter.ToString(sha.ComputeHash(stream)).Replace("-", "").ToLowerInvariant();
candidate.KnownHash = string.Equals(candidate.Sha256, LocalStrangerSha256, StringComparison.OrdinalIgnoreCase);
}
catch { candidate.Sha256 = "unavailable (image could not be read)"; }
try { candidate.Version = FileVersionInfo.GetVersionInfo(candidate.Path).FileVersion ?? "unavailable"; }
catch { /* Signature verification can still succeed without version metadata. */ }
AuthenticodeHelper.Verify(candidate.Path, out string status);
candidate.SignatureStatus = status;
try
{
using (var baseCert = X509Certificate.CreateFromSignedFile(candidate.Path))
using (var cert = new X509Certificate2(baseCert))
{
candidate.Signer = cert.Subject;
}
}
catch { /* A catalog signature may have no embedded signer. */ }
}
catch { /* Hash and signature remain unknown if the image cannot be read. */ }
}
// Pure merge/filter step: fixtures need no Windows APIs or device access.
internal static DeviceDriverInventory Merge(IEnumerable<DeviceDriverRecord> psapi,
IEnumerable<DeviceDriverRecord> systemDrivers, int maxOutput, string providerIssue = null)