首页
社区
课程
招聘
[未解决,已结帖] [求助][求助]ZwQueryDirectoryFile 枚举文件失败 50.00雪花
发表于: 2019-12-26 23:07 2110

[未解决,已结帖] [求助][求助]ZwQueryDirectoryFile 枚举文件失败 50.00雪花

2019-12-26 23:07
2110
typedef LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
typedef DWORD ULONG_PTR;

#define STATUS_SUCCESS (NTSTATUS)0x00000000L
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define FILE_OPEN               0x00000001
#define OBJ_CASE_INSENSITIVE    0x00000040L
#define FILE_DIRECTORY_FILE     0x00000001

#define InitializeObjectAttributes( p, n, a, r, s ) {    \
	(p)->uLength = sizeof( OBJECT_ATTRIBUTES );          \
	(p)->hRootDirectory = r;                             \
	(p)->uAttributes = a;                                \
	(p)->pObjectName = n;                                \
	(p)->pSecurityDescriptor = s;                        \
	(p)->pSecurityQualityOfService = NULL;               \
}



typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef USHORT RTL_STRING_LENGTH_TYPE;

typedef struct _STRING {
	USHORT Length;
	USHORT MaximumLength;
	PCHAR Buffer;
} STRING;

typedef STRING *PSTRING;
typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;

typedef struct _OBJECT_ATTRIBUTES {
	ULONG uLength;
	HANDLE hRootDirectory;
	PUNICODE_STRING pObjectName;
	ULONG uAttributes;
	PVOID pSecurityDescriptor;
	PVOID pSecurityQualityOfService;
} OBJECT_ATTRIBUTES;

#define InitializeObjectAttributes( p, n, a, r, s ) {    \
	(p)->uLength = sizeof( OBJECT_ATTRIBUTES );          \
	(p)->hRootDirectory = r;                             \
	(p)->uAttributes = a;                                \
	(p)->pObjectName = n;                                \
	(p)->pSecurityDescriptor = s;                        \
	(p)->pSecurityQualityOfService = NULL;               \
}

typedef OBJECT_ATTRIBUTES * POBJECT_ATTRIBUTES;

typedef struct _IO_STATUS_BLOCK {
	union {
		NTSTATUS Status;
		PVOID Pointer;
	};
	ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef VOID(NTAPI *PIO_APC_ROUTINE) (IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved);

typedef enum _FILE_INFORMATION_CLASS {
	FileDirectoryInformation = 1,
	FileFullDirectoryInformation,
	FileBothDirectoryInformation,
	FileBasicInformation,
	FileStandardInformation,
	FileInternalInformation,
	FileEaInformation,
	FileAccessInformation,
	FileNameInformation,
	FileRenameInformation,
	FileLinkInformation,
	FileNamesInformation,
	FileDispositionInformation,
	FilePositionInformation,
	FileFullEaInformation,
	FileModeInformation,
	FileAlignmentInformation,
	FileAllInformation,
	FileAllocationInformation,
	FileEndOfFileInformation,
	FileAlternateNameInformation,
	FileStreamInformation,
	FilePipeInformation,
	FilePipeLocalInformation,
	FilePipeRemoteInformation,
	FileMailslotQueryInformation,
	FileMailslotSetInformation,
	FileCompressionInformation,
	FileObjectIdInformation,
	FileCompletionInformation,
	FileMoveClusterInformation,
	FileQuotaInformation,
	FileReparsePointInformation,
	FileNetworkOpenInformation,
	FileAttributeTagInformation,
	FileTrackingInformation,
	FileIdBothDirectoryInformation,
	FileIdFullDirectoryInformation,
	FileValidDataLengthInformation,
	FileShortNameInformation,
	FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

typedef enum _EVENT_TYPE { NotificationEvent, SynchronizationEvent } EVENT_TYPE;

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;

NTSTATUS(WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
NTSTATUS(WINAPI * pZwCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
NTSTATUS(WINAPI * pZwCreateEvent)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN);
NTSTATUS(WINAPI * pZwQuerydirectoryFile)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
NTSTATUS(WINAPI * pZwWaitForSingleobject)(HANDLE, BOOLEAN, PLARGE_INTEGER);
NTSTATUS(WINAPI * pRtlUnicodeStringToAnsiString)(PANSI_STRING, PCUNICODE_STRING, BOOLEAN);
NTSTATUS(WINAPI * pZwClose)(HANDLE);

void IntializeNativeFunctions(VOID)
{
	HMODULE hModule = LoadLibraryW(L"Ntdll.dll");

	pRtlInitUnicodeString = (NTSTATUS(WINAPI *)(PUNICODE_STRING, PCWSTR)) GetProcAddress(hModule, "RtlInitUnicodeString");
	pZwCreateFile = (NTSTATUS(WINAPI *)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG)) GetProcAddress(hModule, "ZwCreateFile");
	pZwCreateEvent = (NTSTATUS(WINAPI *)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN)) GetProcAddress(hModule, "ZwCreateEvent");
	pZwQuerydirectoryFile = (NTSTATUS(WINAPI *)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN)) GetProcAddress(hModule, "ZwQueryDirectoryFile");
	pZwWaitForSingleobject = (NTSTATUS(WINAPI *)(HANDLE, BOOLEAN, PLARGE_INTEGER)) GetProcAddress(hModule, "ZwWaitForSingleObject");
	pRtlUnicodeStringToAnsiString = (NTSTATUS(WINAPI *)(PANSI_STRING, PCUNICODE_STRING, BOOLEAN)) GetProcAddress(hModule, "RtlUnicodeStringToAnsiString");
	pZwClose = (NTSTATUS(WINAPI *)(HANDLE)) GetProcAddress(hModule, "ZwClose");
}

NTSTATUS ListDirectory(WCHAR * pszDirectoryName)
{
	UNICODE_STRING RootDirectoryName;
	ANSI_STRING as;
	OBJECT_ATTRIBUTES RootDirectoryAttributes;
	NTSTATUS ntStatus = STATUS_SUCCESS;
	HANDLE RootDirectoryHandle;
	IO_STATUS_BLOCK Iosb;
	HANDLE Event;
	PUCHAR Buffer[65536] = {0};
	WCHAR wszBuffer[50];

	PFILE_BOTH_DIR_INFORMATION DirInformation;

	if (pRtlInitUnicodeString == NULL) return -1;
	if (pRtlUnicodeStringToAnsiString == NULL) return -1;
	swprintf(wszBuffer, sizeof(wszBuffer), L"\\??\\%s\\", pszDirectoryName);
	ntStatus = ((pRtlInitUnicodeString)(&RootDirectoryName, wszBuffer));
	if (!NT_SUCCESS(ntStatus))
		return ntStatus;
	InitializeObjectAttributes(&RootDirectoryAttributes, &RootDirectoryName, OBJ_CASE_INSENSITIVE, 0, 0);
	if (pZwCreateFile == NULL) return -1;
	ntStatus = ((pZwCreateFile)(&RootDirectoryHandle,
		GENERIC_READ,
		&RootDirectoryAttributes,
		&Iosb,
		0,
		FILE_ATTRIBUTE_DIRECTORY,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
		FILE_OPEN,
		FILE_DIRECTORY_FILE,
		0, 0));

	if (!NT_SUCCESS(ntStatus))
	{
		printf("Unable to open %s, error = 0x%x\n", &RootDirectoryName, ntStatus);
		return ntStatus;
	}
	if (pZwCreateEvent == NULL) return -1;
	ntStatus = ((pZwCreateEvent)(&Event, GENERIC_ALL, 0, NotificationEvent, FALSE));
	if (!NT_SUCCESS(ntStatus))
	{
		printf("Event creation failed with error 0x%x\n", ntStatus);
		return ntStatus;
	}
	if (pZwQuerydirectoryFile == NULL) return -1;
	if (((pZwQuerydirectoryFile)(RootDirectoryHandle,
		Event, 0, 0,
		&Iosb,
		Buffer,
		sizeof(Buffer),
		FileBothDirectoryInformation,
		FALSE,
		NULL,
		FALSE)) == STATUS_PENDING)
	{
		if (pZwWaitForSingleobject == NULL) return -1;
		ntStatus = ((pZwWaitForSingleobject)(Event, FALSE, 0));
	}
	if (!NT_SUCCESS(ntStatus))
	{
		printf("Unable to query directory contents, error 0x%x\n", ntStatus);
		return ntStatus;
	}
	DirInformation = (PFILE_BOTH_DIR_INFORMATION)Buffer;

	while (1)
	{
		UNICODE_STRING EntryName;
		EntryName.MaximumLength = EntryName.Length = (USHORT)DirInformation->FileNameLength;
		EntryName.Buffer = &DirInformation->FileName[0];
		((pRtlUnicodeStringToAnsiString)(&as, &EntryName, TRUE));
		printf("%s\n", as.Buffer);
		OutputDebugStringA(as.Buffer);
		if (0 == DirInformation->NextEntryOffset)
			break;
		else
			DirInformation = (PFILE_BOTH_DIR_INFORMATION)(((PUCHAR)DirInformation) + DirInformation->NextEntryOffset);
	}
	((pZwClose)(RootDirectoryHandle));
	return ntStatus;
}


	WCHAR wszDirectory[] = {L"E:\\VC工程\\Release"};
	IntializeNativeFunctions();
	ListDirectory(wszDirectory);



为什么有时候成功,有时候失败呢 想不明白 调试不出问题来

哪位有Win7 X64能用的代码 可否借来应个急,要直接调用ntdll函数枚举文件


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-12-26 23:11 被哇咔咔zs编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 130
活跃值: (1005)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
简直太奇怪了
看我的注释

BOOLEAN MyQueryFileAndFileFolder(wchar_t *pszDirectoryName)
{
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objectAttributes = { 0 };
	IO_STATUS_BLOCK iosb = { 0 };
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING ustrPath;
	wchar_t wszBuffer[MAX_PATH*2];
	// 获取文件句柄
	swprintf(wszBuffer, sizeof(wszBuffer), L"\\??\\%s", pszDirectoryName);
	((pRtlInitUnicodeString)(&ustrPath, wszBuffer));
	InitializeObjectAttributes(&objectAttributes, &ustrPath, OBJ_CASE_INSENSITIVE, NULL, NULL);


	status = pZwCreateFile(&hFile, GENERIC_READ,
		&objectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_OPEN, FILE_DIRECTORY_FILE,
		NULL, 0);
	if (!NT_SUCCESS(status))
	{
		//		KdPrint(("ZwCreateFile", status));
		return FALSE;
	}

	// 遍历文件
	// 注意此处的大小!!!一定要申请足够内存,否则后面ExFreePool会蓝屏
	ULONG ulLength = (2 * 4096 + sizeof(FILE_BOTH_DIR_INFORMATION)) * 0x2000;
	PFILE_BOTH_DIR_INFORMATION pDir = (PFILE_BOTH_DIR_INFORMATION)new char [ulLength];
	// 保存pDir的首地址,用来释放内存使用!!!
	PFILE_BOTH_DIR_INFORMATION pBeginAddr = pDir;
	// 获取信息



	status = pZwQuerydirectoryFile(hFile, NULL, NULL, NULL, &iosb, pDir, ulLength,
		FileBothDirectoryInformation, FALSE, NULL, FALSE);
	if (!NT_SUCCESS(status))
	{
		delete pDir;
		CloseHandle(hFile);
		return FALSE;
	}
	// 遍历
	UNICODE_STRING ustrTemp;
	UNICODE_STRING ustrOne;
	UNICODE_STRING ustrTwo;
	pRtlInitUnicodeString(&ustrOne, L".");
	pRtlInitUnicodeString(&ustrTwo, L"..");
	WCHAR wcFileName[1024] = { 0 };
        Sleep(500);							//+了这句就正常打印出来,删掉的话,下面就无法打印 执行一次就跳出循环了
	while (TRUE)
	{
		// 判断是否是上级目录或是本目录
		RtlZeroMemory(wcFileName, 1024);
		RtlCopyMemory(wcFileName, pDir->FileName, pDir->FileNameLength);
		pRtlInitUnicodeString(&ustrTemp, wcFileName);
		if ((0 != pRtlCompareUnicodeString(&ustrTemp, &ustrOne, TRUE)) &&
			(0 != pRtlCompareUnicodeString(&ustrTemp, &ustrTwo, TRUE)))
		{
			if (pDir->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				// 目录
				//				KdPrint(("[DIRECTORY]\t%wZ\n", &ustrTemp));
				OutputDebugStringW(ustrTemp.Buffer);
			}
			else
			{
				// 文件
				//				KdPrint(("[FILE]\t\t%wZ\n", &ustrTemp));
				OutputDebugStringA("111");
				OutputDebugStringW(ustrTemp.Buffer);

			}
		}
		// 遍历完毕
		if (0 == pDir->NextEntryOffset)
		{
			//			KdPrint(("\n[QUERY OVER]\n\n"));
			break;
		}
		// pDir指向的地址改变了,所以下面ExFreePool(pDir)会出错!!!所以,必须保存首地址
		pDir = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)pDir + pDir->NextEntryOffset);
	}
	// 释放内存, 关闭文件句柄
	delete pBeginAddr;
	CloseHandle(hFile);

	return TRUE;
}

最后于 2019-12-27 02:09 被哇咔咔zs编辑 ,原因:
2019-12-27 02:05
0
雪    币: 83
活跃值: (1082)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
没看出来 哪里出问题  加群一起讨论  一群二群被封了  加这个482999345 点击链接加入群聊【旧世界备份二群】:https://jq.qq.com/?_wv=1027&k=59BP5bI
2019-12-27 13:31
0
雪    币: 407
活跃值: (1746)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个地方,有两种做法,一种就是一次遍历所有的文件。还有一种是一次遍历一个文件,遍历N次。针对第一种情况,循环调用ZwQuerydirectoryFile,直到返回STATUS_NO_MORE_FILES或者其他值,此时能得到所需要的缓冲区大小,再调用一次,缓冲区里面有所有的文件。针对第二种情况,提供足以容纳一个文件的缓冲区大小,一直到返回失败
2019-12-27 15:01
0
游客
登录 | 注册 方可回帖
返回
//