// Core injection method that actually does all the work. public override IntPtr Inject(string dllPath, IntPtr hProcess) { ClearErrors(); if (hProcess.IsNull() || hProcess.Compare(-1)) { throw new ArgumentOutOfRangeException("hProcess", "Invalid process handle specified."); } try { IntPtr hModule = IntPtr.Zero; // Find the LoadLibraryW function address in the remote process IntPtr fnLoadLibraryW = WinAPI.GetProcAddress(WinAPI.GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); if (fnLoadLibraryW.IsNull()) { throw new Exception("Unable to locate the LoadLibraryW entry point"); } // Create a wchar_t * in the remote process which points to the unicode version of the dll path. IntPtr pLib = WinAPI.CreateRemotePointer(hProcess, Encoding.Unicode.GetBytes(dllPath + "\0"), 0x04); if (pLib.IsNull()) { throw new InvalidOperationException("Failed to allocate memory in the remote process"); } try { // Call LoadLibraryW in the remote process by using CreateRemoteThread. uint hMod = WinAPI.RunThread(hProcess, fnLoadLibraryW, (uint)pLib.ToInt32(), 10000); if (hMod == uint.MaxValue) { throw new Exception("Error occurred when calling function in the remote process"); } else if (hMod == 0) { throw new Exception("Failed to load module into remote process. Error code: " + WinAPI.GetLastErrorEx(hProcess).ToString()); } else { hModule = Win32Ptr.Create(hMod); } } finally { // Cleanup in all cases. WinAPI.VirtualFreeEx(hProcess, pLib, 0, 0x8000); } return(hModule); } catch (Exception e) { SetLastError(e); return(IntPtr.Zero); } }
public override IntPtr Inject(string dllPath, IntPtr hProcess) { this.ClearErrors(); if (hProcess.IsNull() || hProcess.Compare(-1L)) { throw new ArgumentOutOfRangeException("hProcess", "Invalid process handle specified."); } IntPtr result; try { IntPtr intPtr = IntPtr.Zero; IntPtr procAddress = WinAPI.GetProcAddress(WinAPI.GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); if (procAddress.IsNull()) { throw new Exception("Unable to locate the LoadLibraryW entry point"); } IntPtr intPtr2 = WinAPI.CreateRemotePointer(hProcess, Encoding.Unicode.GetBytes(dllPath + "\0"), 4); if (intPtr2.IsNull()) { throw new InvalidOperationException("Failed to allocate memory in the remote process"); } try { uint num = WinAPI.RunThread(hProcess, procAddress, (uint)intPtr2.ToInt32(), 10000); if (num == 4294967295u) { throw new Exception("Error occurred when calling function in the remote process"); } if (num == 0u) { throw new Exception("Failed to load module into remote process. Error code: " + WinAPI.GetLastErrorEx(hProcess).ToString()); } intPtr = Win32Ptr.Create((long)((ulong)num)); } finally { WinAPI.VirtualFreeEx(hProcess, intPtr2, 0, 32768); } result = intPtr; } catch (Exception lastError) { this.SetLastError(lastError); result = IntPtr.Zero; } return(result); }
public override IntPtr Inject(string dllPath, IntPtr hProcess) { this.ClearErrors(); if (hProcess.IsNull() || hProcess.Compare(-1L)) { throw new ArgumentOutOfRangeException("hProcess", "Invalid process handle specified."); } try { IntPtr zero = IntPtr.Zero; IntPtr procAddress = WinAPI.GetProcAddress(WinAPI.GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); if (procAddress.IsNull()) { throw new Exception("Unable to locate the LoadLibraryW entry point"); } IntPtr ptr = WinAPI.CreateRemotePointer(hProcess, Encoding.Unicode.GetBytes(dllPath + "\0"), 4); if (ptr.IsNull()) { throw new InvalidOperationException("Failed to allocate memory in the remote process"); } try { uint num = WinAPI.RunThread(hProcess, procAddress, (uint)ptr.ToInt32(), 0x2710); switch (num) { case uint.MaxValue: throw new Exception("Error occurred when calling function in the remote process"); case 0: throw new Exception("Failed to load module into remote process. Error code: " + WinAPI.GetLastErrorEx(hProcess).ToString()); } zero = Win32Ptr.Create((long)num); } finally { WinAPI.VirtualFreeEx(hProcess, ptr, 0, 0x8000); } return(zero); } catch (Exception exception) { this.SetLastError(exception); return(IntPtr.Zero); } }
public override IntPtr[] InjectAll(string[] dllPaths, IntPtr hProcess) { Exception exception; this.ClearErrors(); try { if (hProcess.IsNull() || hProcess.Compare(-1L)) { throw new ArgumentException("Invalid process handle.", "hProcess"); } int processId = WinAPI.GetProcessId(hProcess); if (processId == 0) { throw new ArgumentException("Provided handle doesn't have sufficient permissions to inject", "hProcess"); } Process processById = Process.GetProcessById(processId); if (processById.Threads.Count == 0) { throw new Exception("Target process has no targetable threads to hijack."); } ProcessThread thread = SelectOptimalThread(processById); IntPtr ptr = WinAPI.OpenThread(0x1a, false, thread.Id); if (ptr.IsNull() || ptr.Compare(-1L)) { throw new Exception("Unable to obtain a handle for the remote thread."); } IntPtr zero = IntPtr.Zero; IntPtr lpAddress = IntPtr.Zero; IntPtr ptr4 = this.CreateMultiLoadStub(dllPaths, hProcess, out zero, 1); IntPtr[] ptrArray = null; if (!ptr4.IsNull()) { if (WinAPI.SuspendThread(ptr) == uint.MaxValue) { throw new Exception("Unable to suspend the remote thread"); } try { uint lpNumberOfBytesRead = 0; WinAPI.CONTEXT pContext = new WinAPI.CONTEXT { ContextFlags = 0x10001 }; if (!WinAPI.GetThreadContext(ptr, ref pContext)) { throw new InvalidOperationException("Cannot get the remote thread's context"); } byte[] array = REDIRECT_STUB; IntPtr ptr5 = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)array.Length, 0x3000, 0x40); if (ptr5.IsNull()) { throw new InvalidOperationException("Unable to allocate memory in the remote process."); } BitConverter.GetBytes(ptr4.Subtract(ptr5.Add(((long)7L))).ToInt32()).CopyTo(array, 3); BitConverter.GetBytes((uint)(pContext.Eip - ((uint)ptr5.Add(((long)array.Length)).ToInt32()))).CopyTo(array, (int)(array.Length - 4)); if (!(WinAPI.WriteProcessMemory(hProcess, ptr5, array, array.Length, out lpNumberOfBytesRead) && (lpNumberOfBytesRead == array.Length))) { throw new InvalidOperationException("Unable to write stub to the remote process."); } pContext.Eip = (uint)ptr5.ToInt32(); WinAPI.SetThreadContext(ptr, ref pContext); } catch (Exception exception1) { exception = exception1; this.SetLastError(exception); ptrArray = null; WinAPI.VirtualFreeEx(hProcess, zero, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, ptr4, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, lpAddress, 0, 0x8000); } WinAPI.ResumeThread(ptr); if (this.GetLastError() == null) { Thread.Sleep(100); ptrArray = new IntPtr[dllPaths.Length]; byte[] buffer2 = WinAPI.ReadRemoteMemory(hProcess, zero, ((uint)dllPaths.Length) << 2); if (buffer2 != null) { for (int i = 0; i < ptrArray.Length; i++) { ptrArray[i] = Win32Ptr.Create((long)BitConverter.ToInt32(buffer2, i << 2)); } } } WinAPI.CloseHandle(ptr); } return(ptrArray); } catch (Exception exception2) { exception = exception2; this.SetLastError(exception); return(null); } }
public override IntPtr[] InjectAll(string[] dllPaths, IntPtr hProcess) { this.ClearErrors(); IntPtr[] result; try { if (hProcess.IsNull() || hProcess.Compare(-1L)) { throw new ArgumentException("Invalid process handle.", "hProcess"); } int processId = WinAPI.GetProcessId(hProcess); if (processId == 0) { throw new ArgumentException("Provided handle doesn't have sufficient permissions to inject", "hProcess"); } Process processById = Process.GetProcessById(processId); if (processById.Threads.Count == 0) { throw new Exception("Target process has no targetable threads to hijack."); } ProcessThread processThread = ThreadHijack.SelectOptimalThread(processById); IntPtr intPtr = WinAPI.OpenThread(26u, false, processThread.Id); if (intPtr.IsNull() || intPtr.Compare(-1L)) { throw new Exception("Unable to obtain a handle for the remote thread."); } IntPtr zero = IntPtr.Zero; IntPtr zero2 = IntPtr.Zero; IntPtr intPtr2 = this.CreateMultiLoadStub(dllPaths, hProcess, out zero, 1u); IntPtr[] array = null; if (!intPtr2.IsNull()) { if (WinAPI.SuspendThread(intPtr) == 4294967295u) { throw new Exception("Unable to suspend the remote thread"); } try { uint num = 0u; WinAPI.CONTEXT cONTEXT = default(WinAPI.CONTEXT); cONTEXT.ContextFlags = 65537u; if (!WinAPI.GetThreadContext(intPtr, ref cONTEXT)) { throw new InvalidOperationException("Cannot get the remote thread's context"); } byte[] rEDIRECT_STUB = ThreadHijack.REDIRECT_STUB; IntPtr intPtr3 = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)rEDIRECT_STUB.Length, 12288, 64); if (intPtr3.IsNull()) { throw new InvalidOperationException("Unable to allocate memory in the remote process."); } BitConverter.GetBytes(intPtr2.Subtract(intPtr3.Add(7L)).ToInt32()).CopyTo(rEDIRECT_STUB, 3); BitConverter.GetBytes((uint)((ulong)cONTEXT.Eip - (ulong)((long)intPtr3.Add((long)rEDIRECT_STUB.Length).ToInt32()))).CopyTo(rEDIRECT_STUB, rEDIRECT_STUB.Length - 4); if (!WinAPI.WriteProcessMemory(hProcess, intPtr3, rEDIRECT_STUB, rEDIRECT_STUB.Length, out num) || num != (uint)rEDIRECT_STUB.Length) { throw new InvalidOperationException("Unable to write stub to the remote process."); } cONTEXT.Eip = (uint)intPtr3.ToInt32(); WinAPI.SetThreadContext(intPtr, ref cONTEXT); } catch (Exception lastError) { this.SetLastError(lastError); array = null; WinAPI.VirtualFreeEx(hProcess, zero, 0, 32768); WinAPI.VirtualFreeEx(hProcess, intPtr2, 0, 32768); WinAPI.VirtualFreeEx(hProcess, zero2, 0, 32768); } WinAPI.ResumeThread(intPtr); if (this.GetLastError() == null) { Thread.Sleep(100); array = new IntPtr[dllPaths.Length]; byte[] array2 = WinAPI.ReadRemoteMemory(hProcess, zero, (uint)((uint)dllPaths.Length << 2)); if (array2 != null) { for (int i = 0; i < array.Length; i++) { array[i] = Win32Ptr.Create((long)BitConverter.ToInt32(array2, i << 2)); } } } WinAPI.CloseHandle(intPtr); } result = array; } catch (Exception lastError2) { this.SetLastError(lastError2); result = null; } return(result); }
public override IntPtr[] InjectAll(string[] dllPaths, IntPtr hProcess) { ClearErrors(); try { if (hProcess.IsNull() || hProcess.Compare(-1)) { throw new ArgumentException("Invalid process handle.", "hProcess"); } int processId = WinAPI.GetProcessId(hProcess); if (processId == 0) { throw new ArgumentException("Provided handle doesn't have sufficient permissions to inject", "hProcess"); } Process target = Process.GetProcessById(processId); if (target.Threads.Count == 0) { throw new Exception("Target process has no targetable threads to hijack."); } //open a handle to the remote thread to allow for thread operations. ProcessThread thread = SelectOptimalThread(target); IntPtr hThread = WinAPI.OpenThread(0x001A, false, thread.Id); if (hThread.IsNull() || hThread.Compare(-1)) { throw new Exception("Unable to obtain a handle for the remote thread."); } IntPtr pModules = IntPtr.Zero; IntPtr pRedirect = IntPtr.Zero; // use the generic multiload stub to load the paths. // call this stub from the REDIRECT_STUB. IntPtr pStub = CreateMultiLoadStub(dllPaths, hProcess, out pModules, 1); IntPtr[] modules = null; if (!pStub.IsNull()) { if (WinAPI.SuspendThread(hThread) == uint.MaxValue) { throw new Exception("Unable to suspend the remote thread"); } //enter a new try/catch block to ensure the suspended thread is resumed, no matter if we fail somewhere else. try { uint nbytes = 0; WinAPI.CONTEXT ctx = default(WinAPI.CONTEXT); ctx.ContextFlags = 0x10001U; // CONTEXT_CONTROL flag. So that we get back the EIP value of the suspended thread. if (!WinAPI.GetThreadContext(hThread, ref ctx)) { throw new InvalidOperationException("Cannot get the remote thread's context"); } byte[] stub = REDIRECT_STUB; IntPtr pAlloc = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)stub.Length, 0x1000 | 0x2000, 0x40); if (pAlloc.IsNull()) { throw new InvalidOperationException("Unable to allocate memory in the remote process."); } //patch the EIP value and the Stub address for the redirection stub before commiting it to the remote process. BitConverter.GetBytes(pStub.Subtract(pAlloc.Add(7)).ToInt32()).CopyTo(stub, 3); BitConverter.GetBytes((uint)(ctx.Eip - pAlloc.Add(stub.Length).ToInt32())).CopyTo(stub, stub.Length - 4); if (!WinAPI.WriteProcessMemory(hProcess, pAlloc, stub, stub.Length, out nbytes) || nbytes != (uint)stub.Length) { throw new InvalidOperationException("Unable to write stub to the remote process."); } ctx.Eip = (uint)pAlloc.ToInt32(); // Set the entry point for the thread to the redirection stub and resume the thread. WinAPI.SetThreadContext(hThread, ref ctx); } catch (Exception e) { SetLastError(e); modules = null; WinAPI.VirtualFreeEx(hProcess, pModules, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pStub, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pRedirect, 0, 0x8000); } WinAPI.ResumeThread(hThread); if (GetLastError() == null) { System.Threading.Thread.Sleep(100); modules = new IntPtr[dllPaths.Length]; byte[] rawHandles = WinAPI.ReadRemoteMemory(hProcess, pModules, (uint)dllPaths.Length << 2); if (rawHandles != null) { for (int i = 0; i < modules.Length; i++) { modules[i] = Win32Ptr.Create(BitConverter.ToInt32(rawHandles, i << 2)); } } } // deliberately didn't clean up the remote memory here. Unfortunately there's no solid way // to ensure the function stub has been scheduled by the operating system. It may not even happen for // ages, or something else may block the thread. When the stub eventually is executes and returns, the reset // of the stub needs to still be there in order for the function to successfully return, otherwise the process just crashes // and we lose the distinct possibility that the injection was successful. WinAPI.CloseHandle(hThread); } return(modules); } catch (Exception e) { SetLastError(e); return(null); } }