lkd> u ntdll!ntcreatefile
ntdll!ZwCreateFile:
7c93d090 b825000000 mov eax,25h
7c93d095 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c93d09a ff12 call dword ptr [edx]
7c93d09c c22c00 ret 2Ch
7c93d09f 90 nop
lkd> u SharedUserData!SystemCallStub
SharedUserData!SystemCallStub:
7ffe0300 f0e493 lock in al,93h
7ffe0303 7cf4 jl SharedUserData+0x2f9 (7ffe02f9)
7ffe0305 e493 in al,93h
7ffe0307 7c00 jl SharedUserData!SystemCallStub+0x9 (7ffe0309)
7ffe0309 0000 add byte ptr [eax],al
7ffe030b 0000 add byte ptr [eax],al
7ffe030d 0000 add byte ptr [eax],al
7ffe030f 0000 add byte ptr [eax],al
???
lkd> u poi(SharedUserData!SystemCallStub)
ntdll!KiFastSystemCall:
7c93e4f0 8bd4 mov edx,esp
7c93e4f2 0f34 sysenter
ntdll!KiFastSystemCallRet:
7c93e4f4 c3 ret
7c93e4f5 8da42400000000 lea esp,[esp]
7c93e4fc 8d642400 lea esp,[esp]
ntdll!KiIntSystemCall:
7c93e500 8d542408 lea edx,[esp+8]
7c93e504 cd2e int 2Eh
7c93e506 c3 ret
!!!
뭐냐이게. 하고 고민했다 왜 sysenter 가 안 나오고 엉뚱한 게 나오나 ?
시스인터널을 뒤지다 보니 같은 질문을 한 사람이 있어서 갖고왔다.
왜 poi() 함수가 필요한가요 ?
SystemCall 은 NTDLL 의 stub 를 가리키는 포인터다.
※ In XP SP2 and Srv03 SP1, in the interests of reducing system attack surface, the KUSER_SHARED_DATA region was marked non-executable, and SystemCall becomes a pointer to a stub residing in NTDLL.
공격 요소를 줄이기 위해서 KUSER_SHARED_DATA 영역의 실행 권한을 없애고
대신 SystemCall 을 포인터로 만들었다. 라는 의미.
XP 이전의 방식에서 시스템콜을 호출하려면 INT 2E 명령어(SW 인터럽트)를 이용했어야 했다.
커널 모드로 들어가는 빠르고 편한 방법이었고, 32비트의 x86 프로세서와 호환이 가능한 방식이었다.
XP 시스템으로 넘어오면서 시스템콜 메커니즘이 바뀌었는데,
이 운영체제는 프로세서 타입에 따라 더 고성능의 커널 트랜지션 매커니즘을 사용했다.
팬티엄 2 이후의 프로세서들은 커널 모드로 진입하는 더 효과적인 방법인 systenter 을 사용하게 되었는데, 기존의 인터럽트 요청 방식보다 더 오버헤드가 적었다.
어떻게 문제 없이 방식을 교체했을까 ? XP SP2 와 Serv03 SP1 운영체제 이후, system service call stub 는 INT 2E처럼 명령어들을 하드코딩하는 방식을 사용하지 않았다. 대신에 KUSER_SHARED_DATA 영역으로 리다이렉텬 시키는 방법을 사용한다. 이전에는 시스템콜 영역의 코드는 고정시켜 두고 실시간으로 적절한 값을 채워주는 형식이었다.
XP sp2 와 Srv03 sp1 에서 KUSER_SHARED_DATA 영역은 실행권한이 없고, SystemCall 은 NTDLL 의 stub 를 가리키는 포인터가 되었다. (이 포인터는 적절한 system call stub 를 찾기 위해서 프로세서 타입에 따라 실시간으로 변한다. - ??)
그래서 NTDLL 함수를 조회했을 때 나왔던 디스어셈블 코드 중 SharedUserData!SystemCallStub (7ffe0300)
7FFE0300 은 그 자체가 아니라 KUSER_SHARED_DATA 영역을 조회했을 때 +300 위치에 있는 포인터 값을 가리킨다.
lkd> dt ntdll!_KUSER_SHARED_DATA
+0x000 TickCountLow : Uint4B
+0x004 TickCountMultiplier : Uint4B
+0x008 InterruptTime : _KSYSTEM_TIME
+0x014 SystemTime : _KSYSTEM_TIME
+0x020 TimeZoneBias : _KSYSTEM_TIME
+0x02c ImageNumberLow : Uint2B
+0x02e ImageNumberHigh : Uint2B
+0x030 NtSystemRoot : [260] Uint2B
+0x238 MaxStackTraceDepth : Uint4B
+0x23c CryptoExponent : Uint4B
+0x240 TimeZoneId : Uint4B
+0x244 Reserved2 : [8] Uint4B
+0x264 NtProductType : _NT_PRODUCT_TYPE
+0x268 ProductTypeIsValid : UChar
+0x26c NtMajorVersion : Uint4B
+0x270 NtMinorVersion : Uint4B
+0x274 ProcessorFeatures : [64] UChar
+0x2b4 Reserved1 : Uint4B
+0x2b8 Reserved3 : Uint4B
+0x2bc TimeSlip : Uint4B
+0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
+0x2c8 SystemExpirationDate : _LARGE_INTEGER
+0x2d0 SuiteMask : Uint4B
+0x2d4 KdDebuggerEnabled : UChar
+0x2d5 NXSupportPolicy : UChar
+0x2d8 ActiveConsoleId : Uint4B
+0x2dc DismountCount : Uint4B
+0x2e0 ComPlusPackage : Uint4B
+0x2e4 LastSystemRITEventTickCount : Uint4B
+0x2e8 NumberOfPhysicalPages : Uint4B
+0x2ec SafeBootMode : UChar
+0x2f0 TraceLogging : Uint4B
+0x2f8 TestRetInstruction : Uint8B
+0x300 SystemCall : Uint4B
+0x304 SystemCallReturn : Uint4B
+0x308 SystemCallPad : [3] Uint8B
+0x320 TickCount : _KSYSTEM_TIME
+0x320 TickCountQuad : Uint8B
+0x330 Cookie : Uint4B
그래서 값을 찾아보면
lkd> dd 7ffe0300
7ffe0300 7c93e4f0 7c93e4f4 00000000 00000000
7ffe0310 00000000 00000000 00000000 00000000
7ffe0320 00000000 00000000 00000000 00000000
7ffe0330 70589fcd 00000000 00000000 00000000
7ffe0340 00000000 00000000 00000000 00000000
7ffe0350 00000000 00000000 00000000 00000000
7ffe0360 00000000 00000000 00000000 00000000
7ffe0370 00000000 00000000 00000000 00000000
7C93E4F0 이 있고, 이 부분을 u 로 디스어셈블 해야 SYSENTER 가 보인다.
lkd> u 7c93e4f0
ntdll!KiFastSystemCall:
7c93e4f0 8bd4 mov edx,esp
7c93e4f2 0f34 sysenter
ntdll!KiFastSystemCallRet:
7c93e4f4 c3 ret
7c93e4f5 8da42400000000 lea esp,[esp]
7c93e4fc 8d642400 lea esp,[esp]
ntdll!KiIntSystemCall:
7c93e500 8d542408 lea edx,[esp+8]
7c93e504 cd2e int 2Eh
7c93e506 c3 ret
www.nynaeve.net/?p=48
"The system call dispatcher on x86"
06년 문서를 이제서야 찾아보다니 할일이 태산이다..
'Research > Kernel' 카테고리의 다른 글
adding sys call on kernel 3.16.x, 3.19.x (0) | 2016.06.14 |
---|---|
윈도우 네임스페이스 / 디바이스 심볼릭 링크 (0) | 2014.07.18 |