DLL Injection

This section will document the standard DLL Injection notes

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]

[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]

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]

[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]

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

GetProcAddress

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

[syntax]

[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]

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]

[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]

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

References

Last updated