我尝试使用 MMGetSystemRoutineAddress 函数查找给定导入的地址。 唯一的问题是这个函数接受一个指向 UNICODE_STRING 的指针,而我的导入名称变量的类型为 char*。
为了将其转换为 UNICODE_STRING,我尝试使用函数 RtlInitUnicodeString。 这里的问题是这个函数需要一个 PCWSTR 并且我读到不可能为此使用非常量值。 这是我的代码:
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(&routineNameByInput); // >> bluescreens
MmGetSystemRoutineAddress((PUNICODE_STRING)&image_import_by_name->Name); // >> bluescreens
我还尝试通过零终止导入名称来重新创建 UNICODE_STRING,但没有任何效果。
没有一些简单的方法可以将 char* 转换为 UNICODE_STRING 吗?
为什么 RtlInitUnicodeString 甚至首先采用 PCWSTR?
快速谷歌搜索
windows ansi to unicode kernel mode
揭示this
RtlAnsiStringToUnicodeString 函数(wdm.h)
RtlAnsiStringToUnicodeString 将给定的 ANSI 源字符串转换为 Unicode 字符串。
定义:
NTSYSAPI NTSTATUS RtlAnsiStringToUnicodeString(
[in, out] PUNICODE_STRING DestinationString,
[in] PCANSI_STRING SourceString,
[in] BOOLEAN AllocateDestinationString
);
听起来这正是你想要的。
为什么 RtlInitUnicodeString 甚至首先采用 PCWSTR?
无论出于何种原因,家人o
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
内核传递 UNICODE_STRING 的实例和
{length, capacity, ptr}
的三重奏可能是为了避免对字符串进行不必要的 wcslen/strlen 扫描。但是为了初始化 UNICODE_STR
,他们提供了辅助函数 RtInitUnicodeString
来转换 PWCSTR (const wchar_t*) 以正确初始化它。
所以如果你有一个 ascii/ansi 字符串,你可能会这样做:
ANSI_STRING astr = {0};
UNICODE_STRING ustr = {0};
RtlInitAnsiString(&astr, image_import_by_name.Name); // assumes Name is char*
RtlAnsiStringToUnicodeString(&ustr, &astr, TRUE);
MmGetSystemRoutineAddress(&ustr);
RtlFreeUnicodeString(&ustr);