public static InjectResult Inject(Process process, string dllPath, TimeSpan timeout) { InjectResult result = InjectResult.None; //Get the full path of the DLL. string fullPath = Path.GetFullPath(dllPath); //Return if the DLL is not found. if (!File.Exists(fullPath)) { return(InjectResult.Dll_Not_Found); } //Process modules aren't automatically updated in a stored process variable. //Grab the updated process. Process updatedProcess = Process.GetProcessById(process.Id); //Sometimes randomly fails due to 64-bit OS accessing 32-bit process ProcessMemory... //Try again if fails. bool success = false; string pathCompare = fullPath.ToLower(); while (!success) { try { foreach (ProcessModule pm in updatedProcess.Modules) { if (pm.FileName.ToLower() == pathCompare) //Return if the DLL is found to //prevent injecting duplicates. { return(InjectResult.Dll_Already_Jnjected); } } success = true; } catch { } } //Open handle with all permissions to avoid any unexpected access violation errors... IntPtr hProcess = ProcessMemory.OpenProcess(ProcessAccessFlags.All, true, process.Id); //Return if the handle is 0. This is an invalid result. if (hProcess == IntPtr.Zero) { return(InjectResult.Process_Handle_Invalid); } //Get the handle for kernel32.dll. IntPtr hKernel = ProcessMemory.GetModuleHandle("kernel32.dll"); //Return if the handle is 0. This is an invalid result. if (hKernel == IntPtr.Zero) { return(InjectResult.Kernel_Module_Not_Found); } //Get the address for LoadLibraryA, which is used to load a process //module into a process and calls the DllMain entry point. IntPtr hLoadLibraryA = ProcessMemory.GetProcAddress(hKernel, "LoadLibraryA"); //Return if the address is 0. This is an invalid result. if (hLoadLibraryA == IntPtr.Zero) { return(InjectResult.Load_Library_A_Not_Found); } //Allocation space for the full path of the module and //+1 for the null terminator (0x00) of the string. int allocationSize = fullPath.Length + 1; //Allocate memory space in the process and store the address //the allocation was made at. IntPtr allocatedAddr = ProcessMemory.VirtualAllocEx(hProcess, IntPtr.Zero, (IntPtr)allocationSize, AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite); //Return if the address is 0. Allocation was not made. if (allocatedAddr == IntPtr.Zero) { return(InjectResult.Memory_Allocation_Failed); } //Convert the full path string into bytes. byte[] buffer = Encoding.UTF8.GetBytes(fullPath); IntPtr numWritten; //Write the bytes to the space we allocated within the process. if (!ProcessMemory.WriteProcessMemory(hProcess, allocatedAddr, buffer, buffer.Length, out numWritten)) { //Writing to memory failed if WriteProcessMemory returned false. result = InjectResult.Memory_Write_Failed; //Free the memory we allocated into the process. //dwSize must be 0 to free all pages allocated by VirtualAllocEx. if (!ProcessMemory.VirtualFreeEx(hProcess, allocatedAddr, 0, FreeType.Release)) { //Freeing the allocated memory failed if VirtualFreeEx returned false. result |= InjectResult.Memory_Release_Failed; } //Return due to failing to write the bytes to ProcessMemory. return(result); } //Create a new remote thread, calling the LoadLibraryA function in our target //process with the address we allocated our string bytes at as the parameter. //This will load the DLL into the process using the full path to the DLL that //was specified and call the DLL's DllMain entry point. IntPtr threadId; IntPtr hThread = ProcessMemory.CreateRemoteThread(hProcess, IntPtr.Zero, 0, hLoadLibraryA, allocatedAddr, 0, out threadId); if (hThread == IntPtr.Zero) { //The remote thread failed to create if the thread handle is is 0. result = InjectResult.Thread_Creation_Failed; //Free the memory we allocated into the process. //dwSize must be 0 to free all pages allocated by VirtualAllocEx. if (!ProcessMemory.VirtualFreeEx(hProcess, allocatedAddr, 0, FreeType.Release)) { //Freeing the allocated memory failed if VirtualFreeEx returned false. result |= InjectResult.Memory_Release_Failed; } //Return due to failing to create the remote thread. return(result); } //Wait for the thread to finish, with specified timeout if it never finishes. ProcessMemory.WaitForSingleObject(hThread, (uint)timeout.TotalMilliseconds); //Free the memory we allocated into the process. //dwSize must be 0 to free all pages allocated by VirtualAllocEx. if (!ProcessMemory.VirtualFreeEx(hProcess, allocatedAddr, 0, FreeType.Release)) { //Freeing the allocated memory failed if VirtualFreeEx returned false. result |= InjectResult.Memory_Release_Failed; } //Close the handle created by CreateRemoteThread. if (!ProcessMemory.CloseHandle(hThread)) { result |= InjectResult.Thread_Close_Failed; } //Close the handle created by OpenProcess. if (!ProcessMemory.CloseHandle(hProcess)) { result |= InjectResult.Process_Handle_Close_Failed; } return(result |= InjectResult.Success); }