首页 > 逆向调试 > 同步(死锁)调试基础

同步(死锁)调试基础

同步问题最常见的表现就是死锁(如果你是从搜索引擎搜索“死锁”进来的,我推荐你点击这个链接看看下面的文章),要调试程序的这类情况需要先了解一下同步相关的一些基础知识(如事件、信号量、临界区、互斥体等)以及Windbg中处理同步问题相关的常见命令(如!handle、!cs、!runaway等命令)。掌握好这些调试基础之后,就可以进行一些实例调试来获取调试经验了。

!handle命令
!handle命令可以列出进程中所有的句柄(包括None[未归类]、Event、Section、File 、Directory、WindowStation、Key、Thread、Desktop、IoCompletion、Timer、KeyedEvent、TpWorkerFactory),或者使用“!handle 句柄号 f”获得特定句柄的详细信息。

0:002> !handle c4 f
Handle c4
  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

临界区
底层的临界区数据结构是_RTL_CRITICAL_SECTION,可以通过dt命令来查看。

0:002> dt _RTL_CRITICAL_SECTION
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

DebugInfo在Windows 2003 SP1开始可以忽略;LockCount表示有多少个线程正在等待进入临界区;RecursionCount表示同一个线程有多少次进入到临界区;Owning Thread表示已经进入临界区的线程ID;LockSemaphore是一个自动重置事件,用来控制临界区的进入用的;SpinCount在多处理器上有效,表示在尝试进入临界区到进入等待状态之间的自旋次数。

!cs命令
使用!cs命令可以获得进程中全部的临界区相关信息;使用“!cs 临界区地址”的命令形式可以获取特定临界区的详细信息,看上去比“dt _RTL_CRITICAL_SECTION 临界区地址”好一点点。

0:002> !cs 0xF0005
-----------------------------------------
Critical section   = 0x000f0005 (+0xF0005)
DebugInfo          = 0x48043004
LOCKED
LockCount          = 0xF07ED7BE
WaiterWoken        = Yes
OwningThread       = 0x03000004
RecursionCount     = 0x42044004
LockSemaphore      = 0x4304BB00
SpinCount          = 0x00043c04
0:002> dt _RTL_CRITICAL_SECTION 0xF0005
ntdll!_RTL_CRITICAL_SECTION
   +0x000 DebugInfo        : 0x48043004 _RTL_CRITICAL_SECTION_DEBUG
   +0x004 LockCount        : 1040490756
   +0x008 RecursionCount   : 1107574788
   +0x00c OwningThread     : 0x03000004 
   +0x010 LockSemaphore    : 0x4304bb00 
   +0x014 SpinCount        : 0x43c04

转储所有线程调用栈
使用“~*kb”命令即可。

0:002> ~*kb
 
   0  Id: 1040.1380 Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr  Args to Child              
0017fc10 75af8f8f 75af8fc2 0017fc54 00000000 ntdll!KiFastSystemCallRet
0017fc14 75af8fc2 0017fc54 00000000 00000000 USER32!NtUserGetMessage+0xc
0017fc30 0008148a 0017fc54 00000000 00000000 USER32!GetMessageW+0x33
0017fc70 000816ec 00080000 00000000 002b2a62 notepad!WinMain+0xe6
0017fd00 77181114 7ffd3000 0017fd4c 7704b3f5 notepad!_initterm_e+0x1a1
0017fd0c 7704b3f5 7ffd3000 76fdf85e 00000000 kernel32!BaseThreadInitThunk+0xe
0017fd4c 7704b3c8 00083689 7ffd3000 00000000 ntdll!__RtlUserThreadStart+0x70
0017fd64 00000000 00083689 7ffd3000 00000000 ntdll!_RtlUserThreadStart+0x1b
 
   1  Id: 1040.187c Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr  Args to Child              
017dfc80 77035e4c 7701ef27 00000003 002e51e8 ntdll!KiFastSystemCallRet
017dfc84 7701ef27 00000003 002e51e8 00000001 ntdll!NtWaitForMultipleObjects+0xc
017dfe18 77181114 00000000 017dfe64 7704b3f5 ntdll!TppWaiterpThread+0x33d
017dfe24 7704b3f5 002e51b8 7797fb76 00000000 kernel32!BaseThreadInitThunk+0xe
017dfe64 7704b3c8 7701edfb 002e51b8 00000000 ntdll!__RtlUserThreadStart+0x70
017dfe7c 00000000 7701edfb 002e51b8 00000000 ntdll!_RtlUserThreadStart+0x1b
 
#  2  Id: 1040.1e04 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr  Args to Child              
01e8fb00 7708d279 7702fe22 00000000 00000000 ntdll!DbgBreakPoint
01e8fb30 77181114 00000000 01e8fb7c 7704b3f5 ntdll!DbgUiRemoteBreakin+0x3c
01e8fb3c 7704b3f5 00000000 7702fe6e 00000000 kernel32!BaseThreadInitThunk+0xe
01e8fb7c 7704b3c8 7708d23d 00000000 00000000 ntdll!__RtlUserThreadStart+0x70
01e8fb94 00000000 7708d23d 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b

其中最后一个线程为调试器注入产生的线程。

!runaway命令
查看个线程的运行时间以及存活时间,通常用“!runaway 7”命令来获取详细信息。调试时通常多次运行此命令并对比结果来进行调试分析。

0:002> !runaway 7
 User Mode Time
  Thread       Time
   0:1380      0 days 0:00:00.015
   2:1e04      0 days 0:00:00.000
   1:187c      0 days 0:00:00.000
 Kernel Mode Time
  Thread       Time
   0:1380      0 days 0:00:00.031
   2:1e04      0 days 0:00:00.000
   1:187c      0 days 0:00:00.000
 Elapsed Time
  Thread       Time
   0:1380      0 days 2:28:37.612
   1:187c      0 days 2:28:37.565
   2:1e04      0 days 2:28:28.423

觉得文章还不错?点击此处对作者进行打赏!


本文地址: 程序人生 >> 同步(死锁)调试基础
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!


更多



分类: 逆向调试 标签: , ,
  1. 2011年10月8日23:25 | #1

    我表示完全看不懂 [em001]

    [回复]

    代码疯子 回复:

    @tl3shi, [em005] 写给自己看的笔记

    [回复]