安全之路 -- 多核处理器同步函数KiIpiGenericCall函数在XP SP3下的寻址方式

前言

众所周知,在进行内核Inline Hook的时候,如果需要Patch的字节数少于等于8,我们可以借助CMPXCHG8B或者Interlockedcompareexchange64大法进行原子挂钩(这两个函数会申请总线锁和缓存锁,达到多核同步的效果);但是如果字节数大于8怎么办呢?我们可以使用DPC播报(KeInsertQueueDpc或者KeGenericCallDpc(XP未导出))完成,将所有核挂入DPC,然后由一个核实现挂钩,最早的安全软件们都是这么做的。但是,如果在申请DPC的过程中,有一个核因为某些原因处于DIRQL状态,无法执行DPC,最后就会导致系统挂死,高版本系统会触发DPC_WATCHDOG_VIOLATION(0x133)蓝屏
所以鉴于以上原因,我们发现了另外一个新函数:KiIpiGenericCall,这个函数会把所有核提到IPI Level,这个IRQL甚至已经高过了时钟中断,这种级别可以打断几乎所有IRQL的例程,强行将CPU提升至IPI。不过遗憾的是,这个函数在XP并未导出
下列提出两种比较WORK-AROUND的方式供大家选择:

  1. 找到导出的KeSetTargetProcessorDpc函数地址,然后按相对偏移+特征码找到下一个KiIpiGenericCall函数地址;
  2. 直接根据NT内核文件相对偏移RVA+特征码验证,找到函数。
.text:8050C6B4                         ; ---------------------------------------------------------------------------
.text:8050C6B9 90 90 90 90 90                          db 5 dup(90h)
.text:8050C6BE                         ; Exported entry 621. KeSetTargetProcessorDpc
.text:8050C6BE
.text:8050C6BE                         ; =============== S U B R O U T I N E =======================================
.text:8050C6BE
.text:8050C6BE                         ; Attributes: bp-based frame
.text:8050C6BE
.text:8050C6BE                         ; void __stdcall KeSetTargetProcessorDpc(PRKDPC Dpc, CCHAR Number)
.text:8050C6BE                                         public _KeSetTargetProcessorDpc@8
.text:8050C6BE                         _KeSetTargetProcessorDpc@8 proc near    ; CODE XREF: PopInvokeSystemStateHandler(x,x)+1B2↓p
.text:8050C6BE                                                                 ; PoInitializePrcb(x)+48↓p ...
.text:8050C6BE
.text:8050C6BE                         Dpc             = dword ptr  8
.text:8050C6BE                         Number          = byte ptr  0Ch
.text:8050C6BE
.text:8050C6BE 8B FF                                   mov     edi, edi
.text:8050C6C0 55                                      push    ebp
.text:8050C6C1 8B EC                                   mov     ebp, esp
.text:8050C6C3 8A 45 0C                                mov     al, [ebp+Number]
.text:8050C6C6 8B 4D 08                                mov     ecx, [ebp+Dpc]
.text:8050C6C9 04 20                                   add     al, 20h ; ' '
.text:8050C6CB 88 41 02                                mov     [ecx+2], al
.text:8050C6CE 5D                                      pop     ebp
.text:8050C6CF C2 08 00                                retn    8
.text:8050C6CF                         _KeSetTargetProcessorDpc@8 endp
.text:8050C6CF
.text:8050C6CF                         ; ---------------------------------------------------------------------------
.text:8050C6D2 90 90 90 90 90                          db 5 dup(90h)
.text:8050C6D7
.text:8050C6D7                         ; =============== S U B R O U T I N E =======================================
.text:8050C6D7
.text:8050C6D7                         ; Attributes: bp-based frame
.text:8050C6D7
.text:8050C6D7                         ; __stdcall KiIpiGenericCall(x, x)
.text:8050C6D7                         _KiIpiGenericCall@8 proc near           ; CODE XREF: KiRestoreFastSyscallReturnState()+36↓p
.text:8050C6D7                                                                 ; KiAdjustInterruptTime(x,x)+3F↓p ...
.text:8050C6D7
.text:8050C6D7                         arg_0           = dword ptr  8
.text:8050C6D7                         arg_4           = dword ptr  0Ch
.text:8050C6D7
.text:8050C6D7                         ; FUNCTION CHUNK AT .text:8051EA7C SIZE 0000000A BYTES
.text:8050C6D7
.text:8050C6D7 8B FF                                   mov     edi, edi
.text:8050C6D9 55                                      push    ebp
.text:8050C6DA 8B EC                                   mov     ebp, esp
.text:8050C6DC 53                                      push    ebx
.text:8050C6DD 56                                      push    esi
.text:8050C6DE 8B 35 7C 86 4D 80                       mov     esi, ds:__imp__KeGetCurrentIrql@0 ; KeGetCurrentIrql()
.text:8050C6E4 FF D6                                   call    esi ; KeGetCurrentIrql() ; KeGetCurrentIrql()
.text:8050C6E6 6A 02                                   push    2
.text:8050C6E8 59                                      pop     ecx             ; NewIrql
.text:8050C6E9 3A C1                                   cmp     al, cl
.text:8050C6EB 0F 83 8B 23 01 00                       jnb     loc_8051EA7C
.text:8050C6F1
.text:8050C6F1                         loc_8050C6F1:                           ; CODE XREF: KiIpiGenericCall(x,x)+123AA↓j
.text:8050C6F1 FF 15 74 86 4D 80                       call    ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x)
.text:8050C6F7 FF 75 0C                                push    [ebp+arg_4]
.text:8050C6FA 8A D8                                   mov     bl, al
.text:8050C6FC FF 55 08                                call    [ebp+arg_0]
.text:8050C6FF 8A CB                                   mov     cl, bl          ; NewIrql
.text:8050C701 8B F0                                   mov     esi, eax
.text:8050C703 FF 15 9C 86 4D 80                       call    ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x)
.text:8050C709 8B C6                                   mov     eax, esi
.text:8050C70B 5E                                      pop     esi
.text:8050C70C 5B                                      pop     ebx
.text:8050C70D 5D                                      pop     ebp
.text:8050C70E C2 08 00                                retn    8
.text:8050C70E                         _KiIpiGenericCall@8 endp
.text:8050C70E
posted @ 2022-04-11 00:38  倚剑问天  阅读(665)  评论(0编辑  收藏  举报