一、API函数调用过程(3环部分)
ReadProcessMemory调用其他模块中的_NtReadVirtualMemory函数
_NtReadVirtualMemory函数在ntdll.dll模块中
0BAH是一个编号,对应操作系统内核函数的编号。7FFE0300h存放的是一个函数,决定了我们用什么方式进0环
二、API函数的调用过程(3环进0环 上)
7FFE0300h为SystemCall
执行了cpuid指令后,SEP的第11位为1表示支持sysenter/sysexit指令,为0表示不支持
如果支持sysenter/sysexit指令,会将nedll.dll!KiFastSystemCall函数放到_KUSER_SHARED_DATA+0x300中,不支持则将ntdll.dll!KiIntSystemCall函数放到_KUSER_SHARED_DATA+0x300中
所有的API进入内核的中断号都是2E
三、API函数的调用过程(3环进0环 下)
0x2e号中断函数进入到了内核模块
通过sysenter进入0环,cs、ss、eip、esp的值全都来自于MSR寄存器
当执行sysenter指令时,CPU会将MSR中的对应的CS、ESP、EIP的值存入对应的寄存器中。SS段的值并没有写到MSR寄存器中,IA32_SYSENTER_CS的值加上8就是SS的值
内核模块的选择取决于操作系统的分页模式,10-10-12分页选择ntoskrnl.exe模块,2-9-9-12分页选择ntkrnlpa.exe模块
四、API函数的调用过程(保存现场)
了解KiSystemService需要了解几个结构体
无论是通过中断门还是KifastcallEntry进入0环,三环的所有寄存器都会存到Trap_Frame结构体中
中断门当权限发生变化时,中断门会像0环堆栈中压入五个值,分别是三环的ss,三环的esp,三环的eflag,三环的cs还有三环的eip
中断门进入0环提权会压入这五个值,KiSystemService在开始执行时Trap_Frame结构体中就有五个值了
如果通过KiFastCallEntry进入0环是没有这五个值的
从这个角度讲可以理解操作系统为什么会设置两个函数进入0环
有些情况中断门会压入六个值,push 0为了补齐
将三环的ExceptionList压栈,0FFDFF000是KPCR的地址,0FFDFF124是KPRCB中的CurrentThread
KThread+0x140是先前模式,也压入到堆栈中
sub esp,48h esp指向Trap_Frame结构体的头
esi指向KTHREAD,KTHREAD+134h指向Trap_Frame,要将栈中形成的Trap_Frame替换原来KTHREAD+134h处的Trap_Frame
判断esi+0x2c DebugActive是否为-1,如果处于调试状态,跳转,将调试寄存器压入到Trap_Frame中。如果不是处于调试状态中,向下执行跳转KiFastCallEntry中的代码
五、API函数的调用过程(系统服务表)
系统服务表中ServiceTables是一个指针,指向一张表,表中存储的是函数的地址。Count表示系统服务表被调用了多少次。ServiceLimit表示系统服务表中一共有多少个函数。ArgentTable指向另一张表,表中数据以字节为单位,表中存储函数参数的个数,如果传递两个参数,每个参数四字节,表中值为8。系统服务表中的函数全是内核文件(Ntoskrl.exe)导出的函数,
并不是内核文件中所有的函数,只是一部分。
系统服务表有两个,第二个系统服务表中所有的函数来自Win32k.sys模块,Win32k.sys模块中是与图形显示以及用户界面相关的系统服务。
如果我们画一个窗口,会使用user32.dll,user32.dll调用GDI32.dll实现画界面功能,GDI32.dll也只是接口,实现全在Win32k.sys系统内核中
CPU只要找到当前线程就能得到系统服务表
三环调用零环函数时候是传递了一个系统服务号,在三环是放到eax寄存器中了,系统服务号决定了函数在哪里,参数在哪里。
系统服务号只使用了低十三位,下标12的位置为0代表要找的函数在第一张表里,为1代表要找的函数在第二张表里。
低十二位对应函数表中的索引
把三环传进来的服务号赋值给edi,将服务号右移八位和30h比较,查看服务号下标12的位置是0还是1,决定查看哪张系统服务表
吧服务号中的函数索引和系统服务表中的第三个成员函数个数比较,看是否超出总个数,如果超出跳转越界
查看是否要调用第二张系统服务表,如果是的话,调用KeGdiFlushUserBatch函数
edx存储三环传入函数参数的指针,得到三环传入参数的个数cl,提升堆栈高度cl,shr ecx 2和rep movsd这两行代码配合看,为了得到参数个数
cmp esi,ds:_MmUserProbeAddress为了查看用户程序能访问地址的最大范围,有没有越界
六、API函数的调用过程(SSDT)
KeServiceDescriptorTable中总共有四张表,xp系统中第三和第四张表没有使用,但是我们只能看见一张表,需要使用KeServiceDescriptorTableShadow来查看
KeServiceDescriptorTable为ntoskrl.exe模块导出的全局变量,KeServiceDescriptorTableShadow并没有导出