奔腾2之前的处理器上,Windows使用中断0x2e实现系统调用。
如图int2eh可知:
1.从KernelBase!CreateFileW开始,函数内部调用call Ntdll!NtCreateFile。
2.来到Ntdll!NtCreateFile,按照惯例,把系统调用号保存到eax,以便之后根据系统调用号索引SSDT上对应的系统调用例程。
值得注意的是,在所有的体系结构中,都有一个称为KUSER_SHARED_DATA的结构体,它属于进程,并且总是映射到0x7ffe0000,
对应的SystemCall字段偏移是0x300(位置会根据不同平台而有所不同)。
KUSER_SHARED_DATA.SystemCall对应的值就是ntdll!KiInitSystemCall的地址。
3.进入KiIntSystemCall,内部调用int 2eh调用IDT上对应的中断处理例程。
其中,IDT上0x2e的项为nt!KiSystemService。
4.走进nt!KiSystemService。它就是系统调用分发函数。
内部就会根据系统调用号索引SSDT上对应的系统调用例程,实现相应的功能。最后返回用户领空。
如图trapx86所示:
1.首先从ntdll!NtQueryInformationProcess开始,首先保存系统调用号,然后调用nt!KiFastSystemCall。
2.来到nt!KiFastSystemCall,首先保存esp,因为后面执行sysenter指令时,rsp/esp会被覆盖,最后执行sysenter。
此处补上sysenter/sysexit指令的简单说明,详情请参考intel白皮书。
sysenter和sysexit是一对配套指令,是快速在R3和R0之间转换的指令。
Intel x64下Windows通过syscall实现系统调用。
如图trapx64可知:
1.从ntdll!NtCreateFile开始,首先保存ecx,保存系统调用号,然后调用syscall。值得注意的是,Windows在处理器初始化进程(参见KiInitializeBootStructures)中把MSR寄存器IA32_LSTAR设置为nt!KiSystemCall64。
下面补上syscall/sysret指令的简单说明,详情请参考intel白皮书。
与sysenter/sysexit类似,syscall和sysret是一对配套指令,
是快速在R3和R0之间转换的指令。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课