You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过NtQueryDirectoryFile钩子隐藏文件夹时资源管理器崩溃问题排查

钩子NtQueryDirectoryFile隐藏文件夹时资源管理器崩溃问题排查

我尝试通过钩子NtQueryDirectoryFile在资源管理器中隐藏文件夹,最初找到一段可正常隐藏文件的代码:

NTSTATUS WINAPI Mine_NtQueryDirectoryFile(IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PVOID ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL,
    OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass,
    IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan)
{
    NTSTATUS status = originalNtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, Length, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);

    PFILE_FULL_DIR_INFORMATION pFileFullDirInfo;
    PFILE_BOTH_DIR_INFORMATION pFileBothDirInfo;


    switch (FileInformationClass) {
    case fileFullDirectoryInformation:
        pFileFullDirInfo = (PFILE_FULL_DIR_INFORMATION)FileInformation;
        while (pFileFullDirInfo->NextEntryOffset) {
            pFileFullDirInfo = (PFILE_FULL_DIR_INFORMATION)((LPBYTE)pFileFullDirInfo + pFileFullDirInfo->NextEntryOffset);
        }
        break;
    case fileBothDirectoryInformation:
        pFileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformation;
        while (pFileBothDirInfo->NextEntryOffset) {
            pFileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)((LPBYTE)pFileBothDirInfo + pFileBothDirInfo->NextEntryOffset);
        }
        break;
    case fileIdBothDirectoryInformation:

        PFILE_ID_BOTH_DIR_INFORMATION current = (PFILE_ID_BOTH_DIR_INFORMATION)FileInformation;
        while (current->NextEntryOffset) {
            PFILE_ID_BOTH_DIR_INFORMATION next = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)current + current->NextEntryOffset);

            if (compareToFileName(next, "d.txt") == true) {
                if (next->NextEntryOffset != 0) {
                    next = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)next + next->NextEntryOffset);
                    current->NextEntryOffset += next->NextEntryOffset;
                }
                else {
                    current->NextEntryOffset = 0;
                }
            }
            else {
                current = next;
            }
        }


        break;
    }

    return status;
}

但将代码中的目标文件名替换为文件夹名后,注入资源管理器的DLL出现c0000005错误崩溃或冻结。我使用Microsoft Detours进行钩子操作,未找到问题原因,于是添加日志输出修改代码:

NTSTATUS WINAPI Mine_NtQueryDirectoryFile(IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PVOID ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL,
    OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass,
    IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan)
{
    std::ofstream myfile;
    myfile.open("C:\\log.txt");

    NTSTATUS status = originalNtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, Length, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);
    myfile << "1\n";

    PFILE_FULL_DIR_INFORMATION pFileFullDirInfo;
    myfile << "2\n";

    PFILE_BOTH_DIR_INFORMATION pFileBothDirInfo;
    myfile << "3\n";


    switch (FileInformationClass) {
    case fileFullDirectoryInformation:
    {
        pFileFullDirInfo = (PFILE_FULL_DIR_INFORMATION)FileInformation;
        myfile << "ffdi 1\n";
        int counter1 = 0;
        while (pFileFullDirInfo->NextEntryOffset) {
            pFileFullDirInfo = (PFILE_FULL_DIR_INFORMATION)((LPBYTE)pFileFullDirInfo + pFileFullDirInfo->NextEntryOffset);
            myfile << "ffdi while iteration ", counter1, "\n";
            counter1++;
        }
        myfile << "ffdi end\n";
    }
    break;
    case fileBothDirectoryInformation:
    {
        pFileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformation;
        myfile << "fbdi 1\n";
        int counter2 = 0;

        while (pFileBothDirInfo->NextEntryOffset) {
            pFileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)((LPBYTE)pFileBothDirInfo + pFileBothDirInfo->NextEntryOffset);
            myfile << "fbdi while iteration ", counter2, "\n";
            counter2++;
        }
        myfile << "fbdi end\n";
    }
        break;
    case fileIdBothDirectoryInformation:
    {
        PFILE_ID_BOTH_DIR_INFORMATION current = (PFILE_ID_BOTH_DIR_INFORMATION)FileInformation;
        myfile << "fibdi 1\n";
        int counter3 = 0;
        while (current->NextEntryOffset) {
            myfile << "cycle start\n";
            PFILE_ID_BOTH_DIR_INFORMATION next = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
            myfile << "PFILE_ID_BOTH_DIR_INFORMATION ", next, " = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)", current, " + ", current, "->NextEntryOffset)";

            if (compareToFileName(next, "detours") == true) {

                myfile << "if (compareToFileName(", next, ", detours) == true) == true\n";

                if (next->NextEntryOffset != 0) {

                    myfile << "if (", next, "->NextEntryOffset != 0) == true\n";

                    next = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)next + next->NextEntryOffset);

                    myfile << next, " = (PFILE_ID_BOTH_DIR_INFORMATION)((LPBYTE)", next, " + ", next, "->NextEntryOffset);\n";

                    current->NextEntryOffset += next->NextEntryOffset;

                    myfile << current, "->NextEntryOffset += ", next, "->NextEntryOffset; \n";

                }
                else {
                    myfile << "if (", next, "->NextEntryOffset != 0) == false\n";

                    current->NextEntryOffset = 0;

                    myfile << "current->NextEntryOffset = 0 \n";

                }
            }
            else {

                myfile << "if (compareToFileName(", next, ", detours) == true) == false\n";

                current = next;
            }
            myfile << "fibdi while iteration ", counter3, "\n";
            counter3++;
        }

    }
        break;
    }
    myfile << "end \n";
    myfile.close();
    return status;
}

注入后资源管理器再次崩溃,C:\log.txt日志内容为:

1
2
3
fibdi 1
end

崩溃仅在进入目标文件夹所在目录时发生,求排查问题原因。


内容的提问来源于stack exchange,提问作者NBB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:27:04