internal SafeThreadHandle Invoke(SafeProcessHandle processHandle, IntPtr startAddress, IntPtr parameter) { // Initialise a buffer to store the returned thread handle var threadHandleBuffer = MemoryTools.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); } // Marshal the returned thread handle from the buffer var threadHandle = new SafeThreadHandle(Marshal.PtrToStructure <IntPtr>(threadHandleBuffer), true); MemoryTools.FreeMemoryForBuffer(threadHandleBuffer); return(threadHandle); }
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); }
public void Dispose() { foreach (var shellcodeAddress in _shellcodeAddresses) { // Free the memory allocated for the shellcode MemoryTools.FreeMemoryForBuffer(shellcodeAddress); } }
internal TStructure ReadVirtualMemory <TStructure>(IntPtr baseAddress) where TStructure : struct { // Read the bytes of the structure from the memory region var structureBytes = ReadVirtualMemory(baseAddress, Marshal.SizeOf <TStructure>()); // Marshal the bytes into a structure var structureBytesBuffer = MemoryTools.StoreBytesInBuffer(structureBytes); var structure = Marshal.PtrToStructure <TStructure>(structureBytesBuffer); MemoryTools.FreeMemoryForBuffer(structureBytesBuffer); return(structure); }
internal bool Call() { var localDllBaseAddress = MemoryTools.StoreBytesInBuffer(_propertyWrapper.DllBytes); var peHeaders = _propertyWrapper.PeParser.GetHeaders(); // Build the import table of the DLL in the local process BuildImportTable(localDllBaseAddress); // Allocate memory for the DLL in the target process var dllSize = _propertyWrapper.TargetProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.SizeOfImage : peHeaders.NtHeaders64.OptionalHeader.SizeOfImage; var remoteDllAddress = _propertyWrapper.MemoryManager.AllocateVirtualMemory((int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite); // Perform the needed relocations in the local process PerformRelocations(localDllBaseAddress, remoteDllAddress); // Map the sections of the DLL into the target process MapSections(localDllBaseAddress, remoteDllAddress); // Call any TLS callbacks CallTlsCallbacks(remoteDllAddress); // Call the entry point of the DLL var dllEntryPointAddress = _propertyWrapper.TargetProcess.IsWow64 ? (uint)remoteDllAddress + peHeaders.NtHeaders32.OptionalHeader.AddressOfEntryPoint : (ulong)remoteDllAddress + peHeaders.NtHeaders64.OptionalHeader.AddressOfEntryPoint; if (dllEntryPointAddress != 0) { CallEntryPoint(remoteDllAddress, (IntPtr)dllEntryPointAddress); } MemoryTools.FreeMemoryForBuffer(localDllBaseAddress); return(true); }
internal List <Structures.LdrDataTableEntry32> GetWow64PebEntries() { var pebEntries = new List <Structures.LdrDataTableEntry32>(); // Query the target process for the base address of the WOW64 PEB var pebBaseAddressBuffer = (IntPtr)_syscallManager.InvokeSyscall <NtQueryInformationProcess>(Handle, Enumerations.ProcessInformationClass.Wow64Information); var pebBaseAddress = Marshal.PtrToStructure <ulong>(pebBaseAddressBuffer); // Read the WOW64 PEB of the target process var peb = _memoryManager.ReadVirtualMemory <Structures.Peb32>((IntPtr)pebBaseAddress); // Read the loader data of the WOW64 PEB var pebLoaderData = _memoryManager.ReadVirtualMemory <Structures.PebLdrData32>((IntPtr)peb.Ldr); var currentPebEntry = pebLoaderData.InLoadOrderModuleList.Flink; while (true) { if (currentPebEntry == pebLoaderData.InLoadOrderModuleList.Blink) { break; } // Read the current entry from the InLoadOrder doubly linked list var pebEntry = _memoryManager.ReadVirtualMemory <Structures.LdrDataTableEntry32>((IntPtr)currentPebEntry); pebEntries.Add(pebEntry); // Get the address of the next entry in the InLoadOrder doubly linked list currentPebEntry = pebEntry.InLoadOrderLinks.Flink; } MemoryTools.FreeMemoryForBuffer(pebBaseAddressBuffer); return(pebEntries); }
internal void WriteVirtualMemory(IntPtr baseAddress, byte[] bytesToWrite) { // Store the bytes to write in a buffer var bytesBuffer = MemoryTools.StoreBytesInBuffer(bytesToWrite); // Adjust the protection of the memory region to ensure it has write privileges var oldProtectionType = ProtectVirtualMemory(baseAddress, bytesToWrite.Length, Enumerations.MemoryProtectionType.ReadWrite); // Write the bytes into the memory region _syscallManager.InvokeSyscall <NtWriteVirtualMemory>(_processHandle, baseAddress, bytesBuffer, bytesToWrite.Length); // Restore the protection of the memory region ProtectVirtualMemory(baseAddress, bytesToWrite.Length, oldProtectionType); MemoryTools.FreeMemoryForBuffer(bytesBuffer); }
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 byte[] ReadVirtualMemory(IntPtr baseAddress, int bytesToRead) { // Adjust the protection of the memory region to ensure it has read privileges var oldProtectionType = ProtectVirtualMemory(baseAddress, bytesToRead, Enumerations.MemoryProtectionType.ReadWrite); // Read the specified number of bytes from the memory region var bytesReadBuffer = (IntPtr)_syscallManager.InvokeSyscall <NtReadVirtualMemory>(_processHandle, baseAddress, bytesToRead); var bytesRead = new byte[bytesToRead]; Marshal.Copy(bytesReadBuffer, bytesRead, 0, bytesToRead); // Restore the protection of the memory region ProtectVirtualMemory(baseAddress, bytesToRead, oldProtectionType); MemoryTools.FreeMemoryForBuffer(bytesReadBuffer); return(bytesRead); }
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); }
public void Dispose() { MemoryTools.FreeMemoryForBuffer(_dllBuffer); }
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); }