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(); } }
protected InjectionBase(byte[] dllBytes, Process process, InjectionFlags injectionFlags) { DllBytes = dllBytes; InjectionFlags = injectionFlags; PeImage = new PeImage(dllBytes); ProcessManager = new ProcessManager(process); }
internal HijackThread(InjectionWrapper injectionWrapper) { _dllPath = injectionWrapper.DllPath; _injectionFlags = injectionWrapper.InjectionFlags; _peImage = injectionWrapper.PeImage; _process = injectionWrapper.Process; }
internal EjectDll(InjectionWrapper injectionWrapper) { _injectionMethod = injectionWrapper.InjectionMethod; _injectionFlags = injectionWrapper.InjectionFlags; _peImage = injectionWrapper.PeImage; _process = injectionWrapper.Process; }
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 ManualMap(InjectionWrapper injectionWrapper) { _injectionFlags = injectionWrapper.InjectionFlags; _localDllAddress = Marshal.AllocHGlobal(injectionWrapper.DllBytes.Length); Marshal.Copy(injectionWrapper.DllBytes, 0, _localDllAddress, injectionWrapper.DllBytes.Length); _peImage = injectionWrapper.PeImage; _process = injectionWrapper.Process; }
protected InjectionBase(string dllPath, Process process, InjectionFlags injectionFlags) { DllBytes = File.ReadAllBytes(dllPath); DllPath = dllPath; InjectionFlags = injectionFlags; PeImage = new PeImage(DllBytes); ProcessManager = new ProcessManager(process); }
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"); } }
protected InjectionBase(byte[] dllBytes, Process process, InjectionMethod injectionMethod, InjectionFlags injectionFlags) { DllBytes = dllBytes; InjectionFlags = injectionFlags; PdbFile = new Lazy <PdbFile>(() => new PdbFile(ProcessManager.Modules.Find(module => module.Name.Equals("ntdll.dll", StringComparison.OrdinalIgnoreCase)), ProcessManager.IsWow64)); PeImage = new PeImage(dllBytes); ProcessManager = new ProcessManager(process, injectionMethod); ValidateArchitecture(); }
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, 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 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(); } }
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 MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, DllBaseAddress, headerBytes); MemoryManager.ProtectVirtualMemory(ProcessManager.Process.SafeHandle, DllBaseAddress, PeImage.PeHeaders.PEHeader.SizeOfHeaders, MemoryProtectionType.ReadOnly); }
internal InjectionManager(string processName, string dllPath, InjectionMethod injectionMethod, InjectionFlags injectionFlags) { _injectionWrapper = new InjectionWrapper(GetProcess(processName), dllPath, injectionMethod, injectionFlags); ValidationHandler.ValidateDllArchitecture(_injectionWrapper); _ejectDll = new EjectDll(_injectionWrapper); _hideDllFromPeb = new HideDllFromPeb(_injectionWrapper); _injectionMethod = InitialiseInjectionMethod(injectionMethod); }
internal InjectionManager(int processId, byte[] dllBytes, InjectionMethod injectionMethod, InjectionFlags injectionFlags) { _injectionWrapper = new InjectionWrapper(GetProcess(processId), dllBytes, injectionMethod, injectionFlags); ValidationHandler.ValidateDllArchitecture(_injectionWrapper); _ejectDll = new EjectDll(_injectionWrapper); _hideDllFromPeb = new HideDllFromPeb(_injectionWrapper); _injectionMethod = InitialiseInjectionMethod(injectionMethod); }
/// <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"); } }
/// <summary> /// An instance capable of injecting a DLL into a remote process /// </summary> public Injector(string processName, byte[] dllBytes, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { if (injectionMethod == InjectionMethod.ManualMap) { _injectionMethod = new ManualMap(dllBytes, GetProcess(processName), injectionFlags); } else { var dllPath = CreateTemporaryDll(dllBytes); switch (injectionMethod) { case InjectionMethod.CreateThread: { _injectionMethod = new CreateThread(dllPath, GetProcess(processName), injectionFlags); break; } case InjectionMethod.HijackThread: { _injectionMethod = new HijackThread(dllPath, GetProcess(processName), injectionFlags); break; } } } }
public ManualMap(string dllPath, Process process, InjectionFlags injectionFlags) : base(dllPath, process, injectionFlags) { }
internal LdrLoadDll(string dllPath, Process process, InjectionMethod injectionMethod, InjectionFlags injectionFlags) : base(dllPath, process, injectionMethod, injectionFlags) { }
/// <summary> /// Provides the ability to inject a DLL into a process /// </summary> public Injector(string processName, byte[] dllBytes, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { if (injectionMethod == InjectionMethod.ManualMap) { _injectionBase = new ManualMap(dllBytes, GetProcess(processName), injectionMethod, injectionFlags); } else if (injectionMethod == InjectionMethod.CreateThread || injectionMethod == InjectionMethod.HijackThread) { _injectionBase = new LdrLoadDll(CreateTemporaryDll(dllBytes), GetProcess(processName), injectionMethod, injectionFlags); } else { throw new ArgumentException("The injection method provided was invalid"); } }
internal ManualMap(string dllPath, Process process, InjectionMethod injectionMethod, InjectionFlags injectionFlags) : base(dllPath, process, injectionMethod, injectionFlags) { }
internal ManualMap(byte[] dllBytes, Process process, InjectionMethod injectionMethod, InjectionFlags injectionFlags) : base(dllBytes, process, injectionMethod, injectionFlags) { }
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(); } }
public HijackThread(string dllPath, Process process, InjectionFlags injectionFlags) : base(dllPath, process, injectionFlags) { }
/// <summary> /// An instance capable of injecting a DLL into a remote process /// </summary> public Injector(string processName, byte[] dllBytes, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { ValidationHandler.ValidateOperatingSystem(); // Ensure the arguments passed in are valid if (string.IsNullOrWhiteSpace(processName) || dllBytes is null || dllBytes.Length == 0) { throw new ArgumentException("One or more of the arguments provided were invalid"); } _injectionManager = new InjectionManager(processName, dllBytes, injectionMethod, injectionFlags); }
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); } }
/// <summary> /// An instance capable of injecting a DLL into a remote process /// </summary> public Injector(string processName, string dllPath, InjectionMethod injectionMethod, InjectionFlags injectionFlags = InjectionFlags.None) { ValidationHandler.ValidateOperatingSystem(); // Ensure the arguments passed in are valid if (string.IsNullOrWhiteSpace(processName) || string.IsNullOrWhiteSpace(dllPath)) { throw new ArgumentException("One or more of the arguments provided were invalid"); } // Ensure a valid DLL exists at the provided path if (!File.Exists(dllPath) || Path.GetExtension(dllPath) != ".dll") { throw new ArgumentException("No DLL exists at the provided path"); } _injectionManager = new InjectionManager(processName, dllPath, injectionMethod, injectionFlags); }
/// <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; } } }
public ManualMap(byte[] dllBytes, Process process, InjectionFlags injectionFlags) : base(dllBytes, process, injectionFlags) { }