internal IntPtr CreateRemoteUnicodeString(IntPtr stringBuffer) { IntPtr unicodeStringBuffer; if (_injectionWrapper.RemoteProcess.IsWow64) { var unicodeString = new Structures.UnicodeString32(_injectionWrapper.DllPath) { Buffer = (uint)stringBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString32>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } else { var unicodeString = new Structures.UnicodeString64(_injectionWrapper.DllPath) { Buffer = (ulong)stringBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString64>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } return(unicodeStringBuffer); }
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.RemoteProcess.IsWow64) { var unicodeString = new Structures.UnicodeString32(_injectionWrapper.DllPath) { Buffer = (uint)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString32>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } else { var unicodeString = new Structures.UnicodeString64(_injectionWrapper.DllPath) { Buffer = (ulong)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString64>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } // Get the address of the LdrLoadDll function in the remote process var ldrLoadDllAddress = _injectionWrapper.RemoteProcess.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var returnBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <uint>(); var moduleHandleBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <IntPtr>(); // Write the shellcode used to call LdrLoadDll from a thread into the remote process var shellcode = _injectionWrapper.Assembler.AssembleStandardThreadFunctionCall(ldrLoadDllAddress, returnBuffer, new ulong[] { 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 = PInvoke.OpenThread(Enumerations.ThreadAccessMask.AllAccess, false, _injectionWrapper.RemoteProcess.Process.Threads[0].Id); if (_injectionWrapper.RemoteProcess.IsWow64) { // Suspend the thread if (PInvoke.Wow64SuspendThread(firstThreadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the remote process"); } var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Structures.Wow64Context>()); Marshal.StructureToPtr(new Structures.Wow64Context { ContextFlags = Enumerations.ContextFlags.Control }, threadContextBuffer, false); // Get the context of the thread if (!PInvoke.Wow64GetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the remote process"); } var threadContext = Marshal.PtrToStructure <Structures.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 (!PInvoke.Wow64SetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the remote process"); } } else { // Suspend the thread if (PInvoke.SuspendThread(firstThreadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the remote process"); } var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Structures.Context>()); Marshal.StructureToPtr(new Structures.Context { ContextFlags = Enumerations.ContextFlags.Control }, threadContextBuffer, false); // Get the context of the thread if (!PInvoke.GetThreadContext(firstThreadHandle, threadContextBuffer)) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the remote process"); } var threadContext = Marshal.PtrToStructure <Structures.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 (!PInvoke.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 (!PInvoke.FlushInstructionCache(Process.GetCurrentProcess().SafeHandle, IntPtr.Zero, 0)) { ExceptionHandler.ThrowWin32Exception("Failed to flush the instruction cache of the remote process"); } // Resume the thread if (PInvoke.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 PInvoke.PostThreadMessage(_injectionWrapper.RemoteProcess.Process.Threads[0].Id, Enumerations.WindowsMessage.Keydown, Enumerations.VirtualKey.LeftButton, IntPtr.Zero); // Read the returned value of LdrLoadDll from the buffer var ntStatus = (Enumerations.NtStatus)_injectionWrapper.MemoryManager.ReadVirtualMemory <uint>(returnBuffer); if (ntStatus != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to call LdrLoadDll in the remote process", ntStatus); } while (_injectionWrapper.RemoteProcess.Modules.All(module => module.FilePath != _injectionWrapper.DllPath)) { _injectionWrapper.RemoteProcess.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.RemoteProcess.IsWow64) { var unicodeString = new Structures.UnicodeString32(_injectionWrapper.DllPath) { Buffer = (uint)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString32>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } else { var unicodeString = new Structures.UnicodeString64(_injectionWrapper.DllPath) { Buffer = (ulong)dllPathBuffer }; unicodeStringBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <Structures.UnicodeString64>(); _injectionWrapper.MemoryManager.WriteVirtualMemory(unicodeStringBuffer, unicodeString); } var moduleHandleBuffer = _injectionWrapper.MemoryManager.AllocateVirtualMemory <IntPtr>(); // Flush the instruction cache of the remote process to ensure all memory operations have been completed if (!PInvoke.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 ntStatus = (Enumerations.NtStatus)_injectionWrapper.RemoteProcess.CallFunction <uint>("ntdll.dll", "LdrLoadDll", new ulong[] { 0, 0, (ulong)unicodeStringBuffer, (ulong)moduleHandleBuffer }); if (ntStatus != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to call LdrLoadDll in the remote process", ntStatus); } while (_injectionWrapper.RemoteProcess.Modules.All(module => module.FilePath != _injectionWrapper.DllPath)) { _injectionWrapper.RemoteProcess.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); } }