Я пытаюсь закодировать простую функцию чтения NTFS для расширенных атрибутов (а не альтернативных потоков данных!) В C#. Он будет использоваться в некоторых сценариях powershell позже, поэтому мне нужно стричь с C#.Pinvoke NtOpenFile и NtQueryEaFile, чтобы читать расширенные атрибуты NTFS в C#
До сих пор я не собрал некоторые Infos о NtOpenFile:
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct OBJECT_ATTRIBUTES
{
public Int32 Length;
public IntPtr RootDirectory;
public IntPtr ObjectName;
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct IO_STATUS_BLOCK
{
public uint status;
public IntPtr information;
}
[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern int NtOpenFile(
out IntPtr handle,
System.IO.FileAccess access,
ref OBJECT_ATTRIBUTES objectAttributes,
out IO_STATUS_BLOCK ioStatus,
System.IO.FileShare share,
uint openOptions
);
, но до сих пор нет Infos на NtQueryEaFile и нет демо-кода, чтобы вызвать его и Маршалл своих результаты, спасибо за вашу помощь!
EDIT1 Получение немного дальше с этим новым кодом, но все еще застряли в какой-то момент с «Access Denied» после вызова NtQueryEaFile. Есть идеи ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using HANDLE = System.IntPtr;
namespace ConsoleApplication1
{
class Program
{
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct OBJECT_ATTRIBUTES
{
public Int32 Length;
public IntPtr RootDirectory;
public IntPtr ObjectName;
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct IO_STATUS_BLOCK
{
public uint status;
public IntPtr information;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
public IntPtr Buffer;
}
[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern uint NtOpenFile(
out IntPtr handle,
System.IO.FileAccess access,
ref OBJECT_ATTRIBUTES objectAttributes,
out IO_STATUS_BLOCK ioStatus,
System.IO.FileShare share,
uint openOptions
);
[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern uint NtQueryEaFile(
IntPtr handle,
out IO_STATUS_BLOCK ioStatus,
out IntPtr buffer,
uint length,
bool retSingleEntry,
IntPtr eaList,
uint eaListLength,
IntPtr eaIndex,
bool restartScan
);
[DllImport("ntdll.dll")]
public static extern void RtlInitUnicodeString(
out UNICODE_STRING DestinationString,
[MarshalAs(UnmanagedType.LPWStr)] string SourceString);
[DllImport("ntdll.dll")]
public static extern uint RtlNtStatusToDosError(uint Status);
[DllImport("kernel32.dll")]
public static extern uint FormatMessage(int dwFlags, IntPtr lpSource, uint dwMessageId,
int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr Arguments);
static void Main(string[] args)
{
UInt32 FILE_OPEN = 0x1;
UInt32 OBJ_CASE_INSENSITIVE = 0x40;
UInt32 FILE_READ_EA = 8;
UInt32 FILE_RANDOM_ACCESS = 0x00000800;
UInt32 FILE_DIRECTORY_FILE = 0x00000002;
UInt32 FILE_NON_DIRECTORY_FILE = 0x00000040;
UInt32 FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000;
uint NT_SUCCESS = 0x0;
bool restartScan = false;
bool returnSingleEntry = false;
IntPtr _RootHandle; //This will need to be initialized with the root handle, can use CreateFile from kernel32.dll
_RootHandle = IntPtr.Zero;
UNICODE_STRING unicodeString;
RtlInitUnicodeString(out unicodeString, @"\??\C:\temp");
IntPtr unicodeIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(unicodeString));
Marshal.StructureToPtr(unicodeString, unicodeIntPtr, false);
OBJECT_ATTRIBUTES objAttributes = new OBJECT_ATTRIBUTES();
IO_STATUS_BLOCK ioStatusBlock = new IO_STATUS_BLOCK();
//Microsoft.Win32.SafeHandles.SafeFileHandle hFile;
HANDLE hFile;
objAttributes.Length = System.Convert.ToInt32(Marshal.SizeOf(objAttributes));
objAttributes.ObjectName = unicodeIntPtr;
objAttributes.RootDirectory = _RootHandle;
objAttributes.Attributes = OBJ_CASE_INSENSITIVE;
objAttributes.SecurityDescriptor = IntPtr.Zero;
objAttributes.SecurityQualityOfService = IntPtr.Zero;
uint status = NtOpenFile(out hFile, FileAccess.Read, ref objAttributes, out ioStatusBlock, FileShare.Read, FILE_DIRECTORY_FILE | FILE_READ_EA | FILE_OPEN_FOR_BACKUP_INTENT);
if (status != NT_SUCCESS)
ExitWithError(status);
IntPtr buffer = Marshal.AllocHGlobal(65535);
status = NtQueryEaFile(hFile, out ioStatusBlock, out buffer, System.Convert.ToUInt32(Marshal.SizeOf(buffer)), returnSingleEntry, IntPtr.Zero, 0, IntPtr.Zero, restartScan);
if (status != NT_SUCCESS)
ExitWithError(status);
}
public static void ExitWithError(uint errorCode)
{
Console.WriteLine(GetSystemMessage(RtlNtStatusToDosError(errorCode)));
Environment.Exit(1);
}
public static string GetSystemMessage(uint errorCode)
{
int capacity = 512;
int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
StringBuilder sb = new StringBuilder(capacity);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errorCode, 0,
sb, sb.Capacity, IntPtr.Zero);
int i = sb.Length;
if (i > 0 && sb[i - 1] == 10) i--;
if (i > 0 && sb[i - 1] == 13) i--;
sb.Length = i;
return sb.ToString();
}
}
}
EDIT2 Рассмотрев этот код: http://jbutera.net/mirror/git/alexpux/Cygwin/winsup/cygwin/ntea.cc я модифицирована мину со следующим:
NtOpenFile Сейчас:
[DllImport("ntdll.dll", ExactSpelling = true)]
public static extern uint NtOpenFile(
out SafeFileHandle handle,
UInt32 access,
ref OBJECT_ATTRIBUTES objectAttributes,
out IO_STATUS_BLOCK ioStatus,
System.IO.FileShare share,
uint openOptions
);
NtQueryEaFile Сейчас:
[DllImport("ntdll.dll", ExactSpelling = true)]
public static extern uint NtQueryEaFile(
SafeFileHandle handle,
out IO_STATUS_BLOCK ioStatus,
out IntPtr buffer,
uint length,
bool retSingleEntry,
IntPtr eaList,
uint eaListLength,
IntPtr eaIndex,
bool restartScan
);
Вызов NtOpenFile в настоящее время:
UInt32 FILE_OPEN = 0x1;
UInt32 OBJ_CASE_INSENSITIVE = 0x40;
UInt32 FILE_READ_EA = 8;
UInt32 FILE_RANDOM_ACCESS = 0x00000800;
UInt32 FILE_DIRECTORY_FILE = 0x00000002;
UInt32 FILE_NON_DIRECTORY_FILE = 0x00000040;
UInt32 FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000;
UInt32 READ_CONTROL = 0x00020000;
const UInt32 STATUS_NO_EAS_ON_FILE = 0xC0000052;
uint status = NtOpenFile(out hFile, READ_CONTROL | FILE_READ_EA, ref objAttributes, out ioStatusBlock, FileShare.ReadWrite | FileShare.Delete, FILE_OPEN_FOR_BACKUP_INTENT);
if (status != NT_SUCCESS)
ExitWithError(status);
IntPtr buffer = Marshal.AllocHGlobal(65535);
// status = NtQueryEaFile(fileHandle, &ioStatus, qbuf, sizeof(FILE_FULL_EA_INFORMATION), TRUE, NULL, 0, &QueryEAIndex, FALSE);
status = NtQueryEaFile(hFile, out ioStatusBlock,out buffer, System.Convert.ToUInt32(Marshal.SizeOf(buffer)), returnSingleEntry, IntPtr.Zero, 0, IntPtr.Zero, restartScan);
switch (status)
{
case STATUS_NO_EAS_ON_FILE:
Console.WriteLine("No EAs found");
break;
case NT_SUCCESS:
Console.WriteLine("EAs found !");
break;
default:
ExitWithError(status);
break;
}
И угадайте, что? Работает ! Ну .. Почти ... Чтение каталога без EAs правильно выбрасывает STATUS_NO_EAS_ON_FILE. Но чтение каталога с ЭА бросает STATUS_BUFFER_TOO_SMALL (согласно http://msdn.microsoft.com/fr-fr/library/cc704588.aspx), так что я на самом деле есть некоторые PBR с моим буферном определение/распределение: -/
Мой совет получить работающий C++ код и начать оттуда. Тогда у вас есть что-то известное, чтобы работать, и все, что остается, это вмешательство. Зачем использовать Pack = 0? Что заставило вас использовать SetLastError = true? –
Я могу сказать вам, что второй буфер param не так. Это не параметр «out». Это буфер, который вы выделяете. Поэтому '[Out] byte []' будет хорошим вариантом. В любом случае, поскольку это недокументированная функция, нам трудно понять, что правильно или неправильно. Вы уверены, что вам нужно использовать недокументированную apis? –
Для использования Pack = 0 (значение по умолчанию равно 0 в любом случае afaik) и SetLastError, оно исходит из этого примера https://easyhook.codeplex.com/discussions/468770 – Usul