Win8驱动的兼容性问题
引用注明>> 【作者:张佩】【原文:www.yiiyee.cn/blog】
最近我发现为Win8开发的驱动程序,有些能安装在Win7上(包括更早系统),有些则不能。那些不能安装的情况很可怕:一旦安装并加载驱动,系统就会立刻蓝屏。针对这个问题,做了一番调查研究。发现了一个简单的规律:
如果开发时使用的是WDM驱动框架,则存在此问题;如果使用KMDF驱动框架,则正常。
这是为什么呢?一起来看看吧。
VS2012集成开发环境
Visual Studio 2012(简称VS2012)中包含了Windows驱动程序编译器,使得Windows驱动也可以在Visual Studio的集成开发环境中进行开发了。安装VS2012后,再安装Win8 WDK,打开VS2012会发现多了两种新的“平台工具集”,支持Windows内核和用户驱动程序的编译。如下图所示:
新建的内核驱动项目,会自动选择合适的工具集:WindowsKernelModeDriver8.0。更改工作集,会影响相关的工程项目设置,比如包含目录的查找路径等。所以,如果把驱动项目的工作集改成用户程序相关的话,编译器会报很多找不到头文件的错误,比如找不到<ntddk.h>。
和以前的控制台编译环境类似,在IDE环境中,我们也可以选择不同的目标系统:操作系统,硬件平台。通过工具栏上的列表框进行选择。如下图所示:
我们可以通过工程向导来产生一个WDM内核驱动项目,这里将项目名称设为Test。
Security Cookie导致的不兼容
编译器默认开启/GS编译选项,用来保护内核栈的完整性。编译器会在程序开始的地方,保存一个cookie值到栈上;在程序退出时再检查这个cookie值是否被破坏,如果被破坏,说明栈溢出,表明系统遭到了破坏从而需要蓝屏保护。
GS是一种被普遍运用的保护机制。开启了GS选项后,编译器会链接一个GS相关的库文件来实现GS功能,当目标系统为Win7时库文件是BufferOverflowK.lib,当目标系统为Win8+时库文件是BufferOverflowFastFailK.lib。链接器是如何实现栈保护的呢?它先在驱动加载的时候,也就是GsDriverEntry函数内初始化cookie。然后在每个驱动函数的开始和结束的地方,添加cookie检查的代码。
链接器为了对cookie进行初始化,会为驱动程序重新生成一个名为GsDriverEntry的入口函数,初始化Cookie后再调用驱动程序自己的DriverEntry入口函数。下面是一个典型的GsDriverEntry的实现:
Test!GsDriverEntry:
82ea403e 8bff mov edi,edi
82ea4040 55 push ebp
82ea4041 8bec mov ebp,esp
82ea4043 e8bdffffff call Test!__security_init_cookie// 初始化cookie
82ea4048 5d pop ebp
82ea4049 e9b8fff7ff jmp Test!DriverEntry (82e24006)//调用DriverEntry
82ea404e cc int 3
下面是Win7版本security_init_cookie函数的逻辑:
test!__security_init_cookie:
82eb3005 a10050e382 mov eax,dword ptr [test!__security_cookie (82e35000)] ds:0023:82e35000=00300083
82eb300a b94ee640bb mov ecx,0BB40E64Eh
82eb300f 85c0 test eax,eax
82eb3011 7404 je test!__security_init_cookie+0x12 (82eb3017) // 判断是否等于0
82eb3013 3bc1 cmp eax,ecx // 判断是否等于0BB40E64Eh
82eb3015 751a jne test!__security_init_cookie+0x2c (82eb3031)
82eb3017 a13040e382 mov eax,dword ptr [test!KeTickCount (82e34030)] // 获取当前系统时间
82eb301c 8b00 mov eax,dword ptr [eax]
82eb301e 350050e382 xor eax,offset test!__security_cookie (82e35000)
82eb3023 a30050e382 mov dword ptr [test!__security_cookie (82e35000)],eax
82eb3028 7507 jne test!__security_init_cookie+0x2c (82eb3031)
82eb302a 8bc1 mov eax,ecx
82eb302c a30050e382 mov dword ptr [test!__security_cookie (82e35000)],eax // 生成新cookie值 // 返回
82eb3031 f7d0 not eax
82eb3033 a30450e382 mov dword ptr [test!__security_cookie_complement (82e35004)],eax
82eb3038 c3 ret
这段逻辑先检查security_cookie的当前值,如果不等于0且不等于0xBB40E64E,就立即退出;否则根据当前的系统时间,产生一个随机的cookie值。这里的值0xBB40E64E是个特征值,可能是系统默认生成的。大部分的镜像在加载的时候,其cookie都会被初始化成这个特征值。
当目标OS为Win8时,编译器默认链接BufferOverflowFastFailK.lib文件,它使用新的Cookie算法。正是这个新算法导致了不兼容性。看看Win8中security_init_cookie函数的逻辑,它硬是和0xBB40E64E较上了劲:
mov eax, __security_cookie
test eax, eax
jz short loc_404029
cmp eax, 0BB40E64Eh // 如果等于0BB40E64Eh,跳到下面产生0x29中断,产生蓝屏
jz short loc_404029
not eax
mov __security_cookie_complement, eax
retn loc_404029: ; CODE XREF:
push 6
pop ecx
int 29h // 蓝屏
它判断当前的cookie值是否等于特征值0xBB40E64E,如果相等,立刻蓝屏。神奇的是,在 Win7及以前的OS上,大部分的驱动程序的cookie值都会被加载器初始化为0xBB40E64E。而在Win8+系统上则永远不会这样。这就是为什么能在Win8+正常运行的驱动,一放到Win7上就蓝屏的原因。
WDM和KMDF的区别
那为什么使用KMDF编译的驱动,又没有问题呢?原因很简单,KMDF框架链接的静态库文件还是BufferOverflowK.lib。不保证KMDF以后的版本不会链接新库文件的可能。
如何避免
虽然KMDF兼容性良好,但很多情况下,还是会用WDM框架编写驱动,而且还有很多小端口驱动也可能存在类似问题。如何避免呢。有三种简单的方法:
其一是为Win7及以前系统和Win8+系统产生不同的镜像文件。这也是比较推荐的方法。
其二是在Win8+系统上安装为Win7系统编译的驱动程序。经过测试,大多数为Win7编译的驱动程序,都能正常运行在Win8和Win blue系统上。但不保证更新的Windows系统出来后,这种向前兼容性仍然有效。
其三是干脆关闭GS编译选项。但这样就缺少了栈保护,不推荐。
最后介绍一种MSDN中介绍的比较高级的修改编译选项的办法,可以让编译器在为Win8+目标系统编译驱动程序时,仍选择旧版本的栈保护库文件BufferOverflowK.lib:
- 手动编译,手动设定KernelBufferOverflowLib的路径:
msbuild /p:KernelBufferOverflowLib="C:\Program Files (x86)\Windows Kits\8.1\Lib\win8\km\x64\BufferOverflowK.lib" /p:platform=x64 /p:Configuration="Win8 Release" myDriver.sln
- 用记事本软件打开驱动项目的工程文件,并在合适的地方添加下面的属性:
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib<KernelBufferOverflowLib>
Win8驱动的兼容性问题的更多相关文章
- Win8驱动测试模式
打开驱动测试模式(保存成bat文件,双击执行) bcdedit /set testsigning on pause 执行完成后,看见提示操作成功的提示,之后我们重启一下,再次进入系统,在桌面的右下角会 ...
- 解决Win8.1 IE11兼容性问题的方法
装了64位win8.1企业版,IE11出现了一些兼容性问题,如个别网银网页兼容问题,还有office.迅雷.adobe reader.旋风等等插件不兼容不能加载的问题. 折腾了一天总算全部解决了,主要 ...
- USB转串口WIN8驱动安装
http://jingyan.baidu.com/article/11c17a2c0bb606f446e39da0.html //查看百度经验 http://jingyan.baidu.com/ar ...
- 原装win8系统电脑崩溃问题解决
原装win8系统电脑崩溃问题解决 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:之所以撰写本篇关于win8原装系统电脑崩溃的博文,一是要吐槽一下原装w ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计
目 录 第三章 设备驱动的设计... 2 3.1 初始化设备... 4 3.2 运行设备接口设计... 4 3.3 ...
- win8 中使用第三方无线网卡出现无线连接受限解决办法
无线路由 无线网络模式基本设置 模式改为 11bg mixed , 然后在 win8 的设备管理器中找到无线路由 不知道 win8 有些地方兼容性做的不是很到位,我的 xp不做任何配置可以正常使用.
- win8安装matlab7.0
win8和win7下安装matlab7.0要注意许多地方,其实安装最新版一般都是没有问题的. 不过最新版太大,校园网下载太难,所以还是用7.0 基本上在百度经验上已经包括了大部分的注意事项了,可以参考 ...
- windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤
大家都知道,我们打开一堆文件夹的时候,是什么样子 “厚厚的一叠”图标堆叠在一起的,非常的不方便 那么,是不是可以像浏览器一样的tab页面展示呢? 答案是可以的 安装好就是这样子的 是不是方便漂亮了很多 ...
- ImageMagick: win7 | win8 & uac (用户帐户控制) 注册表的一些事
现在用win7,win8的人越来越多了, 程序在一些 win 7, win8 上运行会遇到一些之前没想过的兼容性问题. 比如 64位系统运行32位程序时的注册表重定向,还有因为 uac (用户帐户控制 ...
随机推荐
- ./configure && make && make install 编译安装和卸载 (Linux)
./configure && make && make install 编译安装和卸载 (Linux) 正常的编译安装/卸载: 源码的安装一般由3个步骤组成:配置( ...
- Summary on mapreduce.framework.name init error
An exception occured while performing the indexing job : java.io.IOException: Cannot initialize Cl ...
- JAVA自学作业03
JAVA自学作业03 1.请用最有效率的方式计算2*8的结果 使用位运算是最有效率的. System.out.println(2<<3); 2.请交换两整数的值 int x = 10; i ...
- Mac删除默认美国输入法
1.打开sudo open ~/Library/Preferences/com.apple.HIToolbox.plist 2.找到这个,然后点击删除,最后保存,然后在立马重启 3.如果要还原,直接在 ...
- CentOS下安装Jenkins(Docker/war/tomcat/java -jar)
参考官方提供的安装教程:https://jenkins.io/doc/book/installing/,可以发现官方推荐使用Docker进行安装.虽然用Docker有很多好处,但也有缺点. 下面是各种 ...
- C#多线程技术提高RabbitMQ消费吞吐率
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的第二部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
- 让你提升命令行效率的 Bash 快捷键
生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率. 编辑命令 Ctrl + a :移到命令行首 Ctrl + e :移到命令行尾 Ctrl + f :按字符前移(右向) ...
- 05、transformation操作开发实战
1.map:将集合中每个元素乘以2 2.filter:过滤出集合中的偶数 3.flatMap:将行拆分为单词 4.groupByKey:将每个班级的成绩进行分组 5.reduceByKey:统计每个班 ...
- netty4.0 Server和Client的通信
netty4.0 Server和Client的通信 创建一个maven项目 添加Netty依赖 <dependency> <groupId>io.netty</group ...
- Windows上的字符转换之CP_ACP和CP_OEMCP
原文地址:http://blog.sina.com.cn/s/blog_53c1950a010158mw.html Windows API函数MultiByteToWideChar用于多字节编码字符串 ...