转---派遣例程与IRP结构
提到派遣例程,必须理解IRP(I/O Request Package),即"输入/输出请求包"这个重要数据结构的概念。Ring3通过DeviceIoControl等函数向驱动发出I/O请求后,在内核中由操作系统将其转化为IRP的数据结构,并"派遣"到对应驱动的派遣函数中,如图21.1.6所示。
Ring3程序调用kernel32.dll导出的DeviceIoControl函数后,会调用到ntdll.dll导出的NtDeviceIoControlFile函数,进而调用到系统内核模块提供的服务函数NtDeviceIo ControlFile,该函数会将I/O请求转化为IRP包,并发送到对应驱动的派遣例程函数中。对于其他I/O相关函数,如CreateFile、ReadFile、WriteFile、GetFileSize、SetFileSize、CloseHandle等也是如此。
|
| 图21.1.6 从Ring3的I/O请求到内核的IRP请求包 |
一个IRP包该发往驱动的哪个派遣例程函数,是由IRP结构中的MajorFunction属性决定的,MajorFunction属性的值是一系列宏,如下所示。
- //
- // Define the major function codes for IRPs.
- //
- #define IRP_MJ_CREATE 0x00
- #define IRP_MJ_CREATE_NAMED_PIPE 0x01
- #define IRP_MJ_CLOSE 0x02
- #define IRP_MJ_READ 0x03
- #define IRP_MJ_WRITE 0x04
- #define IRP_MJ_QUERY_INFORMATION 0x05
- #define IRP_MJ_SET_INFORMATION 0x06
- #define IRP_MJ_QUERY_EA 0x07
- #define IRP_MJ_SET_EA 0x08
- #define IRP_MJ_FLUSH_BUFFERS 0x09
- #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
- #define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
- #define IRP_MJ_DIRECTORY_CONTROL 0x0c
- #define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
- #define IRP_MJ_DEVICE_CONTROL 0x0e
- #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
- #define IRP_MJ_SHUTDOWN 0x10
- #define IRP_MJ_LOCK_CONTROL 0x11
- #define IRP_MJ_CLEANUP 0x12
- #define IRP_MJ_CREATE_MAILSLOT 0x13
- #define IRP_MJ_QUERY_SECURITY 0x14
- #define IRP_MJ_SET_SECURITY 0x15
- #define IRP_MJ_POWER 0x16
- #define IRP_MJ_SYSTEM_CONTROL 0x17
- #define IRP_MJ_DEVICE_CHANGE 0x18
- #define IRP_MJ_QUERY_QUOTA 0x19
- #define IRP_MJ_SET_QUOTA 0x1a
- #define IRP_MJ_PNP 0x1b
- #define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
- #define IRP_MJ_MAXIMUM_FUNCTION 0x1b
MajorFunction最多有0x1b(27)个,也就是说驱动中最多可以设置27个不同的派遣例程函数。helloworld.c中为了简单,将所有的派遣例程都设置到了DrvDispatch函数,并且DrvDispatch函数中只做了最简单的处理。
IRP的数据结构非常复杂,如果全部展示出来恐怕需要好几页的篇幅。"授人以鱼不如授人以渔",因此这里重点给出学习IRP数据结构的方法。
对于初学者,在安装了最新版的WDK后,可以通过WDK Help中的"WDK Documentation"文档来学习IRP数据结构,如图2示。
|
| (点击查看大图)图21.1.7 通过WDK帮助文档学习内核数据结构IRP |
该文档会重点介绍驱动程序中用到的一些IRP成员的含义和使用方法,另外文档末尾还有一段Comments,也是非常有价值的内容。
WDK文档中省略了IRP结构中的某些成员(Undocumented members),如果阅读了文档中IRP的Comments后,就会知道这些Undocumented members之所以被保留,是因为只有I/O manager或FSDs才能使用这些成员。为了更全面地了解IRP的数据结构,更直接的办法是找到WDK中定义IRP的头文件,阅读其中的注释。例如,头文件在这里的路径是D:\WINDDK\7600.16385.0\ inc\ddk\wdm.h,其中对IRP定义如图21.1.8所示。
|
| 图21.1.8 通过WDK头文件wdm.h学习内核数据结构IRP |
为了灵活地查阅内核数据结构信息,还可以使用一些PDB辅助工具。一般地,内核数据结构大多定义在内核模块中。有了内核模块,还需要得到对应的PDB符号文件,这里推荐使用SymbolTypeViewer免费工具来下载符号文件。该工具使用非常简单(下载链接:http://www.laboskopia.com/download/SymbolTypeViewer_v1.0_beta.zip),如图21.1.9所示。
|
| (点击查看大图)图21.1.9 通过SymbolTypeViewer免费工具下载符号文件 |
启动SymbolTypeViewer后,单击"File"按钮,选择本机的内核模块文件(例如C:\WINDOWS\system32\ntkrnlpa.exe),然后单击"Symbol Path"按钮,选择要保存符号文件的路径,再单击"Server"按钮,选择默认的微软链接,最后单击"Get Symbols"按钮,就开始下载符号了。点击左侧树形控件中的符号项,右侧的"Info"窗口中就会列出该符号的相关信息,例如这里的D:\WINDOWS\Symbols\ntkrpamp.pdb\140D20ABBC1B433EA7BF82B979B6BF
9D1\ntkrpamp.pdb。
下一步就是浏览下载到的PDB文件,虽然SymbolTypeViewer工具也支持对内部符号的浏览,但是没有链接功能,不太方便。这里推荐使用另一个专门浏览PDB符号信息的免费工具PDB_Explorer(http://blog.titilima.com/wp-content/uploads/attachments/date_200907/pdbexp_v1.10.zip)。
启动PDB Explorer后,单击"打开"按钮,选择前面下载的PDB文件,然后在搜索框中输入"_IRP",在选择列出的第一个匹配项"_IRP",在右侧的内容区就可以看到如图21.1.10所示的符号信息。
可以看到PDB Explorer是支持前进后退的,即展示出的结构体中,如果有类似union或子struct等成员时,还可以"点"进去浏览更多信息。这样浏览的好处是,不至于"一口吃个大胖子",循序渐进地掌握类似IRP这样复杂的内核数据结构。
以上是一些学习内核数据结构的方法,希望这些内容能够起到"授人以渔"的作用,更希望读者能够通过这些方法逐渐理解IRP结构中每个成员的含义和用法。
|
| (点击查看大图)图21.1.10 通过PDB Explorer免费工具浏览符号文件 |
33
转---派遣例程与IRP结构的更多相关文章
- 派遣例程与IRP结构
提到派遣例程,必须理解IRP(I/O Request Package),即"输入/输出请求包"这个重要数据结构的概念.Ring3通过DeviceIoControl等函数向驱动发出I ...
- Windows驱动开发-IRP结构体
IRP的全名是I/O Request Package,即输入输出请求包,它是Windows内核中的一种非常重要的数据结构. 上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的 ...
- OD: Ring0 & Kernel
开发技术讲究封装与模块化,安全技术强调底层安全性.安全技术需要打开封装.追根溯源! <0day 安全:软件漏洞分析技术(第2版)> 第21章 探索 Ring0 笔记 Intel x86 系 ...
- 【旧文章搬运】无Device的驱动如何通信
原文发表于百度空间,2009-07-14========================================================================== 标准的驱动 ...
- 派遣函数IRP
派遣函数是Windows驱动程序中的重要概念.驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的. 用户模式下所有对驱动程序的I/O请求,全部由操作系统转换为一个叫做IR ...
- IRP派遣操作
IRPTrace工具跟踪IRP 派遣函数(Dispathc Funtion)是windows驱动中的重要概念.驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的.用户模式 ...
- IRP 与 派遣函数
什么是派遣函数: 派遣函数是 WIndows 驱动程序中的重要概念.驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的.也就是说,派遣函数是用来处理驱动程序提交过来的 I ...
- Windows NT驱动程序的基本结构和实例
Windows驱动程序分为两类:一类是不支持即插即用功能的NT式驱动程序:另一类是支持即插即用功能的WDM驱动程序. NT式驱动的基本结构: 1)驱动加载过程与驱动入口函数DriverEntry: 驱 ...
- IRP IO_STACK_LOCATION 《寒江独钓》内核学习笔记(1)
在学习内核过滤驱动的过程中,遇到了大量的涉及IRP操作的代码,这里有必要对IRP的数据结构和与之相关的API函数做一下笔记. 1. 相关阅读资料 <深入解析 windows 操作系统(第4版,中 ...
随机推荐
- LNMP的环境搭建
新装的Linux 机器,还没有来得及安装网站环境,这篇文章就是记录一下自己安装LNMP的一般步骤. 之前在Laravel视频中看过这段的讲解,后来也试着安装过,基本的命令不算是熟练掌握,所以还要看看之 ...
- vue-cli3.0相关的坑
vue-cli3.0相对比vue-cli2.0少了 vue-build.js vue-config.js vue-cli2.0 运行命令 npm run devvue-cli3.0 运行命令 npm ...
- MySQL中 IFNULL、NULLIF和ISNULL函数的用法
mysql 中 ifnull().nullif().isnull()函数的用法讲解: 一.IFNULL(expr1,expr2)用法: 假如expr1不为NULL,则 IFNULL() 的返回值为ex ...
- python-类与继承
类的继承 什么是继承? 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类.python中,父类.子类(派生类)只有在继承的时候才会产生. 继承的特性:子类会继承父类所有的属性. 为什么要用 ...
- (转)JVM各种内存溢出是否产生dump
对于java的内存溢出,如果配置-XX:+HeapDumpOnOutOfMemoryError,很明确的知道堆内存溢出时会生成dump文件.但永久代内存溢出不明确是否会生成,今天来做一个实验: 永久代 ...
- python小数据池,代码块深入剖析
小数据池 目的:缓存我们字符串,整数,布尔值.在使用的时候不需要创建更多的对象 缓存:int,str,bool int:缓存范围-5~256 str: 1.长度小于等于1,直接缓存 2.长度大于 ...
- Hive安装步骤
首先解压压缩包 然后进入bin 执行 ./hive 不过现在hive使用的是自己默认的数据库,不方便,可以通过配置使用MySQL数据库 创建hive-site.xml 粘贴一下内容 <confi ...
- 深入了解ASO
ASO对于一些人来说可能很陌生,很多人都听说过SEO,没有听说过ASO(我也是最近才知道这个领域),因为这是一个数字营销的一个新领域.ASO(App Store Optimization)是为了让自己 ...
- 【bzoj2563】阿狸和桃子的游戏 贪心
题目描述 阿狸和桃子正在玩一个游戏,游戏是在一个带权图G=(V, E)上进行的,设节点权值为w(v),边权为c(e).游戏规则是这样的:1. 阿狸和桃子轮流将图中的顶点染色,阿狸会将顶点染成红色,桃子 ...
- 【Luogu】P2045方格取数加强版(最小费用最大流)
题目链接 通过这题我学会了引诱算法的行为,就是你通过适当的状态设计,引诱算法按照你想要它做的去行动,进而达到解题的目的. 最小费用最大流,首先将点拆点,入点和出点连一条费用=-权值,容量=1的边,再连 ...