Unicode_String Ansi_String 内核字符串操作

本文介绍了Windows XP SP1及后续系统中引入的安全字符串函数,以防止缓冲区溢出问题。这些函数考虑了目标缓冲区大小,确保NULL终止,并提供了Unicode和ANSI版本。在内核驱动开发中,可以通过内联或链接库方式引入这些函数,并需要注意与传统c/c++字符串函数的互斥。最大字符串长度为STRSAFE_MAX_CCH。
摘要由CSDN通过智能技术生成
typedef struct _UNICODE_STRING {
  USHORT  Length;//字节数,不是字符数 一定要* sizeof(WCHAR)
  USHORT  MaximumLength;//字节数,不是字符数 一定要* sizeof(WCHAR)
  PWSTR  Buffer;//非零结尾,中间也可能含有零
} UNICODE_STRING, *PUNICODE_STRING;

//常用函数
RtlInitUnicodeString(&uStr1, str1);//注意 这个函数并不是将str1拷贝到uStr1.buffer 而是将buffer指向str1 所以如果这个buffer是程序员为它分配的 那么不能释放 也不能为它分配 一是BSOD 二是内存泄露
RtlCopyUnicodeString(&uStr1, &uStr2);//需要注意这里copy uStr1的buffer必须自己分配 如果后面跟着的是常量 
RtlAppendUnicodeToString(&uStr1, str1);//注意 uStr1的buffer必须自己分配
RtlAppendUnicodeStringToString(&uStr1, &uStr2);//注意 uStr1的buffer必须自己分配
RtlCompareUnicodeString(&uStr1, &uStr2, TRUE/FALSE);//比较 TRUE 指定大小写
RtlAnsiStringToUnicodeString(&uStr1, &aStr1, TRUE/FALSE);// TRUE 指定buffer系统分配 如果是TRUE 则用后需要调用RtlFreeUnicodeString
RtlFreeUnicodeString(&uStr1);


这些函数调用时系统会自动检测是否超过buffer 相对来说安全一些

#include <ntstrsafe.h> 
RtlUnicodeStringInit(&uStr1, str1);
RtlUnicodeStringCopy(&uStr1, &uStr2);
RtlUnicodeStringCat(&uStr1, &uStr2);
#define NTSTRSAFE_UNICODE_STRING_MAX_CCH    (0xffff / sizeof(wchar_t))  (32767个字符)



快速初始化一个UnicodeString字符串

DECLARE_CONST_UNICODE_STRING(ustrTest,L”Hello, world!”);
//这个等同于
UNICODE_STRING ustrTest = {0};
WCHAR *szHello = L”Hello, world!”;
RtlInitUnicodeString(&ustrTest, szHello);
//Length:wcslen(szHello)*sizeof(WCHAR)
//MaximumLength:(wcslen(szHello)+1)*sizeof(WCHAR);

初始化方式:栈上buffer
UNICODE_STRING ustrTest = {0};
WCHAR szHello[512] = L”Hello, world!”;
//Length:wcslen(szHello)*sizeof(WCHAR)
//MaximumLength:(wcslen(szHello)+1)*sizeof(WCHAR);
RtlInitUnicodeString(&ustrTest, szHello);

或者
UNICODE_STRING ustrTest = {0};
WCHAR szHello[512] = L”Hello, world!”;
ustrTest.Buffer = szHello;
ustrTest.Length = wcslen(L”hello,world!”)*sizeof(WCHAR);
ustrTest.MaximumLength = sizeof(szHello);

初始化方式:堆上buffer
UNICODE_STRING ustrTest = {0};
ULONG ulLength = (wcslen(L"Hello world") + 1)*sizeof(WCHAR);
ustrTest.Buffer = ExAllocatePoolWithTag(PagedPool, MAX_PATH*sizeof(WCHAR), 'POCU');
if (ustrTest.Buffer == NULL)
{
	return;
}
RtlZeroMemory(ustrTest.Buffer, MAX_PATH*sizeof(WCHAR));
wcscpy(ustrTest.Buffer, L"Hello, world");//必须使用内存拷贝类函数
ustrTest.Length = ulLength;
ustrTest.MaximumLength = MAX_PATH*sizeof(WCHAR);
DbgPrint("%wZ\n", &ustrTest);
ExFreePool(ustrTest.Buffer);//这样释放就没有问题啦

下个这个演示了UnicodeString的一个蓝屏
UNICODE_STRING ustrTest = {0};
ustrTest.Buffer = ExAllocatePoolWithTag(PagedPool, 
		(wcslen(L"Nice to meet u") + 1)*sizeof(WCHAR), 'POCU');
if (ustrTest.Buffer == NULL)
{
	return;
}
RtlZeroMemory(ustrTest.Buffer, (wcslen(L"Hello, world") + 1)*sizeof(WCHAR));
RtlInitUnicodeString(&ustrTest, L”Hello, world”);//这个时候userTest.buffer指向了hello wolrd的地址 导致了内存泄露 在下面调用ExFree的时候还会蓝屏
DbgPrint("%wZ\n", & ustrTest);
ExFreePool(ustrTest.Buffer); //蓝屏 释放常量区内存

UNICODE_STRING常见问题
计算length的时候,少了*sizeof(WCHAR)
计算字符数的时候,少了/sizeof(WCHAR)
使用了wcscmp/wcscpy等函数操作
更长远的说,缓冲大小长度问题,就是驱动容易出错的问题
WCHAR wszPath[MAX_PATH];
MAX_PATH? MAX_PATH 在windows上是260  在linux是256
sizeof(wszPath)或者MAX_PATH*sizeof(WCHAR) 这才是字符长度
MAX_PATH*2? 也是可以的


使用Copy Append时目标的buffer不是自行分配的 必定失败 如下:
	RtlInitUnicodeString(&uStr1, L"hello"); //直接将L"hello"字符串的指针赋给了uStr.Buffer;
	RtlInitUnicodeString(&uStr2, L"Goodbye");


	DbgPrint("%ws\n", L"hello world");
	DbgPrint("uStr1=%wZ\n", &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值