定义字符串
内核中对字符串的操作没有stdio库里的那些函数,取而代之的是内核安全字符串,每个字符串是一个结构体。主要是利用几个内核API进行操作。
RtlInitAnsiString(&ansi, char_string);
RtlInitUnicodeString(&unicode, wchar_string);
RtlUnicodeStringInit(&str, L"hello kernel");
// 这里网上说改变原字符串会影响新的,但是测试发现不会,比较迷惑
定义上差不多,可以采用普通的定义方式,也可以采用内核特有的定义方式。
//typedef struct _UNICODE_STRING
//{
// USHORT Length;
// USHORT MaxmumLength;
// PWSTR Buffer;
//} UNICODE_STRING;
// 定义内核字符串,其实都是结构体格式
ANSI_STRING ansi;
UNICODE_STRING unicode;
UNICODE_STRING str;
// 定义普通字符串
char* char_string = "hello lyshark";
wchar_t* wchar_string = (WCHAR*)"hello lyshark";
完整的测试代码如下,注意的是需要引用<ntstrsafe.h>
这个库。
#include <ntifs.h>
#include <ntddk.h>
#include <windef.h>
// 使用RtlUnicodeStringInit函数需要这个头文件,定义了内核安全字符串
#include <ntstrsafe.h>
NTSTATUS UseKernelString()
{
//typedef struct _UNICODE_STRING
//{
// USHORT Length;
// USHORT MaxmumLength;
// PWSTR Buffer;
//} UNICODE_STRING;
// 定义内核字符串,其实都是结构体格式
ANSI_STRING ansi;
UNICODE_STRING unicode;
UNICODE_STRING str;
// 定义普通字符串
char* char_string = "hello lyshark";
wchar_t* wchar_string = (WCHAR*)"hello lyshark";
// 初始化字符串,相当于是把第二个参数的字符在复制到第一个参数,符合内核安全的格式
RtlInitAnsiString(&ansi, char_string);
RtlInitUnicodeString(&unicode, wchar_string);
RtlUnicodeStringInit(&str, L"hello lyshark");
// 长度除了unicode没显示不知道为啥,第一个是13,第三个26,符合预期
DbgPrint("输出ANSI: %Z | %d\n", &ansi, ansi.Length);
DbgPrint("输出WCHAR: %Z | %d \n", &unicode, unicode.Length);
DbgPrint("输出字符串: %wZ | %d \n", &str, str.Length);
// 改变原始字符串,不影响上面的初始化的字符串
char_string[0] = 'A'; // char类型每个占用1字节
char_string[1] = 'B';
wchar_string[0] = (WCHAR)'A'; // wchar类型每个占用2字节
wchar_string[2] = (WCHAR)'B';
DbgPrint("输出ANSI: %Z \n", &ansi);
DbgPrint("输出WCHAR: %Z \n", &unicode);
DbgPrint("输出字符串: %wZ \n", &str);
return STATUS_SUCCESS;
}
NTSTATUS unload(PDRIVER_OBJECT driver)
{
DbgPrint("Driver unload success..");
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
driver->DriverUnload = unload;
DbgPrint("2.5 Hello World\n");
if (UseKernelString())
{
DbgPrint("Call UseKernelString function succeed \n");
}
return STATUS_SUCCESS;
}