windowssky 阅读(1482) 评论(0)

杀毒软件的实时监控分为两个部分
  一:Notify部分
  二:Attach到文件系统部分

一:Notify对与杀毒软件致关重要(有些流氓软件也用的),主要用到的是
   PsSetLoadImageNotifyRoutine和
   PsSetCreateProcessNotifyRoutine这两个函数

1 PsSetLoadImageNotifyRoutine(
  IN PLOAD_IMAGE_NOTIFY_ROUTINE  NotifyRoutine
  );
  通过字面意思大家也知道,就是文件被加载的时侯会调用这个NotifyRoutine;最简单的是一个Exe在Run的过程中,PE加载器检查它所depend的dll,然后由PE加载器LoadLibaray这些dll,此时NotifyRoutine就被调用起来了。
(PS:这个NotifyRoutine就是一个callback)

part1: 2k下的分析 
kd> u PsSetLoadImageNotifyRoutine L10
nt!PsSetLoadImageNotifyRoutine:
804e31d4 b89a0000c0       mov     eax,0xc000009a
804e31d9 33c9             xor     ecx,ecx
804e31db ba20324880       mov     edx,0x80483220
804e31e0 833a00           cmp     dword ptr [edx],0x0
804e31e3 740e             jz      nt!PsSetLoadImageNotifyRoutine+0x1f (804e31f3)
804e31e5 83c204           add     edx,0x4
804e31e8 41               inc     ecx
804e31e9 81fa40324880     cmp     edx,0x80483240
804e31ef 72ef             jb      nt!PsSetLoadImageNotifyRoutine+0xc (804e31e0)
804e31f1 eb1a             jmp     nt!PsSetLoadImageNotifyRoutine+0x39 (804e320d)
804e31f3 8b442404         mov     eax,[esp+0x4]
804e31f7 ff0504324880 inc dword ptr [nt!PspLoadImageNotifyRoutineCount (80483204
)]
804e31fd 89048d20324880 mov [nt!PspLoadImageNotifyRoutine (80483220)+ecx*4],eax
804e3204 33c0             xor     eax,eax
804e3206 c6051031488001 mov byte ptr [nt!PsImageNotifyEnabled (80483110)],0x1
804e320d c20400           ret     0x4

对应c代码:
ULONG i;
NTSTATUS Status;
Status = STATUS_INSUFFICIENT_RESOURCES;
for (i=0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++) 
{
   if (PspLoadImageNotifyRoutine[i] == NULL)
   {
       PspLoadImageNotifyRoutine[i] = NotifyRoutine;
       PspLoadImageNotifyRoutineCount+= 1;
       Status = STATUS_SUCCESS;
       PsImageNotifyEnable= TRUE;
       break;
   }
}

我们如果不想让某个NotifyRoutine监控,就把它在PspLoadImageNotifyRoutine数组中对应项清空,可是PspLoadImageNotifyRoutine并没有导出,我们不能直接调用,有什么方法呢?

1)  我们自己写个MyNotifyRoutine.
    VOID MyNotifyRoutine(
    IN PUNICODE_STRING  FullImageName,
    IN HANDLE  ProcessId, 
    IN PIMAGE_INFO  ImageInfo)
{
    return;
}

2) PsSetLoadImageNotifyRoutine(MyNotifyRoutine);

3) 直接在PsSetLoadImageNotifyRoutine函数里找有效地址,然后访问这个地址,看有没有MyNotifyRoutine的地址,没有的话再找下一个;

4) 直到找到为止,那么此时这个有效地址就是PspLoadImageNotifyRoutine的地址了

5) 遍历PspLoadImageNotifyRoutine数组中的地址,检查这些地址是否落在某个驱动程序的地址范围,如果是的话,清了这一项,现在再LoadLibrary这个驱动程序就不会收到任何通知了。
如果你闲麻烦就直接把PspLoadImageNotifyRoutine所有项都清理掉。


part2: xp/2003下的分析
lkd> u  PsSetLoadImageNotifyRoutine  L25
nt!PsSetLoadImageNotifyRoutine:
8062d4f7 8bff             mov     edi,edi
8062d4f9 55               push    ebp
8062d4fa 8bec             mov     ebp,esp
8062d4fc 53               push    ebx
8062d4fd 57               push    edi
8062d4fe 33ff             xor     edi,edi
8062d500 57               push    edi
8062d501 ff7508           push    dword ptr [ebp+0x8]
8062d504 e833790100       call    nt!ExAllocateCallBack (80644e3c)
8062d509 8bd8             mov     ebx,eax
8062d50b 3bdf             cmp     ebx,edi
8062d50d 7507             jnz     nt!PsSetLoadImageNotifyRoutine+0x1f (8062d516)
8062d50f b89a0000c0       mov     eax,0xc000009a
8062d514 eb2a             jmp     nt!PsSetLoadImageNotifyRoutine+0x49 (8062d540)
8062d516 56               push    esi
8062d517 be001d5680       mov     esi,0x80561d00
8062d51c 6a00             push    0x0
8062d51e 53               push    ebx
8062d51f 56               push    esi
8062d520 e84e790100       call    nt!ExCompareExchangeCallBack (80644e73)
8062d525 84c0             test    al,al
8062d527 751d             jnz     nt!PsSetLoadImageNotifyRoutine+0x4f (8062d546)
8062d529 83c704           add     edi,0x4
8062d52c 83c604           add     esi,0x4
8062d52f 83ff20           cmp     edi,0x20
8062d532 72e8             jb      nt!PsSetLoadImageNotifyRoutine+0x25 (8062d51c)
8062d534 53               push    ebx
8062d535 e89134f4ff       call    nt!RtlpSysVolFree (805709cb)
8062d53a b89a0000c0       mov     eax,0xc000009a
8062d53f 5e               pop     esi
8062d540 5f               pop     edi
8062d541 5b               pop     ebx
8062d542 5d               pop     ebp
8062d543 c20400           ret     0x4


对应c代码:
     ULONG i;
     PEX_CALLBACK_ROUTINE_BLOCK CallBack;

     CallBack = ExAllocateCallBack((PEX_CALLBACK_FUNCTION) NotifyRoutine, NULL);
     if (CallBack == NULL) {
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     for (i = 0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++) {

         if (ExCompareExchangeCallBack(&PspLoadImageNotifyRoutine[i],
                                        CallBack,
                                        NULL)) {
             InterlockedIncrement ((PLONG)&PspLoadImageNotifyRoutineCount);
             PsImageNotifyEnable = TRUE;
             return STATUS_SUCCESS;
         }
     }
     ExFreeCallBack(CallBack);

    return STATUS_INSUFFICIENT_RESOURCES;


 
2 PsSetCreateProcessNotifyRoutine

二 Attach到文件系统部分


发表评论
切换编辑模式