Skip to content

Instantly share code, notes, and snippets.

@Extravert-ir
Last active August 14, 2022 19:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Extravert-ir/6617e8019013363a2d972aad231eab9e to your computer and use it in GitHub Desktop.
Save Extravert-ir/6617e8019013363a2d972aad231eab9e to your computer and use it in GitHub Desktop.
Small test program for testing bug in NtQueryDirectoryFile
#include <stdio.h>
#include <windows.h>
#include <ntsecapi.h>
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation,
FileFullDirectoryInformation,
FileBothDirectoryInformation
// ...
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef struct _FILE_BOTH_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
WCHAR ShortName[12];
WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
typedef VOID(NTAPI *PIO_APC_ROUTINE)(
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved);
typedef VOID(NTAPI *_RtlInitUnicodeString)(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
typedef NTSYSCALLAPI NTSTATUS(NTAPI *_NtQueryDirectoryFile)(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass,
BOOLEAN ReturnSingleEntry,
PUNICODE_STRING FileName,
BOOLEAN RestartScan
);
int wmain(int argc, wchar_t *argv[]) {
UNICODE_STRING lookup_us;
IO_STATUS_BLOCK io;
unsigned int data_pos = 0, data_len;
char buffer[8192];
_NtQueryDirectoryFile NtQueryDirectoryFile;
_RtlInitUnicodeString RtlInitUnicodeString;
HMODULE hModule = GetModuleHandle(L"ntdll.dll");
if (argc != 3)
return 1;
if (hModule != 0)
{
NtQueryDirectoryFile = (_NtQueryDirectoryFile)GetProcAddress(hModule, "NtQueryDirectoryFile");
RtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(hModule, "RtlInitUnicodeString");
if (!NtQueryDirectoryFile || !RtlInitUnicodeString)
{
printf("Error Load function!\n");
return 1;
}
}
else
{
printf("Error load ntdll!\n");
return 2;
}
HANDLE hDir = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
RtlInitUnicodeString(&lookup_us, argv[2]);
if (!NtQueryDirectoryFile(hDir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3, FALSE, &lookup_us, TRUE))
{
FILE_BOTH_DIR_INFORMATION *dir_info;
data_len = (ULONG)io.Information;
printf("Directory contents (%ls):\n", argv[1]);
for (;;)
{
if (data_pos >= data_len)
{
if (NtQueryDirectoryFile(hDir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3, FALSE, &lookup_us, FALSE))
break;
data_len = (ULONG)io.Information;
data_pos = 0;
}
dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
else data_pos = data_len;
printf("%.*ls \n", dir_info->FileNameLength / sizeof(WCHAR), dir_info->FileName);
}
}
else printf("no matching file for\n");
return 0;
}
@ryan-weil
Copy link

Question - why did you bother redefining all the structs when they are available in winternl.h???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment