windbg에서 실행할 때 HeapAlloc()이 다르게 동작하는 이유

디버거에서 exe를 launch한 경우 LFH를 사용하지 않는다는 글을 어디선가 본것 같다.
일단 Visual Studio Debugger에 대해서는 해당되지 않는 얘기다.
Windows 10/11 모두 exe를 직접 실행하거나 Visual Studio에서 launch한 경우 LFH를 사용하는 것을 확인했다.

이 와중에 조금 이상한 점을 발견했는데 windbg에서 launch하는 경우 동일 사이즈 메모리 할당에 대해서 HeapAlloc()에서 돌려주는 메모리의 실제 사이즈(heap entry의 사이즈)가 다르다는 것이다.
debug/release 또는 CRT Library의 유형에 따라서 new나 malloc()이 다른 사이즈의 메모리를 할당하려고 할 수는 있다. 그런데 HeapAlloc() ntdll에 들어있는 고정된 코드잖아? 이게 직접실행/VS Debugger/windbg에 따라서 왜 달리 동작하는가?

이해가 안되어서 한참을 들여다봤는데 의외로 답은 쉽게 나왔다.
gflags란게 있었지. 오래전 Windows NT시절부터 지원하던 디버그용 기능-gflags로 Windows의 heap관리 기능을 조정할 수 있다.
windbg가 gflags를 직접 사용하든가 해당하는 API로 heap관리 기능을 조정했다고 하면 충분히 말이 된다.

조금 찾아보니 gflags에서 tail checking이 들어가는 경우 메모리 뒷부분에 0xab로 16bytes padding을 붙인다고 한다.
Visual Studio에서 launch하고 저장한 dump파일을 windbg에서 로드한 상태, windbg에서 launch한 상태에서 각각 heap entry를 조사해봤다.
역시나 vs에서 저장한 dump파일에선 6800 bytes 할당한 메모리 뒷 부분에 0xab채움 패턴이 없다.
반면에 windbg에서 launch한 상태에서는 6800 bytes 뒷 부분이 0xab로 16bytes가 채워져 있음을 확인할 수 있다.

[결론]
Q: 왜 windbg 하에서 launch한 프로세스는 HeapAlloc()이 다르게 동작하는가?
A: windbg가 프로세스 시작할 때 debug heap속성을 바꾸기 때문이다.
끝.


댓글 남기기