二、内核编程环境

1、内核编程的环境

​ 32位系统的进程可访问的内存大小是4G,低位2G是用户空间,高位2G是内核空间。应用程序运行在用户态,进程空间是相互独立的,不必担心进程间访问同一地址空间出错,但是如果如果内核空间获取的信息肯定是一样的。

内核模式也被称为内核态,x86架构下R0层的代码才可以访问内核空间,普通应用程序编译出来都运行在R3层,R3层的代码如果要调用R0层的功能,需要通过系统提供的入口来实现,调用内核API.

内核模块也代表实际的驱动程序,内核空间是所有进程所共享的,系统进程一般是一个名为“system”的进程,PID始终是4。windows一般都用系统进程来加载内核模块,并不是说明内核代码始终运行在System进程里。

2、数据类型

​ 基本数据类型,跟win32应用程序开发用到的基本一样,只是重命名了。

unsigned long ULONG
unsigned char UCHAR
unsigned int UINT
void VOID
unsigned long * PULONG
unsigned char * PUCHAR
unsigned int * PUINT
void * PVOID

绝大部分内核API的返回值类型为NTSTATUS,取值如下:

STATUS_SUCCESS 成功
STATUS_INVALID_PARAMETER 参数错误
STATUS_INSUFFICIENT_RESOURCES 资源不足
STATUS_PENDING 请求未决
STATUS_BUFFER_OVERFLOW 缓冲长度不够
STATUS_BUFFER_TOO_SMALL 缓冲长度不够

和win32应用开发的字符串不一样,驱动开发里的字符串使用的是一个结构里

type struct _UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR Buffer;
}UNICODE_STRING *PUNICODE_STRING;

字符串使用的是宽字符,双字节结构。

3、重要的数据结构

驱动对象(DRIVER_OBJECT),代表一个驱动程序,或者说一个内核模块。在Windows启动之后,这些内核对象都在内存中,驱动对象可以通过WinObj工具查看,显示所有的内核对象。

设备对象,设备对象是内核中的重要对象,类似于windows编程中的窗口,窗口时唯一可以接收消息的东西,任何消息都是发给一个窗口的。内核模块中,大部分消息都以请求(IRP)的方式传递。设备对象(DEVICE_OBJECT)是唯一可以接收请求的实体,任何一个请求都是发送给某个设备对象的。

一个驱动程序含有一个驱动对象,一个驱动对象对应有多个设备对象。

4、函数调用

大部分内核API都有前缀,主要的函数以Io-、Ex、Rtl-、Ke、Zw-、Nt-、和Ps-开头。

Ex开头常用的是分配内存,获取互斥体函数。如:ExAllocatePool、ExFreePoll、ExAcquireFastMutex、ExReleaseFastMutex、ExRaiseStatus

Zw开头常用的是文件操作相关函数,如:ZwCreateFile、ZwWriteFile、ZwReadFile、ZwQueryDirectoryFile、ZwDeviceControlFile、ZwCreateKey、ZwQueryValueKey

Rtl开头常用的是字符串操作相关函数,如:RtlInitUnicodeString、RtlCopyUnicodeString、RtlAppendUnicodeToString、RtlStringCbPrintf、RtlCopyMemory、RtlMoveMemory、RtlZeroMemory、RtlCompareMemory、RtlGetVersion

Io开头的是Io管理相关函数。如:IoCreateFile、IoCreateDevice、IoCallDriver、IoCompleteRequest、IoCopyCurrentIrpStackLocationToNext、IoSkipCurrentIrpStackLocationToNext、IoGetCurrentIrpStackLocation

Ps开头常用的是与进程、线程相关的函数,如:PsGetCurrentProcessId

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章