<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>!analyze -v : Dump</title><link>http://blogs.msdn.com/kocoreinternals/archive/tags/Dump/default.aspx</link><description>Tags: Dump</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>[CDA]크래쉬 덤프 분석 케이스 스터디 (1)</title><link>http://blogs.msdn.com/kocoreinternals/archive/2009/08/26/cda-1.aspx</link><pubDate>Wed, 26 Aug 2009 11:50:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9884908</guid><dc:creator>DebugMachine</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/kocoreinternals/comments/9884908.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kocoreinternals/commentrss.aspx?PostID=9884908</wfw:commentRss><wfw:comment>http://blogs.msdn.com/kocoreinternals/rsscomments.aspx?PostID=9884908</wfw:comment><description>&lt;p&gt;&lt;font face="맑은 고딕"&gt;&lt;span lang="EN-US"&gt;&amp;quot;&lt;/span&gt;이 문서는 &lt;span lang="EN-US"&gt;&lt;a title="http://www.dumpanalysis.org/blog/" href="http://www.dumpanalysis.org/blog/"&gt;http://www.dumpanalysis.org/blog/&lt;/a&gt; blog &lt;/span&gt;의 번역이며 원래의 자료가 통보 없이 변경될 수 있습니다&lt;span lang="EN-US"&gt;. &lt;/span&gt;이 자료는 법률적 보증이 없으며 의견을 주시기 위해 원래의&lt;span lang="EN-US"&gt; blog &lt;/span&gt;를 방문하실 수 있습니다&lt;span lang="EN-US"&gt;. ( &lt;a title="http://www.dumpanalysis.org/blog/index.php/2007/02/21/crash-dump-analysis-case-study-1/" href="http://www.dumpanalysis.org/blog/index.php/2007/02/21/crash-dump-analysis-case-study-1/"&gt;http://www.dumpanalysis.org/blog/index.php/2007/02/21/crash-dump-analysis-case-study-1/&lt;/a&gt; )&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dumpanalysis.org/blog/index.php/2007/02/21/crash-dump-analysis-case-study-1/"&gt;크래쉬 덤프 분석 케이스 스터디 (1)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;덤프를 WinDbg로 열어 보았을때 아래와 같이 빨간색으로 되어 있는 코드를 확인해 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;Consider the following legacy C++/Win32 code fragment highlighted in WinDbg after opening a crash dump:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;1: HANDLE hFile = CreateFile(str.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);      &lt;br /&gt;2: if (hFile != INVALID_HANDLE_VALUE)       &lt;br /&gt;3: {       &lt;br /&gt;4:&amp;#160;&amp;#160;&amp;#160; DWORD dwSize = GetFileSize(hFile, NULL);       &lt;br /&gt;5:&amp;#160;&amp;#160;&amp;#160; DWORD dwRead = 0;       &lt;br /&gt;6:&amp;#160;&amp;#160;&amp;#160; CHAR *bufferA = new CHAR[dwSize+2];       &lt;br /&gt;7:&amp;#160;&amp;#160;&amp;#160; memset(bufferA, 0, dwSize+2);       &lt;br /&gt;8:&amp;#160;&amp;#160;&amp;#160; if (ReadFile(hFile, bufferA, dwSize, &amp;amp;dwRead, NULL))       &lt;br /&gt;9:&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;10:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DWORD i = 0, j = 0;       &lt;br /&gt;11:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (; i &amp;lt; dwSize+2-7; ++i)       &lt;br /&gt;12:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;13:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff0000"&gt;if (bufferA[i] == 0xD &amp;amp;&amp;amp; bufferA[i+1] != 0xA)&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;코드를 먼저 살펴 보면 정상적으로 보입니다. 파일을 열고 사이즈를 얻고 파일을 읽기 위한 버퍼를 할당하고… 모든 인덱스들은 배열 경계 안에 있는것으로 보입니다. 디스어셈블리 코드를 살펴 보도록 하겠습니다.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;0:000&amp;gt; uf component!CMyDlg::OnTimer      &lt;br /&gt;…       &lt;br /&gt;…       &lt;br /&gt;…       &lt;br /&gt;004021bc push&amp;#160;&amp;#160;&amp;#160; 0       &lt;br /&gt;004021be push&amp;#160;&amp;#160;&amp;#160; esi       &lt;br /&gt;004021bf call&amp;#160;&amp;#160;&amp;#160; dword ptr [component!_imp__GetFileSize (0042e26c)]       &lt;br /&gt;004021c5 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi,eax ; &lt;font color="#0000ff"&gt;dwSize&lt;/font&gt;       &lt;br /&gt;004021c7 lea&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebx,[edi+2] ; &lt;font color="#0000ff"&gt;dwSize+2        &lt;br /&gt;&lt;/font&gt;004021ca push&amp;#160;&amp;#160;&amp;#160; ebx       &lt;br /&gt;004021cb mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+34h],0       &lt;br /&gt;004021d3 call&amp;#160;&amp;#160;&amp;#160; component!operator new[] (00408e35)       &lt;br /&gt;004021d8 push&amp;#160;&amp;#160;&amp;#160; ebx       &lt;br /&gt;004021d9 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebp,eax ; &lt;font color="#0000ff"&gt;bufferA&lt;/font&gt;       &lt;br /&gt;004021db push&amp;#160;&amp;#160;&amp;#160; 0       &lt;br /&gt;004021dd push&amp;#160;&amp;#160;&amp;#160; ebp       &lt;br /&gt;004021de call&amp;#160;&amp;#160;&amp;#160; component!memset (00418500)       &lt;br /&gt;004021e3 add&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,10h       &lt;br /&gt;004021e6 push&amp;#160;&amp;#160;&amp;#160; 0       &lt;br /&gt;004021e8 lea&amp;#160;&amp;#160;&amp;#160;&amp;#160; edx,[esp+34h]       &lt;br /&gt;004021ec push&amp;#160;&amp;#160;&amp;#160; edx       &lt;br /&gt;004021ed push&amp;#160;&amp;#160;&amp;#160; edi       &lt;br /&gt;004021ee push&amp;#160;&amp;#160;&amp;#160; ebp       &lt;br /&gt;004021ef push&amp;#160;&amp;#160;&amp;#160; esi       &lt;br /&gt;004021f0 call&amp;#160;&amp;#160;&amp;#160; dword ptr [component!_imp__ReadFile (0042e264)]       &lt;br /&gt;004021f6 test&amp;#160;&amp;#160;&amp;#160; eax,eax       &lt;br /&gt;004021f8 jne&amp;#160;&amp;#160;&amp;#160;&amp;#160; component!CMyDlg::OnTimer+0×3b1 (00402331)       &lt;br /&gt;…       &lt;br /&gt;…       &lt;br /&gt;…       &lt;br /&gt;00402331 xor&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi,esi ; &lt;font color="#0000ff"&gt;i&lt;/font&gt;       &lt;br /&gt;00402333 add&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi,0FFFFFFFBh ; &lt;font color="#0000ff"&gt;+2-7 (edi contains dwSize)&lt;/font&gt;       &lt;br /&gt;00402336 cmp&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi,esi ; &lt;font color="#0000ff"&gt;loop condition&lt;/font&gt;       &lt;br /&gt;00402338 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+24h],esi       &lt;br /&gt;0040233c jbe&amp;#160;&amp;#160;&amp;#160;&amp;#160; component!CMyDlg::OnTimer+0×43e (004023be)       &lt;br /&gt;&lt;font color="#ff0000"&gt;00402342 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; al,byte ptr [esi+ebp] ; bufferA[i]&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;0:000&amp;gt; r      &lt;br /&gt;eax=00002b00 &lt;font color="#ff0000"&gt;ebx=00000002&lt;/font&gt; ecx=00431000 edx=00000000 esi=00002b28 &lt;font color="#ff0000"&gt;edi=fffffffb&lt;/font&gt;       &lt;br /&gt;eip=00402342 esp=0012efd4 ebp=0095b4d8 iopl=0 nv up ei pl nz ac pe cy       &lt;br /&gt;cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000217       &lt;br /&gt;component!CMyDlg::OnTimer+0×3c2:       &lt;br /&gt;00402342 8a042e mov al,byte ptr [esi+ebp] ds:0023:0095e000=??&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;만약 EBX (dwSize+2) 와 EDI 레지스터( 배열의 상위 경계, dwSize+2-7)를 확인하였다면 dwSize 가 0이라는 것을 쉽게 확인할 수 있었을 것 입니다. 버퍼 오버런이 발생한 것으로 배열의 경계가 0+2-7 = FFFFFFFB 로 계산되었기 때문입니다.(루프의 인덱스는 unsinged integer, DWORD 입니다.). 인덱스가 signed integer 값(int) 라면 루프의 비교 조건이 0&amp;lt;0+2-7로 아무런 문제가 발생하지 않습니다. &lt;/p&gt;  &lt;p&gt;아래와 같은 수정이 필요 합니다.&lt;/p&gt;  &lt;p&gt;&lt;code&gt;1: HANDLE hFile = CreateFile(str.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);      &lt;br /&gt;2: if (hFile != INVALID_HANDLE_VALUE)       &lt;br /&gt;3: {       &lt;br /&gt;4:&amp;#160;&amp;#160;&amp;#160; DWORD dwSize = GetFileSize(hFile, NULL);       &lt;br /&gt;5:&amp;#160;&amp;#160;&amp;#160; DWORD dwRead = 0;       &lt;br /&gt;6:&amp;#160;&amp;#160;&amp;#160; CHAR *bufferA = new CHAR[dwSize+2];       &lt;br /&gt;7:&amp;#160;&amp;#160;&amp;#160; memset(bufferA, 0, dwSize+2);       &lt;br /&gt;8:&amp;#160;&amp;#160;&amp;#160; if (ReadFile(hFile, bufferA, dwSize, &amp;amp;dwRead, NULL))       &lt;br /&gt;9:&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&lt;strike&gt;10:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DWORD i = 0, j = 0;&lt;/strike&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;10:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;int&lt;/strong&gt; i = 0, j = 0;&lt;/font&gt;       &lt;br /&gt;&lt;strike&gt;11:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (; i &amp;lt; dwSize+2-7; ++i)&lt;/strike&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;11:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (; i &amp;lt; &lt;strong&gt;(int)&lt;/strong&gt;dwSize+2-7; ++i)&lt;/font&gt;       &lt;br /&gt;12:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;GetFileSize 는 INVALID_FILE_SIZE(0xFFFFFFFF)을 리턴할 수 있고 new 연산자 역시 실패할 수 있어 아래와 같이 수정하는 것이 좋습니다.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;1: HANDLE hFile = CreateFile(str.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);      &lt;br /&gt;2: if (hFile != INVALID_HANDLE_VALUE)       &lt;br /&gt;3: {       &lt;br /&gt;4:&amp;#160;&amp;#160;&amp;#160; DWORD dwSize = GetFileSize(hFile, NULL);       &lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;4a:&amp;#160;&amp;#160; if (dwSize != INVALID_FILE_SIZE)&lt;/strong&gt;         &lt;br /&gt;&lt;strong&gt;4b:&amp;#160;&amp;#160; {&lt;/strong&gt;&lt;/font&gt;       &lt;br /&gt;5:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DWORD dwRead = 0;       &lt;br /&gt;6:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHAR *bufferA = new CHAR[dwSize+2];       &lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;6a:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (bufferA)&lt;/strong&gt;         &lt;br /&gt;&lt;strong&gt;6b:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/strong&gt;&lt;/font&gt;       &lt;br /&gt;7:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; memset(bufferA, 0, dwSize+2);       &lt;br /&gt;8:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (ReadFile(hFile, bufferA, dwSize, &amp;amp;dwRead, NULL))       &lt;br /&gt;9:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;10:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;int&lt;/strong&gt; i = 0, j = 0;       &lt;br /&gt;11:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (; i &amp;lt; (int)dwSize+2-7; ++i)       &lt;br /&gt;12:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="맑은 고딕"&gt;&lt;span lang="EN-US"&gt;&amp;#160;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9884908" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/windbg/default.aspx">windbg</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/Dump/default.aspx">Dump</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/CDA/default.aspx">CDA</category></item><item><title>Notes about NMI_HARDWARE_FAILURE</title><link>http://blogs.msdn.com/kocoreinternals/archive/2008/12/11/notes-about-nmi-hardware-failure.aspx</link><pubDate>Thu, 11 Dec 2008 07:52:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9194912</guid><dc:creator>DebugMachine</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/kocoreinternals/comments/9194912.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kocoreinternals/commentrss.aspx?PostID=9194912</wfw:commentRss><wfw:comment>http://blogs.msdn.com/kocoreinternals/rsscomments.aspx?PostID=9194912</wfw:comment><description>&lt;p&gt;이 문서는 &lt;a href="http://www.dumpanalysis.org/blog"&gt;http://www.dumpanalysis.org/blog&lt;/a&gt; blog 의 번역이며 원래의 자료가 통보 없이 변경될 수 있습니다. 이 자료는 법률적 보증이 없으며 의견을 주시기 위해 원래의 blog 를 방문하실 수 있습니다. (&lt;a href="http://www.dumpanalysis.org/blog/index.php/2006/12/23/notes-about-nmi_hardware_failure/"&gt;http://www.dumpanalysis.org/blog/index.php/2006/12/23/notes-about-nmi_hardware_failure/&lt;/a&gt;)&amp;quot;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;WinDbg Help 에 따르면 NMI_HARDWARE_FAILURE (0x80) bugcheck 80 은 Hardware 문제점을 나타내는 것 입니다. 이 설명은 고객으로부터 kernel 이나 전체 crash dump 를 받았을 경우 더 이상 문제를 분석하지 않고 간단히 결론을 내게 해 줍니다. 그러나 Hardware 부분이 항상 문제인 것은 아니고 고객이 System 이 Hang 이라고 생각하고 강제로 dump 를 생성한 것 일 수 있습니다. 여기서는 Debugging 을 위한 특별한 Hardware 를 사용하였는지 확인해 봐야 한다는 것입니다. Card 또는 &lt;a href="http://en.wikipedia.org/wiki/ILo"&gt;iLO&lt;/a&gt; 칩p &lt;a href="http://en.wikipedia.org/wiki/Integrated_Lights-Out"&gt;(Integrated Lights-Out)&lt;/a&gt; 을 사용해서 원격지에서 Dump 를 생성했을 수 있습니다. 그리고 NMI &lt;a href="http://en.wikipedia.org/wiki/Non-Maskable_interrupt"&gt;(Non Maskable Interrupt)&lt;/a&gt; 를 사용해서 dump 를 생성할 수도 있습니다. 이런 경우에는 왜 System 이 Hang 상태에 빠졌는지를 확인해야 합니다.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9194912" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/windbg/default.aspx">windbg</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/Dump/default.aspx">Dump</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/ntdebugging/default.aspx">ntdebugging</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/NMI/default.aspx">NMI</category></item><item><title>Hung Window?, No Source?, No problem!! Part 2</title><link>http://blogs.msdn.com/kocoreinternals/archive/2008/12/10/hung-window-no-source-no-problem-part-2.aspx</link><pubDate>Wed, 10 Dec 2008 07:58:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9189305</guid><dc:creator>DebugMachine</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/kocoreinternals/comments/9189305.aspx</comments><wfw:commentRss>http://blogs.msdn.com/kocoreinternals/commentrss.aspx?PostID=9189305</wfw:commentRss><wfw:comment>http://blogs.msdn.com/kocoreinternals/rsscomments.aspx?PostID=9189305</wfw:comment><description>&lt;p&gt;이 문서는 &lt;a href="http://blogs.msdn.com/ntdebugging"&gt;http://blogs.msdn.com/ntdebugging&lt;/a&gt; blog 의 번역이며 원래의 자료가 통보 없이 변경될 수 있습니다. 이 자료는 법률적 보증이 없으며 의견을 주시기 위해 원래의 blog 를 방문하실 수 있습니다. (&lt;a title="http://blogs.msdn.com/ntdebugging/archive/2007/06/15/hung-window-no-source-no-problem-part-2.aspx" href="http://blogs.msdn.com/ntdebugging/archive/2007/06/15/hung-window-no-source-no-problem-part-2.aspx"&gt;http://blogs.msdn.com/ntdebugging/archive/2007/06/15/hung-window-no-source-no-problem-part-2.aspx&lt;/a&gt;)&amp;quot;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Hung Window?, No Source?, No problem!! Part 2&lt;/font&gt;    &lt;br /&gt;Jeff Dailey 작성&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;안녕하세요 저의 이름은 Jeff 입니다. 저는 Microsoft CPR (Critical Problem Resolution) platform team 의 Escalation Engineer 입니다. 이 블로그는 저의 이전 블로그의 2편 입니다. &lt;a href="http://blogs.msdn.com/ntdebugging/archive/2007/06/13/hung-window-no-source-no-problem-part-1.aspx"&gt;Hung Window?, No source?, No problem!! Part 1 blog&lt;/a&gt;.&amp;#160; 이번 실습에서는 Multi thread application 과 동기화 객체 그리고 여러가지 문제점들 그리고 어떻게 분석하는지를 알려 드릴 것 입니다. 이 실습을 하기 위해 저의 이전 블로그에서 dumphugnwindow 와 badwindow.exe 를 다운 받고 Debugging tool 을 다운 받으시기 바랍니다.    &lt;br /&gt;Debugging tools:    &lt;br /&gt;&lt;a href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx"&gt;http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx&lt;/a&gt;    &lt;br /&gt;이전 blog &lt;a href="http://blogs.msdn.com/ntdebugging/archive/2007/05/29/detecting-and-automatically-dumping-hung-gui-based-windows-applications.aspx"&gt;http://blogs.msdn.com/ntdebugging/archive/2007/05/29/detecting-and-automatically-dumping-hung-gui-based-windows-applications.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;위의 두가지를 설치해야 이후 내용을 시작할 수 있습니다. 앞으로 우리는 왜 Window 화면출력이 멈추었고 응답 없음 상태에 빠졌는지 Debug 해 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;1 단계 : Badwindow.exe 실행   &lt;br /&gt;2 단계 : Dumphungwindow.exe 실행    &lt;br /&gt;3 단계 : Badwindow.exe 메뉴에서 Hang &amp;#8211; Hang type 2 선택    &lt;br /&gt;Window 가 메시지를 처리하지 못하고 응답 없음 상태에 빠지고 badwindow.exe 의 덤프가 생성되는 것을 확인해야 합니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;************ OUTPUT *************   &lt;br /&gt;C:\source\dumphungwindow\release&amp;gt;dumphungwindow.exe    &lt;br /&gt;Dumps will be saved in C:\Users\jeffda\AppData\Local\Temp\    &lt;br /&gt;scanning for hung windows    &lt;br /&gt;**    &lt;br /&gt;Hung Window found dumping process (12912) badwindow.exe    &lt;br /&gt;Dumping unresponsive process    &lt;br /&gt;C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_14_2007_Time7_34_5_Pid12912_badwindow.exe.dmp    &lt;br /&gt;Dump complete &lt;/p&gt;  &lt;p&gt;Hung Window found dumping process (12912) badwindow.exe   &lt;br /&gt;Dumping unresponsive process    &lt;br /&gt;C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_14_2007_Time7_34_24_Pid12912_badwindow.exe.dmp\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_56_Pid7924_badwindow.exe.dmp    &lt;br /&gt;Dump complete*    &lt;br /&gt;************ OUTPUT ************* &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;4단계 : c:\websymbols 와 같은 로컬 심볼 폴더를 만듭니다.   &lt;br /&gt;5 단계 : WinDbg 에서 File &amp;#8211; Symbols 에서 다음과 같이 Symbol 을 설정 합니다.    &lt;br /&gt;SRV*c:\websymbols*&lt;a href="http://msdl.microsoft.com/download/symbols"&gt;http://msdl.microsoft.com/download/symbols&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx"&gt;http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx&lt;/a&gt; 에 보다 자세한 정보가 있습니다.    &lt;br /&gt;6 단계 : WinDbg 에서 File &amp;#8211; Open crash dump 를 선택한 후 dump 파일을 선택 합니다. WinDbg 에서 보여지는 초기 화면은 다음과 같을 것 입니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Microsoft (R) Windows Debugger&amp;#160; Version 6.7.0001.0   &lt;br /&gt;Copyright (c) Microsoft Corporation. All rights reserved. &lt;/p&gt;  &lt;p&gt;***** WARNING: Your debugger is probably out-of-date.   &lt;br /&gt;*****&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Check &lt;a href="http://dbg"&gt;http://dbg&lt;/a&gt; for updates. &lt;/p&gt;  &lt;p&gt;Loading Dump File [C:\Users\jeffda\AppData\Local\Temp\HWNDDump_Day6_12_2007_Time9_53_34_Pid7924_badwindow.exe.dmp]   &lt;br /&gt;User Mini Dump File with Full Memory: Only application data is available &lt;/p&gt;  &lt;p&gt;Symbol search path is: SRV*c:\websymbols*&lt;a href="http://msdl.microsoft.com/download/symbols;srv"&gt;http://msdl.microsoft.com/download/symbols;srv&lt;/a&gt;    &lt;br /&gt;Executable search path is:     &lt;br /&gt;Windows Vista Version 6000 MP (2 procs) Free x86 compatible    &lt;br /&gt;Product: WinNt, suite: SingleUserTS    &lt;br /&gt;Debug session time: Tue Jun 12 09:53:35.000 2007 (GMT-4)    &lt;br /&gt;System Uptime: 11 days 18:41:43.089    &lt;br /&gt;Process Uptime: 0 days 0:00:32.000    &lt;br /&gt;....................................    &lt;br /&gt;Loading unloaded module list    &lt;br /&gt;.    &lt;br /&gt;eax=00000000 ebx=00000002 ecx=00000000 edx=00000000 esi=00000000 edi=00000000    &lt;br /&gt;eip=777faec5 esp=0017faf4 ebp=0017fb8c iopl=0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; nv up ei pl nz na po nc    &lt;br /&gt;cs=0023&amp;#160; ss=002b&amp;#160; ds=002b&amp;#160; es=002b&amp;#160; fs=0053&amp;#160; gs=002b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; efl=00000202    &lt;br /&gt;ntdll!ZwWaitForMultipleObjects+0x15:    &lt;br /&gt;777faec5 c21400&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ret&amp;#160;&amp;#160;&amp;#160;&amp;#160; 14h    &lt;br /&gt;0:000&amp;gt; !reload &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;7단계 : 디버거 명령창에서 다음 명령을 입력합니다.    &lt;br /&gt;~*k &lt;/p&gt;  &lt;p&gt;다음과 같은 출력을 볼 수 있을 것 입니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;.&amp;#160; 0&amp;#160; Id: 3270.2b10 Suspend: 0 Teb: 7efdd000 Unfrozen   &lt;br /&gt;ChildEBP RetAddr&amp;#160; &lt;br /&gt;0017faf0 76e4edb5 ntdll!ZwWaitForMultipleObjects+0x15    &lt;br /&gt;0017fb8c 76e430c3 kernel32!WaitForMultipleObjectsEx+0x11d    &lt;br /&gt;0017fba8 00401502 kernel32!WaitForMultipleObjects+0x18    &lt;br /&gt;0017fbc8 0040139b badwindow!hangtype2+0x42 [c:\source\badwindow\badwindow\badwindow.cpp @ 340]    &lt;br /&gt;0017fc24 772a87af badwindow!WndProc+0x17b [c:\source\badwindow\badwindow\badwindow.cpp @ 274]    &lt;br /&gt;0017fc50 772a8936 user32!InternalCallWinProc+0x23    &lt;br /&gt;0017fcc8 772a8a7d user32!UserCallWinProcCheckWow+0x109    &lt;br /&gt;0017fd2c 772a8ad0 user32!DispatchMessageWorker+0x380    &lt;br /&gt;0017fd3c 004010fb user32!DispatchMessageW+0xf    &lt;br /&gt;0017ff0c 00401817 badwindow!wWinMain+0xfb [c:\source\badwindow\badwindow\badwindow.cpp @ 124]    &lt;br /&gt;0017ffa0 76eb19f1 badwindow!__tmainCRTStartup+0x150 [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 589]    &lt;br /&gt;0017ffac 7782d109 kernel32!BaseThreadInitThunk+0xe    &lt;br /&gt;0017ffec 00000000 ntdll!_RtlUserThreadStart+0x23 &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 1&amp;#160; Id: 3270.2cd0 Suspend: 0 Teb: 7efda000 Unfrozen   &lt;br /&gt;ChildEBP RetAddr&amp;#160; &lt;br /&gt;026ffebc 777ecfad ntdll!ZwWaitForSingleObject+0x15    &lt;br /&gt;026fff20 777ecf78 ntdll!RtlpWaitOnCriticalSection+0x154    &lt;br /&gt;026fff48 0040153c ntdll!RtlEnterCriticalSection+0x152    &lt;br /&gt;026fff64 757c2848 badwindow!hangtype2threada+0x2c [c:\source\badwindow\badwindow\badwindow.cpp @ 358]    &lt;br /&gt;026fff9c 757c28c8 msvcr80!_endthread+0x4b    &lt;br /&gt;026fffa0 76eb19f1 msvcr80!_endthread+0xcb    &lt;br /&gt;026fffac 7782d109 kernel32!BaseThreadInitThunk+0xe    &lt;br /&gt;026fffec 00000000 ntdll!_RtlUserThreadStart+0x23 &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;ID 의 오른쪽에 있는 숫자들은 Process id 와 Thread id 를 나타냅니다. 3270.2b10 은 3270이 process id 이고 2b10 은 thread id 입니다. 그리고 Suspend: 0 Teb: 7efdd000 Unfrozen 은 thread 상태 정보 입니다. &lt;/p&gt;  &lt;p&gt;각각의 항목은 thread 의 콜 스택 입니다. 가장 최근에 호출된 함수가 스택의 가장 위에 위치 합니다.각각의 호출은 스택을 증가 시킵니다. Thread 0 번을 확인해 보면 winproc 함수가 hangtype2 를 호출하고 멈추어 있는 것을 확인할 수 있을 것 입니다. Hangtype 2 는 WaitForMultipleObjects 를 호출하였고 WaitForMuiltipleObjects 를 좀더 살펴 보겠습니다. &lt;/p&gt;  &lt;p&gt;WaitForMultipleObjects 의 문서는 아래에 있습니다.   &lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms687025.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms687025.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;DWORD WINAPI WaitForMultipleObjects( DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds   &lt;br /&gt;함수의 형태는 위와 같고 전달된 파라미터를 살펴보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;0:000&amp;gt; kv    &lt;br /&gt;ChildEBP RetAddr&amp;#160; Args to Child&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;0017faf0 76e4edb5 00000002 0017fb40 00000000 ntdll!ZwWaitForMultipleObjects+0x15 (FPO: [5,0,0])    &lt;br /&gt;0017fb8c 76e430c3 0017fb40 0017fbc4 00000001 kernel32!WaitForMultipleObjectsEx+0x11d (FPO: [Non-Fpo])    &lt;br /&gt;0017fba8 00401502 00000002 0017fbc4 00000001 kernel32!WaitForMultipleObjects+0x18 (FPO: [Non-Fpo])    &lt;br /&gt;0017fbc8 0040139b 00401220 0017fbfc 00401220 badwindow!hangtype2+0x42 (FPO: [0,2,0]) (CONV: cdecl) [c:\source\badwindow\badwindow\badwindow.cpp @ 340]    &lt;br /&gt;0017fc24 772a87af 00063d36 00000111 00008004 badwindow!WndProc+0x17b (CONV: stdcall) [c:\source\badwindow\badwindow\badwindow.cpp @ 274]    &lt;br /&gt;0017fc50 772a8936 00401220 00063d36 00000111 user32!InternalCallWinProc+0x23    &lt;br /&gt;0017fcc8 772a8a7d 00000000 00401220 00063d36 user32!UserCallWinProcCheckWow+0x109 (FPO: [Non-Fpo])    &lt;br /&gt;0017fd2c 772a8ad0 00401220 00000000 0017ff0c user32!DispatchMessageWorker+0x380 (FPO: [Non-Fpo])    &lt;br /&gt;0017fd3c 004010fb 0017fd54 00403938 00000001 user32!DispatchMessageW+0xf (FPO: [Non-Fpo])    &lt;br /&gt;0017ff0c 00401817 00400000 00000000 00280f8c badwindow!wWinMain+0xfb (CONV: stdcall) [c:\source\badwindow\badwindow\badwindow.cpp @ 124]    &lt;br /&gt;0017ffa0 76eb19f1 7efde000 0017ffec 7782d109 badwindow!__tmainCRTStartup+0x150 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 589]    &lt;br /&gt;0017ffac 7782d109 7efde000 0017fb9e 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])    &lt;br /&gt;0017ffec 00000000 00401987 7efde000 00000000 ntdll!_RtlUserThreadStart+0x23 (FPO: [Non-Fpo]) &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;첫 번째 파라미터는 00000002 이고 기다릴 Object 의 개수 입니다. 두 번째 파라미터는 Object 배열의 주소 이고 Object 들을 보기 위해 배열을 나열해 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;0:000&amp;gt; dd 0017fbc4    &lt;br /&gt;0017fbc4&amp;#160; 000000c4 000000c8 0040139b 00401220    &lt;br /&gt;0017fbd4&amp;#160; 0017fbfc 00401220 00063d36 0017fc48    &lt;br /&gt;0017fbe4&amp;#160; 772a8989 772a894d 53ca28e7 00000000    &lt;br /&gt;0017fbf4&amp;#160; 00063d36 00401220 00000000 00000000    &lt;br /&gt;0017fc04&amp;#160; 00000000 0017fca0 00000001 00000000    &lt;br /&gt;0017fc14&amp;#160; ffffffff 772a88e5 53c4f4b4 75c12459    &lt;br /&gt;0017fc24&amp;#160; 0017fc50 772a87af 00063d36 00000111    &lt;br /&gt;0017fc34&amp;#160; 00008004 00000000 00401220 dcbaabcd &lt;/p&gt;  &lt;p&gt;0:000&amp;gt; !handle 000000c4    &lt;br /&gt;Handle 000000c4    &lt;br /&gt;&amp;#160; Type&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Thread    &lt;br /&gt;0:000&amp;gt; !handle 000000c8     &lt;br /&gt;Handle 000000c8    &lt;br /&gt;&amp;#160; Type&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Error retrieving type&amp;gt; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;두 번째 값을 보면 어떤 이유로 인해 handle 타입을 나타내기에 충분한 정보가 dump 되지 않았다는 것을 볼 수 있습니다. Handle 은 kernel 에 있는 handle table 의 인덱스 값입니다. Dump 가 생성될 때 Handle 정보가 모두 포함되지 않았을 가능성이 있습니다. 이것은 큰 문제가 되지 않으며 간단하게 어떤 일이 있었는지 확인해 볼 것 입니다. &lt;/p&gt;  &lt;p&gt;이전 블로그에서 UF 명령의 사용법을 설명해 드렸습니다.이제 어셈블리 코드를 보면서 확인해 나가도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;0:000&amp;gt; uf 00401502    &lt;br /&gt;badwindow!hangtype2 [c:\source\badwindow\badwindow\badwindow.cpp @ 334]: &lt;/p&gt;  &lt;p&gt;ESP(스택 포인터, 메모리에서 스택이 커진다는 것을 기억할 것) 를 감소시켜 공간확보   &lt;br /&gt;&amp;#160; 334 004014c0 83ec08&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sub&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,8 &lt;/p&gt;  &lt;p&gt;ESP 값을 나중에 사용할 수 있게 저장   &lt;br /&gt;&amp;#160; 334 004014c3 56&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;_beginthread 의 함수 포인터를 구해 ESI 에 저장. &lt;a href="http://msdn2.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx"&gt;http://msdn2.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx&lt;/a&gt; 문서에 따르면 첫번째 파라미터는 start address, 두번째 파라미터는 Stack size, 세 번째 파라미터는 arglist 입니다.    &lt;br /&gt;&amp;#160; 337 004014c4 8b3580204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi,dword ptr [badwindow!_imp___beginthread (00402080)] &lt;/p&gt;  &lt;p&gt;_beginthread 의 마지막 파라미터를&amp;#160; 스택에 넣습니다. 0 이 사용된 것은 arglist 가 없다는 것 입니다.   &lt;br /&gt;&amp;#160; 337 004014ca 6a00&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 0 &lt;/p&gt;  &lt;p&gt;이 공간이 stack spce 입니다. Debugger 에서 ? 2EE0h 명령을 사용해서 16진수를 10진수로 변환해 보면 12000 값을 확인할 수 있습니다.   &lt;br /&gt;&amp;#160; 337 004014cc 68e02e0000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 2EE0h &lt;/p&gt;  &lt;p&gt;우리가 사용할 Thread 함수의 포인터를 저장 합니다. 여기서는 hangtype2threada 입니다.   &lt;br /&gt;&amp;#160; 337 004014d1 6810154000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!hangtype2threada (00401510) &lt;/p&gt;  &lt;p&gt;_beginthread 를 호출하여 thread 를 시작 합니다. Return 값은 thread handle 입니다.   &lt;br /&gt;&amp;#160; 337 004014d6 ffd6&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;_beginthread 의 마지막 파라미터를&amp;#160; 스택에 넣습니다. 0 이 사용된 것은 arglist 가 없다는 것 입니다.   &lt;br /&gt;&amp;#160; 338 004014d8 6a00&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 0 &lt;/p&gt;  &lt;p&gt;_beginthread 에서 사용할 Stack space 를 전달 합니다.   &lt;br /&gt;&amp;#160; 338 004014da 68e02e0000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 2EE0h &lt;/p&gt;  &lt;p&gt;Thread 함수를 위한 함수 포인터를 전달 합니다. 여기서는 hangtype2threadb 입니다.   &lt;br /&gt;&amp;#160; 338 004014df 6870154000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!hangtype2threadb (00401570) &lt;/p&gt;  &lt;p&gt;ESP+1 (stack)에 EAX(_beginthrea 호출 결과)를 저장 합니다.   &lt;br /&gt;&amp;#160; 338 004014e4 8944241c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+1Ch],eax &lt;/p&gt;  &lt;p&gt;_beginthread 를 호출 하여 thread 를 시작 합니다. Return 값은 thread handle 입니다.   &lt;br /&gt;&amp;#160; 338 004014e8 ffd6&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;ESP 에 값을 더해 stack 을 정리 합니다.   &lt;br /&gt;&amp;#160; 338 004014ea 83c418&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; add&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,18h &lt;/p&gt;  &lt;p&gt;WaitForMultipleObjects 에서 사용할 Wait 시간을 저장 합니다. 0xFFFFFFFF(-1) 로 영원히 대기 합니다.   &lt;br /&gt;&amp;#160; 340 004014ed 6aff&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 0FFFFFFFFh &lt;/p&gt;  &lt;p&gt;마지막 호출한 _beginthread 의 return 값인 thread handle 값을 스택에 저장 합니다.   &lt;br /&gt;&amp;#160; 340 004014ef 8944240c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+0Ch],eax &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;아래는 우리의 Wait 방식 입니다. 이번 경우에 WaitAll 로 모든 handle 이 signal 될 때 까지 대기 합니다.    &lt;br /&gt;&amp;#160; 340 004014f3 6a01&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 1 &lt;/p&gt;  &lt;p&gt;EAX 에 Wait 하게될 handle 정보를 저장 합니다.   &lt;br /&gt;&amp;#160; 340 004014f5 8d44240c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lea&amp;#160;&amp;#160;&amp;#160;&amp;#160; eax,[esp+0Ch] &lt;/p&gt;  &lt;p&gt;Stack 에 handle 포인터 배열 값을 저장 합니다.   &lt;br /&gt;&amp;#160; 340 004014f9 50&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; eax &lt;/p&gt;  &lt;p&gt;Object 의 개수를 저장 합니다. 여기서는 2 입니다.   &lt;br /&gt;&amp;#160; 340 004014fa 6a02&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 2 &lt;/p&gt;  &lt;p&gt;Hangtype2threada, hangtype2threadb 가 종료되기를 WaitForMultipleObjects 함수를 호출하여 대기 합니다.   &lt;br /&gt;&amp;#160; 340 004014fc ff1510204000&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; dword ptr [badwindow!_imp__WaitForMultipleObjects (00402010)] &lt;/p&gt;  &lt;p&gt;ESI register 값을 stack 에서 가져 옵니다. 아래 코드들은 WaitForMultipleObjects 에서 return 된 후 호출 됩니다.   &lt;br /&gt;&amp;#160; 340 00401502 5e&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi&amp;#160; &lt;/p&gt;  &lt;p&gt;Stack 포인터 값을 감소 시킵니다.   &lt;br /&gt;&amp;#160; 342 00401503 83c408&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; add&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,8 &lt;/p&gt;  &lt;p&gt;Return 합니다.   &lt;br /&gt;&amp;#160; 342 00401506 c3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ret &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;소스 코드는 아래와 같습니다. &lt;/p&gt;  &lt;p&gt;void hangtype2(void)   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; HANDLE handles[2]; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; handles[0] = (HANDLE)_beginthread(hangtype2threada, 12000, NULL);   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; handles[1] = (HANDLE)_beginthread(hangtype2threadb, 12000, NULL);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WaitForMultipleObjects(2,handles,1,INFINITE); &lt;/p&gt;  &lt;p&gt;} &lt;/p&gt;  &lt;p&gt;무엇이 잘못 되었을까요? 다시 thread 를 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;Message 를 처리하는 Main thread 가 다른 두 개의 thread 를 기다리고 있다는 것을 확인할 수 있습니다. Badwindow!hangtype2thread 는 아직 실행중이고 다른 하나인 hangtype2threadb 는 종료 되었음을 확인할 수 있습니다. &lt;/p&gt;  &lt;p&gt;0&amp;#160; Id: 3270.2b10 Suspend: 0 Teb: 7efdd000 Unfrozen   &lt;br /&gt;ChildEBP RetAddr&amp;#160; &lt;br /&gt;0017faf0 76e4edb5 ntdll!ZwWaitForMultipleObjects+0x15    &lt;br /&gt;0017fb8c 76e430c3 kernel32!WaitForMultipleObjectsEx+0x11d    &lt;br /&gt;0017fba8 00401502 kernel32!WaitForMultipleObjects+0x18    &lt;br /&gt;0017fbc8 0040139b badwindow!hangtype2+0x42 [c:\source\badwindow\badwindow\badwindow.cpp @ 340]    &lt;br /&gt;0017fc24 772a87af badwindow!WndProc+0x17b [c:\source\badwindow\badwindow\badwindow.cpp @ 274]    &lt;br /&gt;0017fc50 772a8936 user32!InternalCallWinProc+0x23    &lt;br /&gt;0017fcc8 772a8a7d user32!UserCallWinProcCheckWow+0x109    &lt;br /&gt;0017fd2c 772a8ad0 user32!DispatchMessageWorker+0x380    &lt;br /&gt;0017fd3c 004010fb user32!DispatchMessageW+0xf    &lt;br /&gt;0017ff0c 00401817 badwindow!wWinMain+0xfb [c:\source\badwindow\badwindow\badwindow.cpp @ 124]    &lt;br /&gt;0017ffa0 76eb19f1 badwindow!__tmainCRTStartup+0x150 [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 589]    &lt;br /&gt;0017ffac 7782d109 kernel32!BaseThreadInitThunk+0xe    &lt;br /&gt;0017ffec 00000000 ntdll!_RtlUserThreadStart+0x23 &lt;/p&gt;  &lt;p&gt;Hangtype2threada 를 확인해 보면 RtlEnterCriticalSection 에서 block 되었음을 볼 수 있습니다. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 1&amp;#160; Id: 3270.2cd0 Suspend: 0 Teb: 7efda000 Unfrozen   &lt;br /&gt;ChildEBP RetAddr&amp;#160; &lt;br /&gt;026ffebc 777ecfad ntdll!ZwWaitForSingleObject+0x15    &lt;br /&gt;026fff20 777ecf78 ntdll!RtlpWaitOnCriticalSection+0x154    &lt;br /&gt;026fff48 0040153c ntdll!RtlEnterCriticalSection+0x152    &lt;br /&gt;026fff64 757c2848 badwindow!hangtype2threada+0x2c [c:\source\badwindow\badwindow\badwindow.cpp @ 358]    &lt;br /&gt;026fff9c 757c28c8 msvcr80!_endthread+0x4b    &lt;br /&gt;026fffa0 76eb19f1 msvcr80!_endthread+0xcb    &lt;br /&gt;026fffac 7782d109 kernel32!BaseThreadInitThunk+0xe    &lt;br /&gt;026fffec 00000000 ntdll!_RtlUserThreadStart+0x23 &lt;/p&gt;  &lt;p&gt;Critical section 호출에 어떠한 문제가 있는지 확인해 보겠습니다. &lt;/p&gt;  &lt;p&gt;Thread 1 번으로 context 를 변경 합니다. &lt;/p&gt;  &lt;p&gt;0:000&amp;gt; ~1s   &lt;br /&gt;eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00403780 edi=00000000    &lt;br /&gt;eip=777fa69d esp=026ffec0 ebp=026fff20 iopl=0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; nv up ei pl nz na po nc    &lt;br /&gt;cs=0023&amp;#160; ss=002b&amp;#160; ds=002b&amp;#160; es=002b&amp;#160; fs=0053&amp;#160; gs=002b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; efl=00000202    &lt;br /&gt;ntdll!ZwWaitForSingleObject+0x15:    &lt;br /&gt;777fa69d c20c00&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ret&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0Ch &lt;/p&gt;  &lt;p&gt;Call stack 을 확인한 후 entercriticalsection 의 첫 번째 파라미터를 확인 합니다. &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; kv   &lt;br /&gt;ChildEBP RetAddr&amp;#160; Args to Child&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;026ffebc 777ecfad 000000cc 00000000 00000000 ntdll!ZwWaitForSingleObject+0x15 (FPO: [3,0,0])    &lt;br /&gt;026fff20 777ecf78 00000000 00000000 76e61d5a ntdll!RtlpWaitOnCriticalSection+0x154 (FPO: [Non-Fpo])    &lt;br /&gt;026fff48 0040153c 00403780 00000000 00000000 ntdll!RtlEnterCriticalSection+0x152 (FPO: [Non-Fpo])    &lt;br /&gt;026fff64 757c2848 00000000 51b22bb2 00000000 badwindow!hangtype2threada+0x2c (FPO: [Uses EBP] [1,1,0]) (CONV: cdecl) [c:\source\badwindow\badwindow\badwindow.cpp @ 358]    &lt;br /&gt;026fff9c 757c28c8 76eb19f1 02274358 026fffec msvcr80!_endthread+0x4b (FPO: [Non-Fpo])    &lt;br /&gt;026fffa0 76eb19f1 02274358 026fffec 7782d109 msvcr80!_endthread+0xcb (FPO: [Non-Fpo])    &lt;br /&gt;026fffac 7782d109 02274358 026ffb9e 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])    &lt;br /&gt;026fffec 00000000 757c286e 02274358 00000000 ntdll!_RtlUserThreadStart+0x23 (FPO: [Non-Fpo]) &lt;/p&gt;  &lt;p&gt;Cs 명령을 통해서 많은 정보를 확인할 수 있습니다. &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; !cs 00403780    &lt;br /&gt;-----------------------------------------    &lt;br /&gt;Critical section&amp;#160;&amp;#160; = 0x00403780 (badwindow!csCritSec1+0x0)    &lt;br /&gt;DebugInfo&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0x0029bd40    &lt;br /&gt;LOCKED&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt; It&amp;#8217;s LOCKED.    &lt;br /&gt;LockCount&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0x1    &lt;br /&gt;WaiterWoken&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = No    &lt;br /&gt;OwningThread&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0x00002048&amp;#160; &amp;lt; This is the owning thread.    &lt;br /&gt;RecursionCount&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0x14    &lt;br /&gt;LockSemaphore&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0xCC    &lt;br /&gt;SpinCount&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = 0x00000000 &lt;/p&gt;  &lt;p&gt;!locks 명령을 사용해서 lock 된 다른 critical section 을 확인할 수 있습니다.   &lt;br /&gt;0:001&amp;gt; !locks &lt;/p&gt;  &lt;p&gt;CritSec badwindow!csCritSec1+0 at 00403780   &lt;br /&gt;WaiterWoken&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; No    &lt;br /&gt;LockCount&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1    &lt;br /&gt;RecursionCount&amp;#160;&amp;#160;&amp;#160;&amp;#160; 20    &lt;br /&gt;OwningThread&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2048    &lt;br /&gt;EntryCount&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0    &lt;br /&gt;ContentionCount&amp;#160;&amp;#160;&amp;#160; 1    &lt;br /&gt;*** Locked &lt;/p&gt;  &lt;p&gt;Scanned 156 critical sections &lt;/p&gt;  &lt;p&gt;어떤 thread 가 동작중이며 2048 은 어떤 thread 일까요? &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; ~   &lt;br /&gt;#&amp;#160; 0&amp;#160; Id: 3270.2b10 Suspend: 0 Teb: 7efdd000 Unfrozen    &lt;br /&gt;.&amp;#160; 1&amp;#160; Id: 3270.2cd0 Suspend: 0 Teb: 7efda000 Unfrozen &lt;/p&gt;  &lt;p&gt;이 부분에서 문제점이 있습니다. Hangtype2threada 와 hangtype2threadb 모두 같은 critical section 을 사용합니다. 그러나 hagntype2threadb 에 문제점이 있습니다. 함수 내부를 살펴보며 어떤 문제점이 있는지 확인해 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;unassembled 한 부분에서 Badwindow!hangtype2 의 address 를 확인 한 후 symbol 이 있다면 ln 명령을 사용하여 어떤 함수인지 확인할 수 있습니다. &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; ln 00401570   &lt;br /&gt;c:\source\badwindow\badwindow\badwindow.cpp(370)    &lt;br /&gt;(00401570)&amp;#160;&amp;#160; badwindow!hangtype2threadb&amp;#160;&amp;#160; |&amp;#160; (004015e0)&amp;#160;&amp;#160; badwindow!hangtype3thread    &lt;br /&gt;Exact matches:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; badwindow!hangtype2threadb (void *) &lt;/p&gt;  &lt;p&gt;정확히 함수를 찾은 것을 볼 수 있습니다. 이 함수를 unassembled 해서 어떤 문제점이 있는지 확인해 보도록 하겠습니다. &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; uf 00401570   &lt;br /&gt;badwindow!hangtype2threadb [c:\source\badwindow\badwindow\badwindow.cpp @ 370]: &lt;/p&gt;  &lt;p&gt;ECX 저장   &lt;br /&gt;&amp;#160; 370 00401570 51&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ecx &lt;/p&gt;  &lt;p&gt;EBX 저장   &lt;br /&gt;&amp;#160; 370 00401571 53&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ebx &lt;/p&gt;  &lt;p&gt;Sprint 함수의 주소를 EBX 에 전달   &lt;br /&gt;&amp;#160; 371 00401572 8b1d7c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebx,dword ptr [badwindow!_imp__sprintf (0040207c)] &lt;/p&gt;  &lt;p&gt;EBP 저장   &lt;br /&gt;&amp;#160; 371 00401578 55&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ebp &lt;/p&gt;  &lt;p&gt;Outputdebugstring 의 주소를 ebp 에 전달   &lt;br /&gt;&amp;#160; 371 00401579 8b2d14204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebp,dword ptr [badwindow!_imp__OutputDebugStringA (00402014)] &lt;/p&gt;  &lt;p&gt;ESI 저장   &lt;br /&gt;&amp;#160; 371 0040157f 56&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;EnterCriticalSection 의 주소를 ESI 에 전달   &lt;br /&gt;&amp;#160; 371 00401580 8b351c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi,dword ptr [badwindow!_imp__EnterCriticalSection (0040201c)] &lt;/p&gt;  &lt;p&gt;EDI 저장   &lt;br /&gt;&amp;#160; 371 00401586 57&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; edi &lt;/p&gt;  &lt;p&gt;Sleep 의 주소를 EDI 에 전달   &lt;br /&gt;&amp;#160; 371 00401587 8b3d0c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi,dword ptr [badwindow!_imp__Sleep (0040200c)] &lt;/p&gt;  &lt;p&gt;16진수로 14h 를 ESP+10h (local stack) 에 저장 아마도 카운터 일 것 같습니다.   &lt;br /&gt;&amp;#160; 371 0040158d c744241014000000 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+10h],14h &lt;/p&gt;  &lt;p&gt;Critical section 의 주소인 csCritSec1 00403780 을 stack 에 저장 합니다.   &lt;br /&gt;&amp;#160; 374 00401595 6880374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec1 (00403780) &lt;/p&gt;  &lt;p&gt;Entercriticalsction 을 호출 합니다.   &lt;br /&gt;&amp;#160; 374 0040159a ffd6&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;250 를 스택에 저장 합니다.   &lt;br /&gt;&amp;#160; 376 0040159c 68fa000000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 0FAh    &lt;br /&gt;Sleep 을 호출 합니다. (250ms 동안 대기 합니다.)    &lt;br /&gt;&amp;#160; 376 004015a1 ffd7&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; edi    &lt;br /&gt;포인터 값을 스택에 저장 합니다. 어떤 내용인지 확인해 보면 다음과 같습니다.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;0:001&amp;gt; db 004021e4   &lt;br /&gt;004021e4&amp;#160; 57 65 20 61 72 65 20 69-6e 20 68 61 6e 67 74 79&amp;#160; We are in hangty    &lt;br /&gt;004021f4&amp;#160; 70 65 32 74 68 72 65 61-64 62 00 00 48 00 00 00&amp;#160; pe2threadb..H...    &lt;br /&gt;00402204&amp;#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&amp;#160; ................    &lt;br /&gt;00402214&amp;#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&amp;#160; ................    &lt;br /&gt;&amp;#160; 377 004015a3 68e4214000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!`string' (004021e4) &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;포인터 값을 스택에 저장 합니다. 어떤 내용일까요?   &lt;br /&gt;0:001&amp;gt; db 00403380    &lt;br /&gt;00403380&amp;#160; 57 65 20 61 72 65 20 69-6e 20 68 61 6e 67 74 79&amp;#160; We are in hangty    &lt;br /&gt;00403390&amp;#160; 70 65 32 74 68 72 65 61-64 62 00 00 00 00 00 00&amp;#160; pe2threadb......    &lt;br /&gt;004033a0&amp;#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&amp;#160; ................    &lt;br /&gt;004033b0&amp;#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&amp;#160; ................    &lt;br /&gt;&amp;#160; 377 004015a8 6880334000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!szTrace (00403380) &lt;/p&gt;  &lt;p&gt;Sprint 를 호출   &lt;br /&gt;&amp;#160; 377 004015ad ffd3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; ebx &lt;/p&gt;  &lt;p&gt;Stack 정리   &lt;br /&gt;&amp;#160; 377 004015af 83c408&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; add&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,8 &lt;/p&gt;  &lt;p&gt;Sprint 에 전달하였던 output buffer 를 스택에 저장   &lt;br /&gt;&amp;#160; 378 004015b2 6880334000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!szTrace (00403380) &lt;/p&gt;  &lt;p&gt;Outputdebugstring 호출   &lt;br /&gt;&amp;#160; 378 004015b7 ffd5&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; ebp &lt;/p&gt;  &lt;p&gt;csCritSec2 의 주소를 스택에 저장   &lt;br /&gt;&amp;#160; 380 004015b9 6868374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec2 (00403768) &lt;/p&gt;  &lt;p&gt;csCritSec2 를 사용해서 LeaveCriticalSection 호출   &lt;br /&gt;&amp;#160; 380 004015be ff1524204000&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; dword ptr [badwindow!_imp__LeaveCriticalSection (00402024)] &lt;/p&gt;  &lt;p&gt;Local 변수인 count fmf 감소 시킵니다.   &lt;br /&gt;&amp;#160; 382 004015c4 836c241001&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sub&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+10h],1 &lt;/p&gt;  &lt;p&gt;Count 값이 0 인지 확인 0 이 아니라면 loop 의 가장 위로 다시 jump   &lt;br /&gt;&amp;#160; 382 004015c9 75ca&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; jne&amp;#160;&amp;#160;&amp;#160;&amp;#160; badwindow!hangtype2threadb+0x25 (00401595) &lt;/p&gt;  &lt;p&gt;저장 하였던 register 를 다시 복원하고&amp;#160; return   &lt;br /&gt;&amp;#160; 382 004015cb 5f&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi    &lt;br /&gt;&amp;#160; 382 004015cc 5e&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi    &lt;br /&gt;&amp;#160; 382 004015cd 5d&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebp    &lt;br /&gt;&amp;#160; 382 004015ce 5b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebx    &lt;br /&gt;&amp;#160; 387 004015cf 59&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ecx    &lt;br /&gt;&amp;#160; 387 004015d0 c3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ret &lt;/p&gt;  &lt;p&gt;Bug 를 확인 하셨나요? 자세히 살펴 보시고 소스가 필요 하시면 아래를 참조 하십시오.   &lt;br /&gt;void __cdecl hangtype2threadb(void *)    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int i=0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while(1)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EnterCriticalSection(&amp;amp;csCritSec1);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Sleep(250);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sprintf(szTrace, &amp;quot;We are in hangtype2threadb&amp;quot;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; OutputDebugStringA(szTrace);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; LeaveCriticalSection(&amp;amp;csCritSec2);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; i++;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if(i==20)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;Critical section 하나를 요청한 후 다른 Critical section 을 해제하고 있습니다. 다음 함수를 보면 count 관련 작업을 진행한 후 csCritSec1 을 소유한 상태로 thread 가 종료 됩니다. 이 문제를 해결하는 방법은 아주 간단하여 csCritSec2 를 해제 하지 않고 CsCritSec1 을 해제 하면 됩니다. 그러나 소스 코드가 없었다면 어떻게 될까요? 역시 간단 합니다. Debugger 를 사용해서 기계어를 어셈블리어로 분석하면 됩니다. 종종 code 를 수정해야 할 때 메모리에 있는 기계어를 수정하기도 합니다. &lt;/p&gt;  &lt;p&gt;변경 작업을 하기 위해 command line 에서 windbg.exe C:\source\badwindow\release\badwindow.exe 를 사용하여 실행 해야 합니다. (badwindow 샘플과 동일한 폴더를 사용하는 것으로 가정 하겠습니다.) WinDbg 가 실행되면 symbol path 를 다음 명령을 사용해서 설정해 주십시오. .sympath SRV*c:\websymbols*&lt;a href="http://msdl.microsoft.com/download/symbols"&gt;http://msdl.microsoft.com/download/symbols&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;우리의 잘못된 함수입니다.   &lt;br /&gt;csCritSec2 의 주소를 스택에 넣습니다. &amp;lt;&amp;lt; &lt;font color="#ff0000"&gt;잘못된 Critical Section     &lt;br /&gt;&lt;/font&gt;&amp;#160; 380 004015b9 6868374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec2 (00403768) &lt;/p&gt;  &lt;p&gt;LeaveCriticalSection 을 호출하여 csCritSec2 를 해제 합니다.   &lt;br /&gt;&amp;#160; 380 004015be ff1524204000&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; dword ptr [badwindow!_imp__LeaveCriticalSection (00402024)] &lt;/p&gt;  &lt;p&gt;csCritSec1 의 주소인 00403780 을 스택에 저장 합니다. &amp;lt;&amp;lt; &lt;font color="#ff0000"&gt;올바른 Critical Section&lt;/font&gt;    &lt;br /&gt;&amp;#160; 374 00401595 6880374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec1 (00403780) &lt;/p&gt;  &lt;p&gt;Entercriticalsection 을 호출 합니다.   &lt;br /&gt;&amp;#160; 374 0040159a ffd6&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; esi &lt;/p&gt;  &lt;p&gt;어떤 Critical Section 을 leavecriticalsection에 사용하도록 변경해야 하는지 기억해 보십시오.   &lt;br /&gt;004015b9 6868374000&amp;#160; (BAD)&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;00401595 6880374000&amp;#160; (GOOD)    &lt;br /&gt;메모리를 수정하여 잘못된 명령을 수정하도록 하겠습니다.    &lt;br /&gt;0:001&amp;gt; eb 004015b9     &lt;br /&gt;004015b9 68 68&amp;#160; &amp;lt;&amp;lt; 입력 68    &lt;br /&gt;68    &lt;br /&gt;004015ba 68 80&amp;#160; &amp;lt;&amp;lt; 68을 원하지 않습니다. 80을 입력 합니다.    &lt;br /&gt;80    &lt;br /&gt;004015bb 37&amp;#160; &amp;lt;&amp;lt; Memory 수정을 종료 합니다. &lt;/p&gt;  &lt;p&gt;수정된 코드 입니다. &lt;/p&gt;  &lt;p&gt;0:001&amp;gt; uf 00401570    &lt;br /&gt;badwindow!hangtype2threadb [c:\source\badwindow\badwindow\badwindow.cpp @ 370]:    &lt;br /&gt;&amp;#160; 370 00401570 51&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ecx    &lt;br /&gt;&amp;#160; 370 00401571 53&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ebx    &lt;br /&gt;&amp;#160; 371 00401572 8b1d7c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebx,dword ptr [badwindow!_imp__sprintf (0040207c)]    &lt;br /&gt;&amp;#160; 371 00401578 55&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; ebp    &lt;br /&gt;&amp;#160; 371 00401579 8b2d14204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebp,dword ptr [badwindow!_imp__OutputDebugStringA (00402014)]    &lt;br /&gt;&amp;#160; 371 0040157f 56&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; esi    &lt;br /&gt;&amp;#160; 371 00401580 8b351c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi,dword ptr [badwindow!_imp__EnterCriticalSection (0040201c)]    &lt;br /&gt;&amp;#160; 371 00401586 57&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; edi    &lt;br /&gt;&amp;#160; 371 00401587 8b3d0c204000&amp;#160;&amp;#160;&amp;#160; mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi,dword ptr [badwindow!_imp__Sleep (0040200c)]    &lt;br /&gt;&amp;#160; 371 0040158d c744241014000000 mov&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+10h],14h    &lt;br /&gt;ENTERING CORRET CRITICAL SECTION csCritSec1    &lt;br /&gt;&amp;#160; 374 00401595 6880374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec1 (00403780)    &lt;br /&gt;&amp;#160; 374 0040159a ffd6&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; esi    &lt;br /&gt;&amp;#160; 376 0040159c 68fa000000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; 0FAh    &lt;br /&gt;&amp;#160; 376 004015a1 ffd7&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; edi    &lt;br /&gt;&amp;#160; 377 004015a3 68e4214000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!`string' (004021e4)    &lt;br /&gt;&amp;#160; 377 004015a8 6880334000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!szTrace (00403380)    &lt;br /&gt;&amp;#160; 377 004015ad ffd3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; ebx    &lt;br /&gt;&amp;#160; 377 004015af 83c408&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; add&amp;#160;&amp;#160;&amp;#160;&amp;#160; esp,8    &lt;br /&gt;&amp;#160; 378 004015b2 6880334000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!szTrace (00403380)    &lt;br /&gt;&amp;#160; 378 004015b7 ffd5&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; ebp    &lt;br /&gt;LEAVING CORRECT CRITICAL SECTION csCritSec1    &lt;br /&gt;&amp;#160; 380 004015b9 6880374000&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push&amp;#160;&amp;#160;&amp;#160; offset badwindow!csCritSec1 (00403780)&amp;#160; &lt;br /&gt;&amp;#160; 380 004015be ff1524204000&amp;#160;&amp;#160;&amp;#160; call&amp;#160;&amp;#160;&amp;#160; dword ptr [badwindow!_imp__LeaveCriticalSection    &lt;br /&gt;(00402024)]    &lt;br /&gt;&amp;#160; 382 004015c4 836c241001&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sub&amp;#160;&amp;#160;&amp;#160;&amp;#160; dword ptr [esp+10h],1    &lt;br /&gt;&amp;#160; 382 004015c9 75ca&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; jne&amp;#160;&amp;#160;&amp;#160;&amp;#160; badwindow!hangtype2threadb+0x25 (00401595)    &lt;br /&gt;&amp;#160; 382 004015cb 5f&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; edi    &lt;br /&gt;&amp;#160; 382 004015cc 5e&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; esi    &lt;br /&gt;&amp;#160; 382 004015cd 5d&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebp    &lt;br /&gt;&amp;#160; 382 004015ce 5b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ebx    &lt;br /&gt;&amp;#160; 387 004015cf 59&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pop&amp;#160;&amp;#160;&amp;#160;&amp;#160; ecx    &lt;br /&gt;&amp;#160; 387 004015d0 c3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ret &lt;/p&gt;  &lt;p&gt;다시 프로그램을 실행(명령창에서 G 명령 입력) 시키면 정상 동작 하는 것을 확인할 수 있습니다.   &lt;br /&gt;정상 동작하는 것을 확인한 후 이 프로그램을 만든 개발자에게 코드 수정을 요청할 수 있습니다. &lt;/p&gt;  &lt;p&gt;많은 도움이 되셨기를 빕니다.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;감사합니다. Jeff &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9189305" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/windbg/default.aspx">windbg</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/Dump/default.aspx">Dump</category><category domain="http://blogs.msdn.com/kocoreinternals/archive/tags/ntdebugging/default.aspx">ntdebugging</category></item></channel></rss>