更新时间:2022-12-01 16:31:41
好的,这是测试和有效的代码。如果某人无法使用它或出现蓝屏死机-可能不是代码问题,而是某人的技能问题
ok, here code which tested and works. if somebody can not use it or got BSOD - probably problem not in code but in somebody skills
一些注意事项-如果您具有以前的模式内核-请使用 Nt *
api(导出时),但不是 Zw *
api。或 Io *
api。如果您不了解原因或以前的模式,***甚至不要尝试在内核中进行编程。
several notes - if you have previous mode kernel - use Nt*
api (when exported) but not Zw*
api. or Io*
api. if you not understand why, or what is your previous mode - better even not try programming in kernel.
强制性使用 FILE_OPEN_REPARSE_POINT
选项,或者如果不理解这是什么以及为什么需要使用
mandatory use FILE_OPEN_REPARSE_POINT
option or even not try run this code if not understand what is this and why need use
进行删除,请尝试运行此代码-用 FILE_DELETE_ON_CLOSE $打开文件c $ c>选项,仅用于转储-改为使用
FILE_DIRECTORY_FILE
选项。
for delete - open files with FILE_DELETE_ON_CLOSE
option, for dump only - with FILE_DIRECTORY_FILE
option instead.
自己编写代码,使用< = 0x1800字节的堆栈最深的文件夹中的x64,例如 c:\Users
-因此内核可以这样做,但始终使用 IoGetRemainingStackSize
code yourself used <= 0x1800 bytes of stack in x64 in deepest folders, like c:\Users
- so this is ok for kernel, but always check stack space with IoGetRemainingStackSize
如果您自己无法执行此操作,我将不正确使用每个逗号
i will be not correct every comma in your code, if you can not do this yourself
#define ALLOCSIZE PAGE_SIZE
#ifdef _REAL_DELETE_
#define USE_DELETE_ON_CLOSE FILE_DELETE_ON_CLOSE
#define FILE_ACCESS FILE_GENERIC_READ|DELETE
#else
#define USE_DELETE_ON_CLOSE FILE_DIRECTORY_FILE
#define FILE_ACCESS FILE_GENERIC_READ
#endif
// int nLevel, PSTR prefix for debug only
void ntTraverse(POBJECT_ATTRIBUTES poa, ULONG FileAttributes, int nLevel, PSTR prefix)
{
if (IoGetRemainingStackSize() < PAGE_SIZE)
{
DbgPrint("no stack!\n");
return ;
}
if (!nLevel)
{
DbgPrint("!nLevel\n");
return ;
}
NTSTATUS status;
IO_STATUS_BLOCK iosb;
UNICODE_STRING ObjectName;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
DbgPrint("%s[<%wZ>]\n", prefix, poa->ObjectName);
#ifdef _REAL_DELETE_
if (FileAttributes & FILE_ATTRIBUTE_READONLY)
{
if (0 <= NtOpenFile(&oa.RootDirectory, FILE_WRITE_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT|FILE_OPEN_REPARSE_POINT))
{
static FILE_BASIC_INFORMATION fbi = { {}, {}, {}, {}, FILE_ATTRIBUTE_NORMAL };
NtSetInformationFile(oa.RootDirectory, &iosb, &fbi, sizeof(fbi), FileBasicInformation);
NtClose(oa.RootDirectory);
}
}
#endif//_REAL_DELETE_
if (0 <= (status = NtOpenFile(&oa.RootDirectory, FILE_ACCESS, poa, &iosb, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|USE_DELETE_ON_CLOSE)))
{
if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (PVOID buffer = ExAllocatePool(PagedPool, ALLOCSIZE))
{
union {
PVOID pv;
PBYTE pb;
PFILE_DIRECTORY_INFORMATION DirInfo;
};
while (0 <= (status = NtQueryDirectoryFile(oa.RootDirectory, NULL, NULL, NULL, &iosb,
pv = buffer, ALLOCSIZE, FileDirectoryInformation, 0, NULL, FALSE)))
{
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
ObjectName.Buffer = DirInfo->FileName;
switch (ObjectName.Length = (USHORT)DirInfo->FileNameLength)
{
case 2*sizeof(WCHAR):
if (ObjectName.Buffer[1] != '.') break;
case sizeof(WCHAR):
if (ObjectName.Buffer[0] == '.') continue;
}
ObjectName.MaximumLength = ObjectName.Length;
#ifndef _REAL_DELETE_
if (DirInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
#endif
{
ntTraverse(&oa, DirInfo->FileAttributes, nLevel - 1, prefix - 1);
}
#ifndef _REAL_DELETE_
else
#endif
{
DbgPrint("%s%8I64u <%wZ>\n", prefix, DirInfo->EndOfFile.QuadPart, &ObjectName);
}
} while (NextEntryOffset = DirInfo->NextEntryOffset);
}
ExFreePool(buffer);
if (status == STATUS_NO_MORE_FILES)
{
status = STATUS_SUCCESS;
}
}
}
NtClose(oa.RootDirectory);
}
if (0 > status)
{
DbgPrint("---- %x %wZ\n", status, poa->ObjectName);
}
}
void ntTraverse()
{
char prefix[MAXUCHAR + 1];
memset(prefix, '\t', MAXUCHAR);
prefix[MAXUCHAR] = 0;
STATIC_OBJECT_ATTRIBUTES(oa, "\\??\\c:\\users");
//STATIC_OBJECT_ATTRIBUTES(oa, "\\systemroot");
ntTraverse(&oa, FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY, MAXUCHAR, prefix + MAXUCHAR);
}