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

内核态调用ZwSetInformationFile重命名文件遇0xc0000034错误求助

内核态调用ZwSetInformationFile重命名文件返回STATUS_OBJECT_NAME_NOT_FOUND问题

我尝试在内核态下通过ZwSetInformationFile重命名文件,原文件能成功打开句柄,但调用API始终返回0xc0000034(STATUS_OBJECT_NAME_NOT_FOUND)错误。代码实现如下:

NTSTATUS Files::RenameFile(WCHAR* OriginalName, WCHAR* NewName)
{
// MSDN说明,调用ZwSetInformationFile时驱动必须处于IRQL PASSIVE_LEVEL级别
    if (KeGetCurrentIrql() != PASSIVE_LEVEL)
    {
        printf("IRQL invalid\n");
        return STATUS_INVALID_LEVEL;
    }

        // 打开文件句柄,OriginalName需传入完整路径,示例:"\\DosDevices\\C:\\named_file.txt"
        // 重命名文件需DELETE权限,这里假设GENERIC_ALL已包含足够权限
    auto FileHandle = Files(OriginalName, Files::OpenExisting, GENERIC_ALL, 0);

    if (FileHandle.CreationStatus != STATUS_SUCCESS)
    {
        printf("Failed to open handle to file %ws. ERR: 0x%x\n", OriginalName, FileHandle.CreationStatus);
        return FileHandle.CreationStatus;
    }

    IO_STATUS_BLOCK ioStatusBlock;

        // MSDN说明,使用FileRenameInformation时,大小需为结构体大小加上新名称的字节数
    const auto size = sizeof(FILE_RENAME_INFORMATION) + sizeof(NewName);

        // 为结构体分配内存
    const auto rename_info = static_cast<PFILE_RENAME_INFORMATION>(ExAllocatePool(PagedPool, size));

    if(rename_info == nullptr)
    {
        printf("Failed allocating rename info structure\n");
        FileHandle.Close();
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    memset(rename_info, 0, size);

    wcscpy(rename_info->FileName, NewName);
    rename_info->FileNameLength = sizeof(NewName);// 字节数 
    rename_info->RootDirectory = nullptr; // MSDN:若文件名是绝对路径则必须为null
    rename_info->ReplaceIfExists = false; // 若文件已存在则不替换

    const auto status = ZwSetInformationFile(FileHandle.hFile, &ioStatusBlock, rename_info, size, FileRenameInformation);

// 释放资源
    ExFreePool(rename_info);
    FileHandle.Close();

// ZwSetInformationFile返回0xc0000034(STATUS_OBJECT_NAME_NOT_FOUND)错误
    if(status != STATUS_SUCCESS)
    {
        printf("0x%x : %ws\n", status, rename_info->FileName); // -> 0xc0000034 : "\\DosDevices\\C:\\renamed_file.txt"
        return status;
    }

    printf("Renamed %ws to %ws\n", OriginalName, NewName);

    return STATUS_SUCCESS;

}

问题根源及修复方案

核心错误在于字符串长度计算逻辑错误:
sizeof(NewName)获取的是指针本身的大小(32位系统4字节,64位系统8字节),而非NewName指向的宽字符串实际字节数。这导致分配的内存空间不足,且传递给FileNameLength的长度完全错误,内核无法正确解析新文件名,因此返回STATUS_OBJECT_NAME_NOT_FOUND。

修复步骤:

  1. 修正内存分配大小计算
    用宽字符串实际长度乘以sizeof(WCHAR)得到字节数,再加上结构体本身大小:

    ULONG nameBytes = wcslen(NewName) * sizeof(WCHAR);
    const auto size = sizeof(FILE_RENAME_INFORMATION) + nameBytes;
    
  2. 修正FileNameLength的值
    FileNameLength需设置为新文件名的实际字节数(不含终止符):

    rename_info->FileNameLength = nameBytes;
    
  3. 替换不安全的字符串拷贝函数
    避免wcscpy的缓冲区溢出风险,改用RtlCopyMemory:

    RtlCopyMemory(rename_info->FileName, NewName, nameBytes);
    
  4. 补充文件打开的共享模式
    重命名操作需要FILE_SHARE_DELETE权限,打开原文件时需添加该共享模式:

    auto FileHandle = Files(OriginalName, Files::OpenExisting, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);
    

修复后的完整代码片段

NTSTATUS Files::RenameFile(WCHAR* OriginalName, WCHAR* NewName)
{
    if (KeGetCurrentIrql() != PASSIVE_LEVEL)
    {
        printf("IRQL invalid\n");
        return STATUS_INVALID_LEVEL;
    }

    // 添加FILE_SHARE_DELETE确保重命名操作可执行
    auto FileHandle = Files(OriginalName, Files::OpenExisting, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);

    if (FileHandle.CreationStatus != STATUS_SUCCESS)
    {
        printf("Failed to open handle to file %ws. ERR: 0x%x\n", OriginalName, FileHandle.CreationStatus);
        return FileHandle.CreationStatus;
    }

    IO_STATUS_BLOCK ioStatusBlock;

    // 计算新文件名的实际字节数
    ULONG nameBytes = wcslen(NewName) * sizeof(WCHAR);
    const auto size = sizeof(FILE_RENAME_INFORMATION) + nameBytes;

    const auto rename_info = static_cast<PFILE_RENAME_INFORMATION>(ExAllocatePool(PagedPool, size));
    if(rename_info == nullptr)
    {
        printf("Failed allocating rename info structure\n");
        FileHandle.Close();
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    memset(rename_info, 0, size);

    // 安全拷贝字符串
    RtlCopyMemory(rename_info->FileName, NewName, nameBytes);
    rename_info->FileNameLength = nameBytes;
    rename_info->RootDirectory = nullptr;
    rename_info->ReplaceIfExists = false;

    const auto status = ZwSetInformationFile(FileHandle.hFile, &ioStatusBlock, rename_info, size, FileRenameInformation);

    ExFreePool(rename_info);
    FileHandle.Close();

    if(status != STATUS_SUCCESS)
    {
        printf("0x%x : %ws\n", status, NewName);
        return status;
    }

    printf("Renamed %ws to %ws\n", OriginalName, NewName);

    return STATUS_SUCCESS;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:00:54