internal Enumerations.MemoryProtectionType Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int protectionSize, Enumerations.MemoryProtectionType newProtectionType) { // Store the base address of the memory region to protect in a buffer var baseAddressBuffer = MemoryTools.StoreStructureInBuffer(baseAddress); // Store the protection size in a buffer var protectionSizeBuffer = MemoryTools.StoreStructureInBuffer(protectionSize); // Initialise a buffer to store the returned old protection of the memory region var oldProtectionBuffer = MemoryTools.AllocateMemoryForBuffer(sizeof(ulong)); // Perform the syscall var syscallResult = _ntProtectVirtualMemoryDelegate(processHandle, baseAddressBuffer, protectionSizeBuffer, newProtectionType, oldProtectionBuffer); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to protect memory in the target process", syscallResult); } // Marshal the returned old protection of the memory region from the buffer var oldProtection = (Enumerations.MemoryProtectionType)Marshal.PtrToStructure <ulong>(oldProtectionBuffer); MemoryTools.FreeMemoryForBuffer(baseAddressBuffer); MemoryTools.FreeMemoryForBuffer(protectionSizeBuffer); MemoryTools.FreeMemoryForBuffer(oldProtectionBuffer); return(oldProtection); }
internal IntPtr Invoke(SafeProcessHandle processHandle, int allocationSize, Enumerations.MemoryProtectionType protectionType) { // Initialise a buffer to store the returned address of the allocated memory region var memoryRegionAddressBuffer = MemoryTools.AllocateMemoryForBuffer(IntPtr.Size); // Store the size of the allocation in a buffer var allocationSizeBuffer = MemoryTools.StoreStructureInBuffer(allocationSize); // Perform the syscall const Enumerations.MemoryAllocationType allocationType = Enumerations.MemoryAllocationType.Commit | Enumerations.MemoryAllocationType.Reserve; var syscallResult = _ntAllocateVirtualMemoryDelegate(processHandle, memoryRegionAddressBuffer, 0, allocationSizeBuffer, allocationType, protectionType); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory in the target process", syscallResult); } // Marshal the returned address of the memory region from the buffer var memoryRegionAddress = Marshal.PtrToStructure <IntPtr>(memoryRegionAddressBuffer); MemoryTools.FreeMemoryForBuffer(memoryRegionAddressBuffer); MemoryTools.FreeMemoryForBuffer(allocationSizeBuffer); return(memoryRegionAddress); }
internal void WriteVirtualMemory <TStructure>(IntPtr baseAddress, TStructure structureToWrite) where TStructure : struct { // Store the structure in a buffer var structureBuffer = MemoryTools.StoreStructureInBuffer(structureToWrite); // Convert the structure into bytes var structureSize = Marshal.SizeOf <TStructure>(); var structureBytes = new byte[structureSize]; Marshal.Copy(structureBuffer, structureBytes, 0, structureSize); // Write the bytes of the structure into the target process WriteVirtualMemory(baseAddress, structureBytes); }
internal IntPtr Invoke(SafeThreadHandle threadHandle) { // Store a context structure in a buffer var context = new Structures.Context { ContextFlags = Enumerations.ContextFlags.Control }; var contextBuffer = MemoryTools.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); }
internal SafeProcessHandle Invoke(int processId) { // Initialise a buffer to store the returned process handle var processHandleBuffer = MemoryTools.AllocateMemoryForBuffer(IntPtr.Size); // Store an empty object attributes structure in a buffer var objectAttributesBuffer = MemoryTools.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 = MemoryTools.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); } // Marshal the returned process handle from the buffer var processHandle = new SafeProcessHandle(Marshal.PtrToStructure <IntPtr>(processHandleBuffer), true); MemoryTools.FreeMemoryForBuffer(processHandleBuffer); MemoryTools.FreeMemoryForBuffer(objectAttributesBuffer); MemoryTools.FreeMemoryForBuffer(clientIdBuffer); return(processHandle); }
internal void Invoke(SafeProcessHandle processHandle, IntPtr baseAddress) { // Store the base address of memory region to free in a buffer var baseAddressBuffer = MemoryTools.StoreStructureInBuffer(baseAddress); // Store the free size in a buffer var freeSizeBuffer = MemoryTools.StoreStructureInBuffer(0); // Perform the syscall var syscallResult = _ntFreeVirtualMemoryDelegate(processHandle, baseAddressBuffer, freeSizeBuffer, Enumerations.MemoryFreeType.Release); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to free memory in the target process", syscallResult); } MemoryTools.FreeMemoryForBuffer(baseAddressBuffer); MemoryTools.FreeMemoryForBuffer(freeSizeBuffer); }
internal bool Call() { // Get the address of the LoadLibraryW function var loadLibraryAddress = _propertyWrapper.TargetProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = _propertyWrapper.MemoryManager.AllocateVirtualMemory(_propertyWrapper.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(_propertyWrapper.DllPath + "\0"); _propertyWrapper.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Open a handle to the first thread in the target process var threadHandle = (SafeThreadHandle)_propertyWrapper.SyscallManager.InvokeSyscall <NtOpenThread>(_propertyWrapper.TargetProcess.Process.Threads[0].Id); if (_propertyWrapper.TargetProcess.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 = MemoryTools.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); // 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 = _propertyWrapper.MemoryManager.AllocateVirtualMemory(shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); _propertyWrapper.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the shellcode buffer threadContext.Eip = (uint)shellcodeBuffer; // Set the context of the thread threadContextBuffer = MemoryTools.StoreStructureInBuffer(threadContext); if (PInvoke.Wow64SetThreadContext(threadHandle, threadContextBuffer) == 0) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the target process"); } MemoryTools.FreeMemoryForBuffer(threadContextBuffer); } else { // Suspend the thread _propertyWrapper.SyscallManager.InvokeSyscall <NtSuspendThread>(threadHandle); // Get the context of the thread var threadContextBuffer = (IntPtr)_propertyWrapper.SyscallManager.InvokeSyscall <NtGetContextThread>(threadHandle); var threadContext = Marshal.PtrToStructure <Structures.Context>(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 = _propertyWrapper.MemoryManager.AllocateVirtualMemory(shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); _propertyWrapper.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the shellcode buffer threadContext.Rip = (ulong)shellcodeBuffer; // Set the context of the thread threadContextBuffer = MemoryTools.StoreStructureInBuffer(threadContext); _propertyWrapper.SyscallManager.InvokeSyscall <NtSetThreadContext>(threadHandle, threadContextBuffer); MemoryTools.FreeMemoryForBuffer(threadContextBuffer); } // Resume the thread _propertyWrapper.SyscallManager.InvokeSyscall <NtResumeThread>(threadHandle); PInvoke.SwitchToThisWindow(_propertyWrapper.TargetProcess.Process.MainWindowHandle, true); threadHandle.Dispose(); return(true); }