ACCESS浅谈系统服务分发

    欢迎转发,转发请注解出处:http://www.cnblogs.com/uAreKongqi/p/6597701.html

0x00.说在头里

  就大家所知,Windows操作系统内核的圈套处理器会分发中断、十分和连串服务调用,那里大家就在那之中的系列服务分发简单分析一下。

 

0x01.粗看不相同电脑进入系统调用

  (1).在PentiumII
从前的x86处理器上,Windows使用int2e指令发出三个骗局,导致执行线程转到内核情势,进入系统服务分发器,eax保存种类服务号,edx指向参数列表。最终通过iret指令回到用户形式;

    
  大家查阅IDT的2e成员,得知该成员保存的地点是系统调用分发器的地址,紧接着u一下KiSystemService,会意识在保留完寄存器等情形之后,他走到了Ki法斯特CallEntry里面!(在Win7
x86下测试)

      ACCESS 1

  (2).在x86Pentium II
处理器上,Windows使用了sysenter指令,内核的体系服务分发器例程的地点保存在与该指令相关联的一个MSPAJERO中,eax,edx保存与int2e相同的剧情。最终经过sysexit指令重临用户形式;

     这里读取MS瑞虎的0x176处,个中涵盖了系统服务分发器地址,发现实际上调用的正是Ki法斯特CallEntry(入口)!(在Win7
x86下测试)

      ACCESS 2

  (3).在x64类别架构上,Windows使用syscall指令,将系统调用号保存在eax中,前多少个参数放在寄存器(rcx/rdx/r8/r9)中,剩下的参数在栈中。

    61个人平台读取MSOdyssey的0xC0000082处,里面保存的是61人的syscall,当大家u一下那一个地点,发现那个正是x64系统调用分发的进口KiSystemCall64(在Win7
x64下测试)

    
 ACCESS 3

    Ps:通过KiSystemCall64的地方能够透过硬编码得到SSDT、SSSDT地址

 ……

ACCESS 4

 

   大家发现,3一人下,系统调用分发操作都会走到Ki法斯特CallEntry里面,而六二十几人下,系统调用分发操作会走到KiSystemCall64,然后去做到相应的种类服务调用。那么大家有个问号,系统是怎么进去到这个种类调用的吧?

 

0x02.举例查看系统调用如何产生

  那里以Win7 x86 平台下的
NtOpenProcess为例,切换成1个经过内(如explorer.exe),u一下NtOpenProcess,那里显示的是ntdll里的NtOpenProcess的反汇编:

  ACCESS 5

  我们有多个获得,二个是观望了系统服务号放在了eax里了,另二个是它呼叫了3个地点,call指令将履行由基础建立起来的系统服务分发代码,该地址保存在ntdll!_KUSER_SHARED_DATA+0x300处,我们跟着进那几个地点看看:

  ACCESS 6

  大家就如有了一定量眉目了,系统调用在ntdll里面发生了,也便是说,在ntdll里面完成了从ring3到ring0的切换,在那之中eax保存服务号,edx保存参数列表首地址,通过服务号能够在SSDT中稳定指标服务例程

  三11个人下的KeServiceDescriptorTable每种成员就算指标连串服务的断然地址,陆十个人下的对象种类服务实在地址是KeServiceDescriptorTable每一个成员保存的偏移量(右移2人后的)+KeServiceDescriptorTable营地址;

  一早先线程的系列服务表地址指向Ntoskrnl.exe中的SSDT表,但当调用了叁个USE奔驰G级或GDI服务时,服务表地址被改动成指向win32k.sys中的系统服务表。 

 

0x03.从用户层到内核层完整的调用进程

  (1).
当3个Windows应用程序调用Kernel32.dll中的OpenProcess时,其导入并调用了API-MS-Win-Core-File-L1-1-0.dll(1个MinWin重定向Dll)中的NtOpenProcess函数;

  (2).
接着上述的NtOpenProcess函数又会调用KernelBase.dll中的OpenProcess函数,那里是函数的真的落到实处,它会对子系统相关的参数做了检查;

  (3).
然后KernelBase!OpenProcess就会调用ntdll.dll中的NtOpenProcess函数,在那时候就会触发系统调用(ntdll!Ki法斯特SystemCall),传递NtOpenProcess的种类服务号和参数列表;

  (4).
系统服务分发器(Ntoskrnl.exe中的KiSystemService函数)就会调用真正的NtOpenProcess函数来拍卖该I/O请求。

 ACCESS 7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x04.内核格局下的系统分发

  在系统调用中,倘若原先进模范式为用户方式,在给系统服务传递的参数指向了用户空间缓冲区时,内核形式代码在操作该缓冲区前会检查是或不是能够访问该缓冲区,而原先进模范式正是基础格局的时候,默许参数有效,则不会对参数实行检查。而既然已经在基本形式了,那就不须求int2e中断或许sysenter之类的操作了,但就算一向像调用API一般直接调用NtOpenProcess之类的系统服务函数时,内核保存的本原情势值如故是用户格局(进基本以前当然是用户情势咯~),但又检测到传递来的地方是三个基本形式地址(因为在当前基础格局下调用),于是会造成调用退步(STATUS_ACCESS_VIOLATION)。

  这里要介绍内核的Zw种类函数了,他们不不过Nt版本函数的小名或卷入,而是对应Nt种类系统调用的翻版,使用了扳平的种类调用分发机制。他们会建立叁个假的中止栈(CPU在暂停后转变的栈),并间接调用KiSystemService例程,这几个进度就在模拟CPU中断,就如调用来自用户形式相似,而在检查和测试到该调用的骨子Ritter权级后将原本方式修改为基本格局,那样也省去了参数校验,成功调用到NtOpenProcess!

  ACCESS 8

 

 0x05.不难小结

   Ring3 —> Ring0 的系统调用:
Kernel32.dll(API)—>ntdll.dll(Nt/Zw)—>用户格局转内核方式—>Ntoskrnl.exe(Nt)—>完毕I/O请求(原路再次来到)

   Ring0 —> Ring0
的体系调用:Ntoskrnl.exe(Zw)—>Ntoskrnl.exe(Nt)

   以上知情参考自《浓厚剖析Windows操作系统6》第2章,假若有不得法的地点还请建议,笔者将谦虚求教!

相关文章