字符串UNICODE_STRING

在Windows下编程,根据字符串的使用分为UNICODE编程和我们平常使用的多字节编程。

我们开发Windows驱动使用的是C语言。在C语言中定义的字符串是以\0为结尾表示一个字符串的结束。

    char* pStr="www.bytekits.com";// ansi字符串
    wchar_t pwStr = L"www.bytekits.com";// unicode字符串
    size_t size = strlen(pStr);// ansi字符串求长度
    size_t wsize = wcslen(pwStr);// unicode字符串求长度

    printf("%s size is %d\n",pStr,len); //打印ansi字符串长度
    printf("%ws size is %d\n",pwStr,wlen);//打印unicode字符串求长度

从上面的代码可以看到,字符串的长度是使用strlen和wcslen函数获取的。但这两个函数获取长度的方式是从字符串的内存头开始,按字符进行计数,当遇到’\0’或L’\0’时结束。所以使用这种字符串相当的不安全。很容易导致缓冲溢出漏洞。这是因为没有任何地方确切的表明一个字符串的长度。仅仅用一个’\0’字符来标明这个字符串的结束。一旦碰到根本就没有空结束的字符串(可能是攻击者恶意的输入、或者是编程错误导致的意外),程序就可能陷入崩溃。

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

windows驱动中的字符串

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

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;
    PSTR Buffer;
} ANSI_STRING, *PANSI_STRING;

说明:这里的长度Length和MaximumLength是以字节长度计算的。

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

在上面的结构体中:

  • Length变量明确指定字符串的长度
  • MaximumLength表示实际的内存空间大小.
  • Buffer指针指向字符串的内存。

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

    UNICODE_STRING str;
    … 
    len = wcslen(str.Buffer);            // 试图求长度。
    DbgPrint(“%ws”,str.Buffer);        // 试图打印str.Buffer。

如果要用以上的方法,必须在编码中保证Buffer始终是以空结束。但这又是一个麻烦的问题。所以,使用微软提供的Rtl系列函数来操作字符串,才是正确的方法。

取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

Powered by bytekits.com,汇天下文字,成非凡梦想!!!