Vista之前的系统,XP及Server 2003只有8个坑,就是说前8个调用成功之后,后续的所有调用都会失败,看来通过注册callback的方式来监控进程非常不靠谱。
从内核角度来说,尽量少的调用不仅提高系统响应时间,也降低了不靠谱的驱动所可能带来问题,但限制为区区8个总不是解决办法吧,比如Symantec家的SEP动不动就占3个,腾讯家(Tencent)更牛B,安全管家要用几个,QQ也要用,就连浏览器也要搞个驱动并也要注册个进程创建的回调通知,这也太让人无语了吧。
好在从Vista开始,这个限制从8个变成了64个,翻了整整8倍,呵呵,这下够用了?!
下面是一个典型的XP系统实例,8个回调会被占满了,后起的驱动们只能想其它办法了:
0: kd> x nt!PspCreateProcessNotifyRoutine 80564a40 nt!PspCreateProcessNotifyRoutine = <no type information> 0: kd> dd 80564a40 80564a40 e101894f e15e4eb7 e2031ff6 e1e8b56f 80564a50 e20a8d9f e51c641f e52246b7 e5ad82cf 80564a60 00000008 00000000 86a85d58 8656fac0 80564a70 86b9b5a0 86be5208 86be45a0 00000000 80564a80 00000000 00000000 00000000 00000000 80564a90 00000000 00000000 00000000 00000000 80564aa0 00000000 6d6f7441 00000000 00000001 80564ab0 00000000 00000000 00000000 00000000 0: kd> .for (r $t0=0; $t0 < 8; r $t0=$t0+1) {r $t1 = poi($t0 * 4 + nt!PspCreateProcessNotifyRoutine); .if ($t1 == 0) {.continue;}; r $t1 = $t1 & 0xFFFFFFF8; r $t1 = poi($t1 + 4); r $t0; r $t1; u $t1; ln $t1;} $t0=00000000 $t1=f7310790 TsFltMgr+0x10790: f7310790 55 push ebp f7310791 8bec mov ebp,esp f7310793 83e4f8 and esp,0FFFFFFF8h f7310796 83ec14 sub esp,14h f7310799 53 push ebx f731079a 56 push esi f731079b 8b35a07b31f7 mov esi,dword ptr [TsFltMgr+0x17ba0 (f7317ba0)] f73107a1 57 push edi $t0=00000001 $t1=f771a788 ghcore+0x3788: f771a788 8bff mov edi,edi f771a78a 55 push ebp f771a78b 8bec mov ebp,esp f771a78d 33c0 xor eax,eax f771a78f 390564b471f7 cmp dword ptr [ghcore+0x4464 (f771b464)],eax f771a795 7508 jne ghcore+0x379f (f771a79f) f771a797 39056cb471f7 cmp dword ptr [ghcore+0x446c (f771b46c)],eax f771a79d 741a je ghcore+0x37b9 (f771a7b9) $t0=00000002 $t1=ed1a3b00 SYMEVENT+0xcb00: ed1a3b00 8bff mov edi,edi ed1a3b02 55 push ebp ed1a3b03 8bec mov ebp,esp ed1a3b05 51 push ecx ed1a3b06 53 push ebx ed1a3b07 8b5d08 mov ebx,dword ptr [ebp+8] ed1a3b0a 56 push esi ed1a3b0b 33f6 xor esi,esi $t0=00000003 $t1=ecfeb120 QQFrmMgr+0xe120: ecfeb120 8bff mov edi,edi ecfeb122 55 push ebp ecfeb123 8bec mov ebp,esp ecfeb125 51 push ecx ecfeb126 51 push ecx ecfeb127 53 push ebx ecfeb128 8b5d0c mov ebx,dword ptr [ebp+0Ch] ecfeb12b 56 push esi $t0=00000004 $t1=ecd098a0 SysPlant+0x78a0: ecd098a0 55 push ebp ecd098a1 8bec mov ebp,esp ecd098a3 83e4f8 and esp,0FFFFFFF8h ecd098a6 51 push ecx ecd098a7 53 push ebx ecd098a8 56 push esi ecd098a9 57 push edi ecd098aa a12480d1ec mov eax,dword ptr [SysPlant+0x16024 (ecd18024)] $t0=00000005 $t1=866b41d0 866b41d0 90 nop 866b41d1 90 nop 866b41d2 e9e7c4f466 jmp QMUdisk+0x26be (ed6006be) 866b41d7 90 nop 866b41d8 90 nop 866b41d9 90 nop 866b41da 90 nop 866b41db 90 nop $t0=00000006 $t1=ecaf8070 BHDrvx86+0x6c070: ecaf8070 8bff mov edi,edi ecaf8072 55 push ebp ecaf8073 8bec mov ebp,esp ecaf8075 807d1000 cmp byte ptr [ebp+10h],0 ecaf8079 750f jne BHDrvx86+0x6c08a (ecaf808a) ecaf807b 8b450c mov eax,dword ptr [ebp+0Ch] ecaf807e 8b0d48e0b8ec mov ecx,dword ptr [BHDrvx86+0x102048 (ecb8e048)] ecaf8084 50 push eax $t0=00000007 $t1=ee461eba dekfs+0x4eba: ee461eba 8bff mov edi,edi ee461ebc 55 push ebp ee461ebd 8bec mov ebp,esp ee461ebf 83ec10 sub esp,10h ee461ec2 807d1000 cmp byte ptr [ebp+10h],0 ee461ec6 53 push ebx ee461ec7 56 push esi ee461ec8 57 push edi
Server 2008 X64系统已经可以支持64个注册回调了,这个限制是硬编码在
函数PsSetCreateProcessNotifyRoutine中的:
0: kd> u nt!PspSetCreateProcessNotifyRoutine nt!PspSetCreateProcessNotifyRoutine: fffff800`01c3fab0 48895c2408 mov qword ptr [rsp+8],rbx fffff800`01c3fab5 48896c2410 mov qword ptr [rsp+10h],rbp fffff800`01c3faba 4889742418 mov qword ptr [rsp+18h],rsi …… fffff800`01c3fad4 bb01000000 mov ebx,1 …… fffff800`01c3fb3e e89d3cf1ff call nt!ExDereferenceCallBackBlock (fffff800`01b537e0) fffff800`01c3fb43 4403e3 add r12d,ebx fffff800`01c3fb46 4183fc40 cmp r12d,40h fffff800`01c3fb4a 72ae jb nt!PspSetCreateProcessNotifyRoutine+0x4a (fffff800`01c3fafa) fffff800`01c3fb4c 66019fb4010000 add word ptr [rdi+1B4h],bx fffff800`01c3fb53 7518 jne nt!PspSetCreateProcessNotifyRoutine+0xbd (fffff800`01c3fb6d) ……
此系统上并未安装腾讯管家等类似的防毒程序,但是64个注册回调已有6个被使用,差不多全是M$自家给占用的:
0: kd> x nt!PspCreateProcessNotifyRoutine fffff800`019f8ee0 nt!PspCreateProcessNotifyRoutine = <no type information> 0: kd> dq fffff800`019f8ee0 fffff800`019f8ee0 fffff880`00008c4f fffff880`006d7acf fffff800`019f8ef0 fffff880`006f694f fffff880`007ff5cf fffff800`019f8f00 fffff880`098168af fffff880`0a30216f fffff800`019f8f10 00000000`00000000 00000000`00000000 fffff800`019f8f20 00000000`00000000 00000000`00000000 fffff800`019f8f30 00000000`00000000 00000000`00000000 fffff800`019f8f40 00000000`00000000 00000000`00000000 fffff800`019f8f50 00000000`00000000 00000000`00000000 0: kd> .for (r $t0=0; $t0 < 0x40; r $t0=$t0+1) {r $t1=poi($t0 * 8 + nt!PspCreateProcessNotifyRoutine); .if ($t1 == 0) {.continue}; r $t0; r $t1 = $t1 & 0xFFFFFFFFFFFFFFF0; r $t1 = poi($t1 + 8); r $t1; u $t1; ln $t1;} $t0=0000000000000000 $t1=fffff8000188dbd0 nt!ViCreateProcessCallback: fffff800`0188dbd0 fff3 push rbx fffff800`0188dbd2 4883ec40 sub rsp,40h fffff800`0188dbd6 833dc3a2160000 cmp dword ptr [nt!ViVerifierEnabled (fffff800`019f7ea0)],0 fffff800`0188dbdd 0f8583b6fcff jne nt! ?? ::FNODOBFM::`string'+0x21140 (fffff800`01859266) fffff800`0188dbe3 4883c440 add rsp,40h fffff800`0188dbe7 5b pop rbx fffff800`0188dbe8 c3 ret fffff800`0188dbe9 90 nop (fffff800`0188dbd0) nt!ViCreateProcessCallback | (fffff800`0188dbf0) nt!IopAllocateFileObjectExtension Exact matches: nt!ViCreateProcessCallback = <no type information> $t0=0000000000000001 $t1=fffffa6000e52ffc ksecdd!CredMarshalTargetInfo+0x8cc: fffffa60`00e52ffc 4883ec28 sub rsp,28h fffffa60`00e53000 488364244800 and qword ptr [rsp+48h],0 fffffa60`00e53006 4584c0 test r8b,r8b fffffa60`00e53009 488bc2 mov rax,rdx fffffa60`00e5300c 7546 jne ksecdd!CredMarshalTargetInfo+0x924 (fffffa60`00e53054) fffffa60`00e5300e 488d542448 lea rdx,[rsp+48h] fffffa60`00e53013 488bc8 mov rcx,rax fffffa60`00e53016 ff15dc00feff call qword ptr [ksecdd!BCryptDestroySecret+0x191c8 (fffffa60`00e330f8)] (fffffa60`00e52730) ksecdd!CredMarshalTargetInfo+0x8cc | (fffffa60`00e535f4) ksecdd!AcquireCredentialsHandleW $t0=0000000000000002 $t1=fffffa600106f830 tcpip+0x69830: fffffa60`0106f830 4d85c0 test r8,r8 fffffa60`0106f833 7405 je tcpip+0x6983a (fffffa60`0106f83a) fffffa60`0106f835 e9860b0000 jmp tcpip+0x6a3c0 (fffffa60`010703c0) fffffa60`0106f83a e911130000 jmp tcpip+0x6ab50 (fffffa60`01070b50) fffffa60`0106f83f 90 nop fffffa60`0106f840 90 nop fffffa60`0106f841 90 nop fffffa60`0106f842 90 nop $t0=0000000000000003 $t1=fffffa600074e06c CI!I_PEProcessNotify: fffffa60`0074e06c 4584c0 test r8b,r8b fffffa60`0074e06f 7528 jne CI!I_PEProcessNotify+0x2d (fffffa60`0074e099) fffffa60`0074e071 53 push rbx fffffa60`0074e072 4883ec20 sub rsp,20h fffffa60`0074e076 488bda mov rbx,rdx fffffa60`0074e079 ff15f1d1f5ff call qword ptr [CI!_imp_IoGetCurrentProcess (fffffa60`006ab270)] fffffa60`0074e07f 488bc8 mov rcx,rax fffffa60`0074e082 ff1530d0f5ff call qword ptr [CI!_imp_PsIsProtectedProcess (fffffa60`006ab0b8)] (fffffa60`0074e06c) CI!I_PEProcessNotify | (fffffa60`0074e0a0) CI!RSA32Alloc Exact matches: CI!I_PEProcessNotify = <no type information> $t0=0000000000000004 $t1=fffffa6002fac964 dekfs+0x6964: fffffa60`02fac964 48895c2408 mov qword ptr [rsp+8],rbx fffffa60`02fac969 48896c2410 mov qword ptr [rsp+10h],rbp fffffa60`02fac96e 56 push rsi fffffa60`02fac96f 57 push rdi fffffa60`02fac970 4154 push r12 fffffa60`02fac972 4155 push r13 fffffa60`02fac974 4156 push r14 fffffa60`02fac976 4883ec50 sub rsp,50h $t0=0000000000000005 $t1=fffffa600c545b2d peauth!I_PEProcessNotify: fffffa60`0c545b2d 48895c2408 mov qword ptr [rsp+8],rbx fffffa60`0c545b32 57 push rdi fffffa60`0c545b33 4883ec20 sub rsp,20h fffffa60`0c545b37 e8cc6bfdff call peauth!WARBIRD::Stub_VerifyVerifierCheckSum (fffffa60`0c51c708) fffffa60`0c545b3c 90 nop fffffa60`0c545b3d 360000 add byte ptr ss:[rax],al fffffa60`0c545b40 00fd add ch,bh fffffa60`0c545b42 140a adc al,0Ah (fffffa60`0c545b2d) peauth!I_PEProcessNotify | (fffffa60`0c545fe1) peauth!PEReturnCertChain Exact matches: peauth!I_PEProcessNotify = <no type information>