[윈도우즈]커널에서 유저랜드 메모리 할당의 이유

금방의 이 예제에서 왜 유저랜드에 메모리를 할당해야 할까?
n = (ULONG *)MmMapLockedPages(mdln, UserMode);
ret = s_fnZwQuerySystemInformation(SystemModuleInformation, n, 0, n);
 
 
s_fnZwQuerySystemInformation을 원래의 ZwQuerySystemInformation를 가리키는 함수 포인터이다. 그런데, 원래의 함수를 부르는데에 MDL로 지정한 유저랜드 영역을 넘겨 주고 있다. 커널 공간에서 nt커널의 함수를 부르는데 왜 유저랜드의 메모리를 인자로 넘겨 주어야만 할까?
 
이유는 간단하다. 하부의 모든 콜에서 GetPreviousMode()를 체크하여 유저랜드에서 유래한 콜인 경우에는 버퍼가 유저랜드에 있는 것으로 가정하기 때문이다. ProbeForRead()등에 의해서 이러한 체크가 이뤄진다.

“The ProbeForRead routine checks that a user-mode buffer actually resides in the user portion of the address space, and is correctly aligned. “

 
이 훅은 결국 바로 앞 모드가 유저랜드이므로 유저랜드의 메모리인 것 처럼 메모리에 대한 MDL을 설정해 주어야 하는 것이다.
 
실제로 MDL로 설정하지 않고, ExAllocatePoolWithTag로만 할당한 메모리를 넘겨 주면 바로 파아란 BSOD를 볼 수 있다.
 
 
그래서 이 이론에 근거해서 NewZwQuerySystemInformation를 다시 보면 참으로 어이 없는 실수를 하고 있는 것을 알 수 있다. 바로 그 자신이 ProbeForRead()로 유저랜드에서 넘어온 버퍼를 검사하고 있지 않은 것이다. 이 경우 유저랜드의 악의적인 프로그램에 의해서 쉽게 BSOD를 내어 주게 된다.

Leave a Reply