引用注明>> 【作者:张佩】【原文: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:

  1. 手动编译,手动设定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
  1. 用记事本软件打开驱动项目的工程文件,并在合适的地方添加下面的属性:
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib<KernelBufferOverflowLib>

Win8驱动的兼容性问题的更多相关文章

  1. Win8驱动测试模式

    打开驱动测试模式(保存成bat文件,双击执行) bcdedit /set testsigning on pause 执行完成后,看见提示操作成功的提示,之后我们重启一下,再次进入系统,在桌面的右下角会 ...

  2. 解决Win8.1 IE11兼容性问题的方法

    装了64位win8.1企业版,IE11出现了一些兼容性问题,如个别网银网页兼容问题,还有office.迅雷.adobe reader.旋风等等插件不兼容不能加载的问题. 折腾了一天总算全部解决了,主要 ...

  3. USB转串口WIN8驱动安装

    http://jingyan.baidu.com/article/11c17a2c0bb606f446e39da0.html  //查看百度经验 http://jingyan.baidu.com/ar ...

  4. 原装win8系统电脑崩溃问题解决

    原装win8系统电脑崩溃问题解决 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:之所以撰写本篇关于win8原装系统电脑崩溃的博文,一是要吐槽一下原装w ...

  5. [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计

    目       录 第三章           设备驱动的设计... 2 3.1           初始化设备... 4 3.2           运行设备接口设计... 4 3.3        ...

  6. win8 中使用第三方无线网卡出现无线连接受限解决办法

    无线路由  无线网络模式基本设置 模式改为 11bg mixed , 然后在 win8 的设备管理器中找到无线路由 不知道 win8 有些地方兼容性做的不是很到位,我的 xp不做任何配置可以正常使用.

  7. win8安装matlab7.0

    win8和win7下安装matlab7.0要注意许多地方,其实安装最新版一般都是没有问题的. 不过最新版太大,校园网下载太难,所以还是用7.0 基本上在百度经验上已经包括了大部分的注意事项了,可以参考 ...

  8. windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤

    大家都知道,我们打开一堆文件夹的时候,是什么样子 “厚厚的一叠”图标堆叠在一起的,非常的不方便 那么,是不是可以像浏览器一样的tab页面展示呢? 答案是可以的 安装好就是这样子的 是不是方便漂亮了很多 ...

  9. ImageMagick: win7 | win8 & uac (用户帐户控制) 注册表的一些事

    现在用win7,win8的人越来越多了, 程序在一些 win 7, win8 上运行会遇到一些之前没想过的兼容性问题. 比如 64位系统运行32位程序时的注册表重定向,还有因为 uac (用户帐户控制 ...

随机推荐

  1. ./configure && make && make install 编译安装和卸载 (Linux)

    ./configure && make && make install 编译安装和卸载 (Linux) 正常的编译安装/卸载:   源码的安装一般由3个步骤组成:配置( ...

  2. Summary on mapreduce.framework.name init error

      An exception occured while performing the indexing job : java.io.IOException: Cannot initialize Cl ...

  3. JAVA自学作业03

    JAVA自学作业03 1.请用最有效率的方式计算2*8的结果 使用位运算是最有效率的. System.out.println(2<<3); 2.请交换两整数的值 int x = 10; i ...

  4. Mac删除默认美国输入法

    1.打开sudo open ~/Library/Preferences/com.apple.HIToolbox.plist 2.找到这个,然后点击删除,最后保存,然后在立马重启 3.如果要还原,直接在 ...

  5. CentOS下安装Jenkins(Docker/war/tomcat/java -jar)

    参考官方提供的安装教程:https://jenkins.io/doc/book/installing/,可以发现官方推荐使用Docker进行安装.虽然用Docker有很多好处,但也有缺点. 下面是各种 ...

  6. C#多线程技术提高RabbitMQ消费吞吐率

    一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的第二部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...

  7. 让你提升命令行效率的 Bash 快捷键

    生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率. 编辑命令 Ctrl + a :移到命令行首 Ctrl + e :移到命令行尾 Ctrl + f :按字符前移(右向) ...

  8. 05、transformation操作开发实战

    1.map:将集合中每个元素乘以2 2.filter:过滤出集合中的偶数 3.flatMap:将行拆分为单词 4.groupByKey:将每个班级的成绩进行分组 5.reduceByKey:统计每个班 ...

  9. netty4.0 Server和Client的通信

    netty4.0 Server和Client的通信 创建一个maven项目 添加Netty依赖 <dependency> <groupId>io.netty</group ...

  10. Windows上的字符转换之CP_ACP和CP_OEMCP

    原文地址:http://blog.sina.com.cn/s/blog_53c1950a010158mw.html Windows API函数MultiByteToWideChar用于多字节编码字符串 ...