Share via


User mode dump 분석 (DbgBreakPoint 로 Dump 가 생성된 경우)

User mode dump 를 분석하는 도중 순간적으로 오류를 일으킬 뻔 한적이 있습니다. Dump 파일을 열어서 Call stack 을 확인해 보면 아래와 같이 되어 있습니다.

0:039> kvL
ChildEBP RetAddr  Args to Child             
030cffc8 7c97fdd8 00000005 00000004 00000001 ntdll!DbgBreakPoint (FPO: [0,0,0])
030cfff4 00000000 00000000 031b0000 01740000 ntdll!DbgUiRemoteBreakin+0x36 (FPO: [Non-Fpo]) (CONV: stdcall)

처음에는 DbgBreakPoint 가 Call stack 의 마지막인 것을 보고 Debug 용으로 설정된 int 3 code 가 실행된 것이 아닌가 싶었으나 Crash dump pattern 1 번에 있던 내용이 기억 났습니다.

https://blogs.msdn.com/kocoreinternals/archive/2008/09/17/part-1.aspx

실제로 문제가 발생한 Thread 가 다른 곳에 있다고 생각하고 모든 Thread 의 Stack 을 확인해 보니 아래와 같이 Exception 이 발생한 Thread 가 있었습니다.

0:002> ~* kvL

...
  29  Id: 91c.a14 Suspend: 1 Teb: 7ff77000 Unfrozen
ChildEBP RetAddr  Args to Child             
45c8d35c 7c96771b 7c807f35 ffffffff 7c824830 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
45c8d360 7c807f35 ffffffff 7c824830 00000000 ntdll!ZwQueryVirtualMemory+0xc (FPO: [6,0,0])
45c8d3ac 7c821a99 00000001 45c8d3d0 00000000 kernel32!_ValidateEH3RN+0xb6 (FPO: [Non-Fpo]) (CONV: cdecl)
45c8d3d0 7c968752 45c8d4b4 45c8ffdc 45c8d4d0 kernel32!_except_handler3+0x39 (FPO: [Uses EBP] [3,0,7]) (CONV: cdecl)
45c8d3f4 7c968723 45c8d4b4 45c8ffdc 45c8d4d0 ntdll!ExecuteHandler2+0x26
45c8d49c 7c96855e 45c88000 45c8d4d0 45c8d4b4 ntdll!ExecuteHandler+0x24
45c8d49c 004e085a 45c88000 45c8d4d0 45c8d4b4 ntdll!KiUserExceptionDispatcher+0xe (FPO: [2,0,0]) (CONTEXT @ 45c8d4d0)
WARNING: Stack unwind information not available. Following frames may be wrong.
45c8d7a8 004dd15a 45c8d7dc 00000000 00000006 TestServer+0xe085a
45c8d7ac 45c8d7dc 00000000 00000006 00000002 TestServer+0xdd15a
45c8d7b0 00000000 00000006 00000002 01a4c204 0x45c8d7dc
...

0:002> ~29 s
eax=7c8401a8 ebx=7c824830 ecx=000000f0 edx=00000000 esi=7c824000 edi=ffffffff
eip=7c9685ec esp=45c8d360 ebp=45c8d3ac iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
ntdll!KiFastSystemCallRet:
7c9685ec c3              ret

문제 발생 당시의 context를 맞추어 보도록 하겠습니다.

0:029> .cxr 45c8d4d0
eax=329f3438 ebx=00000000 ecx=013a5950 edx=013a5950 esi=00000000 edi=013a5988
eip=004e085a esp=45c8d79c ebp=013b5198 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
FieldServer+0xe085a:
004e085a 8b1e            mov     ebx,dword ptr [esi]  ds:0023:00000000=????????

esi 의 값이 NULL 인 것이 문제 입니다.

문제 발생 당시의 Assembly code 를 살펴 보았습니다.

0:029> ub 004e085c L10
TestServer+0xe083c:
004e083c 90              nop
004e083d 90              nop
004e083e 90              nop
004e083f 90               nop
004e0840 51              push    ecx
004e0841 8b4904      mov     ecx,dword ptr [ecx+4]
004e0844 56              push    esi
004e0845 8b742410  mov esi,dword ptr [esp+10h]
004e0849 57              push    edi                                         <== Push 1번
004e084a 8b4104      mov     eax,dword ptr [ecx+4]
004e084d 8b3d50ba5d00    mov     edi,dword ptr [TestServer+0x1dba50 (005dba50)]
004e0853 3bc7            cmp     eax,edi
004e0855 8bd1            mov     edx,ecx
004e0857 742a            je      TestServer+0xe0883 (004e0883)
004e0859 53              push    ebx                                         <== Push 2번
004e085a 8b1e            mov     ebx,dword ptr [esi]

esi 의 값을 접근하다가 문제가 발생한 것으로 esi 의 값은 esp+10 값 입니다. ebp base 로 Stack 이 이루어져 있지 않은 것으로 보아 최적화가 된 Code 같습니다. 그렇다면 stack 값을 가지고 접근을 해야 하는데 esi 에 esp+10 의 값을 넣은 후 push 가 2회 발생하였으므로 현재 esp 값을 기준으로 보면 esp+18 에 어떤 값이 있는지 확인해 보아야 합니다.

0:029> dd esp+18 L1
45c8d7b4  00000000

결국 TestServer 내에서 잘못된 Parameter 가 전달되어 Application 이 Crash 된 것 입니다.