Wednesday, October 14, 2015

System Service Dispatching

System Service Dispatch ∨ (sysCALL) OS tərəfindən təyin olunmuş kernel əsaslı funksiyaları işə salır (trigger)
(pentium II əvvəlindəki x86 prosesorlar int 0x2e təlimatı əsasında trap handler işə salırdı)
Windows Based
Trap Handler – Trap – interrupt və yaxud exception yarandıqda icrada olan threadi nəzarətə götürür və sabit bir yerə (routine və s.) kontrolun köçürülməsi əməliyyatını yerinə yetirir.
Hardware/Software Interrupts --- > trap handler kontrolu INTERRUPT Service Routines (ISR)-ə transfer edir.
Hardware/Software Exceptions --- > trap handler kontrolu Exception Dispatchers (ED)-ə transfer edir.
System service calls --- > trap handler kontrolu system service function (SSF)-ə transfer edir.
                                                          Trap handler
Interrupt ————— > INTERRUPT SERVICE ROUTINE
System service call ————— > SYSTEM SERVICES
Hardware exceptions|Software Exceptions –> EXCEPTION dispatcher —> Exception handlers
Virtual addr exceptions —- > Virtual memory manager’s pager
Hardware və software exception və interrupt generasiya edə bilir. Misal üçün: ‘Bus error exception’ hardware probleminƏ görə yaranır. ‘divide-by-zero exception’ isə sofware probleminə görə yaranır. Həmçinin I/O cihazları interrupt generasiya edə bilər. Kernel özü də bir software interrupt verə bilər.
Yuxarıdakı schema-da kernel trap işləyicileri interrupts,exceptions və system service çağırışlarını göndərir. System service dispatch, System service dispatchingdə təyin olunmuş təlimatının(instruction) icrası nəticəsində işə düşür.

System Service Dispatching

x86 prosessorlarında Pentium II-dən əvvəl Windows int 0x2e (46 onluq) təlimatı (instruction) istifadə edirdi. Bu interrupt vektoru trap ilə nəticələnir. Windows IDT-da (Interrupt Descriptor Table) 46cı entry SSD-ni(System Service dispatcher) göstərir.
Fig 1.0
lkd> !idt 2e
Dumping IDT: 80b95400
898023cf0000002e:    82e9822e nt!KiSystemService
Trap icrada olan thread-in kernel mode keçidinə və system service dispatcher-a daxil olmasına səbəb olur. EAX prosessor registerinə daxil edilmiş rəqəmli arqument istənilən system servis nömrəsini göstərir. İstifadəçi moduna geri dönmək üçün, system service dispatcher iret (interrupt return instruction) istifadə edir.
x86 Pentium II və yüksək prosessorlarda, Windows systen təlimatı(instruction) istifadə edir, İntel bunu xüsusi olaraq daha sürətli system service dispatch üçün təyin edib. Windows boot zamanı kernel system service dispatch routine adresini MSR (Machine specific register-da saxlayır. System servis nömrəsi EAX prosessor registerində qeyd edilir. Bu təlimatın icrasın kernel moda keçişə və system service dispatcher işə düşməsinə səbəb olur. User moda qayitmaq üçün isə sysexit təlimatı istifadə olunur.
  1. Fig 1.0 göstərildiyi kimi 32 bit kernel debugger-da sistemlərdə system call dispatcher handler !idt 2eilə göstərilə bilir.
  2. Handler-in sysenter versiyasına baxmaq üçün rdmsr təlimatından istifadə edərək MSR 0x176 registerindən oxumaq mümkündür.
lkd> rdmsr 176
msr[176] = 00000000`82e5b300
lkd> ln 00000000`82e5b300
(82e5b300)   nt!KiFastCallEntry
SharedUserData strukturunda doğru kod üçün bir pointer saxlanaraq istifadə etmək üçün uyğun system call kodunu təyin edər. User modda NtReadFile üçün system service code buna bənzəyir.
lkd> u ntdll!NtReadFile
ntdll!NtReadFile:
77125700 b811010000      mov     eax,111h
77125705 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
7712570a ff12            call    dword ptr [edx]
7712570c c22400          ret     24h
System service number 0x111-dir(273 onluq), və kernel tərəfindən təyin edilmiş system dispatch code call təlimatı icra edir, onun pointeri 0x7ffe0300adresindədir. (Bu KUSER_SHARED_DATA strukturunun SystemCallStub member-nə qarşılıq gəlir, bu da 0x7FFE0000 adresindən başlayır)
#define MM_SHARED_USER_DATA_VA      0x7FFE0000
#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)MM_SHARED_USER_DATA_VA)
lkd> u 771264f0
ntdll!KiFastSystemCall:
771264f0 8bd4            mov     edx,esp
771264f2 0f34            sysenter
E.g 1.0-da göstərildiyi kimi, kernel system service dispatch table system service (servis) məlumatlarını tapmaq üçün system call number istifadə edir.
E.g 1.0:
User Mode ————-> system call —-(transition to kernel mode)—- > kernel mode
kernel mode: System service dispatcher (2) ——> System service dispatch table (2):
0System service 0
1System service 1
2System service 2
Bu table Interrupt dispatch table bənzəyir ancaq hər giriş system service əvəzinə interrupt-handling routine göstərir.
System service dispatcher KiSystemService, işə salanın argumentlərini user mod stack-dən kernel stack-ə moda copy edir daha sonra system service icra edilir. Kernel nə qədər stack byte olduğunu bilmək üçün second table istifadə edərək kopyalama tələb edir, bu table argument table adlanır.
typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID *ServiceTable; //System Service Dispatch Table
    PVOID *CounterTable; //istifadə edilmir
    ULONG ServiceLimit; // SSDT table dəyərlərinin sayı
    PUCHAR ArgumentTable; // Dispatch table içindəki ki routine-lər üçün argumentləri saxlayır.
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
reference kimi bir şəkildə verirəm: 
(ServiceTable this the array of function pointers to kernel routines)
lkd> dps !KeServiceDescriptorTable
82f809c0  82e876f0 nt!KiServiceTable
82f809c4  00000000 //not used
82f809c8  00000191 //servicelimit
82f809cc  82e87d38 nt!KiArgumentTable
Sistem servisinə daxil edilmiş arqumentlər istifadəçi sahəsindəki buferdədirsə. Kernel-moda kod kopyalamadan öncə giriş imkanı üçün bu bufer problanmalıdır (yoxlanılmalıdır). Bu problama yalnız threadin previous modu user mode təyin edildikdə həyata keçirilir. Previous mode kernelin thread üzərində trap handler icra edildiyində və daxil olan istisnanın,trap,və yaxud syscall (sistem çağırışının) imtiyaz səviyyəsini müəyyən etmək üçün saxladığı bir dəyərdir (kernel və yaxud user). Optimallaşdırma üçün isə system çağırışının driver və yaxud kernel modun özündən gəldiyi halda probing (yoxlama) və capturing parametrləri nəzərə alınmır və bütün parametrlər etibarlı kernel mod buferlərinə işarə edilir. Kernel mode-da system çağırışları edə bilir. Hər sistem çağırışı üçün kod kernel modda olduğundan və caller kernel modda olduğu üçün siz burada interrupt və sysenter əməliyyatlarına ehtiyyac olmadığını görə bilərsiniz. Driver və yaxud kernel yalnız tələb olunan funksiyanı birbaşa işə sala bilər.