Context

Most people working in offensive security, or anyone who regularly spends time in Hack The Box or HackSmarter labs, are probably already familiar with ligolo-ng. It was a genuine game changer for pivoting and tunneling during internal assessments and quickly became a go-to tool for many operators.

Ligolo-MP builds directly on that foundation. While it isn’t entirely new (it’s based on ligolo-ng), it introduces a multiplayer-capable architecture and, more importantly in my opinion, a much cleaner and more intuitive user interface. I haven’t fully explored the multiplayer functionality yet, but purely from a usability perspective, ligolo-mp feels like a meaningful improvement and is extremely operator-friendly.

To demonstrate the tool in a realistic scenario, I’ll be using it while completing the Pivot Smarter lab from HackSmarter:

https://www.hacksmarter.org


Setup

Before diving into the lab, let’s walk through installing ligolo-mp locally.

Start by navigating to the GitHub repository maintained by ttpreport, cloning the project, and installing the binaries:

https://github.com/ttpreport/ligolo-mp

1
2
3
git clone https://github.com/ttpreport/ligolo-mp
cd ligolo-mp
sudo make install

Once installed, you can start the Ligolo-MP server with:

1
sudo ligolo-mp

Login screen

By default, Ligolo-MP starts a server on port 58008 and listens for agents on port 11601. In some lab environments, I’ve noticed that the default agent port isn’t always reachable. When that happens, it’s easy to override the listening configuration.

To change the port used by agents, use the -agent-addr flag:

1
sudo ligolo-mp -agent-addr 0.0.0.0:8443

If you want operators to connect on a different port, you can also specify that using -operator-addr:

1
sudo ligolo-mp -operator-addr 4444

With the default settings, simply press Enter at the prompt to connect as an operator. Once connected, you’ll notice the interface is broken into a few key sections:

  1. Sessions – Displays active agent connections and their status.
  2. Interfaces – Shows network interface and subnet information for each host.
  3. Routes – Lists routes to internal subnets you’ve configured.
  4. Redirectors – Displays any active port forwards.

Main interface


Usage / Walkthrough

Rather than explaining Ligolo-MP in the abstract, we’ll walk through a real demonstration using the Pivot Smarter lab.

For this walkthrough, I’ll start the server using a custom agent port:

1
sudo ligolo-mp -agent-addr 0.0.0.0:8443

First, let’s take a look at the environment and host connectivity:

Hosts


Objective

1
2
3
4
You're a penetration tester on the Hack Smarter Red Team. During the engagement, you have discovered credentials for a web server but your attack machine does not have direct access to the server.

Goal:
You have already compromised a Windows Server providing you access to the internal network. Connect to this machine with evil-winrm. Use this Windows Server as a proxy to access the web server from your attack machine, log in with the credentials, and retrieve the final flag.

Windows Server Credentials

1
2
Username: j.smith
Password: HackSmarter123

Web Server Credentials

1
2
Username: t.ramsbey
Password: HackSmarter123321123

In short, we’ll use our access to the Windows server as a pivot point to reach the internal web server.

First, let’s confirm access to the Windows server via WinRM:

1
nxc winrm 10.1.158.153 -u 'j.smith' -p 'HackSmarter123'
1
2
WINRM       10.1.158.153    5985   EC2AMAZ-IIE0STR  [*] Windows Server 2022 Build 20348
WINRM       10.1.158.153    5985   EC2AMAZ-IIE0STR  [+] EC2AMAZ-IIE0STR\j.smith:HackSmarter123 (admin)

For sanity, let’s verify that our attack machine cannot directly reach the web server:

1
curl http://10.1.9.208/

As expected, the request hangs.

Next, we connect to the Windows server using evil-winrm:

1
evil-winrm -i 10.1.158.153 -u 'j.smith' -p 'HackSmarter123'

From within the session:

1
curl http://10.1.9.208/
1
2
StatusCode        : 200
StatusDescription : OK

This confirms that the Windows server can reach the internal web server. Our goal now is to proxy that access back to our attack machine using Ligolo-MP.


Pivoting with Ligolo-MP

Agent Setup

From the Ligolo-MP UI, generate a new agent by pressing Ctrl+N. You’ll be prompted to fill in several fields (use Tab to move between them). For this walkthrough, the key fields are:

  • Save To – Where the agent binary will be saved.
  • Servers – The IP and port of your attack host (in this case, port 8443).
  • OS – Windows.
  • Arch – The architecture of the target host.

Example configuration:

Agent Setup

Press Enter to generate the agent.


Deployment

Deployment is straightforward. Since we’re already connected via evil-winrm, we can simply upload the binary:

1
upload proxy.exe
1
Info: Upload successful!

Run the agent:

1
.\proxy.exe

The agent will immediately connect back to the Ligolo-MP server, but it won’t be active yet. We still need to configure routes and start the proxy.


Route Configuration

In the Ligolo-MP UI, highlight the agent under Sessions and press Enter. Select Add Route.

Add Route

When prompted for a CIDR, you can typically start with the subnet listed under the Interfaces tab. Leave the priority at 0 and submit:

Route Setup

Once added, the route will appear in the UI:

Route Added

Now select Start Proxy. If everything is configured correctly, you should see green indicators showing an active connection:

Green Flags


Lateral Movement

Back on the attack machine, try accessing the web server again:

1
curl http://10.1.9.208/

It still fails and this is intentional. While we routed through the compromised host’s subnet, we didn’t explicitly route traffic to the web server itself.

To fix this, add another route using a /32 CIDR for the web server’s IP address:

Web Route

Test again:

1
curl http://10.1.9.208/

Success:

curl success

From here, a quick directory brute-force reveals a login page:

1
wfuzz -c --hc 404 -L -w `fzf-wordlists` -u "http://10.1.9.208/FUZZ"
1
2
index.html
login.html

Navigate to login.html, authenticate using the provided credentials, and retrieve the flag:

Login Screen Flag Retrieved

At this point, the pivot is complete and the objective is satisfied.