前情回顾
反汇编
上次我们分析到KiFastCallEntry
和KiSystemService
交汇的地方,但是由于篇幅过长,所以截断了
系统服务表
索引这个表的是服务号,服务号的第12位是用来区分是在哪一个表里的
这两个表其实是一模一样的,只是表的的东西有些不同而已
绿色是普通的系统调用,黄色的是GUI相关的系统调用
更多详细信息在下面的逆向分析中会有答案
继续分析
我们继续来到代码交汇处
00407781 loc_407781: ; CODE XREF: _KiBBTUnexpectedRange+18↑j
.text:00407781 ; _KiSystemService+6E↑j
.text:00407781 mov edi, eax ; eax没有动过,所以还是 服务号
.text:00407783 shr edi, 8
.text:00407786 and edi, 30h ; edi = 系统服务表 ? 0x00 : 0x10
.text:00407786 ; 0x00: 普通服务函数
.text:00407786 ; 0x10: 图形界面函数
.text:00407789 mov ecx, edi ; ecx记录使用什么表
.text:0040778B add edi, [esi+0E0h] ; edi = _KThread.ServiceTable + 系统服务表项(0x00 or 0x10)
.text:0040778B ; 一个表四个项,刚好0x10,真是好算计
.text:00407791 mov ebx, eax ; ebx = 服务号
.text:00407793 and eax, 0FFFh ; 服务号.bit_12 = 0 (第十二位置零)
.text:00407798 cmp eax, [edi+8]
.text:0040779B jnb _KiBBTUnexpectedRange ; if (服务表.ServiceLimit < 服务号) 跳走(没有这个服务)
.text:004077A1 cmp ecx, 10h
.text:004077A4 jnz short loc_4077C0 ; if (ecx == 0 (普通函数表)) 跳转
.text:004077A6 mov ecx, ds:0FFDFF018h ; ecx = _KPCR._NT_TIB(异常链表).self
.text:004077A6 ; 这个结构体是嵌在_KPCR里的,所以刚好也指向了_KPCR的头部
.text:004077AC xor ebx, ebx
.text:004077AE
.text:004077AE loc_4077AE: ; DATA XREF: _KiTrap0E+110↓o
.text:004077AE or ebx, [ecx+0F70h]
.text:004077B4 jz short loc_4077C0 ; _KPCR._KPRCB.KeSystemCalls += 1;
.text:004077B6 push edx ; 3环参数头部
.text:004077B7 push eax ; 第几个 系统服务表
.text:004077B8 call ds:_KeGdiFlushUserBatch
.text:004077BE pop eax
.text:004077BF pop edx
.text:004077C0
.text:004077C0 loc_4077C0: ; CODE XREF: _KiFastCallEntry+B4↑j
.text:004077C0 ; _KiFastCallEntry+C4↑j
.text:004077C0 inc dword ptr ds:0FFDFF638h ; _KPCR._KPRCB.KeSystemCalls += 1;
.text:004077C6 mov esi, edx ; esi = 3环参数头部
.text:004077C8 mov ebx, [edi+0Ch] ; ebx = 系统服务表.ArgmentTable(参数表首地址)
.text:004077CB xor ecx, ecx
.text:004077CD mov cl, [eax+ebx] ; eax = 服务号 & 0xFFF (往上看)
.text:004077CD ; cl = ((BYTE*)参数表)[服务号]
.text:004077D0 mov edi, [edi] ; edi = 系统服务表.ServiceTable (函数地址表)
.text:004077D2 mov ebx, [edi+eax*4] ; ebx = *(DWORD*)(函数地址表(首地址) + 服务号 * 4)
.text:004077D2 ; //或者 ebx = ((DWORD*)函数地址表)[服务号]
.text:004077D2 ; 其中 服务号 * 4 是 地址偏移
.text:004077D5 sub esp, ecx ; 预留 压入参数 的空间
.text:004077D7 shr ecx, 2 ; ecx = 参数个数
.text:004077DA mov edi, esp ; edi = 参数首地址
.text:004077DC cmp esi, ds:_MmUserProbeAddress ; 检查 C0000005
.text:004077E2 jnb loc_407990
.text:004077E8
.text:004077E8 loc_4077E8: ; CODE XREF: _KiFastCallEntry+2A4↓j
.text:004077E8 ; DATA XREF: _KiTrap0E+106↓o
.text:004077E8 rep movsd ; 参数复制,一次一个DWORD
.text:004077E8 ; 这里base都一样,es ds可以忽略
.text:004077E8 ; while (ecx != 0){
.text:004077E8 ; step = Eflags.D ? -sizeof(dowrd) : sizeof(dword);
.text:004077E8 ; mov dword ptr es:[edi], dword ptr ds:[esi];
.text:004077E8 ; edi += step, esi += step;
.text:004077E8 ; ecx--;
.text:004077E8 ; }
.text:004077EA call ebx ; 要么C0000005,要么执行这个
.text:004077EA ; 这个就是之前找到的 服务函数,也就是最终的目标
.text:004077EC
.text:004077EC loc_4077EC: ; CODE XREF: _KiFastCallEntry+2AF↓j
.text:004077EC ; DATA XREF: _KiTrap0E+126↓o ...
.text:004077EC mov esp, ebp
.text:004077EE
好吧,这就算跟踪完了,但是返回怎么回呢,只能继续保持好奇心等学完APC再来看咯
学习没有好奇心哪来的动力,就好像小说不挖坑怎么吸引人