三、字符串操作

    技术2023-06-18  66

    1、UNICODE_STRING

    ​ windows内核编码字符集采用unicode字符集,字符串处理使用UNICODE_STRING,是一个结构体,定义如下:

    typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; #ifdef MIDL_PASS [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer; #else // MIDL_PASS _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer; #endif // MIDL_PASS } UNICODE_STRING;

    Length 字符串长度,MaximumLength 字符串缓冲区长度,Buffer 字符串缓冲区指针变量。

    2、字符串声明与初始化

    ​ 第一种方式,以局部变量方式,让UNICODE_STRING的Buffer指向一个已声明的WCHAR数组。

    UNICODE_STRING strDest; WCHAR dest_buf[256]; RtlInitEmptyUnicodeString(&strDest, dest_buf, 256*sizeof(WCHAR));

    RtlInitEmptyUnicodeString去初始化strDest。

    ​ 第二种方式,使用RtlInitUnicodeString函数去初始化一个UNICODE_STRING变量,给其复制,分配空间

    UNICODE_STRING strSource; RtlInitUnicodeString(&strSource, L"测试字符串连接");

    ​ 第三种方式,动态申请空间,类似应用程序的malloc函数。

    UNICODE_STRING strDest; strDest.Length = 0; strDest.MaximumLength = sizeof(WCHAR) * 1024; strDest.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR)*1024, MEMTAG); if (!strDest.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; }

    3、字符串拷贝

    UNICODE_STRING strSource; RtlInitUnicodeString(&strSource, L"测试字符串连接"); KdPrint(("source is %wZ字节长度%d 最大长度%d.\n", &strSource, strSource.Length, strSource.MaximumLength)); RtlCopyUnicodeString(&strDest,&strSource); KdPrint(("dest is %wZ 字节长度%d 最大长度%d.\n", strDest, strDest.Length, strDest.MaximumLength));

    unicode格式化字符串输出使用%wZ,ansi格式化字符串输出使用%x

    4、字符串连接

    UNICODE_STRING strTmp; RtlInitUnicodeString(&strTmp, L"this is a new string"); ntres = RtlAppendUnicodeStringToString(&strDest, &strTmp);

    字符串连接使用,根据第二个参数类型而定,如果是unicode,选择RtlAppendUnicodeStringToString,如果是ansi,选择RtlAppendUnicodeToString。

    5、字符串比较

    UNICODE_STRING uCp1, uCp2; RtlInitUnicodeString(&uCp1, L"hello a world."); RtlInitUnicodeString(&uCp2, L"hello b world."); LONG lRet = RtlCompareUnicodeString(&uCp1, &uCp2, TRUE); if (lRet > 0) { KdPrint(("%wZ 大于 %wZ .", &uCp1, &uCp2)); } else if(lRet < 0) { KdPrint(("%wZ 小于 %wZ .", &uCp1, &uCp2)); } else { KdPrint(("%wZ 等于 %wZ .", &uCp1, &uCp2)); }

    RtlCompareUnicodeString类似应用程序的strcmp函数,返回值为三种值,大于0,等于0,小于0,其第三个参数表示是否大小写敏感。

    6、UNICODE_STRING与ANSI_STRING互转

    //unicode与多字节互转 UNICODE_STRING uniTrans; RtlInitUnicodeString(&uniTrans, L"test unicode to ansi"); ANSI_STRING ansiTrans; RtlUnicodeStringToAnsiString(&ansiTrans, &uniTrans, TRUE); KdPrint(("%wZ to ansi is %Z", &uniTrans, &ansiTrans)); RtlAnsiStringToUnicodeString(&uniTrans, &ansiTrans, TRUE); KdPrint(("%Z to ansi is %wZ", &ansiTrans, &uniTrans));

    7、上述测试完整代码

    #include <ntddk.h> #define MEMTAG 'test' VOID DriverUnload(PDRIVER_OBJECT pDriverObject) { KdPrint(("卸载驱动成功\n")); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING reg_path) { NTSTATUS ntres; KdPrint(("驱动加载成功\n")); HANDLE hPid = PsGetCurrentProcessId(); KdPrint(("当前进程id:%d\n",(int)hPid)); UNICODE_STRING strDest; strDest.Length = 0; strDest.MaximumLength = sizeof(WCHAR) * 1024; strDest.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR)*1024, MEMTAG); if (!strDest.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } UNICODE_STRING strSource; RtlInitUnicodeString(&strSource, L"测试字符串连接"); KdPrint(("source is %wZ字节长度%d 最大长度%d.\n", &strSource, strSource.Length, strSource.MaximumLength)); RtlCopyUnicodeString(&strDest,&strSource); KdPrint(("dest is %wZ 字节长度%d 最大长度%d.\n", strDest, strDest.Length, strDest.MaximumLength)); UNICODE_STRING strTmp; RtlInitUnicodeString(&strTmp, L"this is a new string"); ntres = RtlAppendUnicodeStringToString(&strDest, &strTmp); if (NT_SUCCESS(ntres)) { } else { KdPrint(("拼接失败")); } KdPrint(("打印 %wZ 字节长度%d 最大长度%d.\n", &strDest, strDest.Length, strDest.MaximumLength)); //比较字符串 UNICODE_STRING uCp1, uCp2; RtlInitUnicodeString(&uCp1, L"hello a world."); RtlInitUnicodeString(&uCp2, L"hello b world."); LONG lRet = RtlCompareUnicodeString(&uCp1, &uCp2, TRUE); if (lRet > 0) { KdPrint(("%wZ 大于 %wZ .", &uCp1, &uCp2)); } else if(lRet < 0) { KdPrint(("%wZ 小于 %wZ .", &uCp1, &uCp2)); } else { KdPrint(("%wZ 等于 %wZ .", &uCp1, &uCp2)); } //unicode与多字节互转 UNICODE_STRING uniTrans; RtlInitUnicodeString(&uniTrans, L"test unicode to ansi"); ANSI_STRING ansiTrans; RtlUnicodeStringToAnsiString(&ansiTrans, &uniTrans, TRUE); KdPrint(("%wZ to ansi is %Z", &uniTrans, &ansiTrans)); RtlAnsiStringToUnicodeString(&uniTrans, &ansiTrans, TRUE); KdPrint(("%Z to ansi is %wZ", &ansiTrans, &uniTrans)); if (strDest.Buffer != NULL) { ExFreePool(strDest.Buffer); strDest.Length = strDest.MaximumLength = 0; } pDriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; }

    8、测试结果

    Processed: 0.039, SQL: 9