Windows内核情景分析-系统调用3

系统调用1和系统调用2说了这么多,还未进入int 0x2e所对应的系统服务函数KiSystemService(),这里来看下这个函数内部的处理;通过0x2e和IDTR从IDT中 查询获取对应的方法KiSystemService()。

  • 所以这里 int 0x2e  对应  KiSystemService 入口
  • sysenter 对应的是 KiFastCallEntry 入口,这里不要被这些函数给搞乱了。

 系统空间堆栈

 每个线程有自己的系统空间堆栈,其系统空间的SS和ESP保存在TSS数据结构里面。TR寄存器存放当前线程的TSS地址,当从用户空间进入系统空间,CPU根据TR寄存器从TSS获取系统空间的SS和ESP。

KiSystemService()

 从SharedCode开始的代码是共同的,前奏SYSCALL_PORLOG部分则是专门针对自陷指令系统调用的。

KPCR 处理器控制区(Processor Control Region)

 Windows内核特殊的基本要求,当CPU在内核运行,那么FS指向KPCR的数据结构,且每个CPU(核心?)都有自己的KPCR结构,其次,要使ESI 指向当前线程KTHREAD结构,这两个过程将在SYSCALL_PORLOG宏中实现,再次,KPCR结构存放在固定的虚拟地址,这就可以通过构造特殊的段选择子使得其指向该地址;在保护模式中段寄存器存放的是段选择子,共16bit,特殊的结构使其最终指向GDT或者LDT,如下图:

这里就是特殊构造的段选择子(FS),使其指向KPCR结构 

KPCR结构大小0x120 Byte:

  

其中子结构PRCB 结构(部分,见下图):注意在+0x004处指向了当前运行的线程KTHREAD结构体,所以通过KPRC能够获取线程的很多信息(在线程切换后会去更新PRCB结构开始的相关数据?)

先前模式 

 指在进入KiSystemService这个函数的前夕,CPU处于何种状态(系统态或者用户态);由于windows运行在内核中发起系统调用,所以如果从内核中发起的调用,那么这里先前模式就是系统态,从用户系统调用进入的则为用户态。这里通过将先前模式保存当当前线程KTHREAD结构中对应的先前模式字段中,为了可以方便,高效访问先前模式;先前模式的作用就是用来区分是从内核还是用户空间进入的,所以在系统调用返回的时候要做不同的处理。其次,系统调用是可以嵌套的了,这里会在赋值先前模式字段时,先将原有的内容入栈。KTHREAD 中字段TrapFrame也要更新指向当前的调用堆栈框架。

其次,内核版函数Zwxxxxxx(),通常就是模拟自陷指令的效果,把一些寄存器的内容压入系统空间堆栈,然后调用进行系统调用,先前模式就是系统态。

这里接着看SharedCode 

 Windows NT 基本系统调用多个,如果调用号大于0x1000,则判断为扩展系统调用号(windows将视窗部分移入内核造成)。对应的线程控制块KTHREAD结构中指针ServiceTable,指向本线程的系统调用函数表,不是指向KeServiceDescriptorTable[]就是指向KeServiceDescriptorTableShadow[],前者基本系统调用,后者则额外包含了扩展系统调用。

SSDT与SSPT 

typedef struct _KSYSTEM_SERVICE_TABLE{
        PULONG ServiceTableBase;            //SSDT的基地址指针
        PULONG ServiceCounterTableBase;     //SSDT中每个服务被调用次数表的基地址指针
        ULONG NumberOfService;              //服务函数个数,*4就是整个地址表的大小
        ULONG ParamTableBase;               //SSPT的基地址
    }KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE;
    typedef struct _KSERVICE_TABLE_DESCRIPTOR{
        KSYSTEM_SERVICE_TABLE ntoskrnl;     //ntoskrnl.exe的服务函数
        KSYSTEM_SERVICE_TABLE win32k;       //win32k.sys的服务函数(GDI32/User32)
        KSYSTEM_SERVICE_TABLE notUsed1;
        KSYSTEM_SERVICE_TABLE notUsed2;
    }KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR;

结构如上图,对应的SSPT表则记录索引对应函数的参数数量。

在SharedCode中通过一系列判断与运算,最终决定使用的SSDT,然后根据系统调用号计算出本次调用的函数地址以及函数的参数,将用户空间堆栈的参数复制到系统空间堆栈,最后调用该函数。

 

注:这里所涉及细节需要结合书籍内容理解,上面所说的并不完整,只是挑出容易让人混的内容,需要细细推敲。

参考:https://blog.csdn.net/hu3167343/article/details/7612595    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值