浅谈系统服务分发

0x02.举例查看系统调用怎么样爆发

 

0x04.根本情势下的种类分发

  图片 1

  这里要介绍内核的Zw类别函数了,他们不光是Nt版本函数的小名或包装,而是对应Nt体系系统调用的翻版,使用了同一的系统调用分发机制。他们会树立1个假的间歇栈(CPU在暂停后变卦的栈),并直接调用KiSystemService例程,那几个进程就在模拟CPU中断,就如调用来自用户方式相似,而在检查和测试到该调用的实际上特权级后将原先进模范式修改为基石格局,那样也节约了参数校验,成功调用到NtOpenProcess!

 

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

 0x05.简单小结

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

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

  (2).在x86Pentium II
处理器上,Windows使用了sysenter指令,内核的连串服务分发器例程的地点保存在与该指令相关联的三个MSLacrosse中,eax,edx保存与int2e相同的剧情。最终通过sysexit指令重回用户方式;

 

 

 

      图片 2

  一早先线程的体系服务表地址指向Ntoskrnl.exe中的SSDT表,但当调用了三个USE瑞鹰或GDI服务时,服务表地址被涂改成指向win32k.sys中的系统服务表。 

   以上知情参考自《深切解析Windows操作系统6》第①章,假诺有不得法的地点还请建议,小编将谦虚请教!

 

 

图片 3

    
 图片 4

  图片 5

      图片 6

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

 

  图片 7

   我们发现,三拾个人下,系统调用分发操作都会走到KiFastCallEntry里面,而6二个人下,系统调用分发操作会走到KiSystemCall64,然后去完结相应的系统服务调用。那么大家有个问号,系统是怎么进来到那几个类别调用的呢?

  大家有八个获得,一个是看看了系统服务号放在了eax里了,另五个是它呼叫了3个地方,call指令将执行由基础建立起来的类别服务分发代码,该地点保存在ntdll!_KUSER_SHARED_DATA+0x300处,我们随后进这几个地点看看:

 

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

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

 

 

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

0x01.粗看不一样电脑进入系统调用

 图片 8

 

 

 

 

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

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

    61人平台读取MS福睿斯的0xC0000082处,里面保存的是6四人的syscall,当大家u一下以此地点,发现那么些正是x64系统调用分发的输入KiSystemCall64(在Win7
x64下测试)

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

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

  大家就像有了零星眉目了,系统调用在ntdll里面产生了,相当于说,在ntdll里面完结了从ring3到ring0的切换,其中eax保存服务号,edx保存参数列表首地址,通过服务号能够在SSDT中一定目的服务例程

 

0x00.说在前面

 ……

 

 

 

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

 

  三1四位下的KeServiceDescriptorTable各个成员固然目的类别服务的断然地址,61位下的目的种类服务真正地址是KeServiceDescriptorTable每一个成员保存的偏移量(右移三位后的)+KeServiceDescriptorTable集散地址;

   Ring0 —> Ring0
的种类调用:Ntoskrnl.exe(Zw)—>Ntoskrnl.exe(Nt)

  在系统调用中,若是原本形式为用户方式,在给系统服务传递的参数指向了用户空间缓冲区时,内核形式代码在操作该缓冲区前会检查是还是不是能够访问该缓冲区,而原来方式正是基本方式的时候,默许参数有效,则不会对参数举办检讨。而既然已经在基础形式了,那就不须求int2e中断或然sysenter之类的操作了,但一旦平素像调用API一般直接调用NtOpenProcess之类的连串服务函数时,内核保存的本来格局值如故是用户情势(进基本在此之前当然是用户形式咯~),但又检查和测试到传递来的地方是一个基础情势地址(因为在眼下根本格局下调用),于是会促成调用失利(STATUS_ACCESS_VIOLATION)。

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

 

     那里读取MS大切诺基的0x176处,在那之中富含了系统服务分发器地址,发现其实调用的正是Ki法斯特CallEntry(入口)!(在Win7
x86下测试)

相关文章