Skip to content
This repository was archived by the owner on Jan 21, 2021. It is now read-only.

Commit fc04f97

Browse files
Generalized ACE creation and added LDAP logonhours conversion
Added ConvertFrom-LDAPLogonHours and New-ADObjectAccessControlEntry
1 parent 9f4e32e commit fc04f97

File tree

1 file changed

+324
-9
lines changed

1 file changed

+324
-9
lines changed

Recon/PowerView.ps1

Lines changed: 324 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6400,6 +6400,330 @@ scriptpath
64006400
}
64016401

64026402

6403+
function ConvertFrom-LDAPLogonHours {
6404+
<#
6405+
.SYNOPSIS
6406+
6407+
Converts the LDAP LogonHours array to a processible object.
6408+
6409+
Author: Lee Christensen (@tifkin_)
6410+
License: BSD 3-Clause
6411+
Required Dependencies: None
6412+
6413+
.DESCRIPTION
6414+
6415+
Converts the LDAP LogonHours array to a processible object. Each entry
6416+
property in the output object corresponds to a day of the week and hour during
6417+
the day (in UTC) indicating whether or not the user can logon at the specified
6418+
hour.
6419+
6420+
.PARAMETER LogonHoursArray
6421+
6422+
21-byte LDAP hours array.
6423+
6424+
.EXAMPLE
6425+
6426+
$hours = (Get-DomainUser -LDAPFilter 'userworkstations=*')[0].logonhours
6427+
ConvertFrom-LDAPLogonHours $hours
6428+
6429+
Gets the logonhours array from the first AD user with logon restrictions.
6430+
6431+
.OUTPUTS
6432+
6433+
PowerView.LogonHours
6434+
#>
6435+
6436+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
6437+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
6438+
[OutputType('PowerView.LogonHours')]
6439+
[CmdletBinding()]
6440+
Param (
6441+
[Parameter( ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
6442+
[ValidateNotNullOrEmpty()]
6443+
[byte[]]
6444+
$LogonHoursArray
6445+
)
6446+
6447+
Begin {
6448+
if($LogonHoursArray.Count -ne 21) {
6449+
throw "LogonHoursArray is the incorrect length"
6450+
}
6451+
6452+
function ConvertTo-LogonHoursArray {
6453+
Param (
6454+
[int[]]
6455+
$HoursArr
6456+
)
6457+
6458+
$LogonHours = New-Object bool[] 24
6459+
for($i=0; $i -lt 3; $i++) {
6460+
$Byte = $HoursArr[$i]
6461+
$Offset = $i * 8
6462+
$Str = [Convert]::ToString($Byte,2).PadLeft(8,'0')
6463+
6464+
$LogonHours[$Offset+0] = [bool] [convert]::ToInt32([string]$Str[7])
6465+
$LogonHours[$Offset+1] = [bool] [convert]::ToInt32([string]$Str[6])
6466+
$LogonHours[$Offset+2] = [bool] [convert]::ToInt32([string]$Str[5])
6467+
$LogonHours[$Offset+3] = [bool] [convert]::ToInt32([string]$Str[4])
6468+
$LogonHours[$Offset+4] = [bool] [convert]::ToInt32([string]$Str[3])
6469+
$LogonHours[$Offset+5] = [bool] [convert]::ToInt32([string]$Str[2])
6470+
$LogonHours[$Offset+6] = [bool] [convert]::ToInt32([string]$Str[1])
6471+
$LogonHours[$Offset+7] = [bool] [convert]::ToInt32([string]$Str[0])
6472+
}
6473+
6474+
$LogonHours
6475+
}
6476+
}
6477+
6478+
Process {
6479+
$Output = @{
6480+
Sunday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[0..2]
6481+
Monday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[3..5]
6482+
Tuesday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[6..8]
6483+
Wednesday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[9..11]
6484+
Thurs = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[12..14]
6485+
Friday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[15..17]
6486+
Saturday = ConvertTo-LogonHoursArray -HoursArr $LogonHoursArray[18..20]
6487+
}
6488+
6489+
$Output = New-Object PSObject -Property $Output
6490+
$Output.PSObject.TypeNames.Insert(0, 'PowerView.LogonHours')
6491+
$Output
6492+
}
6493+
}
6494+
6495+
6496+
function New-ADObjectAccessControlEntry {
6497+
<#
6498+
.SYNOPSIS
6499+
6500+
Creates a new Active Directory object-specific access control entry.
6501+
6502+
Author: Lee Christensen (@tifkin_)
6503+
License: BSD 3-Clause
6504+
Required Dependencies: None
6505+
6506+
.DESCRIPTION
6507+
6508+
Creates a new object-specific access control entry (ACE). The ACE could be
6509+
used for auditing access to an object or controlling access to objects.
6510+
6511+
.PARAMETER PrincipalIdentity
6512+
6513+
A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local),
6514+
SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201)
6515+
for the domain principal to add for the ACL. Required. Wildcards accepted.
6516+
6517+
.PARAMETER PrincipalDomain
6518+
6519+
Specifies the domain for the TargetIdentity to use for the principal, defaults to the current domain.
6520+
6521+
.PARAMETER PrincipalSearchBase
6522+
6523+
The LDAP source to search through for principals, e.g. "LDAP://OU=secret,DC=testlab,DC=local"
6524+
Useful for OU queries.
6525+
6526+
.PARAMETER Server
6527+
6528+
Specifies an Active Directory server (domain controller) to bind to.
6529+
6530+
.PARAMETER SearchScope
6531+
6532+
Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree).
6533+
6534+
.PARAMETER ResultPageSize
6535+
6536+
Specifies the PageSize to set for the LDAP searcher object.
6537+
6538+
.PARAMETER ServerTimeLimit
6539+
6540+
Specifies the maximum amount of time the server spends searching. Default of 120 seconds.
6541+
6542+
.PARAMETER Tombstone
6543+
6544+
Switch. Specifies that the searcher should also return deleted/tombstoned objects.
6545+
6546+
.PARAMETER Credential
6547+
6548+
A [Management.Automation.PSCredential] object of alternate credentials
6549+
for connection to the target domain.
6550+
6551+
.PARAMETER Right
6552+
6553+
Specifies the rights set on the Active Directory object.
6554+
6555+
.PARAMETER AccessControlType
6556+
6557+
Specifies the type of ACE (allow or deny)
6558+
6559+
.PARAMETER AuditFlag
6560+
6561+
For audit ACEs, specifies when to create an audit log (on success or failure)
6562+
6563+
.PARAMETER ObjectType
6564+
6565+
Specifies the GUID of the object that the ACE applies to.
6566+
6567+
.PARAMETER InheritanceType
6568+
6569+
Specifies how the ACE applies to the object and/or its children.
6570+
6571+
.PARAMETER InheritedObjectType
6572+
6573+
Specifies the type of object that can inherit the ACE.
6574+
6575+
.EXAMPLE
6576+
6577+
$Guids = Get-DomainGUIDMap
6578+
$AdmPropertyGuid = $Guids.GetEnumerator() | ?{$_.value -eq 'ms-Mcs-AdmPwd'} | select -ExpandProperty name
6579+
$CompPropertyGuid = $Guids.GetEnumerator() | ?{$_.value -eq 'Computer'} | select -ExpandProperty name
6580+
$ACE = New-ADObjectAccessControlEntry -Verbose -PrincipalIdentity itadmin -Right ExtendedRight,ReadProperty -AccessControlType Allow -ObjectType $AdmPropertyGuid -InheritanceType All -InheritedObjectType $CompPropertyGuid
6581+
$OU = Get-DomainOU -Raw Workstations
6582+
$DsEntry = $OU.GetDirectoryEntry()
6583+
$dsEntry.PsBase.Options.SecurityMasks = 'Dacl'
6584+
$dsEntry.PsBase.ObjectSecurity.AddAccessRule($ACE)
6585+
$dsEntry.PsBase.CommitChanges()
6586+
6587+
Adds an ACE to all computer objects in the OU "Workstations" permitting the
6588+
user "itadmin" to read the confidential ms-Mcs-AdmPwd computer property.
6589+
6590+
.OUTPUTS
6591+
6592+
System.Security.AccessControl.AuthorizationRule
6593+
#>
6594+
6595+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')]
6596+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
6597+
[OutputType('System.Security.AccessControl.AuthorizationRule')]
6598+
[CmdletBinding()]
6599+
Param (
6600+
[Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, Mandatory = $True)]
6601+
[Alias('DistinguishedName', 'SamAccountName', 'Name')]
6602+
[String]
6603+
$PrincipalIdentity,
6604+
6605+
[ValidateNotNullOrEmpty()]
6606+
[String]
6607+
$PrincipalDomain,
6608+
6609+
[ValidateNotNullOrEmpty()]
6610+
[Alias('DomainController')]
6611+
[String]
6612+
$Server,
6613+
6614+
[ValidateSet('Base', 'OneLevel', 'Subtree')]
6615+
[String]
6616+
$SearchScope = 'Subtree',
6617+
6618+
[ValidateRange(1, 10000)]
6619+
[Int]
6620+
$ResultPageSize = 200,
6621+
6622+
[ValidateRange(1, 10000)]
6623+
[Int]
6624+
$ServerTimeLimit,
6625+
6626+
[Switch]
6627+
$Tombstone,
6628+
6629+
[Management.Automation.PSCredential]
6630+
[Management.Automation.CredentialAttribute()]
6631+
$Credential = [Management.Automation.PSCredential]::Empty,
6632+
6633+
[Parameter(Mandatory = $True)]
6634+
[ValidateSet('AccessSystemSecurity', 'CreateChild','Delete','DeleteChild','DeleteTree','ExtendedRight','GenericAll','GenericExecute','GenericRead','GenericWrite','ListChildren','ListObject','ReadControl','ReadProperty','Self','Synchronize','WriteDacl','WriteOwner','WriteProperty')]
6635+
$Right,
6636+
6637+
[Parameter(Mandatory = $True, ParameterSetName=’AccessRuleType’)]
6638+
[ValidateSet('Allow', 'Deny')]
6639+
[String[]]
6640+
$AccessControlType,
6641+
6642+
[Parameter(Mandatory = $True, ParameterSetName=’AuditRuleType’)]
6643+
[ValidateSet('Success', 'Failure')]
6644+
[String]
6645+
$AuditFlag,
6646+
6647+
[Parameter(Mandatory = $False, ParameterSetName=’AccessRuleType’)]
6648+
[Parameter(Mandatory = $False, ParameterSetName=’AuditRuleType’)]
6649+
[Parameter(Mandatory = $False, ParameterSetName=’ObjectGuidLookup’)]
6650+
[Guid]
6651+
$ObjectType,
6652+
6653+
[ValidateSet('All', 'Children','Descendents','None','SelfAndChildren')]
6654+
[String]
6655+
$InheritanceType,
6656+
6657+
[Guid]
6658+
$InheritedObjectType
6659+
)
6660+
6661+
Begin {
6662+
$PrincipalSearcherArguments = @{
6663+
'Identity' = $PrincipalIdentity
6664+
'Properties' = 'distinguishedname,objectsid'
6665+
}
6666+
if ($PSBoundParameters['PrincipalDomain']) { $PrincipalSearcherArguments['Domain'] = $PrincipalDomain }
6667+
if ($PSBoundParameters['Server']) { $PrincipalSearcherArguments['Server'] = $Server }
6668+
if ($PSBoundParameters['SearchScope']) { $PrincipalSearcherArguments['SearchScope'] = $SearchScope }
6669+
if ($PSBoundParameters['ResultPageSize']) { $PrincipalSearcherArguments['ResultPageSize'] = $ResultPageSize }
6670+
if ($PSBoundParameters['ServerTimeLimit']) { $PrincipalSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit }
6671+
if ($PSBoundParameters['Tombstone']) { $PrincipalSearcherArguments['Tombstone'] = $Tombstone }
6672+
if ($PSBoundParameters['Credential']) { $PrincipalSearcherArguments['Credential'] = $Credential }
6673+
$Principal = Get-DomainObject @PrincipalSearcherArguments
6674+
if (-not $Principal) {
6675+
throw "Unable to resolve principal: $PrincipalIdentity"
6676+
} elseif($Principal.Count -gt 1) {
6677+
throw "PrincipalIdentity matches multiple AD objects, but only one is allowed"
6678+
}
6679+
6680+
$ADRight = 0
6681+
foreach($r in $Right) {
6682+
$ADRight = $ADRight -bor (([System.DirectoryServices.ActiveDirectoryRights]$r).value__)
6683+
}
6684+
$ADRight = [System.DirectoryServices.ActiveDirectoryRights]$ADRight
6685+
6686+
$Identity = [System.Security.Principal.IdentityReference] ([System.Security.Principal.SecurityIdentifier]$Principal.objectsid)
6687+
}
6688+
6689+
Process {
6690+
if($PSCmdlet.ParameterSetName -eq 'AuditRuleType') {
6691+
6692+
if($ObjectType -eq $null -and $InheritanceType -eq [String]::Empty -and $InheritedObjectType -eq $null) {
6693+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag
6694+
} elseif($ObjectType -eq $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -eq $null) {
6695+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag, ([System.DirectoryServices.ActiveDirectorySecurityInheritance]$InheritanceType)
6696+
} elseif($ObjectType -eq $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -ne $null) {
6697+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag, ([System.DirectoryServices.ActiveDirectorySecurityInheritance]$InheritanceType), $InheritedObjectType
6698+
} elseif($ObjectType -ne $null -and $InheritanceType -eq [String]::Empty -and $InheritedObjectType -eq $null) {
6699+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag, $ObjectType
6700+
} elseif($ObjectType -ne $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -eq $null) {
6701+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag, $ObjectType, $InheritanceType
6702+
} elseif($ObjectType -ne $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -ne $null) {
6703+
New-Object System.DirectoryServices.ActiveDirectoryAuditRule -ArgumentList $Identity, $ADRight, $AuditFlag, $ObjectType, $InheritanceType, $InheritedObjectType
6704+
}
6705+
6706+
} else {
6707+
6708+
if($ObjectType -eq $null -and $InheritanceType -eq [String]::Empty -and $InheritedObjectType -eq $null) {
6709+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType
6710+
} elseif($ObjectType -eq $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -eq $null) {
6711+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType, ([System.DirectoryServices.ActiveDirectorySecurityInheritance]$InheritanceType)
6712+
} elseif($ObjectType -eq $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -ne $null) {
6713+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType, ([System.DirectoryServices.ActiveDirectorySecurityInheritance]$InheritanceType), $InheritedObjectType
6714+
} elseif($ObjectType -ne $null -and $InheritanceType -eq [String]::Empty -and $InheritedObjectType -eq $null) {
6715+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType, $ObjectType
6716+
} elseif($ObjectType -ne $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -eq $null) {
6717+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType, $ObjectType, $InheritanceType
6718+
} elseif($ObjectType -ne $null -and $InheritanceType -ne [String]::Empty -and $InheritedObjectType -ne $null) {
6719+
New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $Identity, $ADRight, $AccessControlType, $ObjectType, $InheritanceType, $InheritedObjectType
6720+
}
6721+
6722+
}
6723+
}
6724+
}
6725+
6726+
64036727
function Set-DomainObjectOwner {
64046728
<#
64056729
.SYNOPSIS
@@ -6910,15 +7234,6 @@ for the domain principal to add for the ACL. Required. Wildcards accepted.
69107234

69117235
Specifies the domain for the TargetIdentity to use for the principal, defaults to the current domain.
69127236

6913-
.PARAMETER PrincipalLDAPFilter
6914-
6915-
Specifies an LDAP query string that is used to filter for the Active Directory object principal.
6916-
6917-
.PARAMETER PrincipalSearchBase
6918-
6919-
The LDAP source to search through for principals, e.g. "LDAP://OU=secret,DC=testlab,DC=local"
6920-
Useful for OU queries.
6921-
69227237
.PARAMETER Server
69237238

69247239
Specifies an Active Directory server (domain controller) to bind to.

0 commit comments

Comments
 (0)