windbg学习21(!handle和!cs)
1.查看句柄信息!handle
!handle 扩展显示目标系统中一个或所有进程拥有的句柄的信息
0:001> !handle Handle 4 Type Directory Handle 8 Type File Handle c Type File Handle 10 Type Key Handle 14 Type ALPC Port Handle 18 Type Mutant Handle 1c Type Key Handle 20 Type Event Handle 24 Type Key Handle 2c Type Event Handle 30 Type WindowStation Handle 34 Type Desktop Handle 38 Type WindowStation Handle 3c Type File Handle 84 Type Event Handle 88 Type Event Handle 8c Type Event Handle 90 Type Event Handle 94 Type Event Handle 98 Type Event Handle 9c Type Directory Handle a0 Type Event Handle a4 Type Event Handle a8 Type File Handle ac Type File Handle b0 Type Event Handle b4 Type Mutant Handle b8 Type Event Handle bc Type Mutant Handle c0 Type Section Handle c4 Type Section Handle c8 Type Mutant Handle cc Type Section Handle d0 Type Key Handle d4 Type Key Handle d8 Type Key Handle dc Type Key Handle e0 Type Key Handle e4 Type File Handle e8 Type Section Handle f4 Type File Handle f8 Type ALPC Port Handle fc Type Mutant Handle 100 Type Section Handle 104 Type File Handle 10c Type File Handle 110 Type Key Handle 114 Type Key Handle 11c Type Key 49 Handles Type Count None 2 Event 12 Section 5 File 9 Directory 2 Mutant 5 WindowStation 2 Key 11 Desktop 1
我们注意到最下面这一部分统计了各种类型句柄的各自数目
要得到某个句柄更详细的信息,可以用这个句柄做为参数,再用'f'表示显示最详细的信息:
0:001> !handle 4 f Handle 4 Type Directory Attributes 0x10 GrantedAccess 0x3: None Query,Traverse HandleCount 60 PointerCount 99 Name \KnownDlls No Object Specific Information available
0:001> !handle 84 f Handle 84 Type Event Attributes 0 GrantedAccess 0x1f0003: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState,ModifyState HandleCount 2 PointerCount 3 Name <none> Object Specific Information Event Type Manual Reset Event is Waiting
重新写一个代码测试Mutex:
0:001> !handle xx f Handle 78 Type Mutant Attributes 0 GrantedAccess 0x1f0001: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState HandleCount 2 PointerCount 3 Name <none> Object Specific Information Mutex is Free 0:001> !handle xx f Handle e0 Type Mutant Attributes 0 GrantedAccess 0x1f0001: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState HandleCount 2 PointerCount 3 Name <none> Object Specific Information Mutex is Owned
再写个代码验证信号量:
0:001> !handle dc f Handle dc Type Semaphore Attributes 0 GrantedAccess 0x1f0003: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState,ModifyState HandleCount 2 PointerCount 3 Name <none> Object Specific Information Semaphore Count 4 Semaphore Limit 5
可以看到,上面给出了这个句丙的类型,属性,访问权限以及句柄计数,我们甚至看到这个事件是Manual Reset(人工重置事件)如果是Event Type Auto Reset(自动重置事件),状态是Waiting(未触发),如果是Event is set表示已触发状态,如果Mutex is free 表示互斥量已有信号,如果Mutex is owned表示互斥量已被占用,对于信号量,Semaphore Count 表示可用的信号量,Limit表示总数
我们不知道!handle具体用法,可以使用-?来查询
0:001> !handle -? !handle [<handle>] [<flags>] [<type>] <handle> - Handle to get information about 0 or -1 means all handles <flags> - Output control flags 1 - Get type information (default) 2 - Get basic information 4 - Get name information 8 - Get object specific info (where available) <type> - Limit query to handles of the given type Display information about open handles
当handle很多时,我们也许只想知道所有互斥量的信息:
0:001> !handle 0 1 Mutant Handle 78 Type Mutant Handle e0 Type Mutant Handle ec Type Mutant 3 handles of type Mutant
1对应flags,至于名字Mutant可以参看windbg帮助说明:
Specifies the type of handle that you want to examine. Only handles that match this type are displayed.TypeName is case sensitive. Valid types include Event, Section, File, Port, Directory, SymbolicLink, Mutant, WindowStation, Semaphore, Key, Token, Process, Thread, Desktop, IoCompletion, Timer, Job, and WaitablePort.
上面红色标明为区分大小写,怀疑:下面明显是成功的!
0:001> !handle 0 3 mutanT Handle 78 Type Mutant Attributes 0 GrantedAccess 0x1f0001: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState HandleCount 2 PointerCount 3 Handle e0 Type Mutant Attributes 0 GrantedAccess 0x1f0001: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState HandleCount 2 PointerCount 3 Handle ec Type Mutant Attributes 0 GrantedAccess 0x100000: Synch None HandleCount 13 PointerCount 15 3 handles of type Mutant
2.临界区 (!cs)
底层的临界区数据结构为_RTL_CRITICAL_SECTION
反正我经常记不住,所以可以使用通配符先查找一下:
0:001> dt ntdll!_RTL_CR* ntdll!_RTL_CRITICAL_SECTION ntdll!_RTL_CRITICAL_SECTION_DEBUG 0:001> dt ntdll!_RTL_CRITICAL_SECTION +0x000 DebugInfo : Ptr32 _RTL_CRITICAL_SECTION_DEBUG +0x004 LockCount : Int4B +0x008 RecursionCount : Int4B +0x00c OwningThread : Ptr32 Void +0x010 LockSemaphore : Ptr32 Void +0x014 SpinCount : Uint4B
LockCount默认为-1,如果>=0,则表示有线程进入到临界区,要找出有多少线程正在等待进入临界区,可以:
正在等待的线程数量=LockCount - RecursionCount + 1
RecursionCount:表示同一个线程进入到临界区多少次,默认为0
OwningThread:如果有线程进入到临界区,这是进入临界区的线程ID
LockSemaphore:这是一个自动重置事件,当线程试图进入一个其他线程占用的临界区时,将会创建这个事件
SpinCount:自旋锁的次数
进一步看DebugInfo结构:
0:001> dt _RTL_CRITICAL_SECTION_DEBUG ntdll!_RTL_CRITICAL_SECTION_DEBUG +0x000 Type : Uint2B +0x002 CreatorBackTraceIndex : Uint2B +0x004 CriticalSection : Ptr32 _RTL_CRITICAL_SECTION +0x008 ProcessLocksList : _LIST_ENTRY +0x010 EntryCount : Uint4B +0x014 ContentionCount : Uint4B +0x018 Flags : Uint4B +0x01c CreatorBackTraceIndexHigh : Uint2B +0x01e SpareUSHORT : Uint2B
CriticalSection:在这个域上包含敢一个指针指向与这个结构相关的临界区
ProcessLocksList:任何进程在操作系统中都将维护一张链表,其中包含了在这个进程中所有处于活跃状态的临界区,你可以通过这个节点中FLINK和BLINK来遍历进程中的临界区链表
EntryCount:每当线程尝试进入一个已经被其他线程拥有的临界区并由此进入到等待状态,这个域的值都会被加1
!cs 扩展显示一个或多个临界区(critical section)或者整个临界区树
!cs startAddr endAddr
0:001> !cs 0x001af1f0 00400000 ----------------------------------------- DebugInfo = 0x00197a48 Critical section = 0x003a0138 (+0x3A0138) NOT LOCKED LockSemaphore = 0x0 SpinCount = 0x00000fa0 ----------------------------------------- DebugInfo = 0x001aed68 Critical section = 0x001af5c0 (+0x1AF5C0) NOT LOCKED LockSemaphore = 0x0 SpinCount = 0x00000000 ----------------------------------------- DebugInfo = 0x001aedb8 Critical section = 0x001afd34 (+0x1AFD34) NOT LOCKED LockSemaphore = 0x0 SpinCount = 0x00000000
!cs -l仅显示锁定的临界区