- 注册时间
- 2011-3-10
- 最后登录
- 1970-1-1
该用户从未签到
|
前几天去当面膜拜了女王大牛,果然****,还让我等了一个来小时。。。
在xp中ntdll.dll的调用都是通过sysenter切换到内核的,sysenter调用了KiFastCallEntry,而KiFastCallEntry函数则是在ssdt表找到相应的
函数地址,然后call,所以只要伪造一张原始的ssdt表,并且欺骗过KiFastCallEntry函数,这样ssdt hook就无效了。。。
先看KiFastCallEntry函数:
- nt!KiFastCallEntry:
- 80541790 b923000000 mov ecx,23h
- 80541795 6a30 push 30h
- 80541797 0fa1 pop fs
- 80541799 8ed9 mov ds,cx
- 8054179b 8ec1 mov es,cx
- 8054179d 648b0d40000000 mov ecx,dword ptr fs:[40h]
- 805417a4 8b6104 mov esp,dword ptr [ecx+4]
- 805417a7 6a23 push 23h
- 805417a9 52 push edx
- 805417aa 9c pushfd
- 805417ab 6a02 push 2
- 805417ad 83c208 add edx,8
- 805417b0 9d popfd
- 805417b1 804c240102 or byte ptr [esp+1],2
- 805417b6 6a1b push 1Bh
- 805417b8 ff350403dfff push dword ptr ds:[0FFDF0304h]
- 805417be 6a00 push 0
- 805417c0 55 push ebp
- 805417c1 53 push ebx
- 805417c2 56 push esi
- 805417c3 57 push edi
- //ebx=_KPCR.SelfPcr
- 805417c4 648b1d1c000000 mov ebx,dword ptr fs:[1Ch]
- 805417cb 6a3b push 3Bh
- //esi=_KPCR.PrcbData.CurrentThread
- 805417cd 8bb324010000 mov esi,dword ptr [ebx+124h]
- 805417d3 ff33 push dword ptr [ebx]
- 805417d5 c703ffffffff mov dword ptr [ebx],0FFFFFFFFh
- 805417db 8b6e18 mov ebp,dword ptr [esi+18h]
- 805417de 6a01 push 1
- 805417e0 83ec48 sub esp,48h
- 805417e3 81ed9c020000 sub ebp,29Ch
- 805417e9 c6864001000001 mov byte ptr [esi+140h],1
- 805417f0 3bec cmp ebp,esp
- 805417f2 758d jne nt!KiFastCallEntry2+0x49 (80541781)
- 805417f4 83652c00 and dword ptr [ebp+2Ch],0
- 805417f8 f6462cff test byte ptr [esi+2Ch],0FFh
- 805417fc 89ae34010000 mov dword ptr [esi+134h],ebp
- 80541802 0f8538feffff jne nt!Dr_FastCallDrSave (80541640)
- 80541808 8b5d60 mov ebx,dword ptr [ebp+60h]
- 8054180b 8b7d68 mov edi,dword ptr [ebp+68h]
- 8054180e 89550c mov dword ptr [ebp+0Ch],edx
- 80541811 c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h
- 80541818 895d00 mov dword ptr [ebp],ebx
- 8054181b 897d04 mov dword ptr [ebp+4],edi
- 8054181e fb sti
- //eax为函数序号,但是在KeServiceDescriptorTableShadow时是函数序号+1000h,
- //所以在KeServiceDescriptorTableShadow经过下面运算ecx最终为10h,否则为0
- 8054181f 8bf8 mov edi,eax
- 80541821 c1ef08 shr edi,8
- 80541824 83e730 and edi,30h
- 80541827 8bcf mov ecx,edi
- //KTHREAD.ServiceTable gdi32.dll和user32.dll调用时,
- //ServiceTable为KeServiceDescriptorTableShadow,
- //ntdll.dll调用时ServiceTable为KeServiceDescriptorTable
- //在KeServiceDescriptorTableShadow时+10正好得到win32.sys调用
- 80541829 03bee0000000 add edi,dword ptr [esi+0E0h]
- 8054182f 8bd8 mov ebx,eax
- //保留三个字节,得到正真的序号
- 80541831 25ff0f0000 and eax,0FFFh
- //和ssdt或shadow ssdt总共项数比较,eax大则跳
- 80541836 3b4708 cmp eax,dword ptr [edi+8]
- 80541839 0f8333fdffff jae nt!KiBBTUnexpectedRange (80541572)
- //判断是shadow ssdt还是ssdt,不跳则是shadow ssdt,跳则是ssdt
- 8054183f 83f910 cmp ecx,10h
- 80541842 751b jne nt!KiFastCallEntry+0xcf (8054185f)
- 80541844 648b0d18000000 mov ecx,dword ptr fs:[18h]
- 8054184b 33db xor ebx,ebx
- 8054184d 0b99700f0000 or ebx,dword ptr [ecx+0F70h]
- 80541853 740a je nt!KiFastCallEntry+0xcf (8054185f)
- 80541855 52 push edx
- 80541856 50 push eax
- 80541857 ff1528c75580 call dword ptr [nt!KeGdiFlushUserBatch (8055c728)]
- 8054185d 58 pop eax
- 8054185e 5a pop edx
- 8054185f 64ff0538060000 inc dword ptr fs:[638h]
- 80541866 8bf2 mov esi,edx
- 80541868 8b5f0c mov ebx,dword ptr [edi+0Ch]
- 8054186b 33c9 xor ecx,ecx
- 8054186d 8a0c18 mov cl,byte ptr [eax+ebx]
- //edi=KeServiceDescriptorTable->ServiceTableBase
- //在这里patch 把edi指向构造的ssdt
- 80541870 8b3f mov edi,dword ptr [edi]
- //得到真实地址,edi为KiServiceTable,eax为函数序号
- 80541872 8b1c87 mov ebx,dword ptr [edi+eax*4]
- 80541875 2be1 sub esp,ecx
- 80541878 c1e902 shr ecx,2
- 8054187a 8bfc mov edi,esp
- 8054187c 3b3574f73ff4 cmp esi,dword ptr ds:[0F43FF774h]
- 80541882 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (80541a30)
- //把参数复制到内核
- 80541888 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
- //调用函数
- 8054188a ffd3 call ebx
- 8054188c 8be5 mov esp,ebp
- 8054188e 648b0d24010000 mov ecx,dword ptr fs:[124h]
- 80541895 8b553c mov edx,dword ptr [ebp+3Ch]
- 80541898 899134010000 mov dword ptr [ecx+134h],edx
复制代码
KiFastCallEntry函数先通过fs寄存器的_KPCR得到了当前线程的ETHREAD,然后通过ETHREAD得到ServiceTable
这个就是main SDT或者是shadow sdt,在shadow sdt中要保留24位得到函数序号,之后根据main sdt或者shadow sdt
和函数序号得到函数地址,最后call这个函数。
所以可以在
- 80541868 8b5f0c mov ebx,dword ptr [edi+0Ch]
- 8054186b 33c9 xor ecx,ecx
- 8054186d 8a0c18 mov cl,byte ptr [eax+ebx]
- //edi=KeServiceDescriptorTable->ServiceTableBase
- //在这里patch 把edi指向构造的ssdt
- 80541870 8b3f mov edi,dword ptr [edi]
复制代码
这里inline hook
完整代码如下:
假如要anit shadow ssdt hook 只要同时hook KiFastCallEntry和KiSystemService俩函数就可以了。。。
又度过了一个没有情人的情人节了。。。。 |
|