一直使用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
解决由于Security Cookie初始算法不兼容导致的加载时蓝屏
用VS2017配合WDK10搭了个驱动开发环境,用其中的WDM模板写了个NT式的HelloWorld驱动,编译后拖到测试机里运行居然蓝屏了。故障定位是/GS机制造成的:
放到IDA里仔细看看:
很明显,这里就和0x0BB40E64E这个魔数杠上了,只要二者相等就直接蓝屏。当然,直接关闭/GS这个编译开关肯定能解决,但也就意味着程序可能被栈溢出攻击。其主要问题是在Win7下,Loader将__security_cookie就是初始化成了这个值!将这个16进制数搜一下,第一篇链接就解答了我们的疑惑。
WDM驱动针对Win8前后系统的兼容性问题(张佩) <http://www.yiiyee.cn/Blog/win8-driver/>
为不同版本的 Windows 构建驱动程序 <https://msdn.microsoft.com/ZH-CN/library/jj572863.ASPX>
同时也给出了解决方案:
* 手动编译,手动设定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
* 用记事本打开驱动项目的工程文件(.vcproj)并添加下面的内容: <KernelBufferOverflowLib>
$(DDK_LIB_PATH)\BufferOverflowK.lib<KernelBufferOverflowLib>
然而我们是在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_cookieINIT: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_40403EINIT:00404029 INIT:00404029 loc_404029: ; CODE XREF:
___security_init_cookie+13↑j INIT:00404029 rdtsc INIT:0040402B xor eax, offset
___security_cookieINIT:00404030 mov ___security_cookie, eax INIT:00404035 jnz
short loc_40403EINIT:00404037 mov eax, ecx INIT:00404039 mov
___security_cookie, eaxINIT: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 endpINIT:00404048 INIT:00404048 ;
---------------------------------------------------------------------------
这个流程就比较正常了,如果和魔数值相等,就将当前时间和魔数异或,然后取反作为初始种子。再测试一下,没问题了。
使用WDK10 生成兼容旧版Windows的驱动
另外在搜索过程中,还顺带搜到了一篇《vs2015 WDK10 生成 低于win7 的驱动》,可见这里:
vs2015 WDK10 生成 低于 win7 的驱动
<https://blog.csdn.net/qq_18218335/article/details/77480475>
Single Binary Opt-In: POOL_NX_OPTIN
<https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/single-binary-opt-in-pool-nx-optin>
将其中重点摘录如下:
* 定义两个宏:C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN=1
* 驱动入口处加入:ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
解决看不到KdPrint的问题
这样是可以正常加载运行驱动了,然而却看不到KdPrint的信息。原因是需要在被调试机中,对调试过滤级别进行设定:
* 定位到HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/
* 新建Key,名字为Debug Print Filter
* 然后在此Key下新建一个DWORD value ,名字为DEFAULT,然后设置值为0x00000008,
热门工具 换一换