펜티엄 2 이상 부터의 IA-32 Instruction을 보면 Sysenter와 Sysexit라는 녀석이 추가 되어 있습니다. 바로 기존의 Trap Handler를 통한 System Call을 대체하기 위한 Instruction이지요. 많은 책들이 이부분에 대해서 설명을 하고는 있지만 사실 자세히 설명하고 있지는 않습니다. Intel Manual 을 뒤져 보기 전에는 이해가 힘든 부분이 있지요. 우리가 Windows API를 호출하면 System Stub이 호출되어 Kernel로 넘어 가는건 누구나 알고 있는 사실입니다. 바로 System Stub에 해당하는 녀석이 sysenter Instruction 입니다.
uf ntdll!NtCreateFile
ntdll!NtCreateFile:
7c93d682 b825000000 mov eax,25h
7c93d687 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c93d68c ff12 call dword ptr [edx]
7c93d68e c22c00 ret 2Chlkd> dd 7ffe0300 L4
7ffe0300 7c93eb8b 7c93eb94 00000000 00000000
lkd> uf 7c93eb8b
ntdll!KiFastSystemCall:
7c93eb8b 8bd4 mov edx,esp
7c93eb8d 0f34 sysenter
7c93eb8f 90 nop
7c93eb90 90 nop
7c93eb91 90 nop
7c93eb92 90 nop
7c93eb93 90 nop
7c93eb94 c3 ret
NtCreateFile의 경우 결과적보면 eax에 ServiceTable의 Index를 넣고 현재 스택을 edx에 넣고 sysenter를 호출하는 군요. 그럼 sysenter가 호출되는 시점에는 어떤 동작을 하게 될까요 ?? sysenter를 호출하게 되면 CPU는 MSR을 참고하여 커널 모드로 넘어가기 위한 동작을 합니다.
-
Kernel Mode에서 동작하기 위한 CS 와 EIP를 설정
-
Kernel Mode에서 동작하기 위한 SS 와 ESP를 설정
-
Switches to Privilege Level 0
-
Clear VM Flag
-
System Procedure 실행
SS 를 설정할 때는 MSR[ IA32_SYSENTER_CS] + 8 의 값을 설정해 줍니다. 일종에 규약입니다. 그러한 이유에서 GDT를 구성할 때 SS의 위치를 CS 다음에 설정해 줘야합니다.
IA32_SYSENTER_CS ==> 174H
IA32_SYSENTER_ESP ==> 175H
IA32_SYSENTER_EIP ==> 176HCS <- MSR[ IA32_SYSENTER_CS ]
SS <- MSR[ IA32_SYSENTER_CS ] +8
EIP <- MSR[IA32_SYSENTER_EIP ]
ESP <- MSR[IA32_SYSENTER_ESP ]
결과적으로 위와 같은 형태가 되겠죠 . 이러한 과정을 모두 마치게 되면 EIP에 설정된 Instruction을 실행하게 됩니다.
lkd> rdmsr 0x176
msr[176] = 00000000`804df89flkd> u 00000000`804df89f
nt!KiFastCallEntry:
804df89f b923000000 mov ecx,23h
804df8a4 6a30 push 30h
804df8a6 0fa1 pop fs
804df8a8 8ed9 mov ds,cx
804df8aa 8ec1 mov es,cx
804df8ac 648b0d40000000 mov ecx,dword ptr fs:[40h]
804df8b3 8b6104 mov esp,dword ptr [ecx+4]
804df8b6 6a23 push 23h
결과적으로 nt!KiFastCallEntry 를 호출하는 것을 알수 있습니다. 그럼 KiSystemService 는 어떨까 ?? KiSystemService 역시 결과 적으로 KiFastCallEntry의 Instruction 영역으로 jump 하는 것을 알 수 있습니다.
nt!KiSystemService:
804df7d1 6a00 push 0
804df7d3 55 push ebp
804df7d4 53 push ebx
804df7d5 56 push esi
804df7d6 57 push edi
804df7d7 0fa0 push fs
804df7d9 bb30000000 mov ebx,30h
804df7de 8ee3 mov fs,bx
804df7e0 64ff3500000000 push dword ptr fs:[0]
804df7e7 64c70500000000ffffffff mov dword ptr fs:[0],0FFFFFFFFh
804df7f2 648b3524010000 mov esi,dword ptr fs:[124h]
804df7f9 ffb640010000 push dword ptr [esi+140h]
804df7ff 83ec48 sub esp,48h
804df802 8b5c246c mov ebx,dword ptr [esp+6Ch]
804df806 83e301 and ebx,1
804df809 889e40010000 mov byte ptr [esi+140h],bl
804df80f 8bec mov ebp,esp
804df811 8b9e34010000 mov ebx,dword ptr [esi+134h]
804df817 895d3c mov dword ptr [ebp+3Ch],ebx
804df81a 89ae34010000 mov dword ptr [esi+134h],ebp
804df820 fc cld
804df821 8b5d60 mov ebx,dword ptr [ebp+60h]
804df824 8b7d68 mov edi,dword ptr [ebp+68h]
804df827 89550c mov dword ptr [ebp+0Ch],edx
804df82a c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h
804df831 895d00 mov dword ptr [ebp],ebx
804df834 897d04 mov dword ptr [ebp+4],edi
804df837 f6462cff test byte ptr [esi+2Ch],0FFh
804df83b 0f858bfeffff jne nt!Dr_kss_a (804df6cc)nt!KiSystemService+0x71:
804df841 fb sti
804df842 e9eb000000 jmp nt!KiFastCallEntry+0×8f (804df932)
좀더 자세한 내용은 Intel Software Developer’s Manual을 참고 하시기 바랍니다.
최근 답글