Forked from olafhartong/GetTracelogProviderSecurity.ps1
Created
January 3, 2025 19:03
-
-
Save f-bader/df5d0628c1af689586e63e4999df7c27 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### USAGE: | |
### | |
### GetTracelogProviderSecurity.ps1 (to get all provider info) | |
### | |
### GetTracelogProviderSecurity.ps1 -ProviderName f2e68291-2367-5d51-3488-46f7a0e3f2cf | |
### (to get the info for 1 provider guid) | |
## | |
# | |
# Provider: f2e68291-2367-5d51-3488-46f7a0e3f2cf | |
# Control Flags: 45076 | |
# Owner SID: S-1-5-18 | |
# Owner Name: Unable to resolve | |
# Group SID: S-1-5-18 | |
# Group Name: Unable to resolve | |
# DACL Offset: 52 | |
# DACL Information: | |
# Revision: 2 | |
# Size: 28 bytes | |
# ACE Count: 1 | |
# Access Control Entry [0]: | |
# Type: Allow | |
# Flags: None | |
# Rights: Custom (0x00001FFF) | |
# Principal: S-1-5-18 | |
# Principal Name: NT AUTHORITY\SYSTEM | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory = $false)] | |
[string]$ProviderName = "all" | |
) | |
# Function to convert a binary SID to a readable format | |
function Convert-SID { | |
param ( | |
[byte[]]$BinarySID | |
) | |
try { | |
return (New-Object System.Security.Principal.SecurityIdentifier ($BinarySID, 0)).Value | |
} catch { | |
Write-Warning "Failed to convert binary SID" | |
return $null | |
} | |
} | |
# Function to parse an Access Control Entry (ACE) | |
function Parse-ACE { | |
param ( | |
[byte[]]$ACEData | |
) | |
$AceType = $ACEData[0] | |
$AceFlags = $ACEData[1] | |
$AceSize = [BitConverter]::ToUInt16($ACEData[2..3], 0) | |
$Mask = [BitConverter]::ToUInt32($ACEData[4..7], 0) | |
$SidStart = 8 | |
$SID = $ACEData[$SidStart..($AceSize - 1)] | |
$ReadableSID = Convert-SID -BinarySID $SID | |
return @{ | |
AceType = $AceType | |
AceFlags = $AceFlags | |
AccessMask = $Mask | |
SID = $ReadableSID | |
} | |
} | |
Add-Type @' | |
using System; | |
using System.Runtime.InteropServices; | |
public class SidResolver { | |
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
public static extern bool LookupAccountSid( | |
string lpSystemName, | |
[MarshalAs(UnmanagedType.LPArray)] byte[] Sid, | |
System.Text.StringBuilder lpName, | |
ref uint cchName, | |
System.Text.StringBuilder ReferencedDomainName, | |
ref uint cchReferencedDomainName, | |
out int peUse); | |
} | |
'@ | |
function Resolve-SidToName { | |
param ([string]$SidString) | |
try { | |
$objSID = New-Object System.Security.Principal.SecurityIdentifier($SidString) | |
$objAccount = $objSID.Translate([System.Security.Principal.NTAccount]) | |
return $objAccount.Value | |
} | |
catch { | |
return "Unable to resolve" | |
} | |
} | |
function Parse-DACL { | |
param ( | |
[byte[]]$BinaryData, | |
[int]$DaclOffset | |
) | |
$AclStart = $DaclOffset | |
if ($AclStart -ge $BinaryData.Length -or ($AclStart + 8) -gt $BinaryData.Length) { | |
Write-Output "Error: Invalid DACL offset" | |
return | |
} | |
$AclRevision = $BinaryData[$AclStart] | |
$AclSize = [BitConverter]::ToUInt16($BinaryData[($AclStart + 2)..($AclStart + 3)], 0) | |
$AceCount = [BitConverter]::ToUInt16($BinaryData[($AclStart + 4)..($AclStart + 5)], 0) | |
Write-Output "DACL Information:" | |
Write-Output " Revision: $AclRevision" | |
Write-Output " Size: $AclSize bytes" | |
Write-Output " ACE Count: $AceCount`n" | |
if ($AclSize -lt 8 -or ($AclStart + $AclSize) -gt $BinaryData.Length) { | |
Write-Output "Error: Invalid ACL size" | |
return | |
} | |
$CurrentOffset = $AclStart + 8 | |
for ($i = 0; $i -lt $AceCount; $i++) { | |
if ($CurrentOffset + 4 -gt $BinaryData.Length) { break } | |
$AceType = $BinaryData[$CurrentOffset] | |
$AceFlags = $BinaryData[$CurrentOffset + 1] | |
$AceSize = [BitConverter]::ToUInt16($BinaryData[($CurrentOffset + 2)..($CurrentOffset + 3)], 0) | |
# Get Access Mask (4 bytes after ACE header) | |
$AccessMask = [BitConverter]::ToUInt32($BinaryData[($CurrentOffset + 4)..($CurrentOffset + 7)], 0) | |
# Get SID (starts 8 bytes after ACE header) | |
$SidStart = $CurrentOffset + 8 | |
$SidLength = $AceSize - 8 | |
$SidBytes = $BinaryData[$SidStart..($SidStart + $SidLength - 1)] | |
$ReadableSID = Convert-SID -BinarySID $SidBytes | |
Write-Output "Access Control Entry [$i]:" | |
Write-Output " Type: $(Get-AceType $AceType)" | |
Write-Output " Flags: $(Get-AceFlags $AceFlags)" | |
Write-Output " Rights: $(Get-AccessMask $AccessMask)" | |
Write-Output " Principal: $ReadableSID" | |
write-host " Principal Name: $(Resolve-SidToName $ReadableSID)" -ForegroundColor Yellow | |
# Write-Output " Principal Name: $(Resolve-SidToName $ReadableSID)`n" | |
Write-Output "`n" | |
$CurrentOffset += $AceSize | |
} | |
} | |
function Get-AceType { | |
param ([byte]$Type) | |
switch ($Type) { | |
0x00 { "Allow" } | |
0x01 { "Deny" } | |
0x02 { "Audit" } | |
default { "Unknown ($Type)" } | |
} | |
} | |
function Get-AceFlags { | |
param ([byte]$Flags) | |
$FlagStrings = @() | |
if ($Flags -band 0x80) { $FlagStrings += "Inherited" } | |
if ($Flags -band 0x40) { $FlagStrings += "Inherit-Only" } | |
if ($Flags -band 0x20) { $FlagStrings += "No-Propagate" } | |
if ($Flags -band 0x10) { $FlagStrings += "Container-Inherit" } | |
if ($Flags -band 0x08) { $FlagStrings += "Object-Inherit" } | |
if ($FlagStrings.Count -eq 0) { return "None" } | |
return $FlagStrings -join ", " | |
} | |
function Get-AccessMask { | |
param ([uint32]$Mask) | |
$Rights = @() | |
# Generic Rights | |
if ($Mask -band 0x80000000) { $Rights += "Read" } | |
if ($Mask -band 0x40000000) { $Rights += "Write" } | |
if ($Mask -band 0x20000000) { $Rights += "Execute" } | |
if ($Mask -band 0x10000000) { $Rights += "Full Control" } | |
# Standard Rights | |
if ($Mask -band 0x00010000) { $Rights += "Delete" } | |
if ($Mask -band 0x00020000) { $Rights += "Read Control" } | |
if ($Mask -band 0x00040000) { $Rights += "Write DAC" } | |
if ($Mask -band 0x00080000) { $Rights += "Write Owner" } | |
if ($Rights.Count -eq 0) { | |
return "Custom (0x$($Mask.ToString('X8')))" | |
} | |
return $Rights -join ", " | |
} | |
function Parse-SecurityDescriptor { | |
param ([byte[]]$BinaryData) | |
if ($BinaryData.Length -lt 20) { | |
Write-Output "Error: Invalid security descriptor (too short)" | |
return | |
} | |
# Parse Security Descriptor Header | |
$Revision = $BinaryData[0] | |
$Sbz1 = $BinaryData[1] | |
$Control = [BitConverter]::ToUInt16($BinaryData[2..3], 0) | |
$OwnerOffset = [BitConverter]::ToUInt32($BinaryData[4..7], 0) | |
$GroupOffset = [BitConverter]::ToUInt32($BinaryData[8..11], 0) | |
$SaclOffset = [BitConverter]::ToUInt32($BinaryData[12..15], 0) | |
$DaclOffset = [BitConverter]::ToUInt32($BinaryData[16..19], 0) | |
Write-Output "Control Flags: $Control" | |
# Check if DACL is present | |
if (-not ($Control -band 0x0004)) { | |
Write-Output "DACL: Not Present (Control flags indicate no DACL)" | |
return | |
} | |
function Get-SIDLength { | |
param ([byte[]]$SidData) | |
if ($SidData.Length -lt 8) { return 0 } | |
$SubAuthCount = $SidData[1] | |
return 8 + (4 * $SubAuthCount) | |
} | |
# Process Owner SID | |
if ($OwnerOffset -ne 0) { | |
$OwnerSID = $BinaryData[$OwnerOffset..$($OwnerOffset + (Get-SIDLength $BinaryData[$OwnerOffset..($BinaryData.Length-1)]) - 1)] | |
$ReadableOwnerSID = Convert-SID -BinarySID $OwnerSID | |
Write-Output "Owner SID: $ReadableOwnerSID" | |
Write-Output "Owner Name: $(Resolve-SidToName $OwnerSID)" | |
} | |
# Process Group SID | |
if ($GroupOffset -ne 0) { | |
$GroupSID = $BinaryData[$GroupOffset..$($GroupOffset + (Get-SIDLength $BinaryData[$GroupOffset..($BinaryData.Length-1)]) - 1)] | |
$ReadableGroupSID = Convert-SID -BinarySID $GroupSID | |
Write-Output "Group SID: $ReadableGroupSID" | |
Write-Output "Group Name: $(Resolve-SidToName $GroupSID)" | |
} | |
# Process DACL | |
if ($DaclOffset -ne 0 -and $DaclOffset -lt $BinaryData.Length) { | |
Write-Output "DACL Offset: $DaclOffset" | |
Parse-DACL -BinaryData $BinaryData -DaclOffset $DaclOffset | |
} else { | |
Write-Output "DACL: Invalid Offset ($DaclOffset)" | |
} | |
} | |
# Main script | |
# $RegistryPath = "HKLM:\System\CurrentControlSet\Control\WMI\" | |
# try { | |
# $SubKeys = Get-ChildItem -Path $RegistryPath -ErrorAction Stop | |
# foreach ($SubKey in $SubKeys) { | |
# Write-Output "Processing SubKey: $($SubKey.PSChildName)" | |
# $Values = Get-ItemProperty -Path $SubKey.PSPath | |
# foreach ($Property in $Values.PSObject.Properties) { | |
# if ($Property.MemberType -eq "NoteProperty" -and $Property.Value -is [byte[]]) { | |
# Write-Host "Provider: $($Property.Name)" -ForegroundColor Blue | |
# # Write-Output " Type: System.Byte[] (processing)" | |
# Parse-SecurityDescriptor -BinaryData $Property.Value | |
# } else { | |
# Write-Host "Provider: $($Property.Name)" -ForegroundColor Blue | |
# Write-Output " Type: $($Property.Value.GetType().Name) (not processed)" | |
# } | |
# } | |
# } | |
# } catch { | |
# Write-Error "An error occurred: $_" | |
# } | |
$RegistryPath = "HKLM:\System\CurrentControlSet\Control\WMI\" | |
try { | |
$SubKeys = Get-ChildItem -Path $RegistryPath -ErrorAction Stop | |
foreach ($SubKey in $SubKeys) { | |
# Write-Output "Processing SubKey: $($SubKey.PSChildName)" | |
$Values = Get-ItemProperty -Path $SubKey.PSPath | |
foreach ($Property in $Values.PSObject.Properties) { | |
# Filter based on ProviderName parameter | |
if ($ProviderName -ne "all" -and $Property.Name -notlike "*$ProviderName*") { | |
continue | |
} | |
if ($Property.MemberType -eq "NoteProperty" -and $Property.Value -is [byte[]]) { | |
Write-Host "Provider: $($Property.Name)" -ForegroundColor Blue | |
Parse-SecurityDescriptor -BinaryData $Property.Value | |
} else { | |
Write-Host "Provider: $($Property.Name)" -ForegroundColor Blue | |
Write-Output " Type: $($Property.Value.GetType().Name) (not processed)" | |
} | |
} | |
} | |
} catch { | |
Write-Error "An error occurred: $_" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment