字符串本质上就是一段内存,之所以和内存使用分开讲,是因为内核里的字符串太有花样了,细数下来竟然有 4 种字符串!这四种字符串,分别是:CHAR、WCHAR、ANSI_STRING、UNICODE_STRING。当然,内核里使用频率最多的是 UNICODE_STRING,其次是 WCHAR,再次是 CHAR,而 ANSI_STRING,则几乎没见过有什么内核函数使用。
但其实这四种字符串也不是完全独立的,ANSI_STRING 可以看成是CHAR的安全性扩展,UNICODE_STRING 可以看成是 WCHAR的安全性扩展。CHAR,可以理解成 CHAR 数组,本质上来说是一个地址,它的有效长度是多少?不知道。字符串有多长?不清楚,遇到0 就当成是字符串的结尾。综上所述,CHAR的安全性是非常糟糕的,如果内核使用 CHAR作为主要字符串,那么会非常不稳定。WCHAR和 CHAR类似,和 CHAR的唯一不同在于一个WCHAR 占 2 个字节,而一个 CHAR 只占 1 个字节。所以,WCHAR*的安全性也是非常糟糕的。微软为了安全性着想,推出了这两种字符串的扩展集,ANSI_STRING和UNICODE_STRING。ANSI_STRING 和 UNICODE_STRING 都是结构体。定义如下:
typedef struct _ANSI_STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} ANSI_STRING, *PANSI_STRING;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWCHAR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
可以看到,ANSI_STRING 和 UNICODE_STRING 的结构体大小是一样的,唯一不同在于第三个成员,他们分别对应 CHAR和 WCHAR。它们的第一和第二个成员分别代表字符串的长度和内存的有效长度。比如 BUFFER 的长度是 260 字节,而 BUFFER 只是一个单词”FUCK”,则 ANSI_STRING 的 Length=4 、 MaximumLength=260 ; UNICODE_STRING 的 Length=8 、MaximumLength=260。另外需要注意的是,CHAR和 WCHAR都是以 0 结尾的(CHAR以 1个0 结尾,WCHAR以 2 个0 结尾),但 ANSI_STRING 和 UNICODE_STRING 不一定以 0 结尾。因为有了长度的说明,就不需要用特殊标识符来表示结尾了。有些自以为是的人直接把ANSI_STRING 或 UNICODE_STRING 的 BUFFER 当作字符串用,是极端错误的。
下面是一些字符串常规操作
1.字符串初始化、2.字符串拷贝、3.字符串比较、4.字符串变大写、5.字符串与整型相
互转化、6. ANSI_STRING 字符串与 UNICODE_STRING 字符串相互转换。
//1.字符串初始化
VOID StringInitTest()
{
//(1)用 RtlInitAnsiString 初始化字符串
ANSI_STRING AnsiString1;
CHAR * string1= "hello";
//初始化 ANSI_STRING 字符串
RtlInitAnsiString(&AnsiString1,string1);
KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印 hello
string1[0]='H';
string1[1]='E';
string1[2]='L';
string1[3]='L';
string1[4]='O';
//改变 string1,AnsiString1 同样会导致变化
KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印 HELLO
//(2)程序员自己初始化字符串
#define BUFFER_SIZE 1024
UNICODE_STRING UnicodeString1 = {0};
//设置缓冲区大小
UnicodeString1.MaximumLength = BUFFER_SIZE;
//分配内存
UnicodeString1.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
WCHAR* wideString = L"hello";
//设置字符长度,因为是宽字符,所以是字符长度的 2 倍
UnicodeString1.Length = 2*wcslen(wideString);
//保证缓冲区足够大,否则程序终止
ASSERT(UnicodeString1.MaximumLength>=UnicodeString1.Length);
//内存拷贝,
RtlCopyMemory(UnicodeString1.Buffer,wideString,UnicodeString1.Length);
//设置字符长度
UnicodeString1.Length = 2*wcslen(wideString);
KdPrint(("UnicodeString:%wZ\n",&UnicodeString1));
//清理内存
ExFreePool(UnicodeString1.Buffer);
UnicodeString1.Buffer = NULL;
UnicodeString1.Length = UnicodeString1.MaximumLength = 0;
}
//2.字符串拷贝
VOID StringCopyTest()
{
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");
//初始化 UnicodeString2
UNICODE_STRING UnicodeString2={0};
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE;
//将初始化 UnicodeString2 拷贝到 UnicodeString1
RtlCopyUnicodeString(&UnicodeString2,&UnicodeString1);
//分别显示 UnicodeString1 和 UnicodeString2
KdPrint(("UnicodeString1:%wZ\n",&UnicodeString1));
KdPrint(("UnicodeString2:%wZ\n",&UnicodeString2));
//销毁 UnicodeString2
//注意!!UnicodeString1 不用销毁
RtlFreeUnicodeString(&UnicodeString2);
}
//3.字符串比较
VOID StringCompareTest()
{
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");
//初始化 UnicodeString2
UNICODE_STRING UnicodeString2;
RtlInitUnicodeString(&UnicodeString1,L"Hello");
if (RtlEqualUnicodeString(&UnicodeString1,&UnicodeString2,TRUE))
KdPrint(("UnicodeString1 and UnicodeString2 are equal\n"));
else
KdPrint(("UnicodeString1 and UnicodeString2 are NOT equal\n"));
}
//4.字符串变大写
VOID StringToUpperTest()
{
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
UNICODE_STRING UnicodeString2;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");
//变化前
DbgPrint("UnicodeString1:%wZ\n",&UnicodeString1);
//变大写
RtlUpcaseUnicodeString(&UnicodeString2,&UnicodeString1,TRUE);
//变化后
DbgPrint("UnicodeString2:%wZ\n",&UnicodeString2);
//销毁 UnicodeString2(UnicodeString1 不用销毁)
RtlFreeUnicodeString(&UnicodeString2);
}
//5.字符串与整型相互转化
VOID StringToIntegerTest()
{
//(1)字符串转换成数字
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"-100");
ULONG lNumber;
NTSTATUS nStatus = RtlUnicodeStringToInteger(&UnicodeString1,10,&lNumber);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("Conver to integer succussfully!\n"));
KdPrint(("Result:%d\n",lNumber));
}
else
{
KdPrint(("Conver to integer unsuccessfully!\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(("Conver to string succussfully!\n"));
KdPrint(("Result:%wZ\n",&UnicodeString2));
}
else
{
KdPrint(("Conver to string unsuccessfully!\n"));
}
//销毁 UnicodeString2
//注意!!UnicodeString1 不用销毁
RtlFreeUnicodeString(&UnicodeString2);
}
//6. ANSI_STRING 字符串与 UNICODE_STRING 字符串相互转换
VOID StringConverTest()
{
//(1)将 UNICODE_STRING 字符串转换成 ANSI_STRING 字符串
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");
ANSI_STRING AnsiString1;
NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1,&UnicodeString1,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("Conver succussfully!\n"));
KdPrint(("Result:%Z\n",&AnsiString1));
}
else
{
KdPrint(("Conver unsuccessfully!\n"));
}
//销毁 AnsiString1
RtlFreeAnsiString(&AnsiString1);
//(2)将 ANSI_STRING 字符串转换成 UNICODE_STRING 字符串
//初始化 AnsiString2
ANSI_STRING AnsiString2;
RtlInitString(&AnsiString2,"Hello World");
UNICODE_STRING UnicodeString2;
nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2,&AnsiString2,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("Conver succussfully!\n"));
KdPrint(("Result:%wZ\n",&UnicodeString2));
}
else
{
KdPrint(("Conver unsuccessfully!\n"));
}
//销毁 UnicodeString2
RtlFreeUnicodeString(&UnicodeString2);
}
//UNICODE_STRINGz 转换为 CHAR*
//输入 UNICODE_STRING 的指针,输出窄字符串,BUFFER 需要已经分配好空间
VOID UnicodeToChar(PUNICODE_STRING dst, char *src)
{
ANSI_STRING string;
RtlUnicodeStringToAnsiString(&string,dst, TRUE);
strcpy(src,string.Buffer);
RtlFreeAnsiString(&string);
}
//WCHAR*转换为 CHAR*
//输入宽字符串首地址,输出窄字符串,BUFFER 需要已经分配好空间
VOID WcharToChar(PWCHAR src, PCHAR dst)
{
UNICODE_STRING uString;
ANSI_STRING aString;
RtlInitUnicodeString(&uString,src);
RtlUnicodeStringToAnsiString(&aString,&uString,TRUE);
strcpy(dst,aString.Buffer);
RtlFreeAnsiString(&aString);
}
//CHAR*转 WCHAR*
//输入窄字符串首地址,输出宽字符串,BUFFER 需要已经分配好空间
VOID CharToWchar(PCHAR src, PWCHAR dst)
{
UNICODE_STRING uString;
ANSI_STRING aString;
RtlInitAnsiString(&aString,src);
RtlAnsiStringToUnicodeString(&uString,&aString,TRUE);
wcscpy(dst,uString.Buffer);
RtlFreeUnicodeString(&uString);
}
版权属于: 顾锦歌——发现生活的美!
本文链接: https://main.huat.fun/index.php/archives/32/
本文最后更新于2022年05月09日 ,已超过989天没有更新,若内容或图片失效,请留言反馈。
本文允许转载,但请在转载时请以超链接或其它形式标明文章出处
Your go-to source for leads. We can provide business to business and business to consumer leads, custom-tailored to your needs. CustomDatabases.org
Hi, It is with sad regret to inform you TopDataList.com is shutting down. We are ceasing operations on TopDataList.com and have made our leads available at a $149 once off fee. Visit us on TopDataList.com Regards, Otilia
Hello, from CustomData.click we are a provider of unique databases that could help your business. Please visit us at CustomData.click to see if we can help you. Regards, Ervin
Hello. It is with sad regret to inform you TopDataList.com is shutting down. We have made all our databases available for you for a once off fee. Visit us on TopDataList.com
ZippyLeads.org is running an easter special till the 18th of April. Get all the leads you need for your company with our easter special.
Hello. My name is Johan Fourie and I am looking to sell DataList.biz. We are a data company that has been in the industry for 12 years. We do around $170k/year in revenue. 1) I am looking to sell 50% of the business for $5k. 2) It would be helpful if you are knowledgeable about the Data Business. 3) I am looking for someone that is willing to take over administration, support, client relations. 4) I will continue to do the marketing for new products. 5) You will accept all future income and pay me from it. Please contact me on WhatsApp +27 72 280 1952 or my personal email: johanfourieinc@gmail.com if you are interested in this and we can have a call. Regards, Johan Fourie
Hi, I am interested in some of your products. Please give me a call on +1 304-873-4360
欢迎加入 Typecho 大家族