前几天去当面膜拜了女王大牛,果然****,还让我等了一个来小时。。。
在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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)