C++ Windows内核在用户模式下不会发生损坏吗
我目前正在使用liveKD执行内核调试 在发生阻塞的所有情况下(aC++ Windows内核在用户模式下不会发生损坏吗,c++,windows,kernel,windbg,corruption,C++,Windows,Kernel,Windbg,Corruption,我目前正在使用liveKD执行内核调试 在发生阻塞的所有情况下(a::CloseHandle()函数调用永远不会返回),我碰巧有一个stacktrace,它在同步事件上阻塞内核 但是当我这样做的时候!对象12345678如果123456789是进程的线程信息中报告的我的同步事件,则表示不是有效对象(ObjectType invalid)。 我担心用户模式下应用程序级的损坏是否会损坏内核? windows是否保证内存空间的分离,从而防止类似的事情发生 应用程序代码采用C++、COM/DCOM和Wi
::CloseHandle()
函数调用永远不会返回),我碰巧有一个stacktrace,它在同步事件上阻塞内核
但是当我这样做的时候!对象12345678
如果123456789是进程的线程信息中报告的我的同步事件
,则表示不是有效对象(ObjectType invalid)。
我担心用户模式下应用程序级的损坏是否会损坏内核?
windows是否保证内存空间的分离,从而防止类似的事情发生
应用程序代码采用C++、COM/DCOM和Win32。
一条评论要求提供有关stacktrace和句柄类型的更多信息。 在这种情况下,它与串行com端口有关。但我想我也有它的文件句柄(还没有调试这些案例) 这就是我的stacktrace类型: THREAD 856a2d48 Cid 0660.0350 Teb: 7ff25000 Win32Thread: ffaaedd8 WAIT: (Executive) KernelMode Non-Alertable 860c6f9c SynchronizationEvent IRP List: babea5d8: (0006,01d8) Flags: 00000404 Mdl: 00000000 Not impersonating DeviceMap 89809fc8 Owning Process 86212d40 Image: DataCaptorIS.exe Attached Process N/A Image: N/A Wait Start TickCount 27315407 Ticks: 6067021 (1:02:17:26.134) Context Switch Count 2259 IdealProcessor: 0 UserTime 00:00:04.976 KernelTime 00:00:02.184 Win32 Start Address 0x775c03e9 Stack Init 8aa0dfd0 Current 8aa0da98 Base 8aa0e000 Limit 8aa0b000 Call 0 Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5 ChildEBP RetAddr Args to Child 8aa0dab0 824bfced 856a2d48 00000000 8ab00120 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4]) 8aa0dae8 824beb4b 856a2e08 856a2d48 860c6f9c nt!KiSwapThread+0x266 8aa0db10 824b856f 856a2d48 856a2e08 00000000 nt!KiCommitThreadWait+0x1df 8aa0db88 914539fb 860c6f9c 00000000 00000000 nt!KeWaitForSingleObject+0x393 8aa0dbcc 82478c1e 860c6f98 babea5d8 babea73c serial!SerialClose+0x332 (FPO: [Non-Fpo]) 8aa0dbe4 886206b9 babea5d8 861986d0 bc859308 nt!IofCallDriver+0x63 8aa0dc08 82478c1e 861986d0 860c6890 00000800 serenum!Serenum_CreateClose+0x77 (FPO: [Non-Fpo]) 8aa0dc20 82673be6 84aa7a00 bc8592f0 00000000 nt!IofCallDriver+0x63 8aa0dc64 826647c9 bc859308 bc859308 bc8592f0 nt!IopDeleteFile+0x10c 8aa0dc7c 824ba1e0 00000000 856a2d48 bc8592f0 nt!ObpRemoveObjectRoutine+0x59 8aa0dc90 824ba150 bc859308 82687556 960a5578 nt!ObfDereferenceObjectWithTag+0x88 (FPO: [0,0,3]) 8aa0dc98 82687556 960a5578 856a2d48 00000c80 nt!ObfDereferenceObject+0xd (FPO: [0,1,0]) 8aa0dcdc 8268727c 960a5578 a7d21900 86212d40 nt!ObpCloseHandleTableEntry+0x21d 8aa0dd0c 82687616 86212d40 856a2d01 0763f3b4 nt!ObpCloseHandle+0x7f 8aa0dd28 8247f8a6 00000c80 0763f3b8 775d7094 nt!NtClose+0x4e 8aa0dd28 775d7094 00000c80 0763f3b8 775d7094 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ 8aa0dd34) WARNING: Frame IP not in any known module. Following frames may be wrong. 0763f3b8 00000000 00000000 00000000 00000000 0x775d7094 在应用程序级别,在usermode中,这发生在本应取消并清除任何IRP的代码之后:
::CancelIoEx(m_handle_to_serial_port_com);
WaitForRequestToComplete(); // our function calls ::GetOverlappedResult(..., bWait) for any OVERLAPPED that was pending, with bWait == TRUE
::PurgeComm(m_handle_to_serial_port_com);
WaitForRequestToComplete(); // our function calls ::GetOverlappedResult(..., bWait) for any OVERLAPPED that was pending, with bWait == TRUE
::CloseHandle(m_handle_to_serial_port_com); // the closeHandle which never returns
这些问题确实是随机发生的。有时需要几天才能繁殖
显示SynchronizationEvent对象的内存地址86184f9c(在另一台有相同错误的机器上): 0:kd>dp 86184f9c-@@c++(sizeof(nt!\u对象\u头)-(RTL\u字段\u大小(nt!\u对象\u头,体)) 86184f84 0000000 6 00000000 00000000 00000000 86184f94 00000000 00000001 00040001 00000000 86184fa4 85917420 85917420 00000000 00000000 86184fb4 0000000000000000000000000000000 d 86184fc4 86184890 000000 40 00000000 000000800 86184 FD4 00000000 85747a68 00000000 00000000 86184fe4 00000000000000 86184fec 86184fec 86184ff4 86184ff4 86184ff4 96d4c000 04040000 并尝试显示对象标题: 0: kd> dt nt!_object_header 86184f9c - @@c++(sizeof(nt!_object_header) - #RTL_FIELD_SIZE(nt!_object_header, Body)) Cannot find specified field members. 0:kd>dt-nt_object_header 86184f9c-@@c++(sizeof(nt!_object_header)-#RTL_FIELD_SIZE(nt!_object_header,Body)) 找不到指定的字段成员。
当然应该是这样的。如果内核可以从用户模式被破坏,那么您将有一个可能影响机器上所有用户的安全缺陷。您可以通过使内核崩溃来拒绝服务。您可以利用内核缓冲区溢出来提升权限。您可以使用内核信息泄露漏洞窃取其他人的数据 仅仅因为你给内核提供了坏数据并不意味着它有这样一个漏洞。内核可能足够聪明,可以检测和防止此类问题,或者它可以执行任何可能受到userland中损坏的userland输入影响的代码
如果您确实发现了一个bug,该bug会导致内核崩溃、读取其他人传递给内核的数据或类似的内容,那么您应该向Microsoft报告。如果您怀疑发现了什么,请尝试联系MS支持部门,看看他们是否能提供帮助。他们是操作系统方面的专家,最有可能确定您怀疑的缺陷是否是真正的缺陷。很遗憾,运行在环0中的内核不能与运行在环3中的进程进行更改。Windows中继来自微处理器的硬件支持,以实现内存和I/O隔离,因此任何进程都无法访问内核空间或其他用户的内存空间中的内存 访问内核的唯一方法是通过系统调用。Windows中的系统调用采用称为“本机API”的API形式。例如
NtCreateFile
,它是代表调用CreateFile
函数而调用的函数NtCreateFile
必须检查所有参数的有效性。这个函数可以从内核本身作为ZwCreateFile
访问。从内核调用时,它不进行检查,因为内核信任在内核模式下运行的任何代码。CloseHandle()仅在句柄的所有挂起IO完成后才会完成。根据你发布的线程信息,这个线程至少有一个挂起的IRP——我想看看它是否与你试图关闭的对象相同
FWIW,-您的串行设备支持取消吗?这只是为什么
的后续说明!对象
在给定地址上不起作用
TL;DR:您的SynchronizationEvent未损坏。传递给的地址!object
命令不是内核对象,它只是一个内核结构
0: kd> dt _KEVENT
nt!_KEVENT
+0x000 Header : _DISPATCHER_HEADER
kd> dt _dispatcher_header 0xffffd000`6dba6278
ntdll!_DISPATCHER_HEADER
+0x000 Lock : 0n1594228737
+0x000 LockNV : 0n1594228737
+0x000 Type : 0x1 ''
+0x001 Signalling : 0 ''
+0x002 Size : 0x6 ''
+0x003 Reserved1 : 0x5f '_'
+0x000 TimerType : 0x1 ''
+0x001 TimerControlFlags : 0 ''
+0x001 Absolute : 0y0
+0x001 Wake : 0y0
+0x001 EncodedTolerableDelay : 0y000000 (0)
+0x002 Hand : 0x6 ''
+0x003 TimerMiscFlags : 0x5f '_'
+0x003 Index : 0y011111 (0x1f)
+0x003 Inserted : 0y1
+0x003 Expired : 0y0
+0x000 Timer2Type : 0x1 ''
+0x001 Timer2Flags : 0 ''
+0x001 Timer2Inserted : 0y0
+0x001 Timer2Expiring : 0y0
+0x001 Timer2CancelPending : 0y0
+0x001 Timer2SetPending : 0y0
+0x001 Timer2Running : 0y0
+0x001 Timer2Disabled : 0y0
+0x001 Timer2ReservedFlags : 0y00
+0x002 Timer2Reserved1 : 0x6 ''
+0x003 Timer2Reserved2 : 0x5f '_'
+0x000 QueueType : 0x1 ''
+0x001 QueueControlFlags : 0 ''
+0x001 Abandoned : 0y0
+0x001 DisableIncrement : 0y0
+0x001 QueueReservedControlFlags : 0y000000 (0)
+0x002 QueueSize : 0x6 ''
+0x003 QueueReserved : 0x5f '_'
+0x000 ThreadType : 0x1 ''
+0x001 ThreadReserved : 0 ''
+0x002 ThreadControlFlags : 0x6 ''
+0x002 CycleProfiling : 0y0
+0x002 CounterProfiling : 0y1
+0x002 GroupScheduling : 0y1
+0x002 AffinitySet : 0y0
+0x002 ThreadReservedControlFlags : 0y0000
+0x003 DebugActive : 0x5f '_'
+0x003 ActiveDR7 : 0y1
+0x003 Instrumented : 0y1
+0x003 Minimal : 0y1
+0x003 Reserved4 : 0y011
+0x003 UmsScheduled : 0y1
+0x003 UmsPrimary : 0y0
+0x000 MutantType : 0x1 ''
+0x001 MutantSize : 0 ''
+0x002 DpcActive : 0x6 ''
+0x003 MutantReserved : 0x5f '_'
+0x004 SignalState : 0n0
+0x008 WaitListHead : _LIST_ENTRY [ 0xffffe001`ef7a5540 - 0xffffe001`ef7a5540 ]
kd!object
命令只是查找一个特殊的结构(即nt!\u object\u HEADER
),该结构预先添加到所有内核对象。更准确地说,内核结构一有nt_对象头
就在它前面。在结构前面加上这个\u OBJECT\u HEADER
后,它就成为一个内核对象,然后由内核对象管理器处理(特别是以Ob
前缀开头的所有内核函数,但内核中还有其他涉及对象管理的函数)
如果内核想要创建一个事件,但特别是如果这个对象不必跨越用户区域/内核区域边界(或者如果不需要ref计数),那么内核可能只创建一个nt_KEVENT
结构,无nt_对象标题
检查地址是否是内核对象(或不是)
查看堆栈跟踪,我们有以下两行:
8aa0db88 914539fb 860c6f9c 00000000 00000000 nt!KeWaitForSingleObject+0x393
8aa0dbcc 82478c1e 860c6f98 babea5d8 babea73c serial!SerialClose+0x332 (FPO: [Non-Fpo])
幸运的是,serial.sys
是Microsoft驱动程序,因此我们有符号信息。查看serial中的代码!SerialClose
大约偏移量0x332,我们有以下代码:
PAGESER:0001EEFC lea eax, [esi+654h]
PAGESER:0001EF02 push ebx ; Timeout
PAGESER:0001EF03 push ebx ; Alertable
PAGESER:0001EF04 push ebx ; WaitMode
PAGESER:0001EF05 push ebx ; WaitReason
PAGESER:0001EF06 push eax ; Object
PAGESER:0001EF07 call ds:__imp__KeWaitForSingleObject@20 ; KeWaitForSingleObject(x,x,x,x,x)
等待代码的事件(KEVENT
类型)来自[esi+0x654]
。。。
回溯在函数开始时,我们有:
PAGESER:0001EBD5 mov esi, [ebp+DeviceObject]
PAGESER:0001EBD8 push edi
PAGESER:0001EBD9 mov esi, [esi+_DEVICE_OBJECT.DeviceExtension]
因此,esi(在[esi+0x654]
中)是设备ob的设备扩展
PAGESER:0001EBD5 mov esi, [ebp+DeviceObject]
PAGESER:0001EBD8 push edi
PAGESER:0001EBD9 mov esi, [esi+_DEVICE_OBJECT.DeviceExtension]
PAGESRP0:000194AF push esi ; State
PAGESRP0:000194B0 push 1 ; Type
PAGESRP0:000194B2 lea eax, [ebx+654h]
PAGESRP0:000194B8 push eax ; Event
PAGESRP0:000194B9 call edi ; KeInitializeEvent(x,x,x) ; KeInitializeEvent(x,x,x)
kd> !thread ffffe001ef7a5400
THREAD ffffe001ef7a5400 Cid 0538.054c Teb: 00007ff7a9869000 Win32Thread: fffff901406825d0 WAIT: (Executive) KernelMode Non-Alertable
ffffd0006dba6278 SynchronizationEvent
...
kd> dt _kthread ffffe001ef7a5400 waitblocklist
ntdll!_KTHREAD
+0x0d0 WaitBlockList : 0xffffe001`ef7a5540 _KWAIT_BLOCK
kd> dt _kthread ffffe001ef7a5400 alertable
ntdll!_KTHREAD
+0x074 Alertable : 0y0
kd> dt _kthread ffffe001ef7a5400 waitmode
ntdll!_KTHREAD
+0x187 WaitMode : 0 ''
kd> dt _kwait_block 0xffffe001`ef7a5540
ntdll!_KWAIT_BLOCK
+0x000 WaitListEntry : _LIST_ENTRY [ 0xffffd000`6dba6280 - 0xffffd000`6dba6280 ]
+0x010 WaitType : 0x1 ''
+0x011 BlockState : 0x4 ''
+0x012 WaitKey : 0
+0x014 SpareLong : 0n1089
+0x018 Thread : 0xffffe001`ef7a5400 _KTHREAD
+0x018 NotificationQueue : 0xffffe001`ef7a5400 _KQUEUE
+0x020 Object : 0xffffd000`6dba6278 Void
+0x028 SparePtr : (null)
0: kd> dt _KEVENT
nt!_KEVENT
+0x000 Header : _DISPATCHER_HEADER
kd> dt _dispatcher_header 0xffffd000`6dba6278
ntdll!_DISPATCHER_HEADER
+0x000 Lock : 0n1594228737
+0x000 LockNV : 0n1594228737
+0x000 Type : 0x1 ''
+0x001 Signalling : 0 ''
+0x002 Size : 0x6 ''
+0x003 Reserved1 : 0x5f '_'
+0x000 TimerType : 0x1 ''
+0x001 TimerControlFlags : 0 ''
+0x001 Absolute : 0y0
+0x001 Wake : 0y0
+0x001 EncodedTolerableDelay : 0y000000 (0)
+0x002 Hand : 0x6 ''
+0x003 TimerMiscFlags : 0x5f '_'
+0x003 Index : 0y011111 (0x1f)
+0x003 Inserted : 0y1
+0x003 Expired : 0y0
+0x000 Timer2Type : 0x1 ''
+0x001 Timer2Flags : 0 ''
+0x001 Timer2Inserted : 0y0
+0x001 Timer2Expiring : 0y0
+0x001 Timer2CancelPending : 0y0
+0x001 Timer2SetPending : 0y0
+0x001 Timer2Running : 0y0
+0x001 Timer2Disabled : 0y0
+0x001 Timer2ReservedFlags : 0y00
+0x002 Timer2Reserved1 : 0x6 ''
+0x003 Timer2Reserved2 : 0x5f '_'
+0x000 QueueType : 0x1 ''
+0x001 QueueControlFlags : 0 ''
+0x001 Abandoned : 0y0
+0x001 DisableIncrement : 0y0
+0x001 QueueReservedControlFlags : 0y000000 (0)
+0x002 QueueSize : 0x6 ''
+0x003 QueueReserved : 0x5f '_'
+0x000 ThreadType : 0x1 ''
+0x001 ThreadReserved : 0 ''
+0x002 ThreadControlFlags : 0x6 ''
+0x002 CycleProfiling : 0y0
+0x002 CounterProfiling : 0y1
+0x002 GroupScheduling : 0y1
+0x002 AffinitySet : 0y0
+0x002 ThreadReservedControlFlags : 0y0000
+0x003 DebugActive : 0x5f '_'
+0x003 ActiveDR7 : 0y1
+0x003 Instrumented : 0y1
+0x003 Minimal : 0y1
+0x003 Reserved4 : 0y011
+0x003 UmsScheduled : 0y1
+0x003 UmsPrimary : 0y0
+0x000 MutantType : 0x1 ''
+0x001 MutantSize : 0 ''
+0x002 DpcActive : 0x6 ''
+0x003 MutantReserved : 0x5f '_'
+0x004 SignalState : 0n0
+0x008 WaitListHead : _LIST_ENTRY [ 0xffffe001`ef7a5540 - 0xffffe001`ef7a5540 ]