NOTICE


 오늘은 Windows에서 System Call을 하는 과정에 대해 펴보고자 합니다.


 우리가 사용하는 Windows OS는 User 영역과 Kernel 영역으로 나뉘어져 있습니다. 이는 Microsoft에서 OS 안정성 및 보안 등의 이유로 선택한 방식입니다. 그리고 User 영역에서 Kernel 영역으로의 직접적인 접근을 하지 못하도록 하고 있습니다. 그렇다면 우리가 사용하는 Application은 어떻게 동작하는 것인가?

 Windows는 Kernel에 대한 직접적인 접근을 제한하는 대신 System Service API라는 것을 만들어서 윈도우에서 제공하는 기능 이용 및 시스템과 관련된 동작을 할 수 있게 합니다. 직접 만나서 이야기할 수는 없지만 편지로 전달해서 요청할 수 있는 것입니다.

 일반적으로 User 영역에서 API를 호출하면 NTDLL.dll을 거쳐서 커널 모드로 진입하게 됩니다. 그 과정을 OpenProcess API로 예를 들어 살펴보면 다음과 같습니다. 


kernel32!OpenProcess


ntdll!ZwOpenProcess


ntdll!KiFastSystemCall

-----------------------------------------------------------------------------------------------------------------------


nt!KiFastCallEntry


nt!NtOpenProcess


 Windows 2000 서비스팩 이후, 프로세서에서는 커널 모드에 진입하기 위해 Fast System Call을 사용합니다. 이때 EAX에는 KiServiceTable에서 원하는 함수를 찾기위한 Index 값이 저장됩니다. 그리고 SYSENTER 명령어를 사용해 ntdll!KiFastSystemCall을 호출합니다. ( → KiFastSystemCall(SYSENTER); )

 User 영역에서 ntdll!KiFastSystemCall을 호출하면 Kernel 영역에서는 nt!KiFastCallEntry가 호출됩니다. nt!KiFastCallEntry에서는 원하는 함수 주소를 얻어오기 위한 과정이 진행됩니다. 그리고 해당 루틴에서 KeServiceDescriptorTable 주소를 가져옵니다. 

 KeServiceDescriptorTable 구조체의 첫 번째 멤버에는 KiServiceTable의 주소 값이 들어가있습니다. KiServiceTable를 SSDT(System Service Dispatch Table)라고 합니다. 이 곳에는 16진수로 Kernel에서 제공하는 함수들의 주소가 4 Byte 씩 배열되어 있습니다. 여기서 EAX에 저장했던 인덱스를 사용해 원하는 함수의 주소를 구합니다.



  1. no picture unknown 2018.08.05 19:28 신고

    EXA 이거 EAX 오타이신거같아요