KiSystemService 是由用户态进内核态的系统调用,简单分析,写在这里。
进入函数之前
pushfd // ebp+70
push Argument_1 // ebp+6c
push call ip // ebp+68
call
nt!KiSystemService:
80542451 6a00 push 0 // ebp+64
80542453 55 push ebp // ebp+60
80542454 53 push ebx // ebp+5c
80542455 56 push esi // ebp+58
80542456 57 push edi // ebp+54
80542457 0fa0 push fs // ebp+50
80542459 bb30000000 mov ebx,30h
8054245e 668ee3 mov fs,bx
80542461 64ff3500000000 push dword ptr fs:[0] // ebp+4c
fs的值设为30h,根据 System Programming Guide 3.4.1 Segment Selectors 的定义,实际上是 GDTR 第6个值,解析这个数据得到虚拟地址。 直接用dg命令查看段选择子的值。
0: kd> dg 30h
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0030 ffdff000 00001fff Data RW Ac 0 Bg Pg P Nl 00000c93
然后得到这个base地址,据说 这个地址是存放着一个 _KPCR
(Processor Control Region) 结构,第一个成员指向 _NT_TIB
的一个地址,存放当前CPU的各种信息,该结构体最后一个成员是0x120 _KPRCB
,它的第4个成员指向 线程控制块 CurrentThread。
80542468 64c70500000000ffffffff mov dword ptr fs:[0],0FFFFFFFFh
80542473 648b3524010000 mov esi,dword ptr fs:[124h] // CurrentThread _KTHREAD
8054247a ffb640010000 push dword ptr [esi+140h] // _KTHREAD->PreviousMode
80542480 83ec48 sub esp,48h
80542483 8b5c246c mov ebx,dword ptr [esp+6Ch] // Argument_1
80542487 83e301 and ebx,1
8054248a 889e40010000 mov byte ptr [esi+140h],bl // 修改 PreviousMode
80542490 8bec mov ebp,esp
80542492 8b9e34010000 mov ebx,dword ptr [esi+134h] // _KTHREAD->TrapFrame
TrapFrame nt!_KTRAP_FRAME
0: kd> dt nt!_KTRAP_FRAME
+0x000 DbgEbp : Uint4B
+0x004 DbgEip : Uint4B
+0x008 DbgArgMark : Uint4B
+0x00c DbgArgPointer : Uint4B
...
据说 是指中断、自陷、异常进入内核后,在堆栈上形成的一种数据结构。
80542498 895d3c mov dword ptr [ebp+3Ch],ebx // 存起来
8054249b 89ae34010000 mov dword ptr [esi+134h],ebp // 你明白吧
805424a1 fc cld // Clear Direction Flag
805424a2 8b5d60 mov ebx,dword ptr [ebp+60h] // 开头保存的那个 ebp
805424a5 8b7d68 mov edi,dword ptr [ebp+68h] // eip
805424a8 89550c mov dword ptr [ebp+0Ch],edx // Argument_1
805424ab c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h // DbgArgMark 据说是个 Magic Number
805424b2 895d00 mov dword ptr [ebp],ebx
805424b5 897d04 mov dword ptr [ebp+4],edi
805424b8 f6462cff test byte ptr [esi+2Ch],0FFh // _KTHREAD->DebugActive
805424bc 0f858afeffff jne nt!Dr_kss_a (8054234c)
如果老夫没有看错的话,这个应该是保存TrapFrame吧。咳咳。
nt!Dr_kss_a
8054234c f7457000000200 test dword ptr [ebp+70h],20000h // EFLAGS VM Virtual-8086 Mode
80542353 750d jne nt!Dr_kss_a+0x16 (80542362)
nt!Dr_kss_a+0x9:
80542355 f7456c01000000 test dword ptr [ebp+6Ch],1
8054235c 0f8460010000 je nt!KiSystemService+0x71 (805424c2)
nt!Dr_kss_a+0x16:
80542362 0f21c3 mov ebx,dr0
80542365 0f21c9 mov ecx,dr1
80542368 0f21d7 mov edi,dr2
8054236b 895d18 mov dword ptr [ebp+18h],ebx
8054236e 894d1c mov dword ptr [ebp+1Ch],ecx
80542371 897d20 mov dword ptr [ebp+20h],edi
80542374 0f21db mov ebx,dr3
80542377 0f21f1 mov ecx,dr6
8054237a 0f21ff mov edi,dr7
8054237d 895d24 mov dword ptr [ebp+24h],ebx
80542380 894d28 mov dword ptr [ebp+28h],ecx
80542383 33db xor ebx,ebx
80542385 897d2c mov dword ptr [ebp+2Ch],edi
80542388 0f23fb mov dr7,ebx
8054238b 648b3d20000000 mov edi,dword ptr fs:[20h]
80542392 8b9ff8020000 mov ebx,dword ptr [edi+2F8h]
80542398 8b8ffc020000 mov ecx,dword ptr [edi+2FCh]
8054239e 0f23c3 mov dr0,ebx
805423a1 0f23c9 mov dr1,ecx
805423a4 8b9f00030000 mov ebx,dword ptr [edi+300h]
805423aa 8b8f04030000 mov ecx,dword ptr [edi+304h]
805423b0 0f23d3 mov dr2,ebx
805423b3 0f23d9 mov dr3,ecx
805423b6 8b9f08030000 mov ebx,dword ptr [edi+308h]
805423bc 8b8f0c030000 mov ecx,dword ptr [edi+30Ch]
805423c2 0f23f3 mov dr6,ebx
805423c5 0f23f9 mov dr7,ecx
805423c8 e9f5000000 jmp nt!KiSystemService+0x71 (805424c2)
接下来。
nt!KiSystemService+0x71:
805424c2 fb sti // Set Interrupt Flag
805424c3 e9e7000000 jmp nt!KiFastCallEntry+0x8f (805425af)
nt!KiFastCallEntry+0x8f:
805425af 8bf8 mov edi,eax // eax 里保存着 SSDT 表的编号
805425b1 c1ef08 shr edi,8 // edi/256
805425b4 83e730 and edi,30h // 12-14位
805425b7 8bcf mov ecx,edi // edi 验证 shadow ssdt
805425b9 03bee0000000 add edi,dword ptr [esi+0E0h] // _KTHREAD->ServiceTable
805425bf 8bd8 mov ebx,eax
805425c1 25ff0f0000 and eax,0FFFh // 低12位
805425c6 3b4708 cmp eax,dword ptr [edi+8] // ServiceTable->NumberOfServices
805425c9 0f8333fdffff jae nt!KiBBTUnexpectedRange (80542302)
nt!KiFastCallEntry+0xaf:
805425cf 83f910 cmp ecx,10h
805425d2 751b jne nt!KiFastCallEntry+0xcf (805425ef)
nt!KiFastCallEntry+0xb4:
805425d4 648b0d18000000 mov ecx,dword ptr fs:[18h] // _NT_TIB _TEB 当前线程控制块
805425db 33db xor ebx,ebx
805425dd 0b99700f0000 or ebx,dword ptr [ecx+0F70h] // _PEB GdiBatchCount
805425e3 740a je nt!KiFastCallEntry+0xcf (805425ef)
nt!KiFastCallEntry+0xc5:
805425e5 52 push edx
805425e6 50 push eax
805425e7 ff1548d75580 call dword ptr [nt!KeGdiFlushUserBatch (8055d748)]
805425ed 58 pop eax
805425ee 5a pop edx
nt!KiFastCallEntry+0xcf:
805425ef 64ff0538060000 inc dword ptr fs:[638h] // _KPRCB->KeSystemCalls
805425f6 8bf2 mov esi,edx //
805425f8 8b5f0c mov ebx,dword ptr [edi+0Ch] // ParamTableBase
805425fb 33c9 xor ecx,ecx
805425fd 8a0c18 mov cl,byte ptr [eax+ebx] // Params
80542600 8b3f mov edi,dword ptr [edi] // ServiceTable 第一个函数地址
80542602 8b1c87 mov ebx,dword ptr [edi+eax*4] // 计算函数地址
80542605 2be1 sub esp,ecx // param num
80542607 c1e902 shr ecx,2
8054260a 8bfc mov edi,esp
8054260c 3b3534315680 cmp esi,dword ptr [nt!MmUserProbeAddress (80563134)] // 7fff0000
80542612 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (805427c0)
nt!KiFastCallEntry+0xf8:
80542618 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] // 复制到esp
8054261a ffd3 call ebx // 调用
nt!KiFastCallEntry+0xfc:
8054261c 8be5 mov esp,ebp
nt!KiFastCallEntry+0xfe:
8054261e 648b0d24010000 mov ecx,dword ptr fs:[124h] // kthread
80542625 8b553c mov edx,dword ptr [ebp+3Ch] //
80542628 899134010000 mov dword ptr [ecx+134h],edx // 恢复_KTRAP_FRAME
8054262e fa cli
8054262f f7457000000200 test dword ptr [ebp+70h],20000h
80542636 7506 jne nt!KiServiceExit+0x10 (8054263e)
基本流程就这样。还有一些错误处理的分支没有写出来,有时间再看吧。