一直使用Visual Studio + WDK的方式开发Windows驱动,最近想在VS2017下安装WDK10开发驱动,结果遇到问题了,首先是没法实现双机调试,然后是编译出来的驱动在Win7平台下一加载就蓝屏,定位到是security_cookie的问题,紧接着又是生成的驱动与老版本Window兼容性的问题,最后是KdPrint消息看不到的问题。本文主要对遇到的这些问题和解决办法进行记录,主语虚拟机中Win7的安装等常规操作则略过,安装好后的配置,搜一下“虚拟机win7 双机调试”也都能解决。
WinDBG提示找不到对应串口,需将虚拟机中的打印机删除,该打印机默认占用了COM1口:
对应WinDBG参数为:
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe" -b -k com:pipe,port=\\.\pipe\com_1,resets=0,reconnect -y SRV*E:\DBGSymbols*E:\MySymbols*http://msdl.microsoft.com/download/symbols
用VS2017配合WDK10搭了个驱动开发环境,用其中的WDM模板写了个NT式的HelloWorld驱动,编译后拖到测试机里运行居然蓝屏了。故障定位是/GS机制造成的:
这个问题有两种解决方案,第一种算是官方途径,建议大家在没有其他特殊需求的情况下采用这种方案。
建议首选此方法:在驱动工程属性中,找到“Driver Settings”项,然后将其“General”子项中的“Target OS Version”设置成Windows 7即可,如下图所示。
很明显,这里就和0x0BB40E64E这个魔数杠上了,只要二者相等就直接蓝屏。当然,直接关闭/GS这个编译开关肯定能解决,但也就意味着程序可能被栈溢出攻击。其主要问题是在Win7下,Loader将__security_cookie就是初始化成了这个值!将这个16进制数搜一下,第一篇链接就解答了我们的疑惑。
WDM驱动针对Win8前后系统的兼容性问题(张佩)
为不同版本的 Windows 构建驱动程序
同时也给出了解决方案:
>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
$(DDK_LIB_PATH)\BufferOverflowK.lib
然而我们是在VS下编译,应该可以直接设置lib库的路径,试了一下,果然可以:
再看看生成的驱动程序中cookie初始化部分:
INIT:00404010 ; =============== S U B R O U T I N E =======================================
INIT:00404010
INIT:00404010 ; Attributes: library function bp-based frame
INIT:00404010
INIT:00404010 ___security_init_cookie proc near ; CODE XREF: GsDriverEntry(x,x)+5↑p
INIT:00404010
INIT:00404010 InitialSeed = _LARGE_INTEGER ptr -8
INIT:00404010
INIT:00404010 mov edi, edi
INIT:00404012 push ebp
INIT:00404013 mov ebp, esp
INIT:00404015 push ecx
INIT:00404016 push ecx
INIT:00404017 mov eax, ___security_cookie
INIT:0040401C mov ecx, 0BB40E64Eh
INIT:00404021 test eax, eax
INIT:00404023 jz short loc_404029
INIT:00404025 cmp eax, ecx
INIT:00404027 jnz short loc_40403E
INIT:00404029
INIT:00404029 loc_404029: ; CODE XREF: ___security_init_cookie+13↑j
INIT:00404029 rdtsc
INIT:0040402B xor eax, offset ___security_cookie
INIT:00404030 mov ___security_cookie, eax
INIT:00404035 jnz short loc_40403E
INIT:00404037 mov eax, ecx
INIT:00404039 mov ___security_cookie, eax
INIT:0040403E
INIT:0040403E loc_40403E: ; CODE XREF: ___security_init_cookie+17↑j
INIT:0040403E ; ___security_init_cookie+25↑j
INIT:0040403E not eax
INIT:00404040 mov ___security_cookie_complement, eax
INIT:00404045 mov esp, ebp
INIT:00404047 pop ebp
INIT:00404048 retn
INIT:00404048 ___security_init_cookie endp
INIT:00404048
INIT:00404048 ; ---------------------------------------------------------------------------
这个流程就比较正常了,如果和魔数值相等,就将当前时间和魔数异或,然后取反作为初始种子。再测试一下,没问题了。
另外在搜索过程中,还顺带搜到了一篇《vs2015 WDK10 生成 低于win7 的驱动》,可见这里:
vs2015 WDK10 生成 低于 win7 的驱动
Single Binary Opt-In: POOL_NX_OPTIN
将其中重点摘录如下:
这样是可以正常加载运行驱动了,然而却看不到KdPrint的信息。原因是需要在被调试机中,对调试过滤级别进行设定: