using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public class NtFileApi
{
    // NTSTATUS values
    private const uint STATUS_SUCCESS = 0x00000000;

    // File Access Rights
    [Flags]
    public enum FileAccess : uint
    {
        GENERIC_READ = 0x80000000,
        GENERIC_WRITE = 0x40000000,
        GENERIC_EXECUTE = 0x20000000,
        GENERIC_ALL = 0x10000000,
        // ... other specific rights
    }

    // File Attributes
    [Flags]
    public enum FileAttributes : uint
    {
        FILE_ATTRIBUTE_NORMAL = 0x80,
        // ... other attributes
    }

    // Share Access
    [Flags]
    public enum ShareMode : uint
    {
        FILE_SHARE_READ = 0x00000001,
        FILE_SHARE_WRITE = 0x00000002,
        FILE_SHARE_DELETE = 0x00000004,
    }

    // Creation Disposition
    public enum CreationDisposition : uint
    {
        FILE_OPEN = 3,
        FILE_CREATE = 2,
        FILE_OPEN_IF = 4,
        // ... other options
    }

    // Create Options
    [Flags]
    public enum CreateOptions : uint
    {
        FILE_NON_DIRECTORY_FILE = 0x00000040,
        FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020,
        // ... other options
    }

    // I/O Status Block structure
    [StructLayout(LayoutKind.Sequential)]
    public struct IO_STATUS_BLOCK
    {
        public IntPtr Status;
        public IntPtr Information;
    }

    // Object Attributes structure
    [StructLayout(LayoutKind.Sequential)]
    public struct OBJECT_ATTRIBUTES : IDisposable
    {
        public int Length;
        public IntPtr RootDirectory;
        public IntPtr ObjectName; // Pointer to UNICODE_STRING
        public uint Attributes;
        public IntPtr SecurityDescriptor;
        public IntPtr SecurityQualityOfService;

        public OBJECT_ATTRIBUTES(string name, AttributeFlags attrs)
        {
            Length = 0;
            RootDirectory = IntPtr.Zero;
            ObjectName = IntPtr.Zero;
            Attributes = (uint)attrs;
            SecurityDescriptor = IntPtr.Zero;
            SecurityQualityOfService = IntPtr.Zero;

            Length = Marshal.SizeOf(this);
            SetObjectName(name);
        }

        public void SetObjectName(string name)
        {
            if (name != null)
            {
                var unicodeString = new UNICODE_STRING(name);
                ObjectName = Marshal.AllocHGlobal(Marshal.SizeOf(unicodeString));
                Marshal.StructureToPtr(unicodeString, ObjectName, false);
            }
            else
            {
                ObjectName = IntPtr.Zero;
            }
        }

        public void Dispose()
        {
            if (ObjectName != IntPtr.Zero)
            {
                var unicodeString = Marshal.PtrToStructure<UNICODE_STRING>(ObjectName);
                unicodeString.Dispose();
                Marshal.FreeHGlobal(ObjectName);
                ObjectName = IntPtr.Zero;
            }
        }
    }

    // Attribute Flags for OBJECT_ATTRIBUTES
    [Flags]
    public enum AttributeFlags : uint
    {
        OBJ_CASE_INSENSITIVE = 0x00000040,
        OBJ_KERNEL_HANDLE = 0x00000200,
        // ... other flags
    }

    // UNICODE_STRING structure
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct UNICODE_STRING : IDisposable
    {
        public ushort Length;
        public ushort MaximumLength;
        private IntPtr Buffer;

        public UNICODE_STRING(string text)
        {
            if (text != null)
            {
                Length = (ushort)(text.Length * 2);
                MaximumLength = (ushort)((text.Length * 2) + 2);
                Buffer = Marshal.StringToHGlobalUni(text);
            }
            else
            {
                Length = 0;
                MaximumLength = 0;
                Buffer = IntPtr.Zero;
            }
        }

        public void Dispose()
        {
            if (Buffer != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(Buffer);
                Buffer = IntPtr.Zero;
            }
        }

        public override string ToString()
        {
            return Buffer != IntPtr.Zero ? Marshal.PtrToStringUni(Buffer, Length / 2) : null;
        }
    }

    // NtCreateFile function
    [DllImport("ntdll.dll", CharSet = CharSet.Unicode)]
    private static extern uint NtCreateFile(
        out SafeFileHandle FileHandle,
        FileAccess DesiredAccess,
        ref OBJECT_ATTRIBUTES ObjectAttributes,
        out IO_STATUS_BLOCK IoStatusBlock,
        IntPtr AllocationSize,
        FileAttributes FileAttributes,
        ShareMode ShareAccess,
        CreationDisposition CreateDisposition,
        CreateOptions CreateOptions,
        IntPtr EaBuffer,
        uint EaLength);

    public static SafeFileHandle NativeCreateFile(
        string filePath,
        FileAccess desiredAccess,
        ShareMode shareMode,
        CreationDisposition creationDisposition,
        CreateOptions createOptions)
    {
        // Initialize object attributes
        var objectAttributes = new OBJECT_ATTRIBUTES(
            filePath,
            AttributeFlags.OBJ_CASE_INSENSITIVE
        );

        // Initialize I/O status block
        var ioStatusBlock = new IO_STATUS_BLOCK();

        // Call NtCreateFile
        uint status = NtCreateFile(
            out SafeFileHandle fileHandle,
            desiredAccess,
            ref objectAttributes,
            out ioStatusBlock,
            IntPtr.Zero,
            FileAttributes.FILE_ATTRIBUTE_NORMAL,
            shareMode,
            creationDisposition,
            createOptions,
            IntPtr.Zero,
            0
        );

        // Cleanup object attributes
        objectAttributes.Dispose();

        // Check status
        if (status != STATUS_SUCCESS)
        {
            throw new Win32Exception($"NTSTATUS: 0x{status:X8}");
        }

        return fileHandle;
    }
}

// Usage Example
public class Program
{
    
    static void TestVhdxNative(string exedir)
    {
        string exedirraw = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        
        string vhd_path_sourceraw = @"\Device\Mup"+ exedir.Replace(@"\\",@"\")+ @"testsource.vhdx";
        Console.WriteLine(vhd_path_sourceraw);
        ulong DefaultDiskSizeNext = 0x800000 * 4;
        using (SafeFileHandle handle = Kernel32.NativeCreateFile(vhd_path_sourceraw, FileAccess.Read|FileAccess.Write,ShareMode.Read|ShareMode.Write,CreationDisposition.FILE_OPEN_IF,CreateOptions.FILE_NON_DIRECTORY_FILE))
        {
            Console.WriteLine("[INFO]: CreateVHD {0}", vhd_path_sourceraw);

        }
    }
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐