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

「爱情、让人受尽委屈。」 2022-08-04 11:49 303阅读 0赞

1,使用字符串结构

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

  1. char *str ={"my first string"}; //ANSI字符串
  2. wchar_t *wstr = {L"my first string"}; //UNICODE字符串
  3. size_t len = strlen(str); //求出ANSC字符长度
  4. size_t wLen = wcslen(wstr); // 求出unicode字符串长度
  5. printf("%s %ws %d %d", str, wstr, len, wLen); //---输出两种那个字符串

但是,实际上这种字符串相当不安全,很容易导致缓冲溢出漏洞。因为没有任何地方确切的表明一个字符串的长度。仅仅用一个”\0”字符来表明字符串的结束。一旦碰到根本就没有空结束的字符串(坑是攻击者的恶意输入,或者是编程错误导致的意外),程序就可能崩溃。

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

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

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

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

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

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

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

  1. UNICODE_STRING str;
  2. ........
  3. len = wclen(str.Buffer); ///---求长度,
  4. DbgPrin("%ws", str.Buffer); ///---输出字符串

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

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

发表评论

表情:
评论列表 (有 0 条评论,303人围观)

还没有评论,来说两句吧...

相关阅读