Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
다섯번째 크래쉬 덤프 패턴은 최적화된 코드 패턴입니다. 아래는 번역 내용입니다.
---
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/