internal IntPtr InitialiseDllPath() { // Write the DLL path into the remote process var dllPathAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, DllPath.Length, MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, dllPathAddress, Encoding.Unicode.GetBytes(DllPath)); // Write a UnicodeString representing the DLL path into the remote process IntPtr dllPathUnicodeStringAddress; if (ProcessManager.IsWow64) { var dllPathUnicodeString = new UnicodeString32(DllPath, dllPathAddress); dllPathUnicodeStringAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, Marshal.SizeOf <UnicodeString32>(), MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress, dllPathUnicodeString); } else { var dllPathUnicodeString = new UnicodeString64(DllPath, dllPathAddress); dllPathUnicodeStringAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, Marshal.SizeOf <UnicodeString64>(), MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress, dllPathUnicodeString); } return(dllPathUnicodeStringAddress); }
public IntPtr Call() { // Write the DLL path into the remote process var dllPathBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(_injectionWrapper.DllPath.Length); var dllPathBytes = Encoding.Unicode.GetBytes(_injectionWrapper.DllPath); _injectionWrapper.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Write a UnicodeString representing the DLL path into the remote process IntPtr unicodeStringBuffer; if (_injectionWrapper.ProcessManager.IsWow64) { var unicodeString = new UnicodeString32(_injectionWrapper.DllPath) { Buffer = (uint)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>()); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } else { var unicodeString = new UnicodeString64(_injectionWrapper.DllPath) { Buffer = (ulong)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>()); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } var moduleHandleBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(IntPtr.Size); // Flush the instruction cache of the remote process to ensure all memory operations have been completed if (!FlushInstructionCache(Process.GetCurrentProcess().SafeHandle, IntPtr.Zero, 0)) { ExceptionHandler.ThrowWin32Exception("Failed to flush the instruction cache of the remote process"); } // Call LdrLoadDll in the remote process var ldrLoadDllAddress = _injectionWrapper.ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var ntStatus = _injectionWrapper.ProcessManager.CallFunction <uint>(CallingConvention.StdCall, ldrLoadDllAddress, 0, 0, (ulong)unicodeStringBuffer, (ulong)moduleHandleBuffer); if ((NtStatus)ntStatus != NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to call LdrLoadDll in the remote process", (NtStatus)ntStatus); } while (_injectionWrapper.ProcessManager.Modules.All(module => module.FilePath != _injectionWrapper.DllPath)) { _injectionWrapper.ProcessManager.Refresh(); } _injectionWrapper.MemoryManager.FreeVirtualMemory(dllPathBuffer); _injectionWrapper.MemoryManager.FreeVirtualMemory(unicodeStringBuffer); try { // Read the base address of the DLL that was loaded in the remote process return(_injectionWrapper.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleBuffer)); } finally { _injectionWrapper.MemoryManager.FreeVirtualMemory(moduleHandleBuffer); } }
public IntPtr Call() { // Write the DLL path into the remote process var dllPathBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(_injectionWrapper.DllPath.Length); var dllPathBytes = Encoding.Unicode.GetBytes(_injectionWrapper.DllPath); _injectionWrapper.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Write a UnicodeString representing the DLL path into the remote process IntPtr unicodeStringBuffer; if (_injectionWrapper.ProcessManager.IsWow64) { var unicodeString = new UnicodeString32(_injectionWrapper.DllPath) { Buffer = (uint)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>()); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } else { var unicodeString = new UnicodeString64(_injectionWrapper.DllPath) { Buffer = (ulong)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>()); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } // Get the address of the LdrLoadDll function in the remote process var ldrLoadDllAddress = _injectionWrapper.ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var returnBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(sizeof(uint)); var moduleHandleBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(IntPtr.Size); // Write the shellcode used to call LdrLoadDll from a thread into the remote process var shellcode = _injectionWrapper.Assembler.AssembleThreadFunctionCall(CallingConvention.StdCall, ldrLoadDllAddress, returnBuffer, 0, 0, (ulong)unicodeStringBuffer, (ulong)moduleHandleBuffer); var shellcodeBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory(shellcode.Length); _injectionWrapper.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Open a handle to the first thread in the remote process var firstThreadHandle = OpenThread(ThreadAccessMask.AllAccess, false, _injectionWrapper.ProcessManager.Process.Threads[0].Id); if (_injectionWrapper.ProcessManager.IsWow64) { // Suspend the thread if (Wow64SuspendThread(firstThreadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the remote process"); } var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Wow64Context>()); Marshal.StructureToPtr(new Wow64Context { ContextFlags = ContextFlags.Control }, threadContextBuffer, false); // Get the context of the thread if (!Wow64GetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the remote process"); } var threadContext = Marshal.PtrToStructure <Wow64Context>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Esp -= sizeof(uint); _injectionWrapper.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Esp, threadContext.Eip); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Eip = (uint)shellcodeBuffer; Marshal.StructureToPtr(threadContext, threadContextBuffer, true); // Update the context of the thread if (!Wow64SetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the remote process"); } } else { // Suspend the thread if (SuspendThread(firstThreadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the remote process"); } var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context>()); Marshal.StructureToPtr(new Context { ContextFlags = ContextFlags.Control }, threadContextBuffer, false); // Get the context of the thread if (!GetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the remote process"); } var threadContext = Marshal.PtrToStructure <Context>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Rsp -= sizeof(ulong); _injectionWrapper.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Rsp, threadContext.Rip); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Rip = (ulong)shellcodeBuffer; Marshal.StructureToPtr(threadContext, threadContextBuffer, true); // Update the context of the thread if (!SetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the remote process"); } } // Flush the instruction cache of the remote process to ensure all memory operations have been completed if (!FlushInstructionCache(Process.GetCurrentProcess().SafeHandle, IntPtr.Zero, 0)) { ExceptionHandler.ThrowWin32Exception("Failed to flush the instruction cache of the remote process"); } // Resume the thread if (ResumeThread(firstThreadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to resume a thread in the remote process"); } firstThreadHandle.Dispose(); // Send a message to the thread to ensure it resumes PostThreadMessage(_injectionWrapper.ProcessManager.Process.Threads[0].Id, WindowsMessage.Keydown, VirtualKey.LeftButton, IntPtr.Zero); // Read the returned value of LdrLoadDll from the buffer var ntStatus = _injectionWrapper.MemoryManager.ReadVirtualMemory <uint>(returnBuffer); if ((NtStatus)ntStatus != NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to call LdrLoadDll in the remote process", (NtStatus)ntStatus); } while (_injectionWrapper.ProcessManager.Modules.All(module => module.FilePath != _injectionWrapper.DllPath)) { _injectionWrapper.ProcessManager.Refresh(); } _injectionWrapper.MemoryManager.FreeVirtualMemory(dllPathBuffer); _injectionWrapper.MemoryManager.FreeVirtualMemory(unicodeStringBuffer); try { // Read the base address of the DLL that was loaded in the remote process return(_injectionWrapper.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleBuffer)); } finally { _injectionWrapper.MemoryManager.FreeVirtualMemory(moduleHandleBuffer); } }
public IntPtr Inject() { // Write the DLL path into the remote process var dllPathAddress = _process.MemoryManager.AllocateVirtualMemory(_dllPath.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathAddress, Encoding.Unicode.GetBytes(_dllPath)); // Write a UnicodeString representing the DLL path into the remote process IntPtr dllPathUnicodeStringAddress; if (_process.IsWow64) { var dllPathUnicodeString = new UnicodeString32(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } else { var dllPathUnicodeString = new UnicodeString64(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } // Write the shellcode used to call LdrLoadDll into the remote process var ldrLoadDllAddress = _process.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = _process.MemoryManager.AllocateVirtualMemory(IntPtr.Size, MemoryProtectionType.ReadWrite); var shellcodeReturnAddress = _process.MemoryManager.AllocateVirtualMemory(sizeof(int), MemoryProtectionType.ReadWrite); var shellcode = _process.Assembler.AssembleThreadFunctionCall(new FunctionCall(ldrLoadDllAddress, CallingConvention.StdCall, new[] { 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress }, shellcodeReturnAddress)); var shellcodeAddress = _process.MemoryManager.AllocateVirtualMemory(shellcode.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(shellcodeAddress, shellcode); _process.MemoryManager.ProtectVirtualMemory(shellcodeAddress, shellcode.Length, MemoryProtectionType.ExecuteRead); // Open a handle to the first thread in the remote process var firstThreadHandle = Kernel32.OpenThread(Constants.ThreadAllAccess, false, _process.Process.Threads[0].Id); if (firstThreadHandle is null) { throw new PInvokeException("Failed to call OpenThread"); } if (_process.IsWow64) { // Suspend the thread if (Kernel32.Wow64SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call Wow64SuspendThread"); } // Get the context of the thread var threadContext = new Context32 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context32>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.Wow64GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context32>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Esp -= sizeof(int); _process.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Esp, threadContext.Eip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Eip = (int)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.Wow64SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } else { // Suspend the thread if (Kernel32.SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call SuspendThread"); } // Get the context of the thread var threadContext = new Context64 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context64>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context64>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Rsp -= sizeof(long); _process.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Rsp, threadContext.Rip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Rip = (long)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } // Send a message to the thread to ensure it executes the shellcode User32.PostThreadMessage(_process.Process.Threads[0].Id, MessageType.Null, IntPtr.Zero, IntPtr.Zero); // Resume the thread if (Kernel32.ResumeThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call ResumeThread"); } firstThreadHandle.Dispose(); var shellcodeReturn = _process.MemoryManager.ReadVirtualMemory <int>(shellcodeReturnAddress); if ((NtStatus)shellcodeReturn != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrLoadDll", (NtStatus)shellcodeReturn); } // Ensure the DLL is loaded before freeing any memory while (_process.Modules.TrueForAll(module => module.FilePath != _dllPath)) { _process.Refresh(); } _process.MemoryManager.FreeVirtualMemory(dllPathAddress); _process.MemoryManager.FreeVirtualMemory(dllPathUnicodeStringAddress); _process.MemoryManager.FreeVirtualMemory(shellcodeReturnAddress); // Read the address of the DLL that was loaded in the remote process var remoteDllAddress = _process.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleAddress); _process.MemoryManager.FreeVirtualMemory(moduleHandleAddress); if (!_injectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { return(remoteDllAddress); } // Write over the header region of the DLL with random bytes var randomBuffer = new byte[_peImage.PeHeaders.PEHeader.SizeOfHeaders]; new Random().NextBytes(randomBuffer); _process.MemoryManager.WriteVirtualMemory(remoteDllAddress, randomBuffer); return(remoteDllAddress); }
public IntPtr Call() { // Write the DLL path into the remote process var dllPathAddress = _process.MemoryManager.AllocateVirtualMemory(_dllPath.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathAddress, Encoding.Unicode.GetBytes(_dllPath)); // Write a UnicodeString representing the DLL path into the remote process IntPtr dllPathUnicodeStringAddress; if (_process.IsWow64) { var dllPathUnicodeString = new UnicodeString32(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } else { var dllPathUnicodeString = new UnicodeString64(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } // Create a thread to call LdrLoadDll in the remote process var ldrLoadDllAddress = _process.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = _process.MemoryManager.AllocateVirtualMemory(IntPtr.Size, MemoryProtectionType.ReadWrite); var ntStatus = _process.CallFunction <int>(CallingConvention.StdCall, ldrLoadDllAddress, 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress); if ((NtStatus)ntStatus != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrLoadDll", (NtStatus)ntStatus); } // Ensure the DLL is loaded before freeing any memory while (_process.Modules.TrueForAll(module => module.FilePath != _dllPath)) { _process.Refresh(); } _process.MemoryManager.FreeVirtualMemory(dllPathAddress); _process.MemoryManager.FreeVirtualMemory(dllPathUnicodeStringAddress); // Read the address of the DLL that was loaded in the remote process var remoteDllAddress = _process.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleAddress); _process.MemoryManager.FreeVirtualMemory(moduleHandleAddress); if (!_injectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { return(remoteDllAddress); } // Write over the header region of the DLL with random bytes var randomBuffer = new byte[_peImage.PeHeaders.PEHeader.SizeOfHeaders]; new Random().NextBytes(randomBuffer); _process.MemoryManager.WriteVirtualMemory(remoteDllAddress, randomBuffer); return(remoteDllAddress); }