内核编程基础
1.内核API的使用
- 在应用层编程 我们可以使用WINDWOS提供的各种API函数,只要导入头文件<windows.h>就可以了,但是在内核编程的时候,我们不能像Ring3那样直接使用。微软为内核程序提供了专门的API,只要在程序中包含相应的头文件就可以使用了,如:#include <ntddk.h>(假设你已经正确安装了WDK)
- 在应用层编程的时候,我们通过MSDN来了解函数的详细信息,在内核编程的时候,要使用WDK自己的帮助文档
2.未导出函数的使用
WDK说明文档中只包含了内核模块的函数,对于未导出的函数,则不能直接使用。
如果要使用未导出的函数,只有自己定义一个函数指针,并且为函数指针提供正确的函数地址就可以使用了。有两种办法都可以获取未导出的函数地址
<1>特征码搜索
<2>解析内核PDB文件
3.基本数据类型
<1> 在内核编程的时候,强烈建议大家遵守WDK的编码习惯,不要这样写:
unsigned long length;
<2>习惯使用WDK自己的类型:
ULONG(unsigned long) PULONG(unsigned long *)
UCHAR(unsigned char) PUCHAR(unsigned char*)
UINT(unsigned int) PUINT(unsigned int*)
VOID(void) PVOID(void*)
4.返回值
大部分内核函数的返回值都是NTSTATUS类型,如:
NTSTATUS PsCreateSystemThread();
NTSTATUS ZwOpenProcess();
NTSTATUS ZwOpenEvent();
也就是说,这个值能说明函数的执行结果,比如:
STATUS_SUCCESS 0X00000000 成功
STATUS_INBALID_PARAMETER 0xC000000D 参数无效
STATUS_BUFFER_OVERFLOW 0x80000005 缓冲区长度不够
当你调用的内核函数,如果返回的结果不是STATUS_SUCCESS,就说明函数执行中遇到了问题,具体是什么问题,可以在ntstatus.h文件中查看
5.内核中的异常处理
在内核中,一个小小的错误就可能导致蓝屏,比如:读写一个无效的内存地址.为了让自己的内核程序更加健壮,强烈建议大家在编写内核程序时,使用异常处理.
Windows提供了结构化异常处理机制,一般的编译器都是支持的,如下:
__try{
//可能出错的代码
}
__except(filter_value)
{
//出错时要执行的代码
}
出现异常时,可根据filter-value的值来决定程序该如何执行,当filter_value的值为:
EXCEPTION_EXECUTE_HANDLER(filter_value = 1),代码进入except块
EXCEPTION_CONTINUE_SEARCH(filter_value = 0),不处理异常,由上一层调用函数处理
EXCEPTION_CONTINUE_EXECUTION(filter_value = -1),回去继续执行错误处的代码
6.常用的内核内存函数
对内存的使用,主要就是:申请,设置,拷贝以及释放.
C语言 | 内核中 |
---|---|
malloc | ExAllocatePool |
memset | RtlFillMemory |
memcpy | RtlMoveMemory |
free | ExFreePool |
7.内核字符串种类
CHAR(char) //ASCII
WCHAR(wchar_t) //UNICODE
ANSI_STRING //升级版ASCII
UNICODE_STRING //升级版UniCode
在应用层时,无论是ASCII还是UNICODE都是以0结尾,表示字符结束,区别时ascii是一个字节(0),而unicode是两个字节的(00)
ANSI_STRING字符串:
typedef struct _STRING
{
USHORT Length;//长度
USHOST MaximumLength;//最大长度
PCHAR Buffer;//字符串开始地址
}STRING;
UNICODE_STRING字符串:
typedef struct
{
USHORT Length;//长度
USHOST MaximumLength;//最大长度
PWSTR Buffer;//字符开始地址
}UNICODE_STRING;
//区别在于它的是PWSTR,两个字节为单位
在驱动开发中,尽量使用升级版的字符类型
内核字符串常用函数
字符串常用的功能无非就是:
创建,复制,比较以及转换等等
功能 | ANSI_STRING字符串 | UNICODE_字符串 |
---|---|---|
创建 | RtlInitAnsiString | RtlInitUncodeString |
复制 | RtlInitAnsiString | RtlCopyUnicodeString |
比较 | RtlCompareString | RtlCompareUnicodeString |
转换 | RtlAnsiStringToUnicodeString | RtlUnicodeStringToAnsiString |