# Lab 3 - Dumping hashes and performing Pass the Hash

**Bonus: Run tasklist in Empire and hunt for it, what do you see? Run it again and this time tick the "literal" button, what do you see? why is there a difference?**&#x20;

The answer is in how Empire is executing shell commands..  take a look at <https://github.com/BC-SECURITY/Empire/blob/main/empire/server/data/agent/agent.ps1#L349> and be amazed :)&#x20;

1. Interact with your empire agent and use the built-in mimikatz task to dump password hashes by using the powershell\_credentials\_mimikatz\_logonpasswords module. \\

   <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FWEkhGiKJ0BWhulqDIKVR%2Fimage.png?alt=media&#x26;token=a7c57e7d-9477-46d0-bf67-5c8dc1fa4ada" alt=""><figcaption></figcaption></figure>

Since this is PowerShell, you'd expect that we would be able to find mimikatz execution by taking a look at the scriptblock logging (event id 4104) and looking for mimikatz, but that doesn't yield a result... can you figure out why that is? \
\
Empire obfuscates mimikatz by default, check your obfuscation tab in Empire, likely the obfuscation will be different for you&#x20;

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2F63R27C2ctYmzVtRU9zNd%2Fimage.png?alt=media&#x26;token=22dba436-7e2d-4317-8f45-94ec44c003af" alt=""><figcaption></figcaption></figure>

2. Check it out with KQL in your Kibana interface : \
   winlog.event\_data.ScriptBlockText : (Mimi\*)\
   \
   Should yield 0 results. \
   \
   KQL that bypasses the obfuscation: \
   winlog.event\_data.ScriptBlockText : (\*logonpassword\*)\
   \\

   <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FORhgxy7Uj8zXnktDaxRZ%2Fimage.png?alt=media&#x26;token=bdc74ad9-4417-4b9e-95dc-7e29a6723ecc" alt=""><figcaption></figcaption></figure>

3. Alternatively, we can also look for event.code: 10 and winlog.event\_data.TargetImage: *lsass*  \
   Since mimikatz needs to touch LSASS prior to dumping it, it's a dead giveaway, especially when PowerShell is touching LSASS. You will not be fooling anyone in a red team operation with this, even though you did not drop mimikatz to disk :)

4. Inside the mimikatz dump you should find some new credentials... \
   \
   &#x20;

   <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FvbAAj38GARhKD7yutbJt%2Fimage.png?alt=media&#x26;token=2f1b6947-68b9-45b4-a01a-0ef867b6d063" alt=""><figcaption></figcaption></figure>

5. Let's perform pass the hash in Empire, go back to the interact screen, select powershell\_credentials\_pth. \
   Select the credential you want to use (adm\_asnyder) \
   Press Submit \
   \\

   <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FKZEPKgcmWsp4ste9ZCjd%2Fimage.png?alt=media&#x26;token=8d75f995-cf90-47bd-a20d-389275c35d7d" alt=""><figcaption></figcaption></figure>

6. Since mimikatz pth spawns a new process, we can hunt for it using the parent process that we already identified when we hunted for our stager. If you forgot the PID already, don't worry, you can find it in your agent overview. \
   My agent is PID 5344, so my KQL query would look like: \
   \
   event.code: 1 and winlog.event\_data.ParentProcessId: 5344\
   \\

   <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FRPrCEgtUAD4zqrwZ0ha6%2Fimage.png?alt=media&#x26;token=d06d2ad6-43cc-419d-b739-cccd1603c080" alt=""><figcaption></figcaption></figure>

\
Indeed, we see cmd.exe spawned from our process with PID 840 (yours will be different), which corresponds to my empire output. \
\
\\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FjYkQD5bQBFHRXljlwEwM%2Fimage.png?alt=media&#x26;token=2b124971-d0a9-4abb-81bd-ff9e068649e8" alt=""><figcaption></figcaption></figure>

Since our lab has script block logging enabled, we can also find the pth execution by litteraly just looking for it in our scriptblock logs... \\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FJlsMPbS2avo5QDF8Uxym%2Fimage.png?alt=media&#x26;token=a6179358-0a8e-471c-9dbf-f61d7a76a76d" alt=""><figcaption></figcaption></figure>

What is interesting about pass the hash is that a new logon session is created with logontype 9 (the same logon type when using runas /netonly which usually is interesting to investigate. \
\
KQL: winlog.event\_id:4624 and host.hostname : ws01 and winlog.event\_data.LogonType: 9\
\
\\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FMpzJGiPAyDlkddvy0iCj%2Fimage.png?alt=media&#x26;token=a8c7cda4-8d83-4f8a-975a-f98217937f69" alt=""><figcaption></figcaption></figure>

Indeed, we see a new logon impersonating for adm\_asnyder. \\

7. We now have two options, either we steal the token of the process we just spawned, or we steal the token of a process that was actually already running as adm\_asnyder \
   (yes, we did pth for nothing!, we could have just lived off the land!) \
   \
   The technique is the same in both cases, either you look at tasklist to find the PID of a process belonging to adm\_asnyder, or you take a look at the mimikatz output and note the PID of the output there. \
   \
   We will be using powershell\_credentials\_tokens to achieve this task.\
   Set the ImpersonateUser switch to true and specify the processID of the process you wish to steal\\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2Fepi3ebhcEK7wG8r9RzTJ%2Fimage.png?alt=media&#x26;token=6d5e5735-be0c-4eb6-b573-0b46a2723c7d" alt=""><figcaption></figcaption></figure>

The underlying script that is used by Empire to achieve this is:\
\
&#x20;<https://github.com/BC-SECURITY/Empire/blob/main/empire/server/data/module_source/credentials/Invoke-TokenManipulation.ps1#L1397> \\

The core of the token stealing and impersonation logic happens when you run a command like steal\_token -ProcessId \<PID> or invoke\_tokenmanipulation -ImpersonateUser -ProcessId \<PID>. This triggers the following key functions in the script:

**Enum-AllTokens**: This is the reconnaissance phase. It iterates through all processes on the system.

**Get-PrimaryToken**: Inside Enum-AllTokens, this function is called for each process. It uses the Windows API call **OpenProcess** to get a handle to the target process, and then **OpenProcessToken** to get a handle to that process's primary access token.

**Main function logic**: After enumerating all available tokens, the main logic block selects the specific token you requested (e.g., by -ProcessId).

**Invoke-ImpersonateUser**: This is the action phase for impersonation.

* **DuplicateTokenEx**: It first calls this API to create a new, usable copy of the stolen token handle. It specifically requests an **impersonation token**.
* **ImpersonateLoggedOnUser**: This is the final step. It applies the duplicated token to the **current thread** of the PowerShell agent. After this call, that specific thread is now running with the rights and identity of the user whose token was stolen.\
  \
  \
  From a detection point of view, the core telemetry here would be sysmon event ID 10 (process access) and cross refferencing with process ownership. However, sysmon event id 10 is a very noisy event log, which causes a lot of telemetry to be generated. Most of the time in an enterprise environment this will severely be tuned to only monitor relevant processes (i.e LSASS) or be disabled. As a result, we won't be hunting for this step in the killchain. \\

8. using the Shell Command we can now do \
   Invoke-Command -ScriptBlock {\<YOUR EMPIRE STAGER HERE>} -ComputerName sandbox-dc01.sandbox.pwnzone.lab\
   \\

   When you run Invoke-Command -ComputerName \<target>, the following happens:

   1. **Authentication:** Your source machine  authenticates to the target machine over the network.&#x20;
   2. **Connection:** It connects to the **WinRM** service on the target, which listens on TCP ports 5985 (HTTP) or 5986 (HTTPS).
   3. **Session Creation:** The WinRM service on the target creates a new PowerShell session for you.
   4. **Process Spawning:** To host this new session, the WinRM service spawns a new process on the target machine. This is typically a **wsmprovhost.exe** (Windows Services Management Provider Host) process.
   5. **Execution:** The ScriptBlock you provided (your Empire stager) is then executed within the context of this wsmprovhost.exe process.\
      \
      \
      <https://help.fortinet.com/fsiem/Public_Resource_Access/7_3_0/rules/PH_RULE_Remote_PowerShell_Sessions.htm> provides a sample detection rule \
      \
      our KQL would look like the following \
      \
      host.name : "ws01.sandbox.pwnzone.lab" and winlog.channel : "Microsoft-Windows-Sysmon/Operational" and winlog.event\_id : 3 and winlog.event\_data.DestinationPort: 5985\
      \
      To no one's surprise, this yields results! \
      \\

      <figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FLfjdyEfjm1CXJXskwzlz%2Fimage.png?alt=media&#x26;token=cf422fe3-faee-403c-a6c5-c41d759d9128" alt=""><figcaption></figcaption></figure>

\
we can track the movement on the DC using the following KQL \
\
host.name : "sandbox-dc01.sandbox.pwnzone.lab" and winlog.channel : "Security" and winlog.event\_id : 4624 and winlog.event\_data.LogonType : 3 and winlog.event\_data.IpPort: 5999\*\
\
Do note that the SourcePort does not always equal the sourceport on the other side of the tunnel, authentication is a complex process, beyond the scope of this workshop. \
\
\\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FFiHbXdPrHnlR5DcooPgV%2Fimage.png?alt=media&#x26;token=c4c862a5-cd98-4430-9b08-38f1988fb51b" alt=""><figcaption></figcaption></figure>

Finally, we can also take a look at what was actually executed. Tracking PSRemoting is actually reasonably straight forward as the parent process is predictable \
\
host.name : "sandbox-dc01.sandbox.pwnzone.lab" and winlog.channel : "Microsoft-Windows-Sysmon/Operational" and winlog.event\_id : 1 and winlog.event\_data.ParentImage: wsmprovhost.exe\\

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2Fl70IjxQx5mSPg3fog6El%2Fimage.png?alt=media&#x26;token=ad3feafd-e93e-4d70-becb-798622b6993d" alt=""><figcaption></figcaption></figure>

9. We can do exactly the same attack using&#x20;

&#x20;      powershell\_lateral\_movement\_invoke\_psexec\
&#x20;      If you lost your implant from ws01, spawn a new one and perform token impersonation once again.&#x20;

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FN6NAThUbiDQ2rDIJsKp5%2Fimage.png?alt=media&#x26;token=d0aee7cc-a075-466a-bc1e-ccde131e929a" alt=""><figcaption></figcaption></figure>

\
Detection  here is a new service creation\
\
KQL:  \
host.name : "sandbox-dc01.sandbox.pwnzone.lab" and\
winlog.channel : "System" and winlog.event\_id : 7045\
\
You should see a hit, be warned... it aint pretty :)&#x20;

<figure><img src="https://3304936114-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv6nbRHSDGVgaXIiiGM3g%2Fuploads%2FPjyXqjDqdcGcV9D5kE7k%2Fimage.png?alt=media&#x26;token=5b334f37-61ed-4776-9834-fd9f1717d1f7" alt=""><figcaption></figcaption></figure>
