驱动学习6----字符串系列函数
6.1.2 ANSI_STRING字符串和UNICOCE_STRING
用KdPrint表示分别%Z和%wZ表示
如:
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status;
KdPrint(("Enter DriverEntryp RegistryPath:%wZ\n",pRegistryPath) );要注意的是%wZ,w必须是小写,如果是%WZ,是不会打印的.
6.1.3字符串初始化
VOID
RtlInitAnsiString(
IN OUT PANSI_STRING DestinationString,
IN PCSZ SourceString
);
这种方式有个坏处是,如果SourceString改变了,DestinationSting的Buff也会变,因为二者指针相同
以下代码用windbg调试:
UNICODE_STRING symLinkName; WCHAR *wString = L"\\??\\HelloDDK"; RtlInitUnicodeString(&symLinkName,wString);如下图:
可以看到symLinkName的Buffer和wString的地址完全一样,所以二者会同时变化
另一种方式是程序员自己申请内存,并初始化内存,当不用字符串时,需要回收字符串占的内存。
注意的是UNICODE_STRING中的大小都是以字节来计算的,
自己写个小示例:
VOID CopyString()
{
KdPrint(("CopyString start"));
// 第一种方式
WCHAR *wString = L"first copy";
UNICODE_STRING Unicode_String;
RtlInitUnicodeString(&Unicode_String, wString);
KdPrint(("Unicode_String:%wZ\n", &Unicode_String));
// 第二种方式
UNICODE_STRING Second_String = {0};
Second_String.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 1024);
if (Second_String.Buffer)
{
Second_String.MaximumLength = 1024;
Second_String.Length = 2*wcslen(wString);
RtlCopyMemory(Second_String.Buffer, wString, Second_String.Length);
KdPrint(("Second_String:%wZ\n", &Second_String));
RtlFreeUnicodeString(&Second_String);
}
// 第三种方式
UNICODE_STRING Third_String;
Third_String.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 1024);
if (Third_String.Buffer)
{
Third_String.MaximumLength = 1024;// length就不用初始化了,在copy中完成
RtlCopyUnicodeString(&Third_String, &Unicode_String);
KdPrint(("Third_String:%wZ, len:%d\n", &Third_String, Third_String.Length));
RtlFreeUnicodeString(&Third_String);
}
KdPrint(("CopyString end"));
}
需要注意的是第二种第三种方式都需要自己分配、释放内存
6.1.5 字符串比较
LONG
RtlCompareUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2,
IN BOOLEAN CaseInSensitive
);
写了一段测试代码:
#pragma PAGEDCODE
VOID First_StringCompare()
{
//第一种方式
UNICODE_STRING First_String;
RtlInitUnicodeString(&First_String, L"\\??\\First");
KdPrint(("First_String.Length:%d, First_String.MaximumLength:%d, First_String.Buffer:%s\n",
First_String.Length, First_String.MaximumLength, First_String.Buffer));
UNICODE_STRING First_StringCompare = {0};
First_StringCompare.MaximumLength = 1024;
First_StringCompare.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 1024);
if (First_StringCompare.Buffer)
{
RtlCopyUnicodeString(&First_StringCompare, &First_String);
KdPrint(("First_StringCompare.Length:%d, First_StringCompare.MaximumLength:%d, First_StringCompare.Buffer:%s\n",
First_StringCompare.Length, First_StringCompare.MaximumLength, First_StringCompare.Buffer));
LONG bRet = RtlCompareUnicodeString(&First_StringCompare, &First_String, FALSE);
KdPrint(("bRet:%d\n",bRet));
}
}结果bRet返回0,这两个打印的MaximunLength明显是不同的,只是比较buffer和length
windbg跟进这个函数内部:
nt!RtlCompareUnicodeString: 805e2b0a 8bff mov edi,edi 805e2b0c 55 push ebp 805e2b0d 8bec mov ebp,esp 805e2b0f 83ec0c sub esp,0Ch 805e2b12 8b4508 mov eax,dword ptr [ebp+8] 805e2b15 8b4d0c mov ecx,dword ptr [ebp+0Ch]打印下,ecx和eax保存了比较双方
3: kd> r eax, ecx eax=bad17c70 ecx=bad17c68 3: kd> dt bad17c70 UNICODE_STRING HelloDDK!UNICODE_STRING "\??\First" +0x000 Length : 0x12 +0x002 MaximumLength : 0x400 +0x004 Buffer : 0xe115c7f8 "\??\First" 3: kd> dt bad17c68 UNICODE_STRING HelloDDK!UNICODE_STRING "\??\First" +0x000 Length : 0x12 +0x002 MaximumLength : 0x14 +0x004 Buffer : 0xbac44920 "\??\First"可以看到MaximunLength的大小的确不同
805e2b1b 0fb709 movzx ecx,word ptr [ecx]取得第一个比较数的length到ecx中
805e2b23 0fb700 movzx eax,word ptr [eax]取得第二个比较数的length到eax中
805e2b26 3bc1 cmp eax,ecx比较Length
805e2b2f 7e02 jle nt!RtlCompareUnicodeString+0x29 (805e2b33) 805e2b31 8bc1 mov eax,ecx 805e2b33 03c6 add eax,esi小或等于转移,所以上面的会直接跳转到805e2b33
05e2b33 03c6 add eax,esi其中eax是length,esi是buffer起始
3: kd> du esi e115c7f8 "\??\First"
805e2b35 807d1000 cmp byte ptr [ebp+10h],0 805e2b39 8945fc mov dword ptr [ebp-4],eax 805e2b3c 0f84fe000000 je nt!RtlCompareUnicodeString+0x136 (805e2c40) [br=1]比较buffer[Lengh]是否为0,为0则跳转到805e2c40
5e2c40 3bf0 cmp esi,eax最后是一个循环比较,直到esi=eax
3: kd> r eax, esi eax=e115c80a esi=e115c80a
805e2c04 0f8246ffffff jb nt!RtlCompareUnicodeString+0x46 (805e2b50) 805e2c0a 8b45f8 mov eax,dword ptr [ebp-8] 805e2c0d 2b45f4 sub eax,dword ptr [ebp-0Ch] 805e2c10 5f pop edi 805e2c11 5e pop esi 805e2c12 5b pop ebx 805e2c13 c9 leave 805e2c14 c20c00 ret 0Ch其中ebp-8的内存中保存了第一个len,ebp-0c保存了第二个len,两者相差,明显为0
整个过程和max大小没有关系.
另写了一段测试代码,同样ret为0,
#pragma PAGEDCODE
VOID First_StringCompare()
{
//第二种方式
UNICODE_STRING First_String = {0};
First_String.MaximumLength = 100;
First_String.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 100);
if (First_String.Buffer)
{
First_String.Buffer[0] = 0x5c;
First_String.Buffer[1] = 0x6c;
First_String.Buffer[2] = 0x7c;
First_String.Length = 4;
KdPrint(("First_String.Length:%d, First_String.MaximumLength:%d, First_String.Buffer:%s\n",
First_String.Length, First_String.MaximumLength, First_String.Buffer));
}
UNICODE_STRING First_StringCompare = {0};
First_StringCompare.MaximumLength = 1024;
First_StringCompare.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 1024);
if (First_StringCompare.Buffer)
{
First_StringCompare.Buffer[0] = 0x5c;
First_StringCompare.Buffer[1] = 0x6c;
First_StringCompare.Buffer[2] = 0x8c;
First_StringCompare.Length = 4;
KdPrint(("First_StringCompare.Length:%d, First_StringCompare.MaximumLength:%d, First_StringCompare.Buffer:%s\n",
First_StringCompare.Length, First_StringCompare.MaximumLength, First_StringCompare.Buffer));
LONG bRet = RtlCompareUnicodeString(&First_StringCompare, &First_String, FALSE);
KdPrint(("bRet:%d\n",bRet));
}
}同样bRet为0,说明只是比较了buffer的length长度
6.1.6字符串转化为大写
VOID
RtlUpperString(
IN OUT PSTRING DestinationString,
IN PSTRING SourceString
);
NTSTATUS
RtlUpcaseUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
小示例#pragma PAGEDCODE
VOID UpperCase()
{
// ANSI_STRING转换成大写
// 1.自己转换
ANSI_STRING Ansi_String = {0};
RtlInitString(&Ansi_String, "Ansi_String");
KdPrint(("Ansi_String.Length:%d, %d, %s", Ansi_String.Length, Ansi_String.MaximumLength,Ansi_String.Buffer));
RtlUpperString(&Ansi_String, &Ansi_String);
KdPrint(("Ansi_String.Length:%d, %d, %s", Ansi_String.Length, Ansi_String.MaximumLength,Ansi_String.Buffer));
这样会挂掉,跟进RtlUpperString后,可以看到:
kd> p
nt!RtlUpperString+0x36:
805e3cb6 8806 mov byte ptr [esi],al
kd> r esi
esi=f892e770
kd> !vad f892e770 1
VAD @ f892e770
Start VPN 69736e41 End VPN 7274535f Control Area 43676e69
FirstProtoPte 3a79706f LastPte 0a5a7725 Commit Charge 4535f (283487.)
Secured.Flink 0 Blink 0 Banked/Extend 0
File Offset 0
ImageMap ViewUnmap NoChange LargePages AWE MemCommit EXECUTE GUARD因为这个内存是GUARD,所以会直接异常
当然,把属性改成#pragma INITCODE应该就OK,以下是改成INITCODE属性时这部分代码:
kd> !vad f8957230 1
VAD @ f8957230
Start VPN 69736e41 End VPN 7274535f Control Area 20797274
FirstProtoPte 0a646e65 LastPte cccccc00 Commit Charge 57265 (356965.)
Secured.Flink cccccccc Blink cccccccc Banked/Extend 0
File Offset cccccc
ViewShare NoChange CopyOnWrite LargePages MemCommit EXECUTE_READWRITE NOCACHE
MultipleSecured ReadOnly 建议使用自己分配内存的字符串:
#pragma PAGEDCODE
VOID Upper()
{
ANSI_STRING Ansi_String = {0};
RtlInitString(&Ansi_String, "Ansi_String");
ANSI_STRING Ansi_StringCopy = {0};
Ansi_StringCopy.MaximumLength = 100;
Ansi_StringCopy.Buffer = (PCHAR)ExAllocatePool(PagedPool, 100);
if (Ansi_StringCopy.Buffer)
{
RtlCopyString(&Ansi_StringCopy, &Ansi_String);
KdPrint(("Ansi_StringCopy:%Z\n", Ansi_StringCopy));
RtlUpperString(&Ansi_StringCopy, &Ansi_StringCopy);
KdPrint(("Ansi_StringCopy:%Z\n", Ansi_StringCopy));
ExFreePool(Ansi_StringCopy.Buffer);
}
}肯定没问题
6.1.7 字符串和整型数字互换
NTSTATUS
RtlUnicodeStringToInteger(
IN PUNICODE_STRING String,
IN ULONG Base OPTIONAL,
OUT PULONG Value
);
NTSTATUS
RtlIntegerToUnicodeString(
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN OUT PUNICODE_STRING String
);
写了个小示例:
#pragma PAGEDCODE
VOID ConvertInteger()
{
UNICODE_STRING Unicode_String = {0};
RtlInitUnicodeString(&Unicode_String, L"10");
ULONG lNumber = 0;
NTSTATUS nStatus = RtlUnicodeStringToInteger(&Unicode_String, 16, &lNumber);
UNICODE_STRING Unicode_String2 = {0};
Unicode_String2.Buffer = (PWCHAR)ExAllocatePool(PagedPool, 100);
Unicode_String2.MaximumLength = 100;
nStatus = RtlIntegerToUnicodeString(lNumber, 16, &Unicode_String2);
RtlFreeUnicodeString(&Unicode_String2);
}
注意RtlIntegerToUnicodeString这个函数,字符串要先分配足够的大小,
RtlIntegerToUnicodeString returns an NTSTATUS value. Possible return values include : STATUS_SUCCESS The routine successfully converted Value to a Unicode string. STATUS_BUFFER_OVERFLOW Value is too large to convert, or the UNICODE_STRING structure is too small to hold the result. STATUS_INVALID_PARAMETER The specified code base is not valid. The only valid values are 0, 2, 8, 10, and 16.
NTSTATUS
RtlUnicodeStringToAnsiString(
IN OUT PANSI_STRING DestinationString,
IN PUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
一般当然是分配内存,第三个参数为true
6.2内核模式下的文件操作
NTSTATUS
ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
VOID
InitializeObjectAttributes(
OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN HANDLE RootDirectory,
IN PSECURITY_DESCRIPTOR SecurityDescriptor
);
注意,初始化时文件名必须是符号链接或设备名,如"c:\1.log"应该写成"\??\c:\1.log“
测试小代码:
#pragma PAGEDCODE
VOID CreateFileTest()
{
UNICODE_STRING objName;
RtlInitUnicodeString(&objName, L"\\??\\c:\\yy.log");
// 初始化obj
OBJECT_ATTRIBUTES objAttr;
InitializeObjectAttributes(&objAttr, &objName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
// 创建文件
HANDLE hFile;
IO_STATUS_BLOCK iostatus;
NTSTATUS ntStatus = ZwCreateFile
(&hFile,
GENERIC_ALL,
&objAttr,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[CreateFileTest]--ZwCreateFile sucess\n"));
}
else
{
KdPrint(("[CreateFileTest]--ZwCreateFile fail\n"));
}
//关闭文件句柄
ZwClose(hFile);
// 打开文件
ntStatus = ZwCreateFile
(&hFile,
GENERIC_ALL,
&objAttr,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,//打开文件
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[CreateFileTest]--[ZwCreateFile] open file sucess\n"));
}
else
{
KdPrint(("[CreateFileTest]--[ZwCreateFile] open file fail\n"));
}
//关闭文件句柄
ZwClose(hFile);
// 打开文件
ntStatus = ZwOpenFile
(&hFile,
GENERIC_ALL,
&objAttr,
&iostatus,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[CreateFileTest]--[ZwOpenFile] open file sucess\n"));
}
else
{
KdPrint(("[CreateFileTest]--[ZwOpenFile] open file fail\n"));
}
//关闭文件句柄
ZwClose(hFile);
}
注意每次创建或打开后都要调一下ZwCreateFile(hFile);,上面三次使用hFile,少一个关闭,外部打开yy.log就会提示文件被占用.
获取或修改文件属性
NTSTATUS
ZwSetInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
NTSTATUS
ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
FileHandle:文件句柄
FileInformationClass可以理解为文件信息的类型,不同的类型有不同的Length,而FileInformation则依据前者类型不同而不同,
Set就是设置进去FileInformation,Query就是FileInformation返回
typedef struct FILE_STANDARD_INFORMATION {
LARGE_INTEGER AllocationSize;//为文件分配的大小(簇大小,非文件大小)
LARGE_INTEGER EndOfFile;//距文件结尾还有多少字节
ULONG NumberOfLinks;//有多少个链接文件
BOOLEAN DeletePending;//是否准备删除
BOOLEAN Directory;//是否为文件夹
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;typedef struct FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;//文件创建时间
LARGE_INTEGER LastAccessTime;//最后访问时间
LARGE_INTEGER LastWriteTime;//最后写时间
LARGE_INTEGER ChangeTime;//最后修改时间
ULONG FileAttributes;//文件属性,如FILE_ATTRIBUTE_READONLY
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;#pragma PAGEDCODE
VOID FileTest()
{
UNICODE_STRING ObjName;
RtlInitUnicodeString(&ObjName, L"\\??\\c:\\1234.log");
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(&ObjAttr, &ObjName, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE hFile;
IO_STATUS_BLOCK iostatus;
NTSTATUS ntStatus = ZwCreateFile
(&hFile,
GENERIC_READ,
&ObjAttr,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- open file success\n"));
}
//读取文件长度
FILE_STANDARD_INFORMATION fsi;
ntStatus = ZwQueryInformationFile
(hFile,
&iostatus,
&fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- len:%u\n", fsi.EndOfFile.QuadPart));
}
//读取文件的创建访问系列时间
FILE_BASIC_INFORMATION fbi;
ntStatus = ZwQueryInformationFile
(hFile,
&iostatus,
&fbi,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- time:%u\n", fbi.CreationTime.QuadPart));
}
//读取文件名
FILE_NAME_INFORMATION fni;
PWCHAR pName = (PWCHAR)ExAllocatePool(PagedPool, 100);
RtlZeroMemory(pName, 100);
PFILE_NAME_INFORMATION pfni = (PFILE_NAME_INFORMATION)pName;
pfni->FileNameLength = 95;
ntStatus = ZwQueryInformationFile
(hFile,
&iostatus,
pfni,
sizeof(FILE_NAME_INFORMATION),
FileNameInformation
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- name:%s\n", fni.FileName));
ExFreePool(pName);
}
KdPrint(("ntStatus:0x%08x\n", ntStatus));
ZwClose(hFile);
}6.2.4 文件的写操作
NTSTATUS
ZwWriteFile(
IN HANDLE FileHandle,//文件打开句柄
IN HANDLE Event OPTIONAL,//设为NULL
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,//设为NULL
IN PVOID ApcContext OPTIONAL,//设为NULL
OUT PIO_STATUS_BLOCK IoStatusBlock,//写操作的状态
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,//从文件的多少偏移地址开始写
IN PULONG Key OPTIONAL//设为NULL
)小示例
#pragma PAGEDCODE
VOID FileTest()
{
UNICODE_STRING ObjName;
RtlInitUnicodeString(&ObjName, L"\\??\\c:\\1234.log");
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(&ObjAttr, &ObjName, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE hFile;
IO_STATUS_BLOCK iostatus;
NTSTATUS ntStatus = ZwCreateFile
(&hFile,
GENERIC_WRITE,//请求写权限
&ObjAttr,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- open file success\n"));
}
PCHAR pBuffer = (PCHAR)ExAllocatePool(PagedPool, 100);
RtlFillMemory(pBuffer, 100, 0xAA);
//写文件
LARGE_INTEGER Offset;
Offset.QuadPart = 2;
ntStatus = ZwWriteFile
(hFile,
NULL, NULL, NULL,
&iostatus,
pBuffer, 100,
&Offset, NULL
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[FileTest] -- write file success\n"));
}
KdPrint(("ntStatus :0x%08x\n", ntStatus));
ZwClose(hFile);
}
注意打开时文件句柄要获得写权限,写完后用UE在16进制下观看
NTSTATUS
ZwReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,//设为NULL
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,//设为NULL
IN PVOID ApcContext OPTIONAL,//设为NULL
OUT PIO_STATUS_BLOCK IoStatusBlock,//状态,Information 成员记录读了多少
OUT PVOID Buffer,//指向调用者已分配的内存
IN ULONG Length,//buffer的长度
IN PLARGE_INTEGER ByteOffset OPTIONAL,//文件指针的偏移
IN PULONG Key OPTIONAL//设为NULL
);
6.3内核模式下注册表操作
应用编程中对应的子键 驱动编程中的路径写法
HKEY_LOCAL_MACHINE \Registry\Machine
HKEY_USERS \Registry\User
HKEY_CLASSES_ROOT 没有对应的路径
HKEY_CURRENT_USER 没有简单的对应路径,但是可以求得
#pragma PAGEDCODE
VOID RegeditTest()
{
UNICODE_STRING KeyPath;
RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\system\\hgy413");
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(&ObjAttr, &KeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
//创建注册表
HANDLE hKey;
ULONG ulResult;
NTSTATUS ntStatus = ZwCreateKey
(&hKey,
KEY_ALL_ACCESS,
&ObjAttr,
0,
NULL,
REG_OPTION_NON_VOLATILE,
&ulResult
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[RegeditTest]--ulResult:%d\n", ulResult));
}
KdPrint(("ntStatus:0x%08x", ntStatus));
ZwClose(hKey);
hKey = NULL;
//打开注册表
ntStatus = ZwOpenKey
(&hKey,
KEY_ALL_ACCESS,
&ObjAttr
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[RegeditTest]--ZwOpenKey success\n"));
}
UNICODE_STRING ValueName;
RtlInitUnicodeString(&ValueName, L"REG_SZ value");
UNICODE_STRING Value;
RtlInitUnicodeString(&Value, L"Reg_sz");
//设置子键
ntStatus =
ZwSetValueKey
(
hKey,
&ValueName,
0,
REG_SZ,
Value.Buffer,
Value.MaximumLength
);
KdPrint(("ntStatus:0x%08x", ntStatus));
if (NT_SUCCESS(ntStatus))
{
KdPrint(("[RegeditTest]--ZwSetValueKey success\n"));
}
KdPrint(("ntStatus:0x%08x", ntStatus));
//查询子键内容大小
ULONG ulSize;
ntStatus = ZwQueryValueKey
(
hKey,
&ValueName,
KeyValuePartialInformation,
NULL,
0,
&ulSize
);
KdPrint(("ntStatus:0x%08x", ntStatus));
if (STATUS_BUFFER_TOO_SMALL == ntStatus)
{
PKEY_VALUE_PARTIAL_INFORMATION pVaule = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool, ulSize);
//查询子键内容
ntStatus = ZwQueryValueKey
(
hKey,
&ValueName,
KeyValuePartialInformation,
pVaule,
ulSize,
&ulSize
);
KdPrint(("ntStatus:0x%08x", ntStatus));
}
ZwClose(hKey);
hKey = NULL;
}
也可以使用Rtl系列封装函数来实现:
#pragma PAGEDCODE
VOID RtlRegeditTest()
{
// 创建子项
NTSTATUS ntStatus = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\system\\hgy413");
KdPrint(("ntStatus:0x%08x", ntStatus));
// 确认子项是否存在
ntStatus = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\system\\hgy413");
KdPrint(("ntStatus:0x%08x", ntStatus));
// 写注册表
PWCHAR szString = L"sz_Reg";
ntStatus = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\system\\hgy413",
L"sz_Value", REG_SZ, szString, wcslen(szString)*2+2);
KdPrint(("ntStatus:0x%08x", ntStatus));
}
浙公网安备 33010602011771号