《Windows内核安全与驱动编程》-第六章学习

64位和32位的内核开发差异

6.1 64位系统新增机制

6.1.1 WOW64 子系统

WOW64 子系统,是64位 Windows 系统为了兼容32位的应用程序而新增的子系统。当一个32位应用程序发起系统调用时,WOW64 子系统就会先把这些指针的长度转换成合适的长度,然后再把系统调用请求提交给内核。通常把这个“拦截-转换” 的过程称为 “thunking”。

WOW64 子系统有两个重要的模块,分别为文件系统重定向器模块和注册表模块重定向器模块。

​ Windows 64位系统存在两个 System32 目录,,分别为 %windir%\Sysem32%windir%\SysWOW64 目录; 前者目录下主要包含64位系统二进制文件,后者目录下主要包含32位系统二进制文件。当一个32位的程序在32位系统环境下,需要到 System32 目录下加载所依赖的系统DLL,当把这个程序放在64位的系统环境下运行时,64位环境下的同样目录存放的是64位的DLL文件,这样会导致32位程序无法运行。为了解决这个问题, WOW64子系统的文件重定向器对 System32 目录做了透明的重定向。在绝大多数情况下,32 位应用程序访问 %windir%\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_HADLE_VALUE;
}

​ 上面这段代码如果运行在64位的环境下,被编译成32位和64位应用程序,testfile.txt最终保存的目录会不同。如果32位程序想访问真实的 System32 目录,需要调用API关闭重定向功能。

BOOL WINAPI Wow64DisableWow64FsReadirection(_Out_ PVOID *OldValue);

​ 该API只有一个参数,用于保存原来文件重定向器的状态,当需要恢复重定向器的状态的时候,可以使用 Wow64RevertWow64FsReadirection 函数。

BOOL WINAPI Wow64RevertWow64FsReadirection(_In_ PVOID OldValue);
PVOID pOldValue = NULL;
BOOL bRet = Wow64DisableWow64FsReadirection(&pOldValue);
if(bRet == TRUE )
{
        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_HADLE_VALUE;
    }
    Wow64RevertWow64FsReadirection(OldValue);
}

​ 上述代码即可在生成文件前关闭重定向,在文件生成后开启重定向。注意并非所有的 %windir\System32% 下的目录和文件都重定向。还有一些特殊目录是不重定向的,它们分别是:

  • %windir%\System32\catroot
  • %windir%\System32\catroot2
  • %windir%\System32\dirvers\etc
  • %windir%\System32\catroot\logfiles
  • %windir%\System32\catroot\spool

​ 注册表重定向器和文件系统重定向器功能类似,但是注册表重定向器提供的功能更为复杂,它除了提供重定向功能外,还提供注册表反射功能。反射功能与本章关系不大不做介绍。

​ 在64位系统下运行的32位程序,访问 HKEY_LOCAL_MACHINE\SOFTWARE 会被重定向到HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node

​ 如果想明确在指定的位置下创建子项,32位应用程序可以这样实现:

HKEY hKey = NULL;
RegCreateKeyEx(HKEY_LOCAL_MACHINE,T("Software\\Hello"),0,NULL,0,KEY_READ|KEY_WOW64_64KEY,NULL,&hKey,NULL);
if(hKey == NULL)
{
    RegCloseKey(hKey);
    hKey = NULL;
}

​ 32 位程序只要使用 KEY_WOW64_64KEY就可以访问当前的64位注册表,同理64位程序只要使用 KEY_WOW64_32KEY 就可以访问32位注册表。

6.1.2 PatchGuard 技术

​ 对于32位系统来说,驱动程序模块可以对内核的数据结构或者关键的函数进行挂钩和修改,但是这种技术不再适用于 Window64 位系统,原因是 64位系统中加入了 PatchGuard 机制。

​ 简单来说,该机制就是系统会定时检查系统文件的位置,如SSDT(系统服务描述表)、GDT (全局描述表)、IDT(中断描述表)、系统模块等。一旦发现这些关键位置的代码被篡改,系统就会蓝屏。

6.1.3 64位驱动的编译、安装与运行。

​ 这里因为我是使用的64位Win7,在第一部分环境配置中就解决了该问题。

6.2 编程差异

6.2.1 汇编嵌入变化

这里也在环境配置时候提到了,64位程序不再允许内嵌汇编。

int 3; 替换为 DbgBreakPoint(); 
6.2.2 预处理与条件编译

​ 在驱动开发中,有时候代码需要区分不同的平台编译不同的代码分支。比如需要开发一个注册表监控驱动,按照以往 32 位系统的常规做法,通过挂钩系统服务描述表(SSDT)中注册表相关API而得以实现的,但是64位系统下由于 PatchGuard 机制的存在,需要用其他的方法实现。所以在编译的时候需要进行分支

#ifdef _WIN64
	// 64位环境
#else
	// 32位环境
#endif
6.2.3 数据结构调整

​ 本章开头介绍了 thunking 技术,但是当一个32位应用程序通过 IOCTL 控制码的方式与64位驱动程序通信时,如果通信的数据结构里包含指针,此时 thunking 是不会发生的。那么此时会导致 64位期待的数据结构大小大于 32位驱动发送的大小。为了解决这个问题,在定义数据结构的时候,需要使用固定长度的类型来定义结构体成员。比如使用:

VOID * POINTER_32 Event 来替代 HANDLE * Event
UNICODE_STRING32 ObjectName 来替代 UNICODE_STRING ObjectName

​ 使用固定长度的类型来定义成员变量之后,在不同平台大小不再有歧义。

明日计划

继续学习驱动编程开发篇。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书的前身是《天书夜读——从汇编语言到Windows内核编程》和《寒江独钓——Windows内核安全编程》。与Windows客户端安全软件开发相关的驱动程序开发是本书的主题。书中的程序使用环境从32位到64位,从Windows XP到Windows 8都有涉及,大部分程序不经过修改即可在Windows 10上运行。同时本书也深入浅出地介绍了进行内核安全编程所需要的操作系统、汇编等基础知识。 本书共分三篇,基础篇囊括了驱动开发的基础知识,降低了入门的难度;开发篇介绍了在实际工作中可能遇到的各种开发需求的技术实现,包括:串口的过滤、键盘的过滤、磁盘的虚拟、磁盘的过滤、文件系统的过滤与监控、文件系统透明加密、文件系统微过滤驱动、网络传输层过滤、Windows过滤平台、NDIS协议驱动、NDIS小端口驱动、NDIS中间层驱动、IA-32汇编基础、IA-32体系中的内存地址、处理器权限级别切换、IA-32体系结构中的中断和Windows内核挂钩;高级篇包含了汇编语言、操作系统原理、处理器体系架构相关的内容。本书是由长期从事这个行业的工程师自己写的,所以处处以实用为准。对细节的考究主要体现在对实际问题的解决,而不是知识的详尽程度上。 本书适合计算机安全软件从业人员、计算机相关专业院校学生以及有一定C语言和操作系统基础知识的编程爱好者阅读。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值