Exemple #1
0
        internal IntPtr Invoke(SafeThreadHandle threadHandle)
        {
            // Store a context structure in a buffer

            IntPtr contextBuffer;

            if (Environment.Is64BitProcess)
            {
                var context = new Structures.Context {
                    ContextFlags = Enumerations.ContextFlags.Control
                };

                contextBuffer = LocalMemoryTools.StoreStructureInBuffer(context);
            }

            else
            {
                var context = new Structures.Wow64Context {
                    ContextFlags = Enumerations.ContextFlags.Control
                };

                contextBuffer = LocalMemoryTools.StoreStructureInBuffer(context);
            }

            // Perform the syscall

            var syscallResult = _ntGetContextThreadDelegate(threadHandle, contextBuffer);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the target process", syscallResult);
            }

            return(contextBuffer);
        }
Exemple #2
0
        internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int size, Enumerations.MemoryProtectionType protectionType)
        {
            // Store the base address of the allocation in a buffer

            var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress);

            // Store the size of the allocation in a buffer

            var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(size);

            // Perform the syscall

            const Enumerations.MemoryAllocationType allocationType = Enumerations.MemoryAllocationType.Commit | Enumerations.MemoryAllocationType.Reserve;

            var syscallResult = _ntAllocateVirtualMemoryDelegate(processHandle, baseAddressBuffer, 0, sizeBuffer, allocationType, protectionType);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to allocate memory in the target process", syscallResult);
            }

            try
            {
                return(Marshal.PtrToStructure <IntPtr>(baseAddressBuffer));
            }

            finally
            {
                LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer);
            }
        }
Exemple #3
0
        internal SafeThreadHandle Invoke(SafeProcessHandle processHandle, IntPtr startAddress, IntPtr parameter)
        {
            // Initialise a buffer to store the returned thread handle

            var threadHandleBuffer = LocalMemoryTools.AllocateMemoryForBuffer(IntPtr.Size);

            // Perform the syscall

            const Enumerations.ThreadAccessMask desiredAccess = Enumerations.ThreadAccessMask.SpecificRightsAll | Enumerations.ThreadAccessMask.StandardRightsAll;

            var syscallResult = _ntCreateThreadExDelegate(threadHandleBuffer, desiredAccess, IntPtr.Zero, processHandle, startAddress, parameter, Enumerations.ThreadCreationType.HideFromDebugger, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to create a thread in the target process", syscallResult);
            }

            try
            {
                return(new SafeThreadHandle(Marshal.PtrToStructure <IntPtr>(threadHandleBuffer), true));
            }

            finally
            {
                LocalMemoryTools.FreeMemoryForBuffer(threadHandleBuffer);
            }
        }
Exemple #4
0
        private void CreateSyscall <TSyscall>() where TSyscall : class
        {
            // Get the address of the function to syscall

            var functionAddress = PInvoke.GetProcAddress(_ntDllAddress, typeof(TSyscall).Name.Replace("Definition", ""));

            // Copy the first 8 bytes of the function

            var functionBytes = new byte[8];

            Marshal.Copy(functionAddress, functionBytes, 0, 8);

            // Retrieve the syscall index from the bytes

            var syscallIndexBytes = Environment.Is64BitProcess ? functionBytes.Skip(4).Take(4)
                                                               : functionBytes.Skip(1).Take(4);

            // Write the shellcode used to perform the syscall into the local process

            var shellcode = Environment.Is64BitProcess ? SyscallX64.GetShellcode(syscallIndexBytes.ToArray())
                                                       : SyscallX86.GetShellcode(syscallIndexBytes.ToArray());

            var shellcodeBuffer = LocalMemoryTools.StoreBytesInBuffer(shellcode);

            // Create an instance of the syscall class

            var syscallInstance = Activator.CreateInstance(typeof(TSyscall), BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { shellcodeBuffer }, null);

            // Get the parameter and return types of the syscall method

            var methodInformation = typeof(TSyscall).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.NonPublic);

            var methodTypes = new List <Type>(methodInformation.GetParameters().Select(parameter => parameter.ParameterType))
            {
                methodInformation.ReturnType
            };

            // Create the delegate type to represent the syscall method

            Type delegateType;

            if (methodTypes.Last() == typeof(void))
            {
                methodTypes.RemoveAt(methodTypes.Count - 1);

                delegateType = Expression.GetActionType(methodTypes.ToArray());
            }

            else
            {
                delegateType = Expression.GetFuncType(methodTypes.ToArray());
            }

            // Create a delegate for the syscall method

            var syscallDelegate = Delegate.CreateDelegate(delegateType, syscallInstance, "Invoke");

            _syscallCache.Add(typeof(TSyscall).Name, new SyscallInstance(syscallDelegate, shellcodeBuffer));
        }
Exemple #5
0
        internal PeParser(string dllPath)
        {
            _dllBuffer = LocalMemoryTools.StoreBytesInBuffer(File.ReadAllBytes(dllPath));

            _peHeaders = new PeHeaders();

            ReadPeHeaders();
        }
Exemple #6
0
        internal PeParser(byte[] dllBytes)
        {
            _dllBuffer = LocalMemoryTools.StoreBytesInBuffer(dllBytes);

            _peHeaders = new PeHeaders();

            ReadPeHeaders();
        }
Exemple #7
0
        internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress)
        {
            // Initialise a buffer to store the returned memory basic information structure

            var memoryBasicInformationBuffer = LocalMemoryTools.AllocateMemoryForBuffer(Marshal.SizeOf <Structures.MemoryBasicInformation>());

            // Perform the syscall

            var syscallResult = _ntQueryVirtualMemoryDelegate(processHandle, baseAddress, Enumerations.MemoryInformationClass.BasicInformation, memoryBasicInformationBuffer, (ulong)Marshal.SizeOf <Structures.MemoryBasicInformation>(), IntPtr.Zero);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to query memory in the target process", syscallResult);
            }

            return(memoryBasicInformationBuffer);
        }
Exemple #8
0
        internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int bytesToRead)
        {
            // Initialise a buffer to store the returned bytes read

            var bytesReadBuffer = LocalMemoryTools.AllocateMemoryForBuffer(bytesToRead);

            // Perform the syscall

            var syscallResult = _ntReadVirtualMemoryDelegate(processHandle, baseAddress, bytesReadBuffer, (ulong)bytesToRead, IntPtr.Zero);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to read memory from the target process", syscallResult);
            }

            return(bytesReadBuffer);
        }
        internal IntPtr Invoke(SafeProcessHandle processHandle, Enumerations.ProcessInformationClass processInformationClass)
        {
            // Initialise a buffer to store the returned process information structure

            var bufferSize = processInformationClass == Enumerations.ProcessInformationClass.BasicInformation ? Marshal.SizeOf <Structures.ProcessBasicInformation>() : sizeof(ulong);

            var processInformationBuffer = LocalMemoryTools.AllocateMemoryForBuffer(bufferSize);

            // Perform the syscall

            var syscallResult = _ntQueryInformationProcessDelegate(processHandle, processInformationClass, processInformationBuffer, (ulong)bufferSize, IntPtr.Zero);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to query the information of the target process", syscallResult);
            }

            return(processInformationBuffer);
        }
Exemple #10
0
        internal SafeProcessHandle Invoke(int processId)
        {
            // Initialise a buffer to store the returned process handle

            var processHandleBuffer = LocalMemoryTools.AllocateMemoryForBuffer(IntPtr.Size);

            // Store an empty object attributes structure in a buffer

            var objectAttributesBuffer = LocalMemoryTools.StoreStructureInBuffer(new Structures.ObjectAttributes());

            // Store a client id structure in a buffer

            var clientId = new Structures.ClientId {
                UniqueProcess = new IntPtr(processId), UniqueThread = IntPtr.Zero
            };

            var clientIdBuffer = LocalMemoryTools.StoreStructureInBuffer(clientId);

            // Perform the syscall

            var syscallResult = _ntOpenProcessDelegate(processHandleBuffer, Enumerations.ProcessAccessMask.AllAccess, objectAttributesBuffer, clientIdBuffer);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to open a handle to the target process", syscallResult);
            }

            try
            {
                return(new SafeProcessHandle(Marshal.PtrToStructure <IntPtr>(processHandleBuffer), true));
            }

            finally
            {
                LocalMemoryTools.FreeMemoryForBuffer(processHandleBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(objectAttributesBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(clientIdBuffer);
            }
        }
Exemple #11
0
        internal void Invoke(SafeProcessHandle processHandle, IntPtr baseAddress)
        {
            // Store the base address of memory region to free in a buffer

            var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress);

            // Store the free size in a buffer

            var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(0);

            // Perform the syscall

            var syscallResult = _ntFreeVirtualMemoryDelegate(processHandle, baseAddressBuffer, sizeBuffer, Enumerations.MemoryFreeType.Release);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to free memory in the target process", syscallResult);
            }

            LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer);

            LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer);
        }
Exemple #12
0
        internal Enumerations.MemoryProtectionType Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int size, Enumerations.MemoryProtectionType protectionType)
        {
            // Store the base address of the memory region to protect in a buffer

            var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress);

            // Store the protection size in a buffer

            var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(size);

            // Initialise a buffer to store the returned old protection of the memory region

            var oldProtectionBuffer = LocalMemoryTools.AllocateMemoryForBuffer(sizeof(ulong));

            // Perform the syscall

            var syscallResult = _ntProtectVirtualMemoryDelegate(processHandle, baseAddressBuffer, sizeBuffer, protectionType, oldProtectionBuffer);

            if (syscallResult != Enumerations.NtStatus.Success)
            {
                ExceptionHandler.ThrowWin32Exception("Failed to protect memory in the target process", syscallResult);
            }

            try
            {
                return((Enumerations.MemoryProtectionType)Marshal.PtrToStructure <ulong>(oldProtectionBuffer));
            }

            finally
            {
                LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(oldProtectionBuffer);
            }
        }
Exemple #13
0
 public void Dispose()
 {
     LocalMemoryTools.FreeMemoryForBuffer(ShellcodeAddress);
 }
Exemple #14
0
 public void Dispose()
 {
     LocalMemoryTools.FreeMemoryForBuffer(_dllBuffer);
 }
Exemple #15
0
        public bool Call(InjectionProperties injectionProperties)
        {
            // Get the address of the LoadLibraryW function in the target process

            var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW");

            // Write the DLL path into the target process

            var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite);

            var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath);

            injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes);

            // Open a handle to the first thread in the target process

            var threadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtOpenThread>(injectionProperties.RemoteProcess.TargetProcess.Threads[0].Id);

            if (injectionProperties.RemoteProcess.IsWow64)
            {
                // Suspend the thread

                if (PInvoke.Wow64SuspendThread(threadHandle) == -1)
                {
                    ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the target process");
                }

                // Get the context of the thread

                var threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(new Structures.Wow64Context {
                    ContextFlags = Enumerations.ContextFlags.Control
                });

                if (PInvoke.Wow64GetThreadContext(threadHandle, threadContextBuffer) == 0)
                {
                    ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the target process");
                }

                var threadContext = Marshal.PtrToStructure <Structures.Wow64Context>(threadContextBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer);

                // Write the shellcode used to call LoadLibraryW from the thread into the target process

                var shellcode = ThreadHijackX86.GetShellcode((IntPtr)threadContext.Eip, dllPathBuffer, loadLibraryAddress);

                var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite);

                injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode);

                // Overwrite the instruction pointer of the thread with the address of the shellcode buffer

                threadContext.Eip = (uint)shellcodeBuffer;

                threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext);

                // Update the context of the thread

                if (PInvoke.Wow64SetThreadContext(threadHandle, threadContextBuffer) == 0)
                {
                    ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the target process");
                }

                LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer);
            }

            else
            {
                // Suspend the thread

                injectionProperties.SyscallManager.InvokeSyscall <NtSuspendThread>(threadHandle);

                // Get the context of the thread

                var threadContextBuffer = (IntPtr)injectionProperties.SyscallManager.InvokeSyscall <NtGetContextThread>(threadHandle);

                var threadContext = Marshal.PtrToStructure <Structures.Context>(threadContextBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer);

                // Write the shellcode used to call LoadLibraryW from the thread into the target process

                var shellcode = ThreadHijackX64.GetShellcode((IntPtr)threadContext.Rip, dllPathBuffer, loadLibraryAddress);

                var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite);

                injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode);

                // Overwrite the instruction pointer of the thread with the address of the shellcode buffer

                threadContext.Rip = (ulong)shellcodeBuffer;

                threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext);

                // Update the context of the thread

                injectionProperties.SyscallManager.InvokeSyscall <NtSetContextThread>(threadHandle, threadContextBuffer);

                LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer);
            }

            // Resume the thread

            injectionProperties.SyscallManager.InvokeSyscall <NtResumeThread>(threadHandle);

            PInvoke.SwitchToThisWindow(injectionProperties.RemoteProcess.TargetProcess.MainWindowHandle, true);

            threadHandle.Dispose();

            return(true);
        }
Exemple #16
0
        public bool Call(InjectionProperties injectionProperties)
        {
            var localDllAddress = injectionProperties.DllPath is null
                                ? LocalMemoryTools.StoreBytesInBuffer(injectionProperties.DllBytes)
                                : LocalMemoryTools.StoreBytesInBuffer(File.ReadAllBytes(injectionProperties.DllPath));

            // Build the import table of the DLL

            BuildImportTable(injectionProperties, localDllAddress);

            var peHeaders = injectionProperties.PeParser.GetHeaders();

            // Allocate memory for the DLL in the target process

            var allocationBaseAddress = injectionProperties.RemoteProcess.IsWow64
                                      ? peHeaders.NtHeaders32.OptionalHeader.ImageBase
                                      : peHeaders.NtHeaders64.OptionalHeader.ImageBase;

            var dllSize = injectionProperties.RemoteProcess.IsWow64
                        ? peHeaders.NtHeaders32.OptionalHeader.SizeOfImage
                        : peHeaders.NtHeaders64.OptionalHeader.SizeOfImage;

            IntPtr remoteDllAddress;

            try
            {
                remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory((IntPtr)allocationBaseAddress, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite);
            }

            catch (Win32Exception)
            {
                remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite);
            }

            // Perform any needed relocations

            PerformRelocations(injectionProperties, localDllAddress, remoteDllAddress);

            // Map the sections of the DLL

            MapSections(injectionProperties, localDllAddress, remoteDllAddress);

            // Map randomised PE headers

            MapHeaders(injectionProperties, remoteDllAddress);

            // Call any TLS callbacks

            CallTlsCallbacks(injectionProperties, remoteDllAddress);

            // Call the entry point of the DLL

            var dllEntryPointAddress = injectionProperties.RemoteProcess.IsWow64
                                     ? remoteDllAddress.AddOffset(peHeaders.NtHeaders32.OptionalHeader.AddressOfEntryPoint)
                                     : remoteDllAddress.AddOffset(peHeaders.NtHeaders64.OptionalHeader.AddressOfEntryPoint);

            if (dllEntryPointAddress != remoteDllAddress)
            {
                CallEntryPoint(injectionProperties, remoteDllAddress, dllEntryPointAddress);
            }

            LocalMemoryTools.FreeMemoryForBuffer(localDllAddress);

            return(true);
        }