其实是应用程序使用 DeviceIoControl 发送请求,内核使用独享的同步事件(KEVENT)来等待.
当内核想发送数据给应用程序时就设置事件即可.
在应用程序中因为要等待 DeviceIoControl 函数的返回,所以应用程序应该新开一个线程来做这件事情.
内核中的缓冲区链表结构
内核使用一个 双向链表 来保存已经输入的字符串
应用层取 字符串 时, 每次返回一个并从链表中删除 保证先入显出的顺序,就向专门原来传递长度小于 512 字节的字符串的管道一样,双向链表使用 LIST_ENTRY
//定义一个列表原来保存字符串
#define CWK_STR_LEN_MAX 512
typedef struct {
LIST_ENTRY list_entry;
char buf[CWK_STR_LEN_MAX];
} CWK_STR_NODE;
//自旋锁保证链表操作的安全
KSPIN_LOCK g_cwk_lock;
//事件标识是否有字符串可以取
KEVENT g_cwk_event;
//必须的链表头
LIST_ENTRY g_cwk_str_list;
//分配内存并初始化一个链表节点
CWK_STR_NODE *cwkMallocStrNode(){
CWK_STR_NODE *ret = ExAllocatePoolWithTag(NonPagePool,sizeof(CWK_STR_NODE),MEM_TAG);
if(ret == NULL){
return NULL;
}
return ret;
}
//分配节点
str_node = cwkMallocStrNode();
if(str_node == NULL){
status = 资源不足...
break;
}
//拷贝字符串
strncpy(str_node->buf,(char *)buffer,CWK_STR_LEN_MAX);
//新的字符串插入到链表末尾
ExInterlockedInsertTailList(&g_cwk_str_list,(PLIST_ENTRY)str_node,&g_cwk_lock);
//设置事件
KeSetEvent(&g_cwk_event,0,TRUE);
//释放 ExFreePool
使用 while 循环来判断链表是否有数据
使用等待事件来改善CPU的占用,用睡眠也可以
注意使用过的内存需要释放
64位和32位内核开发的差异
64位系统新增机制 - WOW64 子系统
该子系统是为了兼容32位应用程序的,是一个轻量级的兼容层
主要由3个DLL实现,分配是 Wow64.dll Wow64Win.dll Wow64Cpu.dll
当一个32位应用程序发起系统调用,WoW64子系统拦截到系统调用,如果调用参数包涵指针,子系统就会把指针长度转换成合适的长度,然后再把请求提交给内核.
WOW64子系统有两个只要模块,分别是文件系统重定向器模块和注册表重定向器模块
windows 64位系统有两个 system32 目录,分别是 %windir%\System32 和 %windir%\SysWOW64
前者主要包含64位系统二进制文件,后者只要包涵32位系统二进制文件
不同位数的应用程序需要调用不同的系统DLL,如果是32位应用程序 WOW64子系统会对 System32目录做透明重定向 到 %windir%SysWOW64(绝大多数情况下)
例如:
HANDLE hFile = CreateFile(_T("C:\\windows\\system32\\testfile.txt"),
GENERIC_READ,0,NULL,CREATE_ALWAYS,0,NULL);
if(hFile != INVALID_HANDLE_VALUE){
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
这个程序如果编译成32位程序,会在 SysWOW64 目录下生成文件.如果是64位程序,则在 System32 下生成
可以调用系统API来关闭重定向
BOOL WINAPI Wow64DisableWow64FsRedirection(_Out_ PVOID *Oldvalue); //参数用来保存原来的重定向状态
恢复重定向使用 Oldvalue 这个参数
BOOL WINAPI Wow64RevertWow64FsRedirection(_In_ PVOID Oldvalue);
并不是所有的 %windir%System32 下目录和文件都会重定向,一些特殊目录是不重定向的
%windir%\System32\catroot
%windir%\System32\catroot2
%windir%\System32\drivers\etc
%windir%\System32\logfiles
%windir%\System32\spool
注册表重定向器和文件系统重定向器类型,但功能更复杂,除了提供重定向功能外,还提供注册表反射功能
HKEY_LOCAL_MACHINE\SOFTWARE --> HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node
PatchGuard 技术
对于32位系统来说,驱动程序可以对内核的数据结构和关键函数进行挂钩和修改,但是在64位系统不再适用,因为微软在64位系统中引入了 PatchGuard(安全内核) 机制,这个机制会定时检查系统关键位置,如 SSDT(系统服务描述表) GDT(全局描述表) IDT(中断描述表) 系统模块(ntoskrnl.exe hal.sys 等) 一旦发现这些关机位置的数据或代码给篡改,系统就会触发蓝屏(BSOD),例如 SSDT HOOK INLINE HOOK IDT HOOK 等技术都不能在64位下使用(大概),然而并没有什么软用
注意32位应用程序加载64位驱动需要先关闭文件重定向
驱动文件在64位系统需要签名才能被加载,可以选择 禁用驱动签名 模式进入系统
64位驱动不在允许内嵌汇编,可以把汇编代码写成函数放到一个单独的asm文件中,然后通过函数的方式调用
Sources 文件中指定 asm 文件即可