这个还是糅合了 很多资料搞定的
感觉内核 枚举 文件还是简单的 核心函数就一个 ZwQueryDirectoryFile 得出来 _FILE_BOTH_DIR_INFORMATION 结构体 然后枚举 就可以了 然后 可以 封装两个函数 MyFindFirstFile MyFindNextFile 。MyFindFirstFile 可以用 IoCreateFile 来获取句柄
然后 可以用 ZwQueryDirectoryFile 可以验证一下 是否真的可以。。
然后 用 MyFindNextFile 获得 然后就可以 枚举了 这次是用的windows 黑客编程技术详解源码 其中也有 照着看雪论坛写的代码
发现 两者好像差不多 这大概就是传说中 的好多年的轮子吧。。。、
只不过 windows 黑客编程技术详解把两个封装的函数 给取消了 直接变成了一个函数
其实就是 获取句柄 获取结构体 枚举就完事了
下面是代码
#include <ntddk.h>
#define HANDLE_VALUE (HANDLE)-1
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;
NTKERNELAPI NTSTATUS ZwQueryDirectoryFile
(
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
);
VOID DriverUnload(PDRIVER_OBJECT driver)
{
KdPrint(("goodbye"));
}
BOOLEAN MyQueryFileAndFileFolder(UNICODE_STRING ustrPath)
{
HANDLE hFile = NULL;
OBJECT_ATTRIBUTES objectAttributes = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
NTSTATUS status = STATUS_SUCCESS;
// 获取文件句柄
InitializeObjectAttributes(&objectAttributes, &ustrPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateFile(&hFile, FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,
&objectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
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 = ExAllocatePool(PagedPool, ulLength);
// 保存pDir的首地址,用来释放内存使用!!!
PFILE_BOTH_DIR_INFORMATION pBeginAddr = pDir;
// 获取信息
status = ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &iosb, pDir, ulLength,
FileBothDirectoryInformation, FALSE, NULL, FALSE);
if (!NT_SUCCESS(status))
{
ExFreePool(pDir);
ZwClose(hFile);
KdPrint(("ZwQueryDirectoryFile", status));
return FALSE;
}
// 遍历
UNICODE_STRING ustrTemp;
UNICODE_STRING ustrOne;
UNICODE_STRING ustrTwo;
RtlInitUnicodeString(&ustrOne, L".");
RtlInitUnicodeString(&ustrTwo, L"..");
WCHAR wcFileName[1024] = { 0 };
while (TRUE)
{
// 判断是否是上级目录或是本目录
RtlZeroMemory(wcFileName, 1024);
RtlCopyMemory(wcFileName, pDir->FileName, pDir->FileNameLength);
RtlInitUnicodeString(&ustrTemp, wcFileName);
if ((0 != RtlCompareUnicodeString(&ustrTemp, &ustrOne, TRUE)) &&
(0 != RtlCompareUnicodeString(&ustrTemp, &ustrTwo, TRUE)))
{
if (pDir->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// 目录
KdPrint(("[DIRECTORY]\t%wZ\n", &ustrTemp));
}
else
{
// 文件
KdPrint(("[FILE]\t\t%wZ\n", &ustrTemp));
}
}
// 遍历完毕
if (0 == pDir->NextEntryOffset)
{
KdPrint(("\n[QUERY OVER]\n\n"));
break;
}
// pDir指向的地址改变了,所以下面ExFreePool(pDir)会出错!!!所以,必须保存首地址
pDir = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)pDir + pDir->NextEntryOffset);
}
// 释放内存, 关闭文件句柄
ExFreePool(pBeginAddr);
ZwClose(hFile);
return TRUE;
}
HANDLE MyFindfile(LPSTR lp, PFILE_BOTH_DIR_INFORMATION pDir, ULONG ulen)
{
char strFolder[4096] = { 0 };
STRING ast;
UNICODE_STRING ustr;
OBJECT_ATTRIBUTES ob;
IO_STATUS_BLOCK io;
NTSTATUS nt;
HANDLE hfine = HANDLE_VALUE;
memset(strFolder, 0, 4096);
strcpy(strFolder, "\\??\\");
strcat(strFolder, lp);
RtlInitString(&ast, strFolder);
if (RtlAnsiStringToUnicodeString(&ustr, &ast, TRUE) == 0)
{
InitializeObjectAttributes(&ob, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL);
nt = IoCreateFile(&hfine,
FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,
&ob,
&io,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
NULL,
0,
CreateFileTypeNone,
NULL,
IO_NO_PARAMETER_CHECKING);
RtlFreeUnicodeString(&ustr);
if (nt == STATUS_SUCCESS&&hfine != HANDLE_VALUE)
{
nt = ZwQueryDirectoryFile(
hfine,
NULL,
NULL,
NULL,
&io,
pDir,
ulen,
FileBothDirectoryInformation,
TRUE,
NULL,
FALSE
);
if (!NT_SUCCESS(nt))
{
ZwClose(hfine);
return HANDLE_VALUE;
}
}
}
return hfine;
}
BOOLEAN Nextfile(HANDLE hfile, PFILE_BOTH_DIR_INFORMATION pDir, ULONG ulen)
{
IO_STATUS_BLOCK io;
NTSTATUS nt;
nt = ZwQueryDirectoryFile(
hfile,
NULL,
NULL,
NULL,
&io,
pDir,
ulen,
FileBothDirectoryInformation,
FALSE,
NULL,
FALSE
);
if (NT_SUCCESS(nt))
return TRUE;
else
return FALSE;
}
ULONG Searchflie(LPSTR lpPath)
{
ULONG count = 0;
HANDLE hfine = HANDLE_VALUE;
PFILE_BOTH_DIR_INFORMATION pDir;
char *strBuffer = NULL;
char strfilename[255 * 2];
ULONG ulen = 4096 * 2 + sizeof(PFILE_BOTH_DIR_INFORMATION);
strBuffer = (PCHAR)ExAllocatePool(NonPagedPool, ulen);
pDir = (PFILE_BOTH_DIR_INFORMATION)strBuffer;
hfine = MyFindfile(lpPath, pDir, ulen);
if (hfine != HANDLE_VALUE)
{
ExFreePool(strBuffer);
ulen = (4096 * 2 + sizeof(FILE_BOTH_DIR_INFORMATION))*0x2000;
strBuffer = (PCHAR)ExAllocatePool(NonPagedPool, ulen);
pDir = (PFILE_BOTH_DIR_INFORMATION)strBuffer;
if (Nextfile(hfine, pDir, ulen))
{
while (TRUE)
{
memset(strfilename, 0, 255 * 2);
memcpy(strfilename, pDir->FileName, pDir->FileNameLength);
if (strcmp(strfilename, "..") != 0 && strcmp(strfilename, ".") != 0)
{
if (pDir->FileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
KdPrint(("目录: %s\n", strfilename));
}
else
{
KdPrint(("文件: %s\n", strfilename));
}
count++;
}
if (pDir->NextEntryOffset == 0)
break;
pDir = (PFILE_BOTH_DIR_INFORMATION)((char *)pDir + pDir->NextEntryOffset);
}
ExFreePool(strBuffer);
}
KdPrint(("搜索完毕!\n"));
ZwClose(hfine);
}
return count;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING ustrQueryFile;
RtlInitUnicodeString(&ustrQueryFile, L"\\??\\C:\\Windows");
MyQueryFileAndFileFolder(ustrQueryFile);
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
下面是 效果图
参考代码
看雪论坛
windows 黑客编程技术详解