windows内核编程基础篇之字符串的处理

1,使用字符串结构

常常使用传统C语言的程序员比较喜欢用如下的方法定义和使用字符串:

char *str ={"my first string"};           //ANSI字符串
wchar_t *wstr = {L"my first string"};  //UNICODE字符串
size_t len = strlen(str);                    //求出ANSC字符长度
size_t wLen = wcslen(wstr);            // 求出unicode字符串长度
printf("%s %ws %d %d", str, wstr, len, wLen);                                       //---输出两种那个字符串
但是,实际上这种字符串相当不安全,很容易导致缓冲溢出漏洞。因为没有任何地方确切的表明一个字符串的长度。仅仅用一个"\0"字符来表明字符串的结束。一旦碰到根本就没有空结束的字符串(坑是攻击者的恶意输入,或者是编程错误导致的意外),程序就可能崩溃。

使用高级C++特性的编码者则容易忽略这个问题,以为常常是使用 std::string 和 CString 这样的高级类,不用去担忧字符串的安全性。

在驱动开发中,一般不再用空来表示一个字符串的结束,而是定义了如下的一个结构体:

typedef struct  _UNICODE_STRING
{
	USHORT Length;		//---字符串的长度(字节数)
	USHORT MaximumLength;	//---字符串缓冲区的长度(字节数)
	PWSTR Buffer;			//---字符串缓冲区。
}UNICODE_STRING, *PUNICODE_STRING;

以上是unicode字符串,一个字符为双字节。与之对应的还有一个ANSI字符串,ANSI字符串就是c语言中常用的单字节标识一个字符的窄字符串。

typedef struct  _STRING
{
	USHORT Length;		//---字符串的长度(字节数)
	USHORT MaximumLength;	//---字符串缓冲区的长度(字节数)
	PWSTR Buffer;			//---字符串缓冲区。
}ANSI_STRING, *PANSI_STRING;

在驱动开发者中,到处可见的是UNicode字符串,因此可以说,Windows的内核是使用unicode编码的。ANSI_STRING 仅仅在某些碰到窄字符的场合使用,而且这种场合非常罕见。

UNICODE_STRING 并不保证Buffer中的字符串是以空结束的。因此,类下面的做法都是错误的。可能导致内核崩溃:

UNICODE_STRING str;
........
len = wclen(str.Buffer);		///---求长度,
DbgPrin("%ws", str.Buffer);	///---输出字符串
如果要使用以上的方法,必须在编码中保证buffer始终是以空结束,但这又是一个麻烦的问题。所以,使用微软提供的Rtl系列函数来操作字符串,才是正确的方法。

                                           --------------------摘自《[天书夜读-从汇编语言到Windows内核编程]》

你可能感兴趣的:(Windows字符串的处理)