/// <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;
            }
            }
        }
Exemple #2
0
        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();
            }
        }
Exemple #3
0
        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");
            }
        }
Exemple #6
0
        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");
                }
            }
        }
Exemple #7
0
        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)}");
            }
        }
Exemple #8
0
        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();
            }
        }
Exemple #9
0
        /// <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");
            }
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
            }
        }
Exemple #13
0
        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);
        }
Exemple #14
0
        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();
            }
        }