Skip to content

Commit

Permalink
Add hook for NtQueryInformationFile.
Browse files Browse the repository at this point in the history
  • Loading branch information
Holt59 committed Jun 15, 2024
1 parent 576be4d commit a9ce2c4
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 38 deletions.
4 changes: 4 additions & 0 deletions src/shared/ntdll_declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ NtQueryDirectoryFile_type NtQueryDirectoryFile;
NtQueryDirectoryFileEx_type NtQueryDirectoryFileEx;
NtQueryFullAttributesFile_type NtQueryFullAttributesFile;
NtQueryAttributesFile_type NtQueryAttributesFile;
NtQueryObject_type NtQueryObject;
NtQueryInformationFile_type NtQueryInformationFile;
NtOpenFile_type NtOpenFile;
NtCreateFile_type NtCreateFile;
NtClose_type NtClose;
Expand All @@ -46,6 +48,8 @@ void ntdll_declarations_init() {
LOAD_EXT(ntDLLMod, NtQueryDirectoryFileEx);
LOAD_EXT(ntDLLMod, NtQueryFullAttributesFile);
LOAD_EXT(ntDLLMod, NtQueryAttributesFile);
LOAD_EXT(ntDLLMod, NtQueryObject);
LOAD_EXT(ntDLLMod, NtQueryInformationFile);
LOAD_EXT(ntDLLMod, NtCreateFile);
LOAD_EXT(ntDLLMod, NtOpenFile);
LOAD_EXT(ntDLLMod, NtClose);
Expand Down
136 changes: 106 additions & 30 deletions src/shared/ntdll_declarations.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,80 @@ typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
WCHAR FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;

typedef struct _FILE_BASIC_INFORMATION
{
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
ULONG FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

typedef struct _FILE_STANDARD_INFORMATION
{
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG NumberOfLinks;
BOOLEAN DeletePending;
BOOLEAN Directory;
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;

typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;

typedef struct _FILE_INTERNAL_INFORMATION
{
LARGE_INTEGER IndexNumber;
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;

typedef struct _FILE_EA_INFORMATION
{
ULONG EaSize;
} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;

typedef struct _FILE_ACCESS_INFORMATION
{
ACCESS_MASK AccessFlags;
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;

typedef struct _FILE_POSITION_INFORMATION
{
LARGE_INTEGER CurrentByteOffset;
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;

typedef struct _FILE_MODE_INFORMATION
{
ULONG Mode;
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;

typedef struct _FILE_ALIGNMENT_INFORMATION
{
ULONG AlignmentRequirement;
} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;

typedef struct _FILE_NAME_INFORMATION
{
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;

typedef struct _FILE_ALL_INFORMATION
{
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
FILE_INTERNAL_INFORMATION InternalInformation;
FILE_EA_INFORMATION EaInformation;
FILE_ACCESS_INFORMATION AccessInformation;
FILE_POSITION_INFORMATION PositionInformation;
FILE_MODE_INFORMATION ModeInformation;
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
FILE_NAME_INFORMATION NameInformation;
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;

typedef struct _FILE_OBJECTID_INFORMATION {
LONGLONG FileReference;
UCHAR ObjectId[16];
Expand Down Expand Up @@ -158,13 +225,17 @@ typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation = 2,
FileBothDirectoryInformation = 3,
FileStandardInformation = 5,
FileNameInformation = 9,
FileRenameInformation = 10,
FileNamesInformation = 12,
FileAllInformation = 18,
FileObjectIdInformation = 29,
FileReparsePointInformation = 33,
FileIdBothDirectoryInformation = 37,
FileIdFullDirectoryInformation = 38
} FILE_INFORMATION_CLASS,
*PFILE_INFORMATION_CLASS;
FileIdFullDirectoryInformation = 38,
FileNormalizedNameInformation = 48,
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

typedef enum _MODE { KernelMode, UserMode, MaximumMode } MODE;

Expand Down Expand Up @@ -253,6 +324,12 @@ typedef struct _OBJECT_HANDLE_INFORMATION {
ACCESS_MASK GrantedAccess;
} OBJECT_HANDLE_INFORMATION, *POBJECT_HANDLE_INFORMATION;

typedef enum _OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation = 0,
ObjectTypeInformation = 2
} OBJECT_INFORMATION_CLASS;

typedef struct _RTL_RELATIVE_NAME {
UNICODE_STRING RelativeName;
HANDLE ContainingDirectory;
Expand All @@ -269,14 +346,6 @@ typedef struct _FILE_NETWORK_OPEN_INFORMATION {
ULONG FileAttributes;
} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;

typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
ULONG FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_WRITE_THROUGH 0x00000002
#define FILE_SEQUENTIAL_ONLY 0x00000004
Expand All @@ -302,55 +371,62 @@ typedef struct _FILE_BASIC_INFORMATION {
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
#define FILE_CONTAINS_EXTENDED_CREATE_INFORMATION 0x10000000

typedef NTSTATUS(WINAPI *NtQueryDirectoryFile_type)(
// Nt

using NtQueryDirectoryFile_type = NTSTATUS(WINAPI *)(
HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG,
FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);

typedef NTSTATUS(WINAPI *NtQueryDirectoryFileEx_type)(
using NtQueryDirectoryFileEx_type = NTSTATUS(WINAPI *)(
HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG,
FILE_INFORMATION_CLASS, ULONG, PUNICODE_STRING);

typedef NTSTATUS(WINAPI *NtQueryFullAttributesFile_type)(
using NtQueryFullAttributesFile_type = NTSTATUS(WINAPI *)(
POBJECT_ATTRIBUTES, PFILE_NETWORK_OPEN_INFORMATION);

typedef NTSTATUS(WINAPI *NtQueryAttributesFile_type)(POBJECT_ATTRIBUTES,
using NtQueryAttributesFile_type = NTSTATUS(WINAPI *)(POBJECT_ATTRIBUTES,
PFILE_BASIC_INFORMATION);

typedef NTSTATUS(WINAPI *NtOpenFile_type)(PHANDLE, ACCESS_MASK,
using NtQueryObject_type = NTSTATUS (WINAPI *)(
HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
using NtQueryInformationFile_type = NTSTATUS(WINAPI*)(
HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,
ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);

using NtOpenFile_type = NTSTATUS(WINAPI *)(PHANDLE, ACCESS_MASK,
POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
ULONG, ULONG);

typedef NTSTATUS(WINAPI *NtCreateFile_type)(PHANDLE, ACCESS_MASK,
using NtCreateFile_type = NTSTATUS(WINAPI *)(PHANDLE, ACCESS_MASK,
POBJECT_ATTRIBUTES,
PIO_STATUS_BLOCK, PLARGE_INTEGER,
ULONG, ULONG, ULONG, ULONG, PVOID,
ULONG);

typedef NTSTATUS(WINAPI *NtClose_type)(HANDLE);

typedef NTSYSAPI BOOLEAN(NTAPI *RtlDoesFileExists_U_type)(PCWSTR);

typedef NTSTATUS(NTAPI *RtlDosPathNameToRelativeNtPathName_U_WithStatus_type)(
PCWSTR DosFileName, PUNICODE_STRING NtFileName, PWSTR* FilePath, PRTL_RELATIVE_NAME RelativeName);
using NtClose_type = NTSTATUS(WINAPI *)(HANDLE);

typedef void (NTAPI *RtlReleaseRelativeName_type)(PRTL_RELATIVE_NAME RelativeName);
using NtTerminateProcess_type = NTSTATUS(WINAPI *)(HANDLE ProcessHandle, NTSTATUS ExitStatus);

typedef NTSTATUS (NTAPI *RtlGetVersion_type)(PRTL_OSVERSIONINFOW);
// Rtl

typedef NTSTATUS(WINAPI *NtTerminateProcess_type)(HANDLE ProcessHandle, NTSTATUS ExitStatus);
using RtlDoesFileExists_U_type = NTSYSAPI BOOLEAN(NTAPI *)(PCWSTR);
using RtlDosPathNameToRelativeNtPathName_U_WithStatus_type = NTSTATUS(NTAPI *)(
PCWSTR DosFileName, PUNICODE_STRING NtFileName, PWSTR* FilePath, PRTL_RELATIVE_NAME RelativeName);
using RtlReleaseRelativeName_type = void (NTAPI *)(PRTL_RELATIVE_NAME RelativeName);
using RtlGetVersion_type = NTSTATUS (NTAPI *)(PRTL_OSVERSIONINFOW);

extern NtQueryDirectoryFile_type NtQueryDirectoryFile;
extern NtQueryDirectoryFileEx_type NtQueryDirectoryFileEx;
extern NtQueryFullAttributesFile_type NtQueryFullAttributesFile;
extern NtQueryAttributesFile_type NtQueryAttributesFile;
extern NtQueryObject_type NtQueryObject;
extern NtQueryInformationFile_type NtQueryInformationFile;
extern NtOpenFile_type NtOpenFile;
extern NtCreateFile_type NtCreateFile;
extern NtClose_type NtClose;
extern NtTerminateProcess_type NtTerminateProcess;
extern RtlDoesFileExists_U_type RtlDoesFileExists_U;
extern RtlDosPathNameToRelativeNtPathName_U_WithStatus_type RtlDosPathNameToRelativeNtPathName_U_WithStatus;
extern RtlReleaseRelativeName_type RtlReleaseRelativeName;
extern RtlGetVersion_type RtlGetVersion;
extern NtTerminateProcess_type NtTerminateProcess;

// ensures ntdll functions have been initialized (only needed during static objects initialization)
void ntdll_declarations_init();
Expand Down
2 changes: 2 additions & 0 deletions src/usvfs_dll/hookmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ void HookManager::initHooks()
installHook(ntdllMod, nullptr, "NtQueryAttributesFile", hook_NtQueryAttributesFile);
installHook(ntdllMod, nullptr, "NtQueryDirectoryFile", hook_NtQueryDirectoryFile);
installHook(ntdllMod, nullptr, "NtQueryDirectoryFileEx", hook_NtQueryDirectoryFileEx);
installHook(ntdllMod, nullptr, "NtQueryObject", hook_NtQueryObject);
installHook(ntdllMod, nullptr, "NtQueryInformationFile", hook_NtQueryInformationFile);
installHook(ntdllMod, nullptr, "NtOpenFile", hook_NtOpenFile);
installHook(ntdllMod, nullptr, "NtCreateFile", hook_NtCreateFile);
installHook(ntdllMod, nullptr, "NtClose", hook_NtClose);
Expand Down
96 changes: 92 additions & 4 deletions src/usvfs_dll/hooks/ntdll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ void SetInfoFilename(LPVOID address, FILE_INFORMATION_CLASS infoClass,
const std::wstring &fileName)
{
switch (infoClass) {
case FileAllInformation: {
SetInfoFilenameImpl(
&reinterpret_cast<FILE_ALL_INFORMATION*>(address)->NameInformation, fileName);
} break;
case FileBothDirectoryInformation: {
SetInfoFilenameImplSN(
reinterpret_cast<FILE_BOTH_DIR_INFORMATION *>(address), fileName);
Expand All @@ -380,9 +384,17 @@ void SetInfoFilename(LPVOID address, FILE_INFORMATION_CLASS infoClass,
SetInfoFilenameImpl(
reinterpret_cast<FILE_DIRECTORY_INFORMATION *>(address), fileName);
} break;
case FileNameInformation: {
SetInfoFilenameImpl(
reinterpret_cast<FILE_NAME_INFORMATION*>(address), fileName);
} break;
case FileNamesInformation: {
SetInfoFilenameImpl(reinterpret_cast<FILE_NAMES_INFORMATION *>(address),
fileName);
SetInfoFilenameImpl(
reinterpret_cast<FILE_NAMES_INFORMATION *>(address), fileName);
} break;
case FileNormalizedNameInformation: {
SetInfoFilenameImpl(
reinterpret_cast<FILE_NAME_INFORMATION*>(address), fileName);
} break;
case FileIdFullDirectoryInformation: {
SetInfoFilenameImpl(
Expand All @@ -394,8 +406,7 @@ void SetInfoFilename(LPVOID address, FILE_INFORMATION_CLASS infoClass,
} break;
case FileIdBothDirectoryInformation: {
SetInfoFilenameImplSN(
reinterpret_cast<FILE_ID_BOTH_DIR_INFORMATION *>(address),
fileName);
reinterpret_cast<FILE_ID_BOTH_DIR_INFORMATION *>(address), fileName);
} break;
default: {
// NOP
Expand Down Expand Up @@ -1040,6 +1051,83 @@ NTSTATUS WINAPI usvfs::hook_NtQueryDirectoryFileEx(
return res;
}

DLLEXPORT NTSTATUS WINAPI usvfs::hook_NtQueryObject(
HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength)
{
NTSTATUS res;

HOOK_START_GROUP(MutExHookGroup::FILE_ATTRIBUTES)
if (!callContext.active()) {
return ::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation,
ObjectInformationLength, ReturnLength);
}

PRE_REALCALL
res = ::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation,
ObjectInformationLength, ReturnLength);
POST_REALCALL

LOG_CALL()
.addParam("path", ntdllHandleTracker.lookup(Handle))
.PARAM(ObjectInformationClass);

HOOK_END
return res;
}

DLLEXPORT NTSTATUS WINAPI usvfs::hook_NtQueryInformationFile(
HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,
ULONG Length, FILE_INFORMATION_CLASS FileInformationClass)
{
NTSTATUS res;

HOOK_START_GROUP(MutExHookGroup::FILE_ATTRIBUTES)
if (!callContext.active()) {
return ::NtQueryInformationFile(FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
}

PRE_REALCALL
res = ::NtQueryInformationFile(FileHandle, IoStatusBlock, FileInformation, Length,
FileInformationClass);
POST_REALCALL

if (res == STATUS_SUCCESS && (
FileInformationClass == FileNameInformation
|| FileInformationClass == FileAllInformation
|| FileInformationClass == FileNormalizedNameInformation)) {

const auto trackerInfo = ntdllHandleTracker.lookup(FileHandle);
const auto redir = applyReroute(READ_CONTEXT(), callContext, trackerInfo);

// TODO: difference between FileNameInformation and FileNormalizedNameInformation

FILE_NAME_INFORMATION *info;
if (FileInformationClass == FileAllInformation) {
info = &reinterpret_cast<FILE_ALL_INFORMATION*>(FileInformation)->NameInformation;
} else {
info = reinterpret_cast<FILE_NAME_INFORMATION*>(FileInformation);
}

if (redir.redirected)
{
SetInfoFilename(FileInformation, FileInformationClass, static_cast<LPCWSTR>(redir.path));
};

LOG_CALL()
.addParam("tracker_path", trackerInfo)
.PARAM(FileInformationClass)
.PARAM(redir.redirected)
.PARAM(redir.path)
.addParam("name_info", std::wstring{info->FileName, info->FileNameLength});

}

HOOK_END
return res;
}

unique_ptr_deleter<OBJECT_ATTRIBUTES>
makeObjectAttributes(RedirectionInfo &redirInfo,
POBJECT_ATTRIBUTES attributeTemplate)
Expand Down
16 changes: 16 additions & 0 deletions src/usvfs_dll/hooks/ntdll.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ hook_NtQueryDirectoryFileEx(HANDLE FileHandle,
ULONG QueryFlags,
PUNICODE_STRING FileName);

DLLEXPORT NTSTATUS WINAPI
hook_NtQueryObject(
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength);

DLLEXPORT NTSTATUS WINAPI
hook_NtQueryInformationFile(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);

DLLEXPORT NTSTATUS WINAPI hook_NtOpenFile(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
Expand Down
Loading

0 comments on commit a9ce2c4

Please sign in to comment.