Skip to content

Instantly share code, notes, and snippets.

@ricardojoserf
Last active January 15, 2025 08:26
Show Gist options
  • Select an option

  • Save ricardojoserf/6f0a63c4d94b66adfad6fa6dc784fc1a to your computer and use it in GitHub Desktop.

Select an option

Save ricardojoserf/6f0a63c4d94b66adfad6fa6dc784fc1a to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
class NtOpenFileExample
{
// Import NtOpenFile from ntdll.dll
[DllImport("ntdll.dll")]
private static extern int NtOpenFile(
out IntPtr FileHandle,
uint DesiredAccess,
ref OBJECT_ATTRIBUTES ObjectAttributes,
out IO_STATUS_BLOCK IoStatusBlock,
uint ShareAccess,
uint OpenOptions);
// UNICODE_STRING structure
[StructLayout(LayoutKind.Sequential)]
struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
public IntPtr Buffer;
}
// OBJECT_ATTRIBUTES structure
[StructLayout(LayoutKind.Sequential)]
struct OBJECT_ATTRIBUTES
{
public int Length;
public IntPtr RootDirectory;
public IntPtr ObjectName; // UNICODE_STRING*
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
// IO_STATUS_BLOCK structure
[StructLayout(LayoutKind.Sequential)]
struct IO_STATUS_BLOCK
{
public IntPtr Status;
public ulong Information;
}
static void Main()
{
string filePath = @"\??\C:\Windows\System32\wdigest.dll";
IntPtr fileHandle;
// Initialize UNICODE_STRING
UNICODE_STRING unicodeString = new UNICODE_STRING();
unicodeString.Length = (ushort)(filePath.Length * 2);
unicodeString.MaximumLength = (ushort)((filePath.Length + 1) * 2);
unicodeString.Buffer = Marshal.StringToHGlobalUni(filePath);
try
{
// Set up OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES objectAttributes = new OBJECT_ATTRIBUTES();
objectAttributes.Length = Marshal.SizeOf<OBJECT_ATTRIBUTES>();
objectAttributes.RootDirectory = IntPtr.Zero;
objectAttributes.ObjectName = Marshal.AllocHGlobal(Marshal.SizeOf<UNICODE_STRING>());
Marshal.StructureToPtr(unicodeString, objectAttributes.ObjectName, false);
objectAttributes.Attributes = 0x00000040; // OBJ_CASE_INSENSITIVE
objectAttributes.SecurityDescriptor = IntPtr.Zero;
objectAttributes.SecurityQualityOfService = IntPtr.Zero;
// IO_STATUS_BLOCK
IO_STATUS_BLOCK ioStatusBlock;
// Call NtOpenFile
int status = NtOpenFile(
out fileHandle,
0x80000000, // GENERIC_READ
ref objectAttributes,
out ioStatusBlock,
1, // FILE_SHARE_READ
0x00000000); // FILE_OPEN
if (status != 0) // STATUS_SUCCESS is 0
{
Console.WriteLine($"Failed to open file. NTSTATUS: 0x{status:X8}");
}
else
{
Console.WriteLine($"File handle: {fileHandle}");
}
}
finally
{
Marshal.FreeHGlobal(unicodeString.Buffer);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment