-
-
Save tyranid/1431ec4da18c89cdea34cfe3f3af2bc0 to your computer and use it in GitHub Desktop.
This file contains 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
# Script to run experiment on Windows Service Hardening. | |
# Needs to be run as SYSTEM with TCB privilege. | |
Import-Module NtObjectManager | |
function Get-ServiceToken { | |
Param( | |
[Parameter(Mandatory, Position = 0)] | |
[NtObjectManager.ServiceAccountType]$Account, | |
[Parameter(Mandatory, Position = 1)] | |
[string]$ServiceName, | |
[switch]$WriteRestricted | |
) | |
# Build additional group list. | |
$logon_sid = Get-NtSid -NewLogon | |
$groups = @($logon_sid) | |
if ($WriteRestricted) { | |
$groups += Get-NtSid -KnownSid WriteRestricted | |
} | |
$service_sid = Get-NtSid -ServiceName $ServiceName | |
$groups += $service_sid | |
# Create service token, duplicate to ensure it's impersonation. | |
$token = Get-NtToken -Service $Account ` | |
-AdditionalGroups $groups -Duplicate | |
if ($null -eq $token) { | |
return | |
} | |
# Build default DACL. | |
$defdacl = New-NtSecurityDescriptor "D:(A;;GA;;;SY)(A;;RC;;;OW)(A;;GA;;;$service_sid)" | |
$token.DefaultDacl = $defdacl.Dacl | |
# Remove privileges. | |
Remove-NtTokenPrivilege -Token $token ` | |
SeImpersonatePrivilege,SeAssignPrimaryTokenPrivilege | |
if (!$WriteRestricted) { | |
Write-Output $token | |
return | |
} | |
# Create write restricted token. | |
Use-NtObject($token) { | |
$rsids = @(Get-NtSid "WD") + $groups | |
Get-NtToken -Filtered -Token $token -Duplicate ` | |
-RestrictedSids $rsids -Flags WriteRestricted | Write-Output | |
} | |
} | |
function Select-AccessCheckResult { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory, Position = 0)] | |
[NtApiDotNet.NtToken]$Token, | |
[Parameter(Mandatory, Position = 1, ValueFromPipeline)] | |
[NtObjectManager.AccessCheckResult[]]$Result | |
) | |
BEGIN { | |
$owner = $Token.Owner | |
$tokenid = $Token.Id.ToInt64() | |
} | |
PROCESS { | |
$Result | ? {$_.TokenId -eq $tokenid -and $_.Owner -eq $owner} | Write-Output | |
} | |
} | |
function Select-ResultEntry { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory, Position = 0, ValueFromPipeline)] | |
[NtObjectManager.AccessCheckResult[]]$Result | |
) | |
PROCESS { | |
$Result | Select Name,Owner,TypeName,User,GrantedAccess,GrantedAccessString,` | |
IsRead,IsWrite,IsExecute,IsDirectory,SecurityDescriptor | Write-Output | |
} | |
} | |
function Get-CsvName { | |
Param( | |
[Parameter(Mandatory, Position = 0)] | |
[NtApiDotNet.NtToken]$Token | |
) | |
$wr = if ($Token.WriteRestricted) { | |
"WriteRestricted" | |
} else { | |
"Unrestricted" | |
} | |
$user = $Token.User.Sid.Name | |
if ($user.Contains("\")) { | |
$user = $user.Split("\")[1] | |
} | |
if ($user -eq "LOCAL SERVICE" -or $user -eq "NETWORK SERVICE") { | |
"{0}_{1}.csv" -f @($user,$wr) | |
} else { | |
"control.csv" | |
} | |
} | |
Set-NtTokenPrivilege SeTcbPrivilege,SeDebugPrivilege | Out-Null | |
# Build the 5 test tokens. | |
$tokens = @() | |
$tokens += Get-ServiceToken LocalService FakeService | |
$tokens += Get-ServiceToken LocalService FakeService -WriteRestricted | |
$tokens += Get-ServiceToken NetworkService FakeService | |
$tokens += Get-ServiceToken NetworkService FakeService -WriteRestricted | |
$tokens += Get-NtToken -Session -Duplicate | |
Write-Host "Gathering Process and Thread Access" | |
# Get accessible processes and threads. | |
$ps = Get-AccessibleProcess -Tokens $tokens ` | |
-CheckMode ProcessAndThread -AllowEmptyAccess | |
Write-Host "Gathering Named Object Access" | |
# Get accessible named objects. | |
$os = Get-AccessibleObject \ -Recurse ` | |
-Tokens $tokens -AllowEmptyAccess -WarningAction Ignore | |
Write-Host "Gathering File Access" | |
# Get accessible files on the system drive. | |
$fs = Get-AccessibleFile -Win32Path "$env:SystemDrive\" -FormatWin32Path ` | |
-Recurse -Tokens $tokens -AllowEmptyAccess | |
Write-Host "Gathering Registry Key Access" | |
# Get accessible registry keys. | |
$ks = Get-AccessibleKey \Registry -FormatWin32Path -Recurse ` | |
-Tokens $tokens -AllowEmptyAccess | |
function Output-Results { | |
Param( | |
[Parameter(Mandatory, Position = 0)] | |
[NtApiDotNet.NtToken]$Token, | |
[Parameter(Mandatory, Position = 1)] | |
[string]$Path | |
) | |
Write-Host "Writing results file '$Path'" | |
$ps | Select-AccessCheckResult $Token | Select-ResultEntry ` | |
| Export-Csv -Path $Path -NoTypeInformation | |
$os | Select-AccessCheckResult $Token | Select-ResultEntry ` | |
| Export-Csv -Path $Path -Append -NoTypeInformation | |
$fs | Select-AccessCheckResult $Token | Select-ResultEntry ` | |
| Export-Csv -Path $Path -Append -NoTypeInformation | |
$ks | Select-AccessCheckResult $Token | Select-ResultEntry ` | |
| Export-Csv -Path $Path -Append -NoTypeInformation | |
} | |
Use-NtObject($tokens) { | |
foreach($t in $tokens) { | |
$name = Get-CsvName $t | |
Output-Results $t $name | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment