zoukankan      html  css  js  c++  java
  • 驱动学习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
    ",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
    ", &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
    ", &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
    ", &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
    ",
    		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
    ",
    			First_StringCompare.Length, First_StringCompare.MaximumLength, First_StringCompare.Buffer));
    
    		LONG bRet = RtlCompareUnicodeString(&First_StringCompare, &First_String, FALSE);
    		KdPrint(("bRet:%d
    ",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
    ",
    			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
    ",
    			First_StringCompare.Length, First_StringCompare.MaximumLength, First_StringCompare.Buffer));
    
    		LONG bRet = RtlCompareUnicodeString(&First_StringCompare, &First_String, FALSE);
    		KdPrint(("bRet:%d
    ",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
    ", Ansi_StringCopy));
    		RtlUpperString(&Ansi_StringCopy, &Ansi_StringCopy);
    		KdPrint(("Ansi_StringCopy:%Z
    ", 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. 
    


    6.18.ANSI和UNICODE字符串相互转换
    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
    "));
    	}
    	else
    	{
    		KdPrint(("[CreateFileTest]--ZwCreateFile fail
    "));
    	}
    
    	//关闭文件句柄
    	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
    "));
    	}
    	else
    	{
    		KdPrint(("[CreateFileTest]--[ZwCreateFile] open file fail
    "));
    	}
    
    	//关闭文件句柄
    	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
    "));
    	}
    	else
    	{
    		KdPrint(("[CreateFileTest]--[ZwOpenFile] open file fail
    "));
    	}
    
    	//关闭文件句柄
    	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
    "));
    	}
    
    	//读取文件长度
    	FILE_STANDARD_INFORMATION fsi;
    	ntStatus = ZwQueryInformationFile
    		(hFile,
    		&iostatus,
    		&fsi,
    		sizeof(FILE_STANDARD_INFORMATION),
    		FileStandardInformation
    		);
    
    	if (NT_SUCCESS(ntStatus))
    	{
    		KdPrint(("[FileTest] -- len:%u
    ", 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
    ", 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
    ", fni.FileName));
    		ExFreePool(pName);
    	}
    
    	KdPrint(("ntStatus:0x%08x
    ", 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
    "));
    	}
    
    	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
    "));
    	}
    	KdPrint(("ntStatus :0x%08x
    ", 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    RegistryMachine
    HKEY_USERS        RegistryUser
    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
    ", 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
    "));
    	}
    
    	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
    "));
    	}
    	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));
    	
    }


























  • 相关阅读:
    Java中Volatile关键字详解
    java hashmap&concurrentHashmap源理
    java CAS和AQS
    jvm内存模型
    springAop源码分析
    一个项目设置两个git地址,并最终实现一次性同时推送到到两个git地址上的方法总结
    H5实现横向滚动的方法总结
    tab吸顶的神奇-- css粘性属性
    H5制作显示轮播图的方法Swiper
    微信H5中禁止分享好友及分享到朋友圈的方法
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693356.html
Copyright © 2011-2022 走看看