1)Windows运用程序的文件与注册表操作进入R0层之后,都有对应的内核函数实现。在windows内核中,无论打开的是文件、注册表或者设备,都需要使用InitializeObjectAttributes来初始化一个OBJECT_ATTRIBUTES结构体:

 VOID  InitializeObjectAttributes(
     [out]    POBJECT_ATTRIBUTES InitializedAttributes,    //OBJECT_ATTRIBUTES的指针
     [in]    PUNICODE_STRING ObjectName,    //对象名字字符串(文件则为路径)
     [in]    ULONG Attributes,    //填OBJ_CASE_INSENSITIVE(不区分大小写)|OBJ_KERNEL_HANDLE(内核句柄)
     [in]    HANDLE RootDirectory,    //填NULL
     [in]  PSECURITY_DESCRIPTOR SecurityDescriptor    //安全描述符,使用内核句柄(OBJ_KERNEL_HANDLE)时忽略
 );

2)打开文件(ZwCreateFile)和关闭文件(ZwClose):

 NTSTATUS ZwCreateFile(
     [Out]  PHANDLE FileHandle,//文件句柄指针,它指向打开的文件句柄值
     [In]  ACCESS_MASK DesiredAccess,//申请权限,读写操作,修改文件属性,删除文件等
     [In]  POBJECT_ATTRIBUTES ObjectAttributes,//对象描述,见八(1)
     [Out]  PIO_STATUS_BLOCK IoStatusBlock,//操作结果结构,成功或失败,失败原因
     [In]  PLARGE_INTEGER AllocationSize,//很少使用,置为NULL
     [In]  ULONG FileAttributes,//新建立的文件属性,一般为FILE_ATTRUBITE_NORMAL
     [In]  ULONG ShareAccess,//共享访问,本次打开后允许其他对象以什么方式打开
     [In]  ULONG CreateDisposition,//本次打开意图,如新建或者覆盖
     [In]  ULONG CreateOptions,//打开选项,如打开文件还是目录,同步打开还是异步打开
     [In]  PVOID EaBuffer,//置为NULL
     [In]  ULONG EaLength//置为0
 );

  示例:

 HANDLE file_handle = NULL;//要返回的文件句柄
 NTSTATUS status;//返回值

 //首先初始化含有文件路径的OBJECT_ATTRIBUTES
 OBJECT_ATTRIBUTES object_attributes;
 UNICODE_STRING ufile_name = RTL_CONSTANT_STRING(L"\\??\\c:\\a.dat");
 //要使用对象路径,“C:”是符号链接对象,一般在“\\??\\”
 InitializeObjectAttributes(
     &object_attributes,
     &ufile_name,
     OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
     NULL,
     NULL);
 //以OPEN_IF方式打开
 IO_STATUS_BLOCK io_status;
 status = ZwCreateFile(
     &file_handle,
     GENERIC_READ|GENERIC_WRITE,//普通读写
     &object_attributes,
     &io_status,
     NULL,
     FILE_ATTRIBUTE_NORMAL,//新建立文件为为普通属性
     FILE_SHARE_READ,//打开文件到关闭前,允许被其他进程已读方式打开
     FILE_OPEN_IF,//文件存在则打开,不存在则新建
     FILE_NON_DIRECTORY_FILE|FILE_RANDOM_ACCESS|FILE_SYNCHRONOUS_IO_NONALERT,//打开文件,随机存取打开,同步打开
     NULL,
     );

   内核文件句柄的关闭不需要在同一个进程当中,调用ZwClose(file_handle);即可

3)文件读(ZwReadFile)和文件写(ZwWriteFile),方法对称,只不过参数输入输出方向不同。

 NTSTATUS  ZwReadFile(
     IN  HANDLE  FileHandle,//文件句柄,由ZwFileCreate获取
     IN  HANDLE  Event  OPTIONAL,//事件,用于异步完成读。同步置位NULL
     IN  PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,//回调例程,用于异步完成读
     IN  PVOID  ApcContext  OPTIONAL,
    OUT  PIO_STATUS_BLOCK  IoStatusBlock, //返回结果状态
    OUT  PVOID  Buffer, //缓冲区,读成功则内容在该缓冲区
     IN  ULONG  Length,//描述缓冲区长度,即试图读取文件的长度
     IN  PLARGE_INTEGER  ByteOffset  OPTIONAL,//读取内容在文件中的起始偏移量
     IN  PULONG  Key  OPTIONAL//附加信息,一般置为NULL
 );

  ZwWriteFile参数与它类似。

4)内核编程读取HKEY_LOCAL_MACHINE时使用路径“\Registry\Machine”,而读取HKEY_USERS时使用“\Registry\User”,由于内核程序不是面向某个“当前用户”的,所以,没有HKEY_CURRENT_USER和HKEY_CLASSES_ROOT对应的路径。

5)打开注册表(ZwOpenKey或者ZwCreateKey)、读注册表(ZwQueryValueKey)和写注册表(ZwSetValueKey):

 ZwOpenKey原型:
 NTSTATUS ZwOpenKey(
     OUT  PHANDLE  KeyHandle,//返回的句柄
     IN  ACCESS_MASK  DesiredAccess,//权限,如读、设置、生成子键、枚举子键权限
     IN  POBJECT_ATTRIBUTES  ObjectAttributes//指向OBJECT_ATTRIBUTES
     );

 ZwQueryValueKey原型:
 NTSTATUS ZwQueryValueKey(
     IN  HANDLE  KeyHandle,//句柄,由ZwOpenKey或ZwCreateKey取得
     IN  PUNICODE_STRING  ValueName,//要读取的键名
     IN  KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,//读取信息的类型
    OUT  PVOID  KeyValueInformation,
     IN  ULONG  Length,//传入的KeyValueInformation的长度
    OUT  PULONG  ResultLength//返回实际需要的长度
     );

  KeyValueInformationClass有3种类型:KeyValueBaseInformation(基础信息:值名和类型)、KeyValueFullInformation(完整信息:值名、类型和数据)和KeyValuePartialInformation(局部信息:类型和数据)。值名是已知的,所以通常是使用KeyValuePartialInformation,此时,KeyValueInformation参数将返回一个KEY_VALUE_PARTIAL_INFOMATION的结构体的指针。它的原型为:

 typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
   ULONG  TitleIndex;    //忽略
   ULONG  Type;        //数据类型(REG_BINARY(16进制)、REG_DWORD(4字节整数)、REG_SZ(以空结束的Unicode字符串))
   ULONG  DataLength;    //数据长度
   UCHAR  Data[];        //可变长度的数据
 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

 ZwSetValueKey原型(写入的键存在怎覆盖,不存在则新建):
 NTSTATUS ZwSetValueKey(
     IN  HANDLE  KeyHandle,
     IN  PUNICODE_STRING  ValueName,
     IN  ULONG  TitleIndex  OPTIONAL,//始终填入0
     IN  ULONG  Type,
     IN  PVOID  Data,//要写入的数据起始地址
     IN  ULONG  DataSize//要写入的长度
 );

  示例:

 #define  MEM_TAG  ‘MyTt’
 //读取windws目录,在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion中的SystemRoot键中
 //要读取的键名
 UNICODE_STRING my_key_name = RTL_CONSTANT_STRING(L"SystemRoot");
 //用来试探大小的key_info
 KEY_VALUE_PARTIAL_INFORMATION key_info;
 //最后实际用到的key_info指针。内存分配在堆中
 PKEY_VALUE_PARTIAL_INFORMATION ac_key_info;
 ULONG ac_lenth;

 HANDLE my_key = NULL;
 NTSTATUS status;

 //定义要获取的路径
 UNICODE_STRING my_key_path = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
 OBJECT_ATTRIBUTES my_obj_attr = {};

 //初始化OBJECT_ATTRIBUTES
 InitializeObjectAttributes(
     &my_obj_attr,
     &my_key_path,
     OBJ_CASE_INSENSITIVE,
     NULL,
     NULL);

 //打开KEY
 status = ZwOpenKey(&my_key,KEY_READ,&my_obj_attr);
 if ( !NT_SUCCESS(status) )
 {
     //处理失败
 }

 //读取KEY的值
 status = ZwQueryValueKey(
     my_key,
     &my_key_name,
     KeyValuePartialInformation,
     &key_info,
     sizeof(KEY_VALUE_PARTIAL_INFORMATION),
     &ac_lenth);
 if ( !NT_SUCCESS(status) &&
     status != STATUS_BUFFER_TOO_SMALL &&
     status != STATUS_BUFFER_OVERFLOW)
 {
     //处理失败
 }

 //如果没有失败,则分配存储空间不足,再次获取
 ac_key_info = (PKEY_VALUE_PARTIAL_INFORMATION)
     ExAllocatePoolWithTag(NonPagedPool,ac_lenth,MEM_TAG);

 if ( ac_key_info == NULL )
 {
     status = STATUS_INSUFFICIENT_RESOURCES;
     //错误处理
 }

 status = ZwQueryValueKey(
     my_key,
     &my_key_name,
     KeyValuePartialInformation,
     ac_key_info,
     ac_lenth,
     &ac_lenth);
 if ( !NT_SUCCESS(status) )
 {
     //处理失败
 }
 //成功读取数据到ac_key_info->data中

《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作的更多相关文章

  1. 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建

    (原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...

  2. 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求

    1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...

  3. Win64 驱动内核编程-32.枚举与删除注册表回调

    枚举与删除注册表回调 注册表回调是一个监控注册表读写的回调,它的效果非常明显,一个回调能实现在SSDT 上 HOOK 十几个 API 的效果.部分游戏保护还会在注册表回调上做功夫,监控 service ...

  4. 《天书夜读:从汇编语言到windows内核编程》十一 用C++编写内核程序

    ---恢复内容开始--- 1) C++的"高级"特性,是它的优点也是它的缺点,微软对于使用C++写内核程序即不推崇也不排斥,使用C++写驱动需注意: a)New等操作符不能直接使用 ...

  5. 《天书夜读:从汇编语言到windows内核编程》四 windows内核调试环境搭建

    1) 基础篇是讲理论的,先跳过去,看不到代码运行的效果要去记代码是一个痛苦的事情.这里先跳入探索篇.其实今天的确也很痛苦,这作者对驱动开发的编译与调试环境介绍得太模糊了,我是各种尝试,对这个环境的搭建 ...

  6. 《天书夜读:从汇编语言到windows内核编程》十 线程与事件

    1)驱动中使用到的线程是系统线程,在system进程中.创建线程API函数:PsCreateSystemThread:结束线程(线程内自行调用)API函数:PsTerminateSystemThrea ...

  7. 《天书夜读:从汇编语言到windows内核编程》九 时间与定时器

    1)使用如下自定义函数获取自系统启动后经历的毫秒数:KeQueryTimeIncrement.KeQueryTickCount void MyGetTickCount(PULONG msec) { L ...

  8. 《天书夜读:从汇编语言到windows内核编程》七 内核字符串与内存

    1)驱动中的字符串使用如下结构: typedef struct _UNICODE_STRING{ USHORT Length; //字符串的长度(字节数) USHORT MaximumLength; ...

  9. 《天书夜读:从汇编语言到windows内核编程》三 练习反汇编C语言程序

    1) Debug版本算法反汇编,现有如下3×3矩阵相乘的程序: #define SIZE 3 int MyFunction(int a[SIZE][SIZE],int b[SIZE][SIZE],in ...

随机推荐

  1. 跨平台的 NodeJS 组件解决 .NetCore 不支持 System.Drawing图形功能的若干问题

    问题 生成缩略图 生成验证码 生成二维码 给图片加水印 外部引用 Node  不解释  https://nodejs.org/en/download/ sharp 高性能缩略图  https://gi ...

  2. Echarts数据可视化series-effectscatter特效散点图,开发全解+完美注释

    全栈工程师开发手册 (作者:栾鹏) Echarts数据可视化开发代码注释全解 Echarts数据可视化开发参数配置全解 6大公共组件详解(点击进入): title详解. tooltip详解.toolb ...

  3. Mybatis了解(配置)

    Mybatis是一个基于jdbc映射框架.它跟hibernate一样都是对数据库进行操作的.Mybatis 它是通过配置xml或者是注解来进行映射的配置,最后实现操作接口与pojo来操作数据库. 因此 ...

  4. 【学习】ie-css3.htc---让ie8以下支持css3

    学习了偶象大神的一篇文章:<让IE6/IE7/IE8浏览器支持CSS3属性>http://www.zhangxinxu.com/wordpress/?p=783 亲自实践了一下,主要是bo ...

  5. 理解HTTPS

    总结HTTPS HTTPS要使客户端与服务器端的通信过程得到安全保证,必须使用的对称加密算法,但是协商对称加密算法的过程,需要使用非对称加密算法来保证安全,然而直接使用非对称加密的过程本身也不安全, ...

  6. 彻底了解构建 JSON 字符串的三种方式

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7701856.html 前言:JSON 是轻量级的数据交换格式,很常用,尤其是在使用 Ajax ...

  7. 转:C++学习之Pair

    Pair类型概述 pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,基本的定义如下: pair<int, string> a; 表示a中有两个类型,第一个元素是int型的 ...

  8. debian change system language

    1. select locales: 2. set language: sudo localectl set-locale LANG=zh_CN.utf8 sudo localectl set-loc ...

  9. 【持续更新】.Net 开发中给自己埋下的坑!

    1.文件“XXX”正在由另一进程使用,因此该进程无法访问此文件. 原因剖析:文件在主线程操作,在子线程中读写操作文件,刚开始没有意识到程序的问题所在,总是在FileStream中报错,google后常 ...

  10. (转)利用JConsole工具监控java程序内存和JVM

    转自:http://www.cnblogs.com/luihengk/p/5446279.html 一.找到java应用程序对应的进程PI 性能测试应用程序访问地址:http://192.168.29 ...