您的位置:首页 > 其它

YJX_Driver_038_内核模式下的字串操作

2016-04-14 09:09 423 查看
1、

内核模式下的字串操作
  A、ASCII字符串和UNICODE字符串
  B、ANSI_STRING字符串和UNICODE_STRING字符串
  C、字符串的初始化与销毁
  D、字符串复制,比较,(大小写,整数和字串)相互转换
  E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换

【A00:50】



A、ASNI字符串和UNICODE字符串
  在C语言中,有ANSI和UNICODE 两个不同字串类型。
  char* s1="abc";       //CHAR * s1="abc"; 61
  KdPrint(("%x,%s\n",s1,s1));
  wchar_t * s2=L"abc";    //WCHAR * s2=L"abc";00 61
  KdPrint(("%x,%S\n",s2,s2));


【A01:45】



B、ANSI_STRING字符串和UNICODE_STRING字符串
  在C语言中,传统的char和wchar_t类型的字符串在使用过程中,很容易出现缓冲区溢出错误,从而导致整个系统的崩溃。一般由于程序员没有对字串长度进行校验造成的。
  所以在DDK中 提供了2个带字串长度的类型 ANSI_STRING和UNICODE_STRING
  ANSI_STRING s1 ;      //CHAR Length MaxLength PCHAR
  KdPrint(("%x, %Z\n",s1,s1));
  UNICODE_STRING s2     //WCHAR * = PWSTR
  KdPrint(("%x, %wZ\n",s2,s2));



  【A02:22】ANSI_STRING 包含了 Length(长度)、MaxLength(最大长度)、PCHAR(字串的缓冲区)

  【A02:55】驱动里 用 CHAR代替char,WCHAR代替wchar_t

  【A03:20】UNICODE_STRING 也包含了 Length(长度)、MaxLength(最大长度)、PCHAR(字串的缓冲区)

    ZC: 确定是 PCHAR?不是 PWCHAR之类的?见【A05:08】处,是PWSTR

【A03:33】第37课 代码为例

  【A03:45】37.h ==> 复制 ==> 38.h

  【A03:55】用vs2003打开

  【A04:25】写测试代码

  【A04:37】ZC: 注释掉的代码 照样能够 右击-->转到定义 ?

  【A04:45】ntdef.h ZC: 这个是 STRING 的结构,并非 ANSI_STRING,2者是一样的?

  【A05:08】ntdef.h ==> UNICODE_STRING,可以看到 这里的指针项 是 PWSTR(并非PCHAR)

【A06:08】



C、字符串的初始化与销毁
在使用ANSI_STRING和UNICODE_STRING这2个类型的字串时都需要对其进行初始化 和销毁
RtlInitAnsiString RtlInitString(&s1,"abc"); //%Z
RtlInitUnicodeString(&s2,L"abc");// %wZ
  AnsiString1.Buffer="AnsiString1字符串";
  AnsiString1.Length=strlen( AnsiString1.Buffer);
  AnsiString1.MaximumLength=BUFFER_SIZE;
    UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
    UnicodeString1.Length=wcslen(UnicodeString1.Buffer)*2;
    UnicodeString1.MaximumLength = BUFFER_SIZE;

RtlFreeAnsiString
RtlFreeUnicodeString



  【A06:15】如果我们是手工初始化的话,需要调用 RtlFreeAnsiString、RtlFreeUnicodeString,对它进行销毁

  【A06:28】如果使用 RtlInitAnsiString / RtlInitString / RtlInitUnicodeString 初始化 ANSI_STRING / UNICODE_STRING,就不需要调用 RtlFreeAnsiString、RtlFreeUnicodeString,对它进行销毁

  ZC: 何为 手动/手工 初始化 ANSI_STRING / UNICODE_STRING?如何 手动/手工 初始化 ANSI_STRING / UNICODE_STRING?

  【A06:51】这个方式 就是 手动/手工 初始化 ANSI_STRING / UNICODE_STRING :



  AnsiString1.Buffer="AnsiString1字符串";
  AnsiString1.Length = strlen( AnsiString1.Buffer);
  AnsiString1.MaximumLength = BUFFER_SIZE;

  UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
  UnicodeString1.Length = wcslen(UnicodeString1.Buffer)*2;
  UnicodeString1.MaximumLength = BUFFER_SIZE;



  【A07:03】测试

    【A07:20】直接复制这一段



#define BUFFER_SIZE 1024

#pragma INITCODE
VOID CharTest()
{
  KdPrint(("Char字串测试--Start \n"));
  PCHAR s1="abc11"; //CHAR ANSI
  KdPrint(("%x, %s\n", s1, s1));
  PWSTR s2=L"abc11"; //WCHAR UNICODE // PWSTR ==> WCHAR*
  KdPrint(("%x, %S\n", s2, s2));
  KdPrint(("Char字串测试--End \n"));
  _asm int 3
}

” 

    【A08:46】虚拟机中测试

      【A09:05】开 WInDBG

    【A09:30】WinDBG命令 "da ba045380",显示 ANSI字符串的内容(ba045380: ANSI字符串起始地址)

    【A09:35】WinDBG命令 "du ba045390",显示 宽字符串的内容(ba045390: 宽字符串起始地址)

    【A09:41】WinDBG命令 "da ba045390",只显示了 宽字符串的 第1个字符

    【A09:51】WinDBG命令 "db ba045390",显示 宽字符串的 二进制内容(按byte来显示的)

    【A10:41】第1个字 包含有汉字的话,显示还会不准确

    【A11:20】(这里是断下的状态)通过变量来查看,WinDBG命令 "da s1"

2、

D、字符串复制,比较,(大小写,整数和字串)相互转换

RtlCopyUnicodeString
RtlEqualUnicodeString
RtlUpcaseUnicodeString
RtlUnicodeStringToInteger
RtlIntegerToUnicodeString

E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换
RtlUnicodeStringToAnsiString
RtlAnsiStringToUnicodeString

//----------------------www.yjxsoft.com------------------郁金香灬技术
//文件名 "38.h"
#define BUFFER_SIZE 1024

#pragma INITCODE
VOID CharTest()
{
  KdPrint(("Char字串测试--Start \n"));
  PCHAR s1="abc11"; //CHAR ANSI
  KdPrint(("%x,%s\n",s1,s1));
  PWSTR s2=L"abc11"; //WCHAR UNICODE //PWSTR
  KdPrint(("%x,%S\n",s2,s2));
  KdPrint(("Char字串测试--End \n"));
  _asm int 3
}

//ANSI_STRING
//UNICODE_STRING
//字符串初始化测试
#pragma INITCODE
VOID StringInitTest()
{
  KdPrint(("初始化字串测试--Start \n"));
  ANSI_STRING AnsiString1={0};
  UNICODE_STRING UnicodeString1={0};

  AnsiString1.Buffer="AnsiString1字符串";
  AnsiString1.Length=strlen( AnsiString1.Buffer);
  AnsiString1.MaximumLength=BUFFER_SIZE;
  UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
  UnicodeString1.Length=wcslen(UnicodeString1.Buffer)*2;
  UnicodeString1.MaximumLength = BUFFER_SIZE;

  //方法2 用RTL函数初始化
  //初始化ANSI_STRING字符串
  //RtlInitAnsiString(&AnsiString1,"AnsiString1字符串");
  //RtlInitUnicodeString(&UnicodeString1,L"3333333333333333333322222222221111112");

  //打印ASCII字符用 %Z
  KdPrint(("%x AnsiString1: %Z\n",&AnsiString1, &AnsiString1));
  //打印UNICODE字符用 %wZ 中文字符会被截断
  KdPrint(("%x UnicodeString1:%wZ\n",&UnicodeString1,&UnicodeString1));
  KdPrint(("初始化字串测试--END \n"));
  __asm int 3
}

//D、字符串复制,比较,(大小写,整数和字串)相互转换
#pragma INITCODE
VOID StringCopyTest()
{
  KdPrint(("-------------------字串复制测试开始---------------D \n"));
  //初始化UnicodeString1
  UNICODE_STRING UnicodeString1;
  RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");

  //初始化UnicodeString2
  UNICODE_STRING UnicodeString2={0};
  UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
  UnicodeString2.MaximumLength = BUFFER_SIZE;

  //将初始化UnicodeString1拷贝到UnicodeString2
  RtlCopyUnicodeString(&UnicodeString2,&UnicodeString1);

  //分别显示UnicodeString1和UnicodeString2
  KdPrint(("字串1:%wZ\n",&UnicodeString1));
  KdPrint(("字串2:%wZ\n",&UnicodeString2));

  //销毁UnicodeString2
  //注意!调用过RtlInitUnicodeString 初始化的字串!UnicodeString1不用销毁,

  //RtlFreeUnicodeString(&UnicodeString1); 加上此行会蓝屏
  RtlFreeUnicodeString(&UnicodeString2);
  KdPrint(("-------------------字串复制测试结束--------------- \n"));
}

//字符串比较测试
#pragma INITCODE
VOID StringCompareTest()
{ KdPrint(("\n-------------------字串比较测试 开始--------------- \n"));
  //初始化UnicodeString1
  UNICODE_STRING UnicodeString1;
  RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");

  //初始化UnicodeString2
  UNICODE_STRING UnicodeString2;
  RtlInitUnicodeString(&UnicodeString2,L"UnicodeString2");
  KdPrint(("%wZ 和,%wZ",&UnicodeString1,&UnicodeString2));

  if (RtlEqualUnicodeString(&UnicodeString1,&UnicodeString2,TRUE)) //第三个参数 表示区分大小写
  {
    KdPrint(("UnicodeString1 和 UnicodeString2 相等\n"));
  }
  else
  {
    KdPrint(("UnicodeString1 和 UnicodeString2 不相等\n"));
  }
  KdPrint(("\n-------------------字串比较测试 结束--------------- \n"));
}

//字符串变大写测试
#pragma INITCODE
VOID StringToUpperTest()
{
  KdPrint(("\n-------------------字串转大写测试 开始--------------- \n"));
  //初始化UnicodeString1
  UNICODE_STRING UnicodeString1;
  RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1—Aabc");

  //变化前
  KdPrint(("UnicodeString1 初值:%wZ\n",&UnicodeString1));

  //变大写
  RtlUpcaseUnicodeString(&UnicodeString1,&UnicodeString1,FALSE);

  //变化后
  KdPrint(("UnicodeString1 转换大写后:%wZ\n",&UnicodeString1));
  KdPrint(("\n-------------------字串转大写测试 结束--------------- \n"));
}

//字符串与整型相互转化测试
#pragma INITCODE
VOID StringToIntegerTest()
{
  KdPrint(("\n-------------------字串转整数测试 开始--------------- \n"));
  //(1)字符串转换成数字
  //初始化UnicodeString1
  UNICODE_STRING UnicodeString1;
  RtlInitUnicodeString(&UnicodeString1,L"-100");

  ULONG lNumber;
  KdPrint(("待转换字串%wZ \n",&UnicodeString1));
  NTSTATUS nStatus = RtlUnicodeStringToInteger(&UnicodeString1,10,&lNumber);
  if ( NT_SUCCESS(nStatus))
  {
    KdPrint(("转换整数成功 结果=%d !\n",lNumber));
  }
  else
  {
    KdPrint(("转换整数 失败\n"));
  }

  //(2)数字转换成字符串
  //初始化UnicodeString2
  UNICODE_STRING UnicodeString2={0};
  UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
  UnicodeString2.MaximumLength = BUFFER_SIZE;
  nStatus = RtlIntegerToUnicodeString(200,10,&UnicodeString2);

  if ( NT_SUCCESS(nStatus))
  {
    KdPrint(("转换字串成功! 结果:%wZ\n",&UnicodeString2));
  }
  else
  {
    KdPrint(("转换字串 失败!\n"));
  }

  //销毁UnicodeString2
  //注意!调用过RtlInitUnicodeString 初始化的字串!UnicodeString1不用销毁,
  //RtlFreeUnicodeString(&UnicodeString1); 加上此行会蓝屏
  RtlFreeUnicodeString(&UnicodeString2);
  KdPrint(("\n-------------------字串转整数测试 结束--------------- \n"));
}

//E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换

//ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试
#pragma INITCODE
VOID StringConverTest()
{
  KdPrint(("\n-------------------ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试 开始--------------- \n"));
  //(1)将UNICODE_STRING字符串转换成ANSI_STRING字符串
  //初始化UnicodeString1
  UNICODE_STRING UnicodeString1;
  RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");

  ANSI_STRING AnsiString1;
  NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1,&UnicodeString1,TRUE);

  if ( NT_SUCCESS(nStatus))
  {
    KdPrint(("RtlUnicodeStringToAnsiString 转换成功 结果=%Z\n",&AnsiString1));
  }
  else
  {
    KdPrint(("RtlAnsiStringToUnicodeString 转换失败 !\n"));
  }

  //销毁AnsiString1
  RtlFreeAnsiString(&AnsiString1);

  //(2)将ANSI_STRING字符串转换成UNICODE_STRING字符串
  //初始化AnsiString2
  ANSI_STRING AnsiString2;
  RtlInitString(&AnsiString2,"AnsiString2");

  UNICODE_STRING UnicodeString2;
  nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2,&AnsiString2,TRUE);

  if ( NT_SUCCESS(nStatus))
  {
    KdPrint(("RtlAnsiStringToUnicodeString转换成功 结果=%wZ\n",&UnicodeString2));
  }
  else
  {
    KdPrint(("RtlAnsiStringToUnicodeString字串转换失败!\n"));
  }

  //销毁UnicodeString2
  RtlFreeUnicodeString(&UnicodeString2);
  KdPrint(("\n-------------------ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试 结束--------------- \n"));

}

VOID StringTestAll()
{
  //Char类字符串测试
  CharTest();
  //字串初始化测试
  StringInitTest();

  //字符串拷贝测试
  StringCopyTest();

  //字符串比较测试
  StringCompareTest();

  //字符串变大写测试
  StringToUpperTest();

  //字符串与整型相互转化测试
  StringToIntegerTest();

  //ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试
  StringConverTest();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: