Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save f-bader/df5d0628c1af689586e63e4999df7c27 to your computer and use it in GitHub Desktop.
Save f-bader/df5d0628c1af689586e63e4999df7c27 to your computer and use it in GitHub Desktop.
### 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