Crash Dump Analysis Pattern (Part 5)
다섯번째 크래쉬 덤프 패턴은 최적화된 코드 패턴입니다. 아래는 번역 내용입니다.
---
Crash Dump Analysis Pattern (Part 5)
원문:
https://www.dumpanalysis.org/blog/index.php/2006/12/15/crash-dump-analysis-patterns-part-5/
번역: 김희준(https://insidekernel.net, drost@naver.com, 2007-06-16)
이번에 소개해 드리고 싶은 패턴은 ‘최적화된 코드(Optimized Code) ’ 패턴입니다. 만약 여러분들이 이러한 경우를 접한다면 Windbg와 같은 분석 툴의 crash dump 분석을 신뢰하지 말아야 합니다. 조금이라도 수상하거나 이상한 동작을 툴이 보인다면 컴파일러가 만들어낸 코드가 최적화가 되었구나라고 항상 의심하세요. 스택을 살펴봅시다:
Args to Child
77e44c24 000001ac 00000000 ntdll!KiFastSystemCallRet
000001ac 00000000 00000000 ntdll!NtFsControlFile+0xc
00000034 00000bb8 0013e3f4 kernel32!WaitNamedPipeW+0x2c3
0016fc60 00000000 67c14804 MyModule!PipeCreate+0x48
써드파티 모듈인 MyModule의 PipeCreate 함수가 named pipe를 열고 그것의 첫번째 파라미터(0016fc60)는 파이프 이름인 L\\.\pipe\MyPipe를 가르키고 있습니다. 소스코드 안에서 그것은 Win32 API인 WaitNamedPipeW(파이프가 연결가능 할 때까지 기다리기 위해서)를 호출하고 동일한 파이프 이름을 넘겨줍니다. 그러나 WaitNamedPipeW의 첫번째 파라미터가 00000034로 올바른 유니코드 문자열을 가르키는 포인터가 아님을 알 수 있습니다. 그리고 프로그램은 만약 00000034가 포인터 값이었다면 분명 크래쉬되었겠지요.
WaitNamedPipeW를 디어셈블해서 살펴보면 모든 것이 더욱 명확해집니다. (커멘트는 제가 달았습니다)
0:000> uf kernel32!WaitNamedPipeW
mov edi,edi
push ebp
mov ebp,esp
sub esp,50h
push dword ptr [ebp+8] ; 파이프네임을사용
lea eax,[ebp-18h]
push eax
call dword ptr [kernel32!_imp__RtlCreateUnicodeString (77e411c8)]
…
…
…
…
call dword ptr [kernel32!_imp__NtOpenFile (77e41014)]
cmp dword ptr [ebp-4],edi
mov esi,eax
jne kernel32!WaitNamedPipeW+0×1d5 (77e93316)
cmp esi,edi
jl kernel32!WaitNamedPipeW+0×1ef (77e93331)
movzx eax,word ptr [ebp-10h]
mov ecx,dword ptr fs:[18h]
add eax,0Eh
push eax
push dword ptr [kernel32!BaseDllTag (77ecd14c)]
mov dword ptr [ebp+8],eax ; 파라미터공간을재사용
[ebp+8]은 FPO 아닌 함수에서는 첫번째 함수 파라미터를 가르킵니다. (참고: Parameters and Local Variables)
그리고 LPWSTR에서 UNICODE_STRING으로 변환된 후에는 파라미터 공간이 더 이상 필요하지 않기 때문에 다른 정보를 저장하기 위해서 핸들을 얻기 위한 NtOpenFile 호출에 재사용 됩니다.
OMAP이라고 하는 조심해야 할 또 다른 컴파일러 최적화가 있습니다. 이것은 코드 섹션 내의 코드를 가장 자주 엑세스 되어지는 코드 프레그먼트에 함께 넣어둡니다. 그러한 경우에 Windbg에서 명령어를 다음처럼 명령어를 입력하면,
0:000> uf nt!someFunction
다른 코드를 보여줄 것입니다. 스택이나 디어셈블로부터 얻어낸 함수의 주소가 f4794100이라고 한다면, 올바른 코드를 보기 위해서는 아래처럼 입력해야 합니다.
0:000> uf f4794100
결론은, crash dump 분석을 할 때에는 항상 의심과 경계를 늦추지 말고, 모순점을 찾아보세요.
Happy debugging!
- Dmitry Vostokov -
Comments
- Anonymous
September 16, 2008
PingBack from http://www.easycoded.com/crash-dump-analysis-pattern-part-5/