gpt4 book ai didi

delphi - 如何调用 NtOpenFile?

转载 作者:行者123 更新时间:2023-12-04 01:03:50 25 4
gpt4 key购买 nike

我正在尝试调用 NtOpenFile ,并且失败并出现错误:

STATUS_OBJECT_PATH_SYNTAX_BAD = NTSTATUS($C000003B);

Object Path Component was not a directory object.


基本要点是:
//The file we'll test with
filename: UnicodeString := 'C:\Windows\Explorer.exe'; //23 characters

//Convert the filename to counted UNICODE_STRING
cs: UNICODE_STRING;
cs.Length := Length(filename) * sizeof(WideChar); //46 bytes
cs.MaximumLength := cs.Length + 2; //48 bytes
cs.Buffer := PWideChar(Filename); //"C:\Windows\Explorer.exe"

//Define the OBJECT_ATTRIBUTES
oa: OBJECT_ATTRIBUTES := Default(OBJECT_ATTRIBUTES);
oa.Length := sizeof(OBJECT_ATTRIBUTES); //24 bytes
oa.Attributes := OBJ_CASE_INSENSITIVE;
oa.ObjectName := @cs; //UNICODE_STRING

//Open the file (by Object Attributes) and get a file handle
hFile: THandle;
iosb: IO_STATUS_BLOCK;

status: NTSTATUS := NtOpenFile(@hFile, FILE_READ_ATTRIBUTES, @oa, @iosb, FILE_SHARE_READ, 0);
我究竟做错了什么?
基本要点(C# 风格的伪代码)
//The file we'll test with
UnicodeString filename = "C:\Windows\Explorer.exe"; //23 characters

//Convert the filename to counted UNICODE_STRING
UNICODE_STRING cs;
cs.Length = Length(filename) * sizeof(WideChar); //46 bytes
cs.MaximumLength = cs.Length + 2; //48 bytes
cs.Buffer = Filename; //"C:\Windows\Explorer.exe"

//Define the OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES oa = Default(OBJECT_ATTRIBUTES);
oa.Length = sizeof(OBJECT_ATTRIBUTES); //24 bytes
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.ObjectName = cs; //UNICODE_STRING

//Open the file (by Object Attributes) and get a file handle
THandle hFile;
IO_STATUS_BLOCK iosb;

NTSTATUS status = NtOpenFile(out hFile, FILE_READ_ATTRIBUTES, ref oa, out iosb, FILE_SHARE_READ, 0);
其他样式的文件名


文件名
结果
描述

"C:\Windows\Explorer.exe" STATUS_OBJECT_PATH_SYNTAX_BAD对象路径组件不是目录对象。
"\global??\C:\Windows\Explorer.exe"0xC0000033
对象名称无效
"\??\C:\Windows\Explorer.exe"0xC0000033
对象名称无效

OBJECT_ATTRIBUTES 原始内存转储
因为可能存在内存布局、对齐、填充和缺少成员的问题,让我们转储原始 oa内存:
18 00 00 00                 ;Length. 0x00000018 = 24 bytes (sizeof)
00 00 00 00 ;RootDirectory. 0x00000000 = NULL
28 FF 19 00 ;ObjectName. PUNICODE_STRING 0x0019FF28
40 00 00 00 ;Attributes. (0x00000040 = OBJ_CASE_INSENSITIVE)
00 00 00 00 ;SecurityDescriptor 0x0000000 = NULL
00 00 00 00 ;SecurityQualityOfService 0x00000000 = NULL

**0x0019FF28:**

3C FF 19 00 ;PUNICODE_STRING 0x0019FF3C

**0x0019FF3C**

36 00 ; String length in bytes 0x0036
38 00 ; Buffer size in bytes 0x0038
E8 B6 4E 00 ; PWideChar 0x004EB6E8 ==> "C:\Windows\Explorer.exe"
其中,现在我看到了我的问题:PUNICODE_STRING -> PUNICODE_STRING。
CMRE
program NtOpenFileDemo;

{$APPTYPE CONSOLE}

{$R *.res}
{$ALIGN 8}
{$MINENUMSIZE 4}

uses
SysUtils, Windows, ComObj;

type
NTSTATUS = Cardinal;
const
STATUS_SUCCESS = 0;

type
UNICODE_STRING = packed record
Length: Word; // Length of the string, in bytes (not including the null terminator)
MaximumLength: Word; // Size of the buffer, in bytes
Buffer: PWideChar; //really a PWideChar
end;
PUNICODE_STRING = ^UNICODE_STRING;

type
IO_STATUS_BLOCK = packed record
Status: NTSTATUS;
Information: Pointer;
end;
PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;


OBJECT_ATTRIBUTES = packed record
Length: Cardinal;
RootDirectory: THandle;
ObjectName: PUNICODE_STRING;
Attributes: Cardinal;
SecurityDescriptor: Pointer;
SecurityQualityOfService: Pointer;
end;
POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES;

const
// Define share access rights to files and directories
FILE_SHARE_READ = $00000001;
FILE_SHARE_WRITE = $00000002;
FILE_SHARE_DELETE = $00000004;
FILE_SHARE_VALID_FLAGS = $00000007;


// Valid values for the Attributes field
const
OBJ_INHERIT = $00000002;
OBJ_PERMANENT = $00000010;
OBJ_EXCLUSIVE = $00000020;
OBJ_CASE_INSENSITIVE = $00000040;
OBJ_OPENIF = $00000080;
OBJ_OPENLINK = $00000100;
OBJ_KERNEL_HANDLE = $00000200;
OBJ_VALID_ATTRIBUTES = $000003F2;


function NtOpenFile(FileHandle: PHandle; DesiredAccess: ACCESS_MASK; ObjectAttributes: POBJECT_ATTRIBUTES;
IoStatusBlock: PIO_STATUS_BLOCK; ShareAccess: DWORD; OpenOptions: DWORD): NTSTATUS; stdcall; external 'ntdll.dll';

function NtClose(Handle: THandle): NTSTATUS; stdcall; external 'ntdll.dll';


function FormatNTStatusMessage(const NTStatusMessage: NTSTATUS): string;
var
Buffer: PChar;
Len: Integer;
hMod: HMODULE;

function MAKELANGID(p, s: WORD): WORD;
begin
Result := WORD(s shl 10) or p;
end;
begin
{
KB259693: How to translate NTSTATUS error codes to message strings
Let the OS initialize the Buffer variable. Need to LocalFree it afterward.
}
hMod := SafeLoadLibrary('ntdll.dll');

Len := FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER or
FORMAT_MESSAGE_FROM_SYSTEM or
// FORMAT_MESSAGE_IGNORE_INSERTS or
// FORMAT_MESSAGE_ARGUMENT_ARRAY or
FORMAT_MESSAGE_FROM_HMODULE,
Pointer(hMod),
NTStatusMessage,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
@Buffer, 0, nil);
try
//Remove the undesired line breaks and '.' char
while (Len > 0) and (CharInSet(Buffer[Len - 1], [#0..#32, '.'])) do Dec(Len);
//Convert to Delphi string
SetString(Result, Buffer, Len);
finally
//Free the OS allocated memory block
LocalFree(HLOCAL(Buffer));
end;
FreeLibrary(hMod);
end;


procedure TestCase;
var
filename: UnicodeString;
cs: PUNICODE_STRING;
hFile: THandle;
oa: OBJECT_ATTRIBUTES;
iosb: IO_STATUS_BLOCK;
status: NTSTATUS;
begin
filename := 'C:\Windows\Explorer.exe'; //23 characters

{
Convert the filename to an "Object Attributes" structure

OBJECT_ATTRIBUTES.Length <-- 24
OBJECT_ATTRIBUTES.Attributes <-- OBJ_CASE_INSENSITIVE
OBJECT_ATTRIBUTES.ObjectName.Length <-- 46
OBJECT_ATTRIBUTES.ObjectName.MaximumLength <-- 48
OBJECT_ATTRIBUTES.ObjectName.Buffer <-- "C:\Windows\Explorer.exe"
}
cs.Length := Length(Filename) * sizeof(WideChar);
cs.MaximumLength := cs.Length + 2; //the null terminator
cs.Buffer := PWideChar(Filename);

oa := Default(OBJECT_ATTRIBUTES);
oa.Length := sizeof(OBJECT_ATTRIBUTES);
oa.Attributes := OBJ_CASE_INSENSITIVE;
oa.ObjectName := @cs;

//Open the file (by Object Attributes) and get a file handle
status := NtOpenFile(@hFile, FILE_READ_ATTRIBUTES, @oa, @iosb, FILE_SHARE_READ, 0);
if status <> STATUS_SUCCESS then
begin
WriteLn('Error opening file "'+Filename+'": '+FormatNTStatusMessage(status)+' (0x'+IntToHex(status, 8)+')');
Exit;
end;
try
WriteLn('Successfully opened file');
finally
NtClose(hFile);
end;
end;



begin
try
TestCase;
WriteLn('Press enter to close...');
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
奖金阅读
  • MSDN:RtlInitUnicodeString
  • MSDN:NtOpenFile function
  • 技术网:How to open a file from a kernel mode device driver and how to read from or write to the file archive
  • MSDN:InitializeObjectAttributes macro
  • MSDN:OBJECT_ATTRIBUTES structure
  • 谷歌零项目:The Definitive Guide on Win32 to NT Path Conversion archive
  • 最佳答案

    找到了。
    两件事情:

  • 我不知道“NT 路径”与“DOS 路径”不同
  • "C:\Windows\Notepad.exe""\??\C:\Windows\Notepad.exe"
  • OBJECT_ATTRIBUTES.ObjectName我正在分配 @PUNICODE_STRING ,而不是 @UNICODE_STRING

  • 用例 - 使用文件的进程
    我正在使用 NtOpenFile 为了获取正在使用文件的进程 ID。
    简短的版本是:
  • 调用 NtOpenFile 打开您感兴趣的文件
  • 调用 NtQueryInformationFile FileProcessIdsUsingFileInformation常数
  • 迭代每个返回的进程 ID (pid)
  • 调用 OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid) 获取进程名称
  • function GetProcessIDsUsingFile(Filename: UnicodeString; out ProcessIDs: array of DWORD): string;
    var
    hFile: THandle;
    oa: OBJECT_ATTRIBUTES;
    iosb: TIOStatusBlock;
    status: NTSTATUS;
    fi: FILE_PROCESS_IDS_USING_FILE_INFORMATION;
    i: Integer;
    pid: DWORD;
    hProcess: THandle;
    s: string;
    dw: DWORD;
    cs: UNICODE_STRING;
    ntFilename: UnicodeString;
    const
    PROCESS_QUERY_LIMITED_INFORMATION = $1000;
    begin
    Result := '';

    (*
    Decription

    Get list of processes that are using a file.

    Sample usage

    GetProcessIDsUsingFile('C:\Windows\Notepad.exe', {out}pids);

    Returns

    Result: a text description of the processes using the file

    "PID:12345 (Explorer.exe)"

    ProcessIDs: an array of process IDs (PIDs)

    [12345]
    *)


    ntFilename := Filename;
    {
    Convert the "DOS path" into an "NT Path". NT Paths are not the same as DOS paths.

    DOS Path: C:\Windows\Explorer.exe
    NT Path: \??\C:\Windows\Explorer.exe

    The short version is:

    \DosDevices is a symbolic link for \??
    \?? is a special value understood by the object manager's parser to mean the global \DosDevices directory
    \GLOBAL?? is a folder that is home to global device.

    And in the end all 3 (eventually) end up in the same place.

    But you want to use "??" rather than "\GLOBAL??" because the former understands per-user (i.e. local) drive mappings.

    Bonus Reading:
    - Google Project Zero: The Definitive Guide on Win32 to NT Path Conversion (Google Project Zero)
    https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
    - Google Project Zero: Windows Drivers are True’ly Tricky
    https://googleprojectzero.blogspot.com/2015/10/windows-drivers-are-truely-tricky.html
    - Nynaeve: The kernel object namespace and Win32, part 3
    http://www.nynaeve.net/?p=92

    Apparently you can also use some undocumented functions (exported by name) to convert a DOS path to an NT path; there are like 7 variations

    - RtlGetFullPathName_U
    - RtlDosPathNameToRelativeNtPathName_U
    - RtlDosPathNameToNtPathName_U_WithStatus

    But i'll just prefix it with "\??\"
    }
    if Copy(ntFilename, 1, 4) <> '\??\' then
    ntFilename := '\??\'+Filename;

    {
    Convert the filename to an "Object Attributes" structure

    OBJECT_ATTRIBUTES.Length <-- 24
    OBJECT_ATTRIBUTES.Attributes <-- OBJ_CASE_INSENSITIVE
    OBJECT_ATTRIBUTES.ObjectName.Length <-- 46
    OBJECT_ATTRIBUTES.ObjectName.MaximumLength <-- 48
    OBJECT_ATTRIBUTES.ObjectName.Buffer <-- "C:\Windows\Explorer.exe"
    }
    cs.Length := Length(ntFilename) * sizeof(WideChar);
    cs.MaximumLength := cs.Length + 2; //the null terminator
    cs.Buffer := PWideChar(ntFilename);

    oa := Default(OBJECT_ATTRIBUTES);
    oa.Length := sizeof(OBJECT_ATTRIBUTES);
    oa.Attributes := OBJ_CASE_INSENSITIVE;
    oa.ObjectName := @cs;

    //Open the file (by Object Attributes) and get a file handle
    status := NtOpenFile(@hFile, FILE_READ_ATTRIBUTES, @oa, @iosb, FILE_SHARE_READ, 0);
    if status <> STATUS_SUCCESS then
    raise EOleSysError.Create('Error opening file "'+Filename+'": '+FormatNTStatusMessage(status)+' (0x'+IntToHex(status, 8)+')', status, 0);
    try
    //Query for information about the file (by handle)
    status := NtQueryInformationFile(hFile, @iosb, @fi, sizeof(fi), FileProcessIdsUsingFileInformation);
    if status <> STATUS_SUCCESS then
    raise EOleSysError.Create('Error querying file "'+Filename+'" information: '+FormatNTStatusMessage(status), status, 0);

    for i := 0 to fi.NumberOfProcessIdsInList-1 do
    begin
    pid := fi.ProcessIdList[i];

    if Result <> '' then
    Result := Result+#13#10;
    Result := Result+'PID: '+IntToStr(pid);

    hProcess := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid);
    if hProcess = 0 then
    RaiseLastOSError;
    try
    SetLength(s, 32767);
    dw := GetModuleFileNameEx(hProcess, 0, PChar(s), Length(s));
    if dw <= 0 then
    RaiseLastOSError;
    SetLength(s, dw); //returns characters (not including null terminator)
    Result := Result+' ('+s+')';
    finally
    CloseHandle(hProcess);
    end;
    end;
    finally
    NtClose(hFile);
    end;

    end;

    关于delphi - 如何调用 NtOpenFile?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67187979/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com