SystemServiceTable(系统服务表)
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; //这个指向系统服务函数地址表
PULONG ServiceCounterTableBase; //系统这个服务表调用了几次
ULONG NumberOfService; //服务函数的个数
PULONG ParamTableBase; //参数表
}KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
函数参数表里的是以字节为单位的,SystemServiceTable只有两张。
函数地址表里的函数都是内核导出函数,里面只是Ntoskrl.exe其中的一部分函数并不是所有函数。(3环常用的api基本都在里面了)
函数地址表与函数参数表是一一相对的,比如函数地址表第一个成员那么它的参数个数就是参数表的第一个成员。
画程序界面、gdi之类的都在Win32k.sys中。
SystemServiceTable就在_KTHREAD+0xE0处,当程序执行后CUP只要得到当前程序的线程就能找的系统访问表。
- 在3环调用api进入0环需要提供一个操作码,这操作码将决定我要调用的函数在哪。
- 这个操作码虽然它只有32位但它只使用了低13位。
- 如果它的第13位为0那么他在Ntoskrl.exe,1在win32k.sys
- 它的低12位就是对应的函数地址表的索引
_KiFastCallEntry 的过程
mov edi, eax ; 取出操作码
shr edi, 8 ; 操作码右移8位
and edi, 30h ; 再将它&30h 结果只有两种0和10h
; (也就是下标12的位置为0 或者1)
mov ecx, edi
add edi, [esi+0E0h] ; _KTHREAD->ServiceTable(0xE0)
mov ebx, eax
and eax, 0FFFh ; 取操作码的后12位(索引)
cmp eax, [edi+8] ; typedef struct _SYSTEM_SERVICE_TABLE
; {
;
; PVOID ServiceTableBase; //这个指向系统服务函数地址表
; PULONG ServiceCounterTableBase;//系统这个服务表调用了几次
; ULONG NumberOfService; //服务函数的个数
; ULONG ParamTableBase;//参数表
;
; }SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;
; +8 = NumberOfService
; 这里判断要找的函数有没有超出范围
jnb _KiBBTUnexpectedRange
cmp ecx, 10h ; 与0x10比较 如果是0x10查第二张系统服务表
; 如果为0,jnz 到 第一张系统服务表
jnz short loc_4077C0 ; KPRCD->0x518 KeSystemCalls 增加1
mov ecx, ds:0FFDFF018h
xor ebx, ebx
loc_4077AE: ; DATA XREF: _KiTrap0E+110o
or ebx, [ecx+0F70h] ; 这一块只有调用第二张系统服务表才会执行
jz short loc_4077C0 ; GUI之类的东西不是一次性加载的
push edx ; 要用的时候动态加载的
push eax
call ds:_KeGdiFlushUserBatch
pop eax
pop edx
loc_4077C0: ; CODE XREF: _KiFastCallEntry+B4j
; _KiFastCallEntry+C4j
inc dword ptr ds:0FFDFF638h ; KPRCD->0x518 KeSystemCalls 增加1
mov esi, edx ; edx存着3环传入的参数指针
mov ebx, [edi+0Ch] ; ParamTableBase;//参数表
xor ecx, ecx
mov cl, [eax+ebx] ; eax=索引 +参数表= 得到的调用号得到的参数个数
mov edi, [edi] ; [ServiceTableBase]; 得到函数地址表
mov ebx, [edi+eax*4] ; 0环函数的地址
sub esp, ecx ; 提升堆栈为cl
shr ecx, 2 ; 右移2位 = 参数总长度/4 == 参数个数
; 因为rep指令一次复制4字节,所以除4
mov edi, esp ; 设置要拷贝到的地址
cmp esi, ds:_MmUserProbeAddress ; 判断3环参数是否越界
jnb loc_407990
loc_4077E8: ; CODE XREF: _KiFastCallEntry+2A4j
; DATA XREF: _KiTrap0E+106o
rep movsd ; 开始拷贝参数 ecx几就拷贝几次
call ebx ; 调用函数