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

使用RtlAppendUnicodeStringToString导致内核崩溃的驱动问题求助

Windows驱动中RtlAppendUnicodeStringToString多次拼接导致内核崩溃的解决方法

崩溃原因分析

问题代码里有两个致命错误:

  1. NewBuffer是用RTL_CONSTANT_STRING初始化的,这会生成一个只读的栈上常量字符串,缓冲区根本不可写。RtlAppendUnicodeStringToString需要目标字符串有可写缓冲区,强行写入直接触发内存访问违例。
  2. 手动修改NewBuffer.MaximumLength但实际缓冲区物理大小未变,拼接时必然缓冲区溢出,破坏内核栈或触发页错误,直接导致崩溃。

替换后的代码能运行但功能不对,是因为直接修改了ImagePathName的缓冲区,既没给路径加引号,也没正确构造CommandLine格式,完全没实现预期需求。

正确实现代码

KeStackAttachProcess(Process, &apcstate);
PPEB peb = PsGetProcessPeb(Process);
if (peb != NULL)
{
    const UNICODE_STRING prefix = RTL_CONSTANT_STRING(L"\"");
    const UNICODE_STRING imagePath = peb->ProcessParameters->ImagePathName;
    const UNICODE_STRING suffix = RTL_CONSTANT_STRING(L"\" --DEBUGMODE");

    // 计算总字节数:前缀+路径+后缀,额外留空字符的空间
    const USHORT totalLength = prefix.Length + imagePath.Length + suffix.Length;
    const USHORT totalMaxLength = totalLength + sizeof(WCHAR);

    // 在目标进程堆上分配可写缓冲区(必须用进程自己的堆,否则进程访问不到)
    PWSTR buffer = (PWSTR)RtlAllocateHeap(peb->ProcessHeap, HEAP_ZERO_MEMORY, totalMaxLength);
    if (buffer != NULL)
    {
        UNICODE_STRING newCommandLine = {0};
        newCommandLine.Buffer = buffer;
        newCommandLine.MaximumLength = totalMaxLength;
        newCommandLine.Length = 0;

        // 依次拼接各部分
        RtlAppendUnicodeStringToString(&newCommandLine, &prefix);
        RtlAppendUnicodeStringToString(&newCommandLine, &imagePath);
        RtlAppendUnicodeStringToString(&newCommandLine, &suffix);

        // 释放原CommandLine的缓冲区,避免内存泄漏
        if (peb->ProcessParameters->CommandLine.Buffer != NULL)
        {
            RtlFreeHeap(peb->ProcessHeap, 0, peb->ProcessParameters->CommandLine.Buffer);
        }

        // 更新进程的CommandLine参数
        peb->ProcessParameters->CommandLine = newCommandLine;
    }
}
KeUnstackDetachProcess(&apcstate);

关键注意事项

  • 缓冲区必须在目标进程地址空间:PEB和ProcessParameters属于目标进程,内核栈内存其他进程无法访问,必须调用RtlAllocateHeap用进程自己的堆分配内存。
  • 提前计算总长度:确保分配的缓冲区足够容纳所有内容和末尾空终止符,避免拼接时溢出。
  • 释放原缓冲区:替换CommandLine前要释放原来的缓冲区,防止进程堆内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:01:59