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

内核中char*转UNICODE_STRING失败,MMGetSystemRoutineAddress调用异常求助

问题描述

我尝试使用MmGetSystemRoutineAddress函数获取指定导入函数的地址,但该函数的参数为UNICODE_STRING指针,而我的导入名称变量类型为char*。

为了将其转换为UNICODE_STRING,我尝试使用RtlInitUnicodeString函数,但该函数接收PCWSTR类型参数,无法直接传入非const的char*值。以下是我的代码:

DbgPrint("%s", image_import_by_name->Name); // >> outputs "DbgPrintEx"
                
UNICODE_STRING routineNameByInput;
RtlInitUnicodeString(&routineNameByInput, L"DbgPrintEx");

UNICODE_STRING routineNameByVar;
RtlInitUnicodeString(&routineNameByVar, (PUNICODE_STRING)&image_import_by_name->Name);

DbgPrint("%wZ", routineNameByInput); // >> outputs "DbgPrintEx"
DbgPrint("%wZ", routineNameByVar); // >> outputs "???"
                 
MmGetSystemRoutineAddress(&routineNameByInput); // >> works perfectly
MmGetSystemRoutineAddress(&routineNameByVar); // >> bluescreens
MmGetSystemRoutineAddress((PUNICODE_STRING)&image_import_by_name->Name); // >> bluescreens

我还尝试通过给导入名称补零终止符来重新构造UNICODE_STRING,但均无效。

请问是否有简便的方法将char*转换为UNICODE_STRING?另外,RtlInitUnicodeString为何要接收PCWSTR类型参数?


解决方法与解释

1. char*转UNICODE_STRING的正确方法

内核模式下,ANSI字符串(char*)转UNICODE_STRING不能用强制类型转换(会因内存布局不匹配触发蓝屏),必须用内核提供的编码转换函数RtlAnsiStringToUnicodeString,具体步骤如下:

// 1. 初始化ANSI_STRING,绑定目标char*变量
ANSI_STRING ansiName;
RtlInitAnsiString(&ansiName, image_import_by_name->Name);

// 2. 声明并转换为UNICODE_STRING,第三个参数设为TRUE会自动分配缓冲区
UNICODE_STRING unicodeName = {0};
NTSTATUS status = RtlAnsiStringToUnicodeString(&unicodeName, &ansiName, TRUE);

if (NT_SUCCESS(status)) {
    // 3. 调用MmGetSystemRoutineAddress获取函数地址
    PVOID routineAddr = MmGetSystemRoutineAddress(&unicodeName);
    
    // 4. 用完后必须释放转换分配的缓冲区,避免内存泄漏
    RtlFreeUnicodeString(&unicodeName);
}

2. RtlInitUnicodeString参数为PCWSTR的原因

RtlInitUnicodeString的核心作用是把一个已存在的宽字符字符串直接绑定到UNICODE_STRING结构,它不会分配内存,也不做任何编码转换:

  • 用PCWSTR(const宽字符指针)是因为该函数仅读取原字符串,不会修改它,const修饰明确了这一设计意图,同时避免意外修改原字符串引发的问题。
  • 如果传入非const指针,会误导开发者认为函数会修改原字符串,但实际上它只是将指针和字符串长度写入UNICODE_STRING的结构字段。

3. 你的代码错误分析

  • 强制将char*转PUNICODE_STRING完全错误:UNICODE_STRING是包含Length、MaximumLength、Buffer的结构体,而char*只是单字节字符指针,内存布局完全不匹配,这会导致DbgPrint输出乱码,调用MmGetSystemRoutineAddress时访问非法内存触发蓝屏。
  • 手动补零无效:ANSI是单字节编码,宽字符是双字节编码,单纯补零无法完成编码转换,必须通过内核转换函数处理编码差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:22:40