周末在家看了一天《Windows驱动开发技术详解》,一点点心得在这里记录一下,如果有理解不对的地方,还望海涵,指出。
驱动程序
I/O管理器接收应用程序的请求后,创建响应的IRP,并传送至驱动程序进行处理,有如下集中处理方法:
1.根据IRP的请求,直接操作具体硬件,然后完成此IRP,并返回。
2.将此IRP的请求,转发到更底层的驱动中,并等待底层驱动的返回。
3.接收到IRP请求后,不急于完成,分配新的IRP发到其他驱动程序中,并等待返回。
Windows与微内核:微内核和单一内核的概念是相互对立的。
单一内核,一般是讲系统的主要核心组件全部在内核实现(进程管理器,内存管理器,I/O管理器),内核各组件之间关联很大,耦合性很大,不利于模块化设计,但是速度快,组件的通信全部在内核态完成,没有进程间的切换也没有用户态到内核态的切换。例如Linux操作系统。
微内核,操作系统的主要组件运行在独立的进程中,使用进程间通讯提供服务,耦合度降低的同时,但是效率也有下降。
Windows不是纯粹的微内核系统,内核的各个核心组件相对耦合性较小,克服微内核效率低的特点。
从应用程序到驱动程序
1.WIN32 API CreateFile
2.传递到Kernel32.dll子系统内
3.进而调用Ntdll.dll中的Native API NtCreateFile
4.通过软中断进入内核,调用内核态的NtCreateFile系统服务函数
5.调用I/O管理器,创建IRP并传输到设备驱动程序中
PS:在一层层的调用中,每层都会严格的检查保证参数的合法性。
安全软件会对一些重点函数进行特殊过滤,不管是内核HOOK还是什么,看雪一篇文章《瑞星全功能安全软件2011内核拒绝服务漏洞》,刚好就是对参数的合法性没有处理,导致的BSOD。
大概的过程就是:瑞星在NtCreateKey HOOK函数中对ObjectAttributes结构体的参数校验不严格,就将参数传递给内核函数ZwOpenKey,结果引发蓝屏。在未安装瑞星的系统下没有影响。可见做内核HOOK,对于设计精良的操作系统都会进行层层检查,但是HOOK的检查不足,就有可能导致BSOD。
好了,现在搞内核HOOK不是我的目标,还是认真的打基础。
对于内核部分的操作不是很熟悉,但是可以看看上层WIN32 API的调用。
随便写个小程序调用OpenProcess函数。
#include <windows.h> #define QQPROCESSID 7288 int main() { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, QQPROCESSID); TerminateProcess(hProcess, 0); CloseHandle (hProcess); return 0; }
使用OD调试。大概有如下调用关系。
用户态:EXE-->kernel32.OpenProcess-->ntdll.ZwOpenProcess-->KiFastSystemCall-->sysenter
这里可以看出来,从Ring3 API-->Native API-->进入内核-->SSDT
进入Ring0之后,系统会根据服务号(eax = 0xBE)在SSDT这个系统服务描述符表中查找对应的表项,这个找到的表项就是系统服务函数NtOpenProcess在内核中的真正地址。之后,系统会根据这个地址调用相应的系统服务函数,并把结果返回给ntdll.dll中的NtOpenProcess。
PS:感觉内核这个东西越看越有意思,希望能一点点掌握吧,给自己加油。