종종 윈도우커널에서 삽질을 하면서, 현재 쓰레드가 Win32Thread인지의 여부를 확인해야 될때가 있다.

그럴때는  Thread Control Block인 KTHREAD의 Win32Thread 멤버의 값을 확인해야하는데,
이 멤버의 값이 어떠한 NULL이 아닌 포인터를 지니고 있다면, Win32Thread로 판단하면 된다.

문제는 MS에서 KTHREAD구조체를 명시해주지 않았기 때문에, 
실제로 저 멤버를 찾아가는데 있어서 아래와 같이 OS버젼별로 상당한 도박이 뒤따르게 된다. 

//+0x130 Win32Thread      : Ptr32 Void Windows XP SP3
//+0x18c Win32Thread      : Ptr32 Void  Windows 7 7600

위와 같이 하드코딩 해주게 되면, 나중에 OS가 패치될때라던가, 어떻게 될지 모르기 때문에 상당히 위험하다.

따라서 조금이나마 위험도를 줄이고자, 이리저리 알아보니 커널에서 Win32Thread인지 확인하는 용도로 제공되는 Undocument API가 제공되고 있음을 확인하였다.

NTKERNELAPI PVOID PsGetThreadWin32Thread(__in PETHREAD pThread);

Win32Thread 여부를 확인하고자하는 Target Thread의 PETHREAD를 파라메터로 전달해주면 Win32Thread멤버의 값을 리턴해주는 역할을 한다. 실제 내부가 어떻게 구현되어져있는지 Windbg와 Ollydbg로 한번 살펴보았다.

//MS WindowsXP SP3
0: kd> u nt!PsGetThreadWin32Thread
nt!PsGetProcessWin32Process:
8052d208 8bff            mov     edi,edi
8052d20a 55              push    ebp
8052d20b 8bec            mov     ebp,esp
8052d20d 8b4508          mov     eax,dword ptr [ebp+8]
8052d210 8b8030010000    mov     eax,dword ptr [eax+130h]
8052d216 5d              pop     ebp
8052d217 c20400          ret     4
8052d21a cc              int     3


//MS Windows7


두 OS별로 함수를 비교해보면 결국은 다섯번째 줄에있는 eax+130h냐  eax+18ch냐의 차이만 있다.
(KTHREAD 구조체가 다르기 때문)


PsGetThreadWin32Thread와  거의 동일한 기능을 제공하는 함수로써,  
PVOID PsGetCurrentThreadWin32Thread(VOID); 
가 있는데, 이 함수는  FS:[124]에 접근해서 현재 쓰레드의 PETHREAD를 얻어온뒤, Win32Thread에 접근하는 방식이다.


이런 Undocument 함수를 사용함으로써 명심해야될것은, 커널에서 제공해주는 API이긴 하나, 
어찌됐건간에 공개되지 않은 Undocument API이므로 언제 어떻게 될지 모른다는 것이다.  그러므로 100% 안전하다고 볼수없다.



* 참고 *

이 함수와 반대되는 기능을 가진 Undocument API로는 PsSetThreadWin32Thread가 있다.
이 함수의 타입은 다음과 같다.
NTKERNELAPI VOID PsSetThreadWin32Thread(__in PETHREAD pThread, __in PVOID Win32Thread);
저작자 표시 비영리 변경 금지
신고
by Sone 2011.01.07 15:17
| 1 |