搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)

一直使用Visual Studio + WDK的方式开发Windows驱动,最近想在VS2017下安装WDK10开发驱动,结果遇到问题了,首先是没法实现双机调试,然后是编译出来的驱动在Win7平台下一加载就蓝屏,定位到是security_cookie的问题,紧接着又是生成的驱动与老版本Window兼容性的问题,最后是KdPrint消息看不到的问题。本文主要对遇到的这些问题和解决办法进行记录,主语虚拟机中Win7的安装等常规操作则略过,安装好后的配置,搜一下“虚拟机win7 双机调试”也都能解决。

搭建双机调试环境时的坑

WinDBG提示找不到对应串口,需将虚拟机中的打印机删除,该打印机默认占用了COM1口:
搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)_第1张图片

对应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机制造成的:
搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)_第2张图片
这个问题有两种解决方案,第一种算是官方途径,建议大家在没有其他特殊需求的情况下采用这种方案。

方案一:更改目标平台

建议首选此方法:在驱动工程属性中,找到“Driver Settings”项,然后将其“General”子项中的“Target OS Version”设置成Windows 7即可,如下图所示。
搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)_第3张图片

方案二:修改链接到的KernelBufferOverflowLib库

将产生故障的代码放到IDA里仔细看看:
搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)_第4张图片

很明显,这里就和0x0BB40E64E这个魔数杠上了,只要二者相等就直接蓝屏。当然,直接关闭/GS这个编译开关肯定能解决,但也就意味着程序可能被栈溢出攻击。其主要问题是在Win7下,Loader将__security_cookie就是初始化成了这个值!将这个16进制数搜一下,第一篇链接就解答了我们的疑惑。

WDM驱动针对Win8前后系统的兼容性问题(张佩)

为不同版本的 Windows 构建驱动程序

同时也给出了解决方案:

  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. 用记事本打开驱动项目的工程文件(.vcproj)并添加下面的内容:
$(DDK_LIB_PATH)\BufferOverflowK.lib

然而我们是在VS下编译,应该可以直接设置lib库的路径,试了一下,果然可以:

搭建VS2017+WDK10+WinDBG双机调试Win7环境过程遇到的坑与解决(WinDBG找不到串口、security_cookie导致的蓝屏、看不到调试消息等)_第5张图片

再看看生成的驱动程序中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 ; ---------------------------------------------------------------------------

这个流程就比较正常了,如果和魔数值相等,就将当前时间和魔数异或,然后取反作为初始种子。再测试一下,没问题了。

使用WDK10 生成兼容旧版Windows的驱动

另外在搜索过程中,还顺带搜到了一篇《vs2015 WDK10 生成 低于win7 的驱动》,可见这里:

vs2015 WDK10 生成 低于 win7 的驱动

Single Binary Opt-In: POOL_NX_OPTIN

将其中重点摘录如下:

  1. 定义两个宏:C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN=1
  2. 驱动入口处加入:ExInitializeDriverRuntime(DrvRtPoolNxOptIn);

解决看不到KdPrint的问题

这样是可以正常加载运行驱动了,然而却看不到KdPrint的信息。原因是需要在被调试机中,对调试过滤级别进行设定:

  1. 定位到HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/
  2. 新建Key,名字为Debug Print Filter
  3. 然后在此Key下新建一个DWORD value ,名字为DEFAULT,然后设置值为0x00000008,

你可能感兴趣的:(调试与反汇编)