/// <summary> /// An instance capable of injecting a DLL into a remote process /// </summary> public Injector(int processId, string dllPath, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { if (injectionFlags.HasFlag(InjectionFlags.RandomiseDllName)) { dllPath = CreateTemporaryDll(File.ReadAllBytes(dllPath)); } switch (injectionMethod) { case InjectionMethod.CreateThread: { _injectionMethod = new CreateThread(dllPath, GetProcess(processId), injectionFlags); break; } case InjectionMethod.HijackThread: { _injectionMethod = new HijackThread(dllPath, GetProcess(processId), injectionFlags); break; } case InjectionMethod.ManualMap: { _injectionMethod = new ManualMap(dllPath, GetProcess(processId), injectionFlags); break; } } }
internal override void Inject() { _dllBuffer = DllBytes; // Allocate memory for the DLL in the process try { DllBaseAddress = ProcessManager.Memory.AllocateBlock((IntPtr)PeImage.Headers.PEHeader.ImageBase, PeImage.Headers.PEHeader.SizeOfImage, ProtectionType.ReadWrite); } catch (Win32Exception) { DllBaseAddress = ProcessManager.Memory.AllocateBlock(IntPtr.Zero, PeImage.Headers.PEHeader.SizeOfImage, ProtectionType.ReadWrite); } BuildImportTable(); RelocateImage(); MapSections(); MapHeaders(); SetupExceptionHandling(); CallInitRoutines(DllReason.DllProcessAttach); if (InjectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { RandomiseDllHeaders(); } }
internal InjectionWrapper(Process process, string dllPath, InjectionMethod injectionMethod, InjectionFlags injectionFlags) { DllBytes = File.ReadAllBytes(dllPath); DllPath = injectionFlags.HasFlag(InjectionFlags.RandomiseDllName) ? CreateTemporaryDll() : dllPath; InjectionMethod = injectionMethod; InjectionFlags = injectionFlags; PeImage = new PeImage(DllBytes); Process = new ManagedProcess(process); if (injectionMethod == InjectionMethod.ManualMap || injectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { ResolveApiSetImportedFunctions(); } }
internal override void Inject() { // Write the DLL path into the remote process var dllPathUnicodeStringAddress = InitialiseDllPath(); // Create a thread to call LdrLoadDll in the remote process var ldrLoadDllAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, IntPtr.Size, MemoryProtectionType.ReadWrite); var ntStatus = ProcessManager.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 (ProcessManager.Modules.TrueForAll(module => module.FilePath != DllPath)) { ProcessManager.Refresh(); } var dllPathAddress = ProcessManager.IsWow64 ? (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString32>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer : (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString64>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer; MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress); // Read the address of the DLL that was loaded in the remote process DllBaseAddress = MemoryManager.ReadVirtualMemory <IntPtr>(ProcessManager.Process.SafeHandle, moduleHandleAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, moduleHandleAddress); if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { // Hide the DLL from the PEB of the remote process HideDllFromPeb(); } if (InjectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { // Randomise the DLL headers RandomiseDllHeaders(DllBaseAddress); } }
internal override void Eject() { if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { return; } var freeLibraryAddress = ProcessManager.GetFunctionAddress("kernel32.dll", "FreeLibrary"); if (!ProcessManager.CallFunction <bool>(CallingConvention.StdCall, freeLibraryAddress, (long)DllBaseAddress)) { throw new RemoteFunctionCallException("Failed to call FreeLibrary"); } }
internal void Call(IntPtr remoteDllAddress) { if (_injectionMethod == InjectionMethod.ManualMap || _injectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { // Call the entry point of the DLL with DllProcessDetach if (!_process.CallFunction <bool>(CallingConvention.StdCall, remoteDllAddress + _peImage.PeHeaders.PEHeader.AddressOfEntryPoint, (long)remoteDllAddress, Constants.DllProcessDetach, 0)) { throw new RemoteFunctionCallException("Failed to call the entry point of the DLL"); } // Remove the entry for the DLL from the LdrpInvertedFunctionTable var rtRemoveInvertedFunctionTableAddress = _process.PdbFile.Value.Symbols["RtlRemoveInvertedFunctionTable"]; _process.CallFunction(CallingConvention.FastCall, rtRemoveInvertedFunctionTableAddress, (long)remoteDllAddress); // Decrease the reference count of the DLL dependencies var freeLibraryAddress = _process.GetFunctionAddress("kernel32.dll", "FreeLibrary"); if (_peImage.ImportedFunctions.Value.GroupBy(importedFunction => importedFunction.Dll).Select(dll => _process.Modules.Find(module => module.Name.Equals(dll.Key, StringComparison.OrdinalIgnoreCase)).BaseAddress).Any(dependencyAddress => !_process.CallFunction <bool>(CallingConvention.StdCall, freeLibraryAddress, (long)dependencyAddress))) { throw new RemoteFunctionCallException("Failed to call FreeLibrary"); } // Free the memory allocated for the DLL if (_injectionMethod == InjectionMethod.ManualMap) { _process.MemoryManager.FreeVirtualMemory(remoteDllAddress); } else { Ntdll.NtUnmapViewOfSection(_process.Process.SafeHandle, remoteDllAddress); } } else { var freeLibraryAddress = _process.GetFunctionAddress("kernel32.dll", "FreeLibrary"); if (!_process.CallFunction <bool>(CallingConvention.StdCall, freeLibraryAddress, (long)remoteDllAddress)) { throw new RemoteFunctionCallException("Failed to call FreeLibrary"); } } }
internal override void Eject() { if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { return; } var ldrUnloadDllAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "LdrUnloadDll"); var ntStatus = ProcessManager.CallFunction <int>(CallingConvention.StdCall, ldrUnloadDllAddress, (long)DllBaseAddress); if ((NtStatus)ntStatus != NtStatus.Success) { throw new Win32Exception($"Failed to call LdrUnloadDll in the context of the remote process with error code {Ntdll.RtlNtStatusToDosError((NtStatus) ntStatus)}"); } }
internal InjectionWrapper(Process process, byte[] dllBytes, InjectionMethod injectionMethod, InjectionFlags injectionFlags) { DllBytes = dllBytes; if (injectionMethod != InjectionMethod.ManualMap) { DllPath = CreateTemporaryDll(); } InjectionMethod = injectionMethod; InjectionFlags = injectionFlags; PeImage = new PeImage(dllBytes); Process = new ManagedProcess(process); if (injectionMethod == InjectionMethod.ManualMap || injectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { ResolveApiSetImportedFunctions(); } }
/// <summary> /// Provides the ability to inject a DLL into a process /// </summary> public Injector(string processName, string dllPath, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { if (injectionFlags.HasFlag(InjectionFlags.RandomiseDllName)) { dllPath = CreateTemporaryDll(File.ReadAllBytes(dllPath)); } if (injectionMethod == InjectionMethod.ManualMap) { _injectionBase = new ManualMap(dllPath, GetProcess(processName), injectionMethod, injectionFlags); } else if (injectionMethod == InjectionMethod.CreateThread || injectionMethod == InjectionMethod.HijackThread) { _injectionBase = new LdrLoadDll(dllPath, GetProcess(processName), injectionMethod, injectionFlags); } else { throw new ArgumentException("The injection method provided was invalid"); } }
private void MapHeaders() { var headerBytes = new byte[_peImage.PeHeaders.PEHeader.SizeOfHeaders]; if (_injectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { // Generate random PE headers new Random().NextBytes(headerBytes); } else { // Read the PE headers of the DLL Marshal.Copy(_localDllAddress, headerBytes, 0, headerBytes.Length); } // Write the PE headers into the remote process _process.MemoryManager.WriteVirtualMemory(_remoteDllAddress, headerBytes); _process.MemoryManager.ProtectVirtualMemory(_remoteDllAddress, _peImage.PeHeaders.PEHeader.SizeOfHeaders, MemoryProtectionType.ReadOnly); }
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); }
internal override void Inject() { // Write the DLL path into the remote process var dllPathUnicodeStringAddress = InitialiseDllPath(); // Write the shellcode used to call LdrLoadDll into the remote process var ldrLoadDllAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, IntPtr.Size, MemoryProtectionType.ReadWrite); var shellcodeReturnAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, sizeof(int), MemoryProtectionType.ReadWrite); var shellcode = Assembler.AssembleThreadFunctionCall(new FunctionCall(ProcessManager.IsWow64, ldrLoadDllAddress, CallingConvention.StdCall, new[] { 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress }, shellcodeReturnAddress)); var shellcodeAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, shellcode.Length, MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeAddress, shellcode); MemoryManager.ProtectVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeAddress, shellcode.Length, MemoryProtectionType.ExecuteRead); // Open a handle to the first thread in the remote process var firstThreadHandle = Kernel32.OpenThread(Constants.ThreadAllAccess, false, ProcessManager.Process.Threads[0].Id); if (firstThreadHandle is null) { throw new PInvokeException("Failed to call OpenThread"); } if (ProcessManager.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); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, (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); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, (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(ProcessManager.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 = MemoryManager.ReadVirtualMemory <int>(ProcessManager.Process.SafeHandle, 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 (ProcessManager.Modules.TrueForAll(module => module.FilePath != DllPath)) { ProcessManager.Refresh(); } var dllPathAddress = ProcessManager.IsWow64 ? (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString32>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer : (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString64>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer; MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeReturnAddress); // Read the address of the DLL that was loaded in the remote process DllBaseAddress = MemoryManager.ReadVirtualMemory <IntPtr>(ProcessManager.Process.SafeHandle, moduleHandleAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, moduleHandleAddress); if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { // Hide the DLL from the PEB of the remote process HideDllFromPeb(); } if (InjectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { // Randomise the DLL headers RandomiseDllHeaders(DllBaseAddress); } }
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); }
internal override void Inject() { // Write the DLL path into the process var dllPathBytes = Encoding.Unicode.GetBytes(DllPath); var dllPathBuffer = ProcessManager.Memory.AllocateBlock(IntPtr.Zero, dllPathBytes.Length, ProtectionType.ReadWrite); ProcessManager.Memory.WriteBlock(dllPathBuffer, dllPathBytes); // Initialise a UnicodeString representing the DLL path in the process var dllPathUnicodeStringBuffer = ProcessManager.IsWow64 ? ProcessManager.Memory.AllocateBlock(IntPtr.Zero, Unsafe.SizeOf <UnicodeString <int> >(), ProtectionType.ReadWrite) : ProcessManager.Memory.AllocateBlock(IntPtr.Zero, Unsafe.SizeOf <UnicodeString <long> >(), ProtectionType.ReadWrite); var rtlInitUnicodeStringAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "RtlInitUnicodeString"); ProcessManager.CallFunction(CallingConvention.StdCall, rtlInitUnicodeStringAddress, (long)dllPathUnicodeStringBuffer, (long)dllPathBuffer); // Call LdrLoadDll in the process var ldrLoadDllAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleBuffer = ProcessManager.Memory.AllocateBlock(IntPtr.Zero, IntPtr.Size, ProtectionType.ReadWrite); var ntStatus = ProcessManager.CallFunction <int>(CallingConvention.StdCall, ldrLoadDllAddress, 0, 0, (long)dllPathUnicodeStringBuffer, (long)moduleHandleBuffer); if ((NtStatus)ntStatus != NtStatus.Success) { throw new Win32Exception($"Failed to call LdrLoadDll in the context of the remote process with error code {Ntdll.RtlNtStatusToDosError((NtStatus) ntStatus)}"); } if (ProcessManager.IsWow64) { ProcessManager.Memory.FreeBlock((IntPtr)ProcessManager.Memory.Read <UnicodeString <int> >(dllPathUnicodeStringBuffer).Buffer); } else { ProcessManager.Memory.FreeBlock((IntPtr)ProcessManager.Memory.Read <UnicodeString <long> >(dllPathUnicodeStringBuffer).Buffer); } ProcessManager.Memory.FreeBlock(dllPathUnicodeStringBuffer); // Read the base address of the DLL that was loaded in the process DllBaseAddress = ProcessManager.Memory.Read <IntPtr>(moduleHandleBuffer); ProcessManager.Memory.FreeBlock(moduleHandleBuffer); if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { HideDllFromPeb(); } if (InjectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { RandomiseDllHeaders(); } }