internal bool Inject(Process process, string dllPath) { _process = process; // Get the id of the process var processId = _process.Id; // Get the bytes of the dll var dllBytes = File.ReadAllBytes(dllPath); // Pin the dll bytes in the memory of the host process var baseAddress = GCHandle.Alloc(dllBytes, GCHandleType.Pinned); // Get the pe headers of the dll var peHeaders = new PeFile(dllPath); // Allocate memory for the dll in the remote process var dllSize = peHeaders.ImageNtHeaders.OptionalHeader.SizeOfImage; var remoteDllAddress = _memoryModule.AllocateMemory(processId, (int)dllSize); // Map the imports of the dll into the host process MapImports(peHeaders, baseAddress.AddrOfPinnedObject()); // Perform the relocations needed in the host process PerformRelocations(peHeaders, baseAddress.AddrOfPinnedObject(), remoteDllAddress); // Map the sections of the dll into the remote process MapSections(peHeaders, baseAddress.AddrOfPinnedObject(), remoteDllAddress); // Map the tls entries of the dll into the remote process MapTlsEntries(peHeaders, baseAddress.AddrOfPinnedObject()); // Call the entry point of the dll in the remote process var dllEntryPointAddress = remoteDllAddress + (int)peHeaders.ImageNtHeaders.OptionalHeader.AddressOfEntryPoint; CallEntryPoint(remoteDllAddress, dllEntryPointAddress); // Unpin the dll bytes from the memory of the host process baseAddress.Free(); return(true); }
public void TestAllocateMemory() { // Allocate memory in the host process const int testRegionSize = 32; var testRegionAddress = _memoryModule.AllocateMemory(_hostProcessName, testRegionSize); Assert.True(testRegionAddress != IntPtr.Zero); // Free the memory that was allocated _memoryModule.FreeMemory(_hostProcessName, testRegionAddress); }
public void TestPatternScan() { // Allocate memory in the host process const int testRegionSize = 32; var testRegionAddress = _memoryModule.AllocateMemory(_hostProcessName, testRegionSize); // Write a test array of bytes into memory var testArray = new byte[] { 0xFF, 0x01, 0x5A, 0xFF, 0x22, 0x00, 0x1A, 0xAA, 0xFF, 0xFF, 0xFF }; _memoryModule.WriteMemory(_hostProcessName, testRegionAddress, testArray); // Scan the host process for test array pattern const string testArrayPattern = "FF 01 ?? FF 22 00 ?? AA FF ?? FF"; var result = _memoryModule.PatternScan(_hostProcessName, IntPtr.Zero, testArrayPattern); Assert.Contains(testRegionAddress, result); // Free the memory that was allocated _memoryModule.FreeMemory(_hostProcessName, testRegionAddress); }
internal bool Inject(Process process, string dllPath) { // Ensure the process has kernel32.dll loaded if (Native.LoadLibrary("kernel32.dll") is null) { ExceptionHandler.ThrowWin32Exception("Failed to load kernel32.dll into the process"); } // Get the id of the process var processId = process.Id; // Get the address of the LoadLibraryW method from kernel32.dll var loadLibraryAddress = Native.GetProcAddress(Native.GetModuleHandle("kernel32.dll"), "LoadLibraryW"); if (loadLibraryAddress == IntPtr.Zero) { ExceptionHandler.ThrowWin32Exception("Failed to find the address of the LoadLibraryW method in kernel32.dll"); } // Allocate memory for the dll path in the process var dllPathSize = dllPath.Length; var dllPathAddress = IntPtr.Zero; try { dllPathAddress = _memoryModule.AllocateMemory(processId, dllPathSize); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory for the dll path in the process"); } // Write the dll path into the process var dllPathBytes = Encoding.Unicode.GetBytes(dllPath + "\0"); try { _memoryModule.WriteMemory(processId, dllPathAddress, dllPathBytes); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to write the dll path into the memory of the process"); } // Open a handle to the process var processHandle = process.SafeHandle; // Create a remote thread to call load library in the process Native.RtlCreateUserThread(processHandle, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, loadLibraryAddress, dllPathAddress, out var remoteThreadHandle, 0); if (remoteThreadHandle is null) { ExceptionHandler.ThrowWin32Exception("Failed to create a remote thread to call load library in the process"); } // Wait for the remote thread to finish its task Native.WaitForSingleObject(remoteThreadHandle, int.MaxValue); // Free the memory previously allocated for the dll path try { _memoryModule.FreeMemory(processId, dllPathAddress); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to free the memory allocated for the dll path in the process"); } // Close the handle opened to the process processHandle.Close(); // Close the handle opened to the remote thread remoteThreadHandle.Close(); return(true); }
internal bool Inject(Process process, string dllPath) { // Ensure the process has kernel32.dll loaded if (Native.LoadLibrary("kernel32.dll") is null) { ExceptionHandler.ThrowWin32Exception("Failed to load kernel32.dll into the process"); } // Get the id of the process var processId = process.Id; // Get the address of the LoadLibraryW method from kernel32.dll var loadLibraryAddress = Native.GetProcAddress(Native.GetModuleHandle("kernel32.dll"), "LoadLibraryW"); if (loadLibraryAddress == IntPtr.Zero) { ExceptionHandler.ThrowWin32Exception("Failed to find the address of the LoadLibraryW method in kernel32.dll"); } // Allocate memory for the dll path in the process var dllPathSize = dllPath.Length; var dllPathAddress = IntPtr.Zero; try { dllPathAddress = _memoryModule.AllocateMemory(processId, dllPathSize); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory for the dll path in the process"); } // Write the dll path into the process var dllPathBytes = Encoding.Unicode.GetBytes(dllPath + "\0"); try { _memoryModule.WriteMemory(processId, dllPathAddress, dllPathBytes); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to write the dll path into the memory of the process"); } foreach (var thread in process.Threads.Cast <ProcessThread>()) { // Open a handle to the thread var threadHandle = Native.OpenThread(Native.ThreadAccess.SetContext, false, thread.Id); if (threadHandle is null) { ExceptionHandler.ThrowWin32Exception("Failed to open a handle to a thread in the process"); } // Add a user-mode APC to the APC queue of the thread if (!Native.QueueUserAPC(loadLibraryAddress, threadHandle, dllPathAddress)) { ExceptionHandler.ThrowWin32Exception("Failed to queue a user-mode apc to the apc queue of a thread in the process"); } // Close the handle opened to the thread threadHandle?.Close(); } // Free the memory previously allocated for the dll path try { _memoryModule.FreeMemory(processId, dllPathAddress); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to free the memory allocated for the dll path in the process"); } return(true); }
internal bool Inject(Process process, string dllPath) { // Ensure the process has kernel32.dll loaded if (Native.LoadLibrary("kernel32.dll") is null) { ExceptionHandler.ThrowWin32Exception("Failed to load kernel32.dll into the process"); } // Get the id of the process var processId = process.Id; // Get the address of the LoadLibraryW method from kernel32.dll var loadLibraryAddress = Native.GetProcAddress(Native.GetModuleHandle("kernel32.dll"), "LoadLibraryW"); if (loadLibraryAddress == IntPtr.Zero) { ExceptionHandler.ThrowWin32Exception("Failed to find the address of the LoadLibraryW method in kernel32.dll"); } // Allocate memory for the dll path in the process var dllPathSize = dllPath.Length; var dllPathAddress = IntPtr.Zero; try { dllPathAddress = _memoryModule.AllocateMemory(processId, dllPathSize); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory for the dll path in the process"); } // Write the dll path into the process var dllPathBytes = Encoding.Unicode.GetBytes(dllPath + "\0"); try { _memoryModule.WriteMemory(processId, dllPathAddress, dllPathBytes); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to write the dll path into the memory of the process"); } // Open a handle to the process var processHandle = process.SafeHandle; // Determine if the process is running under WOW64 Native.IsWow64Process(processHandle, out var isWow64); // Allocate memory for the shellcode in the process var shellcodeSize = isWow64 ? 22 : 87; var shellcodeAddress = IntPtr.Zero; try { shellcodeAddress = _memoryModule.AllocateMemory(processId, shellcodeSize); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory for the shellcode in the process"); } // Get the id of the first thread in the process var threadId = process.Threads[0].Id; // Open a handle to the thread var threadHandle = Native.OpenThread(Native.ThreadAccess.AllAccess, false, threadId); if (threadHandle is null) { ExceptionHandler.ThrowWin32Exception("Failed to open a handle to the first thread in the process"); } // Suspend the thread if (Native.SuspendThread(threadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend the first thread in the process"); } // If the process is x86 if (isWow64) { var threadContext = new Native.Context { Flags = Native.ContextFlags.ContextControl }; // Store the thread context structure in a buffer var threadContextBuffer = Tools.StructureToPointer(threadContext); // Get the context of the thread and save it in the buffer if (!Native.GetThreadContext(threadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of the first thread in the process"); } // Read the new thread context structure from the buffer threadContext = Tools.PointerToStructure <Native.Context>(threadContextBuffer); // Save the instruction pointer var instructionPointer = threadContext.Eip; // Write the shellcode into the memory of the process var shellcodeBytes = Shellcode.CallLoadLibraryx86(instructionPointer, dllPathAddress, loadLibraryAddress); try { _memoryModule.WriteMemory(processId, shellcodeAddress, shellcodeBytes); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to write the shellcode into the memory of the process"); } // Change the instruction pointer to the shellcode address threadContext.Eip = shellcodeAddress; // Store the thread context structure in a buffer threadContextBuffer = Tools.StructureToPointer(threadContext); // Set the context of the thread with the new context if (!Native.SetThreadContext(threadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of the first thread in the process"); } } // If the process is x64 else { var threadContext = new Native.Context64 { Flags = Native.ContextFlags.ContextControl }; // Store the thread context structure in a buffer var threadContextBuffer = Tools.StructureToPointer(threadContext); // Get the context of the thread and save it in the buffer if (!Native.GetThreadContext(threadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of the first thread in the process"); } // Read the new thread context structure from the buffer threadContext = Tools.PointerToStructure <Native.Context64>(threadContextBuffer); // Save the instruction pointer var instructionPointer = threadContext.Rip; // Write the shellcode into the memory of the process var shellcodeBytes = Shellcode.CallLoadLibraryx64(instructionPointer, dllPathAddress, loadLibraryAddress); try { _memoryModule.WriteMemory(processId, shellcodeAddress, shellcodeBytes); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to write the shellcode into the memory of the process"); } // Change the instruction pointer to the shellcode address threadContext.Rip = shellcodeAddress; // Store the thread context structure in a buffer threadContextBuffer = Tools.StructureToPointer(threadContext); // Set the context of the thread with the new context if (!Native.SetThreadContext(threadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of the first thread in the process"); } } // Resume the suspended thread if (Native.ResumeThread(threadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to resume the first thread in the process"); } // Open a handle to the main window of the process var windowHandle = new SafeWindowHandle(process.MainWindowHandle); // Switch to the process to load the dll Native.SwitchToThisWindow(windowHandle, true); // Buffer the execution by 10 milliseconds to avoid freeing memory before it has been referenced Tools.AsyncWait(10); // Free the memory previously allocated for the dll path try { _memoryModule.FreeMemory(processId, dllPathAddress); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to free the memory allocated for the dll path in the process"); } // Free the memory previously allocated for the shellcode try { _memoryModule.FreeMemory(processId, shellcodeAddress); } catch (Win32Exception) { ExceptionHandler.ThrowWin32Exception("Failed to free the memory allocated for the shellcode in the process"); } // Close the handle opened to the process processHandle?.Close(); // Close the handle opened to the thread threadHandle?.Close(); return(true); }