/// <summary> /// Injects the dll with the path specified into the process with the id specified. /// </summary> /// <param name="processId">the PID of the process to inject the dll into.</param> /// <param name="dllPathNameToInject">The full path + filename of the dll to inject</param> /// <returns>true if succeeded, false otherwise. If false is returned, <see cref="LastError"/> is set with the error code.</returns> public bool PerformInjection(int processId, string dllPathNameToInject) { this.LastError = 0; uint dllLengthToPassInBytes = (uint)((dllPathNameToInject.Length + 1) * Marshal.SizeOf(typeof(char))); this.LastActionPerformed = "Opening the host process"; LogHandlerSingleton.Instance().LogLine("Opening the host process", "DllInjector", true); IntPtr processHandle = Win32Wrapper.OpenProcess(ProcessAccessFlags.CreateThread | ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryOperation | ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.VirtualMemoryRead, false, (uint)processId); if (processHandle == IntPtr.Zero) { // failed, so set the error code and return this.LastError = Marshal.GetLastWin32Error(); return(false); } this.LastActionPerformed = "Obtaining the address of LoadLibraryA"; LogHandlerSingleton.Instance().LogLine("Obtaining the address of LoadLibraryA", "DllInjector", true); IntPtr loadLibraryAddress = Win32Wrapper.GetProcAddress(Win32Wrapper.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (loadLibraryAddress == IntPtr.Zero) { this.LastError = Marshal.GetLastWin32Error(); return(false); } this.LastActionPerformed = "Allocating memory in the host process for the dll filename"; LogHandlerSingleton.Instance().LogLine("Allocating memory in the host process for the dll filename", "DllInjector", true); IntPtr memoryInTargetProcess = Win32Wrapper.VirtualAllocEx(processHandle, IntPtr.Zero, dllLengthToPassInBytes, AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ReadWrite); if (memoryInTargetProcess == IntPtr.Zero) { this.LastError = Marshal.GetLastWin32Error(); return(false); } Thread.Sleep(500); this.LastActionPerformed = "Writing dll filename into memory allocated in host process"; LogHandlerSingleton.Instance().LogLine("Writing dll filename into memory allocated in host process", "DllInjector", true); var bytesToWrite = Encoding.Default.GetBytes(dllPathNameToInject); bool result = Win32Wrapper.WriteProcessMemory(processHandle, memoryInTargetProcess, bytesToWrite, dllLengthToPassInBytes, out var bytesWritten); if (!result || (bytesWritten.ToInt32() != bytesToWrite.Length + 1)) { this.LastError = Marshal.GetLastWin32Error(); return(false); } this.LastActionPerformed = "Creating a thread in the host process to load the dll"; LogHandlerSingleton.Instance().LogLine("Creating a thread in the host process to load the dll", "DllInjector", true); IntPtr remoteThreadHandle = Win32Wrapper.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibraryAddress, memoryInTargetProcess, 0, IntPtr.Zero); if (remoteThreadHandle == IntPtr.Zero) { this.LastError = Marshal.GetLastWin32Error(); return(false); } // no clean up of the memory, we're not going to 'unload' the dll... result = Win32Wrapper.CloseHandle(processHandle); if (!result) { this.LastError = Marshal.GetLastWin32Error(); return(false); } this.LastActionPerformed = "Done"; LogHandlerSingleton.Instance().LogLine("Injection completed", "DllInjector", true); return(true); }