《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作
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内核编程》八 文件操作与注册表操作的更多相关文章
- 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建
(原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...
- 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求
1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...
- Win64 驱动内核编程-32.枚举与删除注册表回调
枚举与删除注册表回调 注册表回调是一个监控注册表读写的回调,它的效果非常明显,一个回调能实现在SSDT 上 HOOK 十几个 API 的效果.部分游戏保护还会在注册表回调上做功夫,监控 service ...
- 《天书夜读:从汇编语言到windows内核编程》十一 用C++编写内核程序
---恢复内容开始--- 1) C++的"高级"特性,是它的优点也是它的缺点,微软对于使用C++写内核程序即不推崇也不排斥,使用C++写驱动需注意: a)New等操作符不能直接使用 ...
- 《天书夜读:从汇编语言到windows内核编程》四 windows内核调试环境搭建
1) 基础篇是讲理论的,先跳过去,看不到代码运行的效果要去记代码是一个痛苦的事情.这里先跳入探索篇.其实今天的确也很痛苦,这作者对驱动开发的编译与调试环境介绍得太模糊了,我是各种尝试,对这个环境的搭建 ...
- 《天书夜读:从汇编语言到windows内核编程》十 线程与事件
1)驱动中使用到的线程是系统线程,在system进程中.创建线程API函数:PsCreateSystemThread:结束线程(线程内自行调用)API函数:PsTerminateSystemThrea ...
- 《天书夜读:从汇编语言到windows内核编程》九 时间与定时器
1)使用如下自定义函数获取自系统启动后经历的毫秒数:KeQueryTimeIncrement.KeQueryTickCount void MyGetTickCount(PULONG msec) { L ...
- 《天书夜读:从汇编语言到windows内核编程》七 内核字符串与内存
1)驱动中的字符串使用如下结构: typedef struct _UNICODE_STRING{ USHORT Length; //字符串的长度(字节数) USHORT MaximumLength; ...
- 《天书夜读:从汇编语言到windows内核编程》三 练习反汇编C语言程序
1) Debug版本算法反汇编,现有如下3×3矩阵相乘的程序: #define SIZE 3 int MyFunction(int a[SIZE][SIZE],int b[SIZE][SIZE],in ...
随机推荐
- 学习如何看懂SQL Server执行计划——基本知识篇
一.基本概念 1.数据的读取 页(page)是SQL SERVER可以读写的最小I/O单位.即使只需访问一行,也要把整个页加载到缓存之中,再从缓存中读取数据.物理读取是从磁盘上读取,逻辑读取是从缓存中 ...
- ubuntu系统如何屏幕截图
我们知道,windows下有很多截图的软件和插件,那么在ubuntu系统下我们该怎样截图呢? 下面就让小编来告诉你几种简单的方法吧. 工具/原料 ubuntu系统电脑 方法一: 1.也许很多朋友都知道 ...
- javaWeb学习笔记——关于交叉连接-内连接-左外连接-右外连接的区别
废话不说:直接上图1 图1-1 table1表 图1-2 table2 图1-3 cross join 交叉连接 图1-4 显示内连接 图1-5 左外链接 图1-6 右外链接
- javascript 三种弹出对话框
第一种:alert()方法 第二种:confirm()方法 返回一个布尔值,根据返回的值可以执行相应操作. 第三种: prompt()方法 返回输入的消息,或者其默认值提示框经常用于提示用户在进入页面 ...
- mysql explain 分析sql语句
鉴于最近做的事情,需要解决慢sql的问题,现补充一点sql语句性能分析之explain的使用方式! 综合返回数据情况,分析各个参数,可以了解sql 使用方法:explain + sql语句 如 :e ...
- c#使用GDI+简单绘图(二)
// Create the in-memory bitmap where you will draw the image. // This bitmap is 300 pixels wide and ...
- 【学习】滚动延迟加载插件scrollLoading用法
今天遇到一个很好用的滚动延迟加载的插件,作者是我的偶象大神张鑫旭,其博客为http://www.zhangxinxu.com/. 以前也写过这种效果,用的是lazyload,不过只能实现图片的加载.而 ...
- 关于extjs表单布局的几种方式
一.用column布局 layout:'column', defaults:{ style:'float:left;margin:4px;', columnWidth: 0.49, msgTarget ...
- win10 uwp 如何拖动一个TextBlock的文字到另一个TextBlock
我在堆栈网看到有人问 如何拖动一个TextBlock的文字到另一个TextBlock 于是看到一个大神给出的方法,下面我就来和大家说下如何拖动 一开始我们需要一个界面,就放两个TextBlock 一个 ...
- win10 UWP 蜘蛛网效果
我看见了知乎首页登录背景和普通的地球人写的博客,发现了个好看的效果. 那么我来告诉大家如何做这个效果. 第一步是在 Canvas 画点,第二步是让点移动,第三步是画线 在 Canvas 画一个点 我们 ...