一、 XP 中SSDT Shadow Hook方法在win8 32中失败
SSDT Shadow hook 不是一个新话题了, 早在 XP系统时就有人对其进行了研究。目前在各大安全技术论坛公布的方法都是基于针对KeAddSystemServiceTable 内核函数的遍历来达到找到SSDT Shadow 表地址的。
这种方法在XP中是可以实现的,因为在XP系统的KeAddSystemServiceTable函数中,SSDT Shadow 地址是明文记录的。但是在WIN8中这种方法却失败了!
我们来看下面反汇编代码。
lkd> u KeAddSystemServiceTable l 40
nt!KeAddSystemServiceTable:
805ba589 8bff mov edi,edi
805ba58b 55 push ebp
805ba58c 8bec mov ebp,esp
805ba58e 837d1803 cmp dword ptr [ebp+18h],3
805ba592 774e ja nt!KeAddSystemServiceTable+0x6b (805ba5e2)
805ba594 8b4518 mov eax,dword ptr [ebp+18h]
805ba597 c1e004 shl eax,4
805ba59a 83b880a6558000 cmp dword ptr nt!KeServiceDescriptorTable (8055a680)[eax],0
805ba5a1 753f jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)
805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax]
//【注意这里,可以看出这个SSDT Shadow表比SSDT表小40】
805ba5a9 833900 cmp dword ptr [ecx],0
805ba5ac 7534 jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)
805ba5ae 837d1801 cmp dword ptr [ebp+18h],1
805ba5b2 8b5508 mov edx,dword ptr [ebp+8]
805ba5b5 56 push esi
805ba5b6 8b7510 mov esi,dword ptr [ebp+10h]
805ba5b9 57 push edi
805ba5ba 8b7d14 mov edi,dword ptr [ebp+14h]
805ba5bd 8911 mov dword ptr [ecx],edx
805ba5bf 8b4d0c mov ecx,dword ptr [ebp+0Ch]
805ba5c2 898844a65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0x4 (8055a644)[eax],ecx
805ba5c8 89b048a65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0x8 (8055a648)[eax],esi
805ba5ce 89b84ca65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0xc (8055a64c)[eax],edi
805ba5d4 0f855a3e0300 jne nt!KeAddSystemServiceTable+0x4d (805ee434)
805ba5da 5f pop edi
805ba5db b001 mov al,1
805ba5dd 5e pop esi
805ba5de 5d pop ebp
805ba5df c21400 ret 14h
805ba5e2 32c0 xor al,al
805ba5e4 ebf8 jmp nt!KeAddSystemServiceTable+0x6d (805ba5de)
805ba5e6 90 nop
805ba5e7 90 nop
805ba5e8 90 nop
805ba5e9 90 nop
805ba5ea 90 nop
我们再来看Win8 系统的KeAddSystemServiceTable函数:
kd> u nt!KeAddSystemServiceTable l 40
nt!KeAddSystemServiceTable:
819d0690 8bff mov edi,edi
819d0692 55 push ebp
819d0693 8bec mov ebp,esp
819d0695 837d1801 cmp dword ptr [ebp+18h],1
819d0699 7750 ja nt!KeAddSystemServiceTable+0x5b (819d06eb)
819d069b 8b4d18 mov ecx,dword ptr [ebp+18h]
819d069e c1e104 shl ecx,4
//------
注意这几句,Win8已经改变了写法。-------------------------------------------------------------
819d06a1 83b900a4878100 cmp dword ptr nt!KeServiceDescriptorTable (8187a400)[ecx],0
819d06a8 7541 jne nt!KeAddSystemServiceTable+0x5b (819d06eb)
819d06aa 83b9c0a3878100 cmp dword ptr nt!KeNumberProcessors+0x209 (8187a3c0)[ecx],0
819d06b1 7538 jne nt!KeAddSystemServiceTable+0x5b (819d06eb)
//------
-XP的写法是-------------------------------------------------------------------------------------------------
805ba59a 83b880a6558000 cmp dword ptr nt!KeServiceDescriptorTable (8055a680)[eax],0
805ba5a1 753f jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)
805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax]
805ba5a9 833900 cmp dword ptr [ecx],0
805ba5ac 7534 jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)
//---------------------------------------------------------------------------------------------------------------------------
819d06b3 837d1801 cmp dword ptr [ebp+18h],1
819d06b7 8b5508 mov edx,dword ptr [ebp+8]
819d06ba 8b4514 mov eax,dword ptr [ebp+14h]
819d06bd 56 push esi
819d06be 8b750c mov esi,dword ptr [ebp+0Ch]
819d06c1 57 push edi
819d06c2 8b7d10 mov edi,dword ptr [ebp+10h]
819d06c5 8991c0a38781 mov dword ptr nt!KeNumberProcessors+0x209 (8187a3c0)[ecx],edx
819d06cb 89b1c4a38781 mov dword ptr nt!KeNumberProcessors+0x20d (8187a3c4)[ecx],esi
819d06d1 89b9c8a38781 mov dword ptr nt!KeNumberProcessors+0x211 (8187a3c8)[ecx],edi
819d06d7 8981cca38781 mov dword ptr nt!KeNumberProcessors+0x215 (8187a3cc)[ecx],eax
819d06dd 0f85cd240d00 jne nt!PcwCloseInstance+0x4da89 (81aa2bb0)
819d06e3 5f pop edi
819d06e4 b001 mov al,1
819d06e6 5e pop esi
819d06e7 5d pop ebp
819d06e8 c21400 ret 14h
二、 WIN8中SSDT Shadow定位原理
1. 代码讲解与调试
系统是如何得到或者区分SSDT ,SSDT SHADOW 地址的呢?我们来反汇编KiFastCallEntry看看:
nt!KiFastCallEntry:
815701d0 b923000000 mov ecx,23h
815701d5 6a30 push 30h
815701d7 0fa1 pop fs
815701d9 8ed9 mov ds,cx
815701db 8ec1 mov es,cx
815701dd 648b0d40000000 mov ecx,dword ptr fs:[40h]
815701e4 8b6104 mov esp,dword ptr [ecx+4]
815701e7 6a23 push 23h
815701e9 52 push edx
815701ea 9c pushfd
815701eb 6a02 push 2
815701ed 83c208 add edx,8
815701f0 9d popfd
815701f1 804c240102 or byte ptr [esp+1],2
815701f6 6a1b push 1Bh
815701f8 ff35f81d5f81 push dword ptr [nt!KeI386FastSystemCallReturn (815f1df8)]
815701fe 6a00 push 0
81570200 55 push ebp
81570201 53 push ebx
81570202 56 push esi
81570203 57 push edi
81570204 648b1d1c000000 mov ebx,dword ptr fs:[1Ch]
8157020b 6a3b push 3Bh
8157020d 8bb324010000 mov esi,dword ptr [ebx+124h]
81570213 ff33 push dword ptr [ebx]
81570215 c703ffffffff mov dword ptr [ebx],0FFFFFFFFh
8157021b 8b6e20 mov ebp,dword ptr [esi+20h]
8157021e 83ec4c sub esp,4Ch
81570221 c644244801 mov byte ptr [esp+48h],1
81570226 81ed8c000000 sub ebp,8Ch
8157022c c6865a01000001 mov byte ptr [esi+15Ah],1
81570233 3bec cmp ebp,esp
81570235 7593 jne nt!KiFastCallEntry2+0x49 (815701ca)
81570237 c6451302 mov byte ptr [ebp+13h],2
8157023b 83652c00 and dword ptr [ebp+2Ch],0
8157023f f64603df test byte ptr [esi+3],0DFh
81570243 896e6c mov dword ptr [esi+6Ch],ebp
81570246 0f8530feffff jne nt!Dr_FastCallDrSave (8157007c)
8157024c 8b5d60 mov ebx,dword ptr [ebp+60h]
8157024f 8b7d68 mov edi,dword ptr [ebp+68h]
81570252 89550c mov dword ptr [ebp+0Ch],edx
81570255 c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h
8157025c 895d00 mov dword ptr [ebp],ebx
8157025f 897d04 mov dword ptr [ebp+4],edi
81570262 fb sti
81570263 8bf8 mov edi,eax
81570265 c1ef08 shr edi,8
81570268 83e710 and edi,10h
8157026b 8bcf mov ecx,edi
8157026d 037e3c add edi,dword ptr [esi+3Ch]
//是KTHREAD中的成员ServiceTable(ds:0023:8ea9e6bc={nt!KeServiceDescriptorTableShadow (816193c0)}),
//那么esi就是KTHREAD结构。这是esi=8ea9e680。edi也是_KSERVICE_TABLE_DESCRIPTOR结构体第一个成员地址。
81570270 8bd8 mov ebx,eax
81570272 25ff0f0000 and eax,0FFFh
81570277 3b4708 cmp eax,dword ptr [edi+8]
8157027a 0f8332fdffff jae nt!KiBBTUnexpectedRange (8156ffb2)
81570280 83f910 cmp ecx,10h
81570283 7521 jne nt!KiFastCallEntry+0xd6 (815702a6)
81570285 8b8ea8000000 mov ecx,dword ptr [esi+0A8h]
8157028b 33f6 xor esi,esi
8157028d 0bb1700f0000 or esi,dword ptr [ecx+0F70h]
81570293 7411 je nt!KiFastCallEntry+0xd6 (815702a6)
81570295 52 push edx
81570296 50 push eax
81570297 6a00 push 0
81570299 6a00 push 0
8157029b 6a00 push 0
8157029d 6a07 push 7
8157029f e8f0911700 call nt!PsInvokeWin32Callout (816e9494)
815702a4 58 pop eax
//得到了shadow表中对应的函数序列号。
815702a5 5a pop edx
815702a6 64ff05b0060000 inc dword ptr fs:[6B0h]
815702ad 8bf2 mov esi,edx
815702af 33c9 xor ecx,ecx
815702b1 8b570c mov edx,dword ptr [edi+0Ch]
//开始计算ssdt shadow函数表地址
815702b4 8b3f mov edi,dword ptr [edi]
//SSDT shadow基地址。
815702b6 8a0c10 mov cl,byte ptr [eax+edx]
815702b9 8b1487 mov edx,dword ptr [edi+eax*4]
//edi是ssdt shadow基地址,eax是函数号,要调用的SSDT shadow 函数放入到edx中。
815702bc 2be1 sub esp,ecx
815702be c1e902 shr ecx,2
815702c1 8bfc mov edi,esp
815702c3 3b358c946181 cmp esi,dword ptr [nt!MmUserProbeAddress (8161948c)]
815702c9 0f8316020000 jae nt!KiSystemCallExit2+0xa5 (815704e5)
815702cf f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
815702d1 f6456c01 test byte ptr [ebp+6Ch],1
815702d5 7410 je nt!KiFastCallEntry+0x117 (815702e7)
815702d7 648b0d24010000 mov ecx,dword ptr fs:[124h]
815702de 8b3c24 mov edi,dword ptr [esp]
815702e1 895964 mov dword ptr [ecx+64h],ebx
815702e4 897968 mov dword ptr [ecx+68h],edi
815702e7 8bda mov ebx,edx
//要调用的ssdt shadow函数放入到ebx中
815702e9 f60548a1618140 test byte ptr [nt!PerfGlobalGroupMask+0x8 (8161a148)],40h
815702f0 0f954512 setne byte ptr [ebp+12h]
815702f4 0f856f030000 jne nt!KiServiceExit2+0x170 (81570669)
815702fa ffd3 call ebx
//调用ssdt shadow服务函数
815702fc f6456c01 test byte ptr [ebp+6Ch],1
81570300 7434 je nt!KiFastCallEntry+0x166 (81570336)
81570302 8bf0 mov esi,eax
81570304 ff1580026181 call dword ptr [nt!_imp__KeGetCurrentIrql (81610280)]
8157030a 0ac0 or al,al
8157030c 0f851e030000 jne nt!KiServiceExit2+0x137 (81570630)
81570312 8bc6 mov eax,esi
81570314 648b0d24010000 mov ecx,dword ptr fs:[124h]
8157031b f68166010000ff test byte ptr [ecx+166h],0FFh
81570322 0f8526030000 jne nt!KiServiceExit2+0x155 (8157064e)
81570328 8b913c010000 mov edx,dword ptr [ecx+13Ch]
8157032e 0bd2 or edx,edx
81570330 0f8518030000 jne nt!KiServiceExit2+0x155 (8157064e)
81570336 8be5 mov esp,ebp
81570338 807d1200 cmp byte ptr [ebp+12h],0
8157033c 0f8533030000 jne nt!KiServiceExit2+0x17c (81570675)
81570342 648b0d24010000 mov ecx,dword ptr fs:[124h]
81570349 8b553c mov edx,dword ptr [ebp+3Ch]
8157034c 89516c mov dword ptr [ecx+6Ch],edx
nt!KiServiceExit:
8157034f fa cli
81570350 f6457202 test byte ptr [ebp+72h],2
81570354 7506 jne nt!KiServiceExit+0xd (8157035c)
81570356 f6456c01 test byte ptr [ebp+6Ch],1
8157035a 7468 je nt!KiServiceExit+0x75 (815703c4)
8157035c 648b1d24010000 mov ebx,dword ptr fs:[124h]
81570363 f6430201 test byte ptr [ebx+2],1
81570367 7408 je nt!KiServiceExit+0x22 (81570371)
81570369 50 push eax
8157036a 53 push ebx
8157036b e8e36cfbff call nt!KiCopyCounters (81527053)
81570370 58 pop eax
81570371 c6435600 mov byte ptr [ebx+56h],0
81570375 80bb8600000000 cmp byte ptr [ebx+86h],0
8157037c 7446 je nt!KiServiceExit+0x75 (815703c4)
8157037e 8bdd mov ebx,ebp
81570380 894344 mov dword ptr [ebx+44h],eax
81570383 c743503b000000 mov dword ptr [ebx+50h],3Bh
8157038a c7433823000000 mov dword ptr [ebx+38h],23h
81570391 c7433423000000 mov dword ptr [ebx+34h],23h
81570398 c7433000000000 mov dword ptr [ebx+30h],0
8157039f b901000000 mov ecx,1
815703a4 ff157c026181 call dword ptr [nt!_imp_KfRaiseIrql (8161027c)]
815703aa 50 push eax
815703ab fb sti
815703ac 53 push ebx
815703ad 6a00 push 0
815703af 6a01 push 1
815703b1 e8ffb5ecff call nt!KiDeliverApc (8143b9b5)
815703b6 59 pop ecx
815703b7 ff1578026181 call dword ptr [nt!_imp_KfLowerIrql (81610278)]
815703bd 8b4344 mov eax,dword ptr [ebx+44h]
815703c0 fa cli
815703c1 eb99 jmp nt!KiServiceExit+0xd (8157035c)
815703c3 90 nop
815703c4 8b54244c mov edx,dword ptr [esp+4Ch]
815703c8 64891500000000 mov dword ptr fs:[0],edx
815703cf 0fb64c2448 movzx ecx,byte ptr [esp+48h]
815703d4 648b3524010000 mov esi,dword ptr fs:[124h]
815703db 888e5a010000 mov byte ptr [esi+15Ah],cl
815703e1 f744242cff23ffff test dword ptr [esp+2Ch],0FFFF23FFh
815703e9 7571 jne nt!KiSystemCallExit2+0x1c (8157045c)
815703eb f744247000000200 test dword ptr [esp+70h],20000h
815703f3 0f85b70b0000 jne nt!KiExceptionExit+0x124 (81570fb0)
815703f9 66f744246cf9ff test word ptr [esp+6Ch],0FFF9h
81570400 0f84ac000000 je nt!KiSystemCallExit2+0x72 (815704b2)
81570406 66837c246c1b cmp word ptr [esp+6Ch],1Bh
8157040c 660fba64246c00 bt word ptr [esp+6Ch],0
81570413 f5 cmc
81570414 0f8786000000 ja nt!KiSystemCallExit2+0x60 (815704a0)
8157041a 66837d6c08 cmp word ptr [ebp+6Ch],8
8157041f 7405 je nt!KiServiceExit+0xd7 (81570426)
81570421 8d6550 lea esp,[ebp+50h]
81570424 0fa1 pop fs
81570426 8d6554 lea esp,[ebp+54h]
81570429 5f pop edi
8157042a 5e pop esi
8157042b 5b pop ebx
8157042c 5d pop ebp
8157042d 83c404 add esp,4
81570430 f744240401000000 test dword ptr [esp+4],1
nt!KiSystemCallExitBranch:
81570438 7506 jne nt!KiSystemCallExit2 (81570440)
8157043a 5a pop edx
8157043b 59 pop ecx
8157043c 9d popfd
8157043d ffe2 jmp edx
nt!KiSystemCallExit:
8157043f cf iretd
nt!KiSystemCallExit2:
81570440 f744240800010000 test dword ptr [esp+8],100h
81570448 75f5 jne nt!KiSystemCallExit (8157043f)
8157044a 5a pop edx
8157044b 83c404 add esp,4
8157044e 812424fffdffff and dword ptr [esp],0FFFFFDFFh
81570455 9d popfd
81570456 59 pop ecx
81570457 fb sti
81570458 0f35 sysexit
8157045a cf iretd
8157045b 90 nop
8157045c f7457000000200 test dword ptr [ebp+70h],20000h
81570463 750d jne nt!KiSystemCallExit2+0x32 (81570472)
81570465 f7456c01000000 test dword ptr [ebp+6Ch],1
8157046c 0f8479ffffff je nt!KiServiceExit+0x9c (815703eb)
81570472 33db xor ebx,ebx
81570474 8b7518 mov esi,dword ptr [ebp+18h]
81570477 8b7d1c mov edi,dword ptr [ebp+1Ch]
8157047a 0f23fb mov dr7,ebx
8157047d 0f23c6 mov dr0,esi
81570480 8b5d20 mov ebx,dword ptr [ebp+20h]
81570483 0f23cf mov dr1,edi
81570486 0f23d3 mov dr2,ebx
81570489 8b7524 mov esi,dword ptr [ebp+24h]
8157048c 8b7d28 mov edi,dword ptr [ebp+28h]
8157048f 8b5d2c mov ebx,dword ptr [ebp+2Ch]
81570492 0f23de mov dr3,esi
81570495 0f23f7 mov dr6,edi
81570498 0f23fb mov dr7,ebx
8157049b e94bffffff jmp nt!KiServiceExit+0x9c (815703eb)
815704a0 8b442444 mov eax,dword ptr [esp+44h]
815704a4 83c430 add esp,30h
815704a7 0fa9 pop gs
815704a9 07 pop es
815704aa 1f pop ds
815704ab 5a pop edx
815704ac 59 pop ecx
815704ad e96fffffff jmp nt!KiServiceExit+0xd2 (81570421)
815704b2 0fb75c2410 movzx ebx,word ptr [esp+10h]
815704b7 895c246c mov dword ptr [esp+6Ch],ebx
815704bb 8b5c2414 mov ebx,dword ptr [esp+14h]
815704bf 83eb0c sub ebx,0Ch
815704c2 895c2464 mov dword ptr [esp+64h],ebx
815704c6 8b742470 mov esi,dword ptr [esp+70h]
815704ca 897308 mov dword ptr [ebx+8],esi
815704cd 8b74246c mov esi,dword ptr [esp+6Ch]
815704d1 897304 mov dword ptr [ebx+4],esi
815704d4 8b742468 mov esi,dword ptr [esp+68h]
815704d8 8933 mov dword ptr [ebx],esi
815704da 83c454 add esp,54h
815704dd 5f pop edi
815704de 5e pop esi
815704df 5b pop ebx
815704e0 5d pop ebp
815704e1 8b2424 mov esp,dword ptr [esp]
815704e4 cf iretd
815704e5 f6456c01 test byte ptr [ebp+6Ch],1
815704e9 0f84e0fdffff je nt!KiFastCallEntry+0xff (815702cf)
815704ef b8050000c0 mov eax,0C0000005h
815704f4 e903feffff jmp nt!KiFastCallEntry+0x12c (815702fc)
nt!KiServiceExit2:
815704f9 fa cli
815704fa f6457202 test byte ptr [ebp+72h],2
815704fe 7506 jne nt!KiServiceExit2+0xd (81570506)
81570500 f6456c01 test byte ptr [ebp+6Ch],1
81570504 7446 je nt!KiServiceExit2+0x53 (8157054c)
81570506 648b1d24010000 mov ebx,dword ptr fs:[124h]
8157050d f6430201 test byte ptr [ebx+2],1
81570511 7406 je nt!KiServiceExit2+0x20 (81570519)
81570513 53 push ebx
81570514 e83a6bfbff call nt!KiCopyCounters (81527053)
81570519 c6435600 mov byte ptr [ebx+56h],0
8157051d 80bb8600000000 cmp byte ptr [ebx+86h],0
81570524 7426 je nt!KiServiceExit2+0x53 (8157054c)
81570526 8bdd mov ebx,ebp
81570528 b901000000 mov ecx,1
8157052d ff157c026181 call dword ptr [nt!_imp_KfRaiseIrql (8161027c)]
81570533 50 push eax
81570534 fb sti
81570535 53 push ebx
81570536 6a00 push 0
81570538 6a01 push 1
8157053a e876b4ecff call nt!KiDeliverApc (8143b9b5)
8157053f 59 pop ecx
81570540 ff1578026181 call dword ptr [nt!_imp_KfLowerIrql (81610278)]
81570546 fa cli
81570547 ebbd jmp nt!KiServiceExit2+0xd (81570506)
81570549 8d4900 lea ecx,[ecx]
8157054c 8b54244c mov edx,dword ptr [esp+4Ch]
81570550 64891500000000 mov dword ptr fs:[0],edx
81570557 0fb64c2448 movzx ecx,byte ptr [esp+48h]
8157055c 648b3524010000 mov esi,dword ptr fs:[124h]
81570563 888e5a010000 mov byte ptr [esi+15Ah],cl
81570569 f744242cff23ffff test dword ptr [esp+2Ch],0FFFF23FFh
81570571 7541 jne nt!KiServiceExit2+0xbb (815705b4)
81570573 f744247000000200 test dword ptr [esp+70h],20000h
8157057b 0f852f0a0000 jne nt!KiExceptionExit+0x124 (81570fb0)
81570581 66f744246cf9ff test word ptr [esp+6Ch],0FFF9h
81570588 7467 je nt!KiServiceExit2+0xf8 (815705f1)
8157058a 8b54243c mov edx,dword ptr [esp+3Ch]
8157058e 8b4c2440 mov ecx,dword ptr [esp+40h]
81570592 8b442444 mov eax,dword ptr [esp+44h]
81570596 66837d6c08 cmp word ptr [ebp+6Ch],8
8157059b 740c je nt!KiServiceExit2+0xb0 (815705a9)
8157059d 8d6530 lea esp,[ebp+30h]
815705a0 0fa9 pop gs
815705a2 07 pop es
815705a3 1f pop ds
815705a4 8d6550 lea esp,[ebp+50h]
815705a7 0fa1 pop fs
815705a9 8d6554 lea esp,[ebp+54h]
815705ac 5f pop edi
815705ad 5e pop esi
815705ae 5b pop ebx
815705af 5d pop ebp
815705b0 83c404 add esp,4
815705b3 cf iretd
815705b4 f7457000000200 test dword ptr [ebp+70h],20000h
815705bb 7509 jne nt!KiServiceExit2+0xcd (815705c6)
815705bd f7456c01000000 test dword ptr [ebp+6Ch],1
815705c4 74ad je nt!KiServiceExit2+0x7a (81570573)
815705c6 33db xor ebx,ebx
815705c8 8b7518 mov esi,dword ptr [ebp+18h]
815705cb 8b7d1c mov edi,dword ptr [ebp+1Ch]
815705ce 0f23fb mov dr7,ebx
815705d1 0f23c6 mov dr0,esi
815705d4 8b5d20 mov ebx,dword ptr [ebp+20h]
815705d7 0f23cf mov dr1,edi
815705da 0f23d3 mov dr2,ebx
815705dd 8b7524 mov esi,dword ptr [ebp+24h]
815705e0 8b7d28 mov edi,dword ptr [ebp+28h]
815705e3 8b5d2c mov ebx,dword ptr [ebp+2Ch]
815705e6 0f23de mov dr3,esi
815705e9 0f23f7 mov dr6,edi
815705ec 0f23fb mov dr7,ebx
815705ef eb82 jmp nt!KiServiceExit2+0x7a (81570573)
815705f1 0fb75c2410 movzx ebx,word ptr [esp+10h]
815705f6 895c246c mov dword ptr [esp+6Ch],ebx
815705fa 8b5c2414 mov ebx,dword ptr [esp+14h]
815705fe 83eb0c sub ebx,0Ch
81570601 895c2464 mov dword ptr [esp+64h],ebx
81570605 8b742470 mov esi,dword ptr [esp+70h]
81570609 897308 mov dword ptr [ebx+8],esi
8157060c 8b74246c mov esi,dword ptr [esp+6Ch]
81570610 897304 mov dword ptr [ebx+4],esi
81570613 8b742468 mov esi,dword ptr [esp+68h]
81570617 8933 mov dword ptr [ebx],esi
81570619 8b442444 mov eax,dword ptr [esp+44h]
8157061d 8b54243c mov edx,dword ptr [esp+3Ch]
81570621 8b4c2440 mov ecx,dword ptr [esp+40h]
81570625 83c454 add esp,54h
81570628 5f pop edi
81570629 5e pop esi
8157062a 5b pop ebx
8157062b 5d pop ebp
8157062c 8b2424 mov esp,dword ptr [esp]
8157062f cf iretd
81570630 64ff3524000000 push dword ptr fs:[24h]
81570637 64c6052400000000 mov byte ptr fs:[24h],0
8157063f fa cli
81570640 55 push ebp
81570641 6a00 push 0
81570643 6a00 push 0
81570645 50 push eax
81570646 53 push ebx
81570647 6a4a push 4Ah
81570649 e87ec6f8ff call nt!KiBugCheck2 (814fcccc)
8157064e 0fb68166010000 movzx eax,byte ptr [ecx+166h]
81570655 8b913c010000 mov edx,dword ptr [ecx+13Ch]
8157065b 55 push ebp
8157065c 6a00 push 0
8157065e 52 push edx
8157065f 50 push eax
81570660 53 push ebx
81570661 6a01 push 1
81570663 e864c6f8ff call nt!KiBugCheck2 (814fcccc)
81570668 c3 ret
81570669 8bcb mov ecx,ebx
8157066b e83343ffff call nt!PerfInfoLogSysCallEntry (815649a3)
81570670 e985fcffff jmp nt!KiFastCallEntry+0x12a (815702fa)
81570675 50 push eax
81570676 8bc8 mov ecx,eax
81570678 e8ca42ffff call nt!PerfInfoLogSysCallExit (81564947)
8157067d 58 pop eax
8157067e e9bffcffff jmp nt!KiFastCallEntry+0x172 (81570342)
从上面KiFastCallEntry分析可以得出结论 ssdt Shadow 表只有在GUI线程使用时才加入到内存中,当KTHREAD中的成员Win32Thread域由0变成非0,说明这个线程是一个GUI线程。如果是GUI线程KTHREAD中的成员ServiceTable域就指向SSDT Shadow表;反之,如果是非GUI线程KTHREAD中的成员ServiceTable域将执行SSDT表。
_KPROCESS结构中成员ThreadListHead是指向_KTHREAD结构中成员ThreadListEntry链表。通过它可以定位_KTHREAD结构了,就可判断这个线程是否是GUI线程了。
在_EPROCESS结构的第一个成员Pcb域指向_KPROCESS结构; 同样在_ETHREAD结构中第一个成员Tcb域指向_KTHREAD结构。所以得到这些结构地址后,结构体是可以互换的。
三、 根据分析结果,代码实现过程:
typedef struct _SSDT
{
PVOID ServiceTableBase; //System Service Dispatch Table 的基地址
PVOID ServiceCounterTable; //包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。
PVOID NumberOfServices; //由 ServiceTableBase 描述的服务的数目。
PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表
}* pSSDT,SSDT;
//切换到带有UI进程的内存空间。否则shadow表将不会出现在内存中。我们使用csrss作为目标进程。
HANDLE GetCsrPid()
{
HANDLE Process,hObject;
HANDLE CsrId = (HANDLE)0;
OBJECT_ATTRIBUTES obj;
CLIENT_ID cid;
UCHAR Buff[0x100];
POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;
PSYSTEM_HANDLE_INFORMATION_EX Handles=NULL;
ULONG i;
ULONG nSize;
NTSTATUS status;
PEPROCESS pEproc;
PETHREAD pEthr;
PKTHREAD pKthr;
PKPROCESS pKproc;
//得到csrss.exe句柄。
Handles = GetInfoTable(&nSize);
//等于null,返回0
if(Handles==(PSYSTEM_HANDLE_INFORMATION_EX)0)
{
return CsrId;
}
for(i = 0; i < Handles->NumberOfHandles; i++)
{
if(Handles->Information[i].ObjectTypeNumber == 21) //Port object "\\Windows\\ApiPort"
{
InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
cid.UniqueProcess = (HANDLE)Handles->Information[i].ProcessID;
cid.UniqueThread = (HANDLE)0;
status=PsLookupProcessByProcessId(Handles->Information[i].ProcessID,&pEproc);
if(!NT_SUCCESS(status))
{
KdPrint(("PsLookupProcessByProcessId operation failed!\n"));
continue;
}
if(CheckProcessName(pEproc))
{
CsrId = (HANDLE)Handles->Information[i].ProcessID;
KdPrint(("Csrss.exe PID = %d\n", CsrId)); //如果上面得不到CsrssId,这里可以。
ObDereferenceObject(pEproc);
goto Done;
}
ObDereferenceObject(pEproc);
}
}
Done:
if(Handles!=NULL) ExFreePool(Handles);
return CsrId;
//返回进程id
}
//得到csrss.exe的PID。根据进程Pid得到进程的PEPROCESS结构。
status = PsLookupProcessByProcessId((ULONG)GetCsrPid(), &crsEProc);
if (!NT_SUCCESS(status))
{
DbgPrint("PsLookupProcessByProcessId() error\n");
return ;
}
else
{
DbgPrint("csrss.exe PEPROCESS address 0x%8x\n",crsEProc);
}
ObDereferenceObject(crsEProc);
//根据csrss进程结构,遍历线程得到shadow地址。
ULONG KeQueryRuntimeProcess (PKPROCESS Process)
{
KLOCK_QUEUE_HANDLE LockHandle;
PULONG SSDTShadowAddress=0;
PLIST_ENTRY NextEntry;
PKTHREAD Thread;
ULONG TotalTime;
PKSPIN_LOCK ProcessLock;
PLIST_ENTRY Thread_List_Head;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ProcessLock = (PKSPIN_LOCK)((ULONG)Process+0x034);
// ProcessLock
//_EPROCESS结构中的ThreadListHead 成员,指向进程保护的线程列表。
Thread_List_Head=(PLIST_ENTRY)((ULONG)Process+0x02c);
NextEntry = Thread_List_Head->Flink;
while (NextEntry != Thread_List_Head)
{
//循环线程列表取出每一个线程_KTHREAD结构体。
Thread = (PKTHREAD)((ULONG)NextEntry - 0x1d4);
//查找每一个线程,看看这个成员是否为0。非0是gui线程表示这个线程是GUI线程。
if(((ULONG)Thread+0x124)!=0)
{
//如果是GUI线程,那么_KTHREAD的ServiceTable成员将指向SSDT SHADOW table地址。
SSDTShadowAddress = (PULONG)((ULONG)Thread +0x03c);
break;
}
NextEntry = NextEntry->Flink;
}
return *SSDTShadowAddress;
//返回shadow地址。
}
//取得SSDT Shadow表地址
KeServiceDescriptorTableShadow = (pSSDTShadow)GetSSDTShadowTableAddress(&ModuleID);
if(KeServiceDescriptorTableShadow==NULL)
return NULL;
//根据_SSDT 结构体,算出目标函数地址,然后HOOK。
pTempSSDT = & KeServiceDescriptorTableShadow->win32k;
t_addr=(ULONG)pTempSSDT->ServiceTableBase;
Module_Adr=(PULONG)(t_addr+ModuleID*4);
return Module_Adr;
这个Demo目前可以屏蔽 画图, 写字板,计算器窗口弹出
源码附件密码:huihai-it
学驱动安全的朋友关注 驱动培训
http://bbs3.driverdevelop.com/read.php?tid-125833.html
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法