多核情况下添加新中断的方法

作者在 2010-08-14 22:34:26 发布以下内容
原创】多核机器下添加新中断的方法

【文章标题】: 多核情况下添加新中断的方法
【文章作者】: chimney

--------------------------------------------------------------------------------
【详细过程】
      中断向量表的修改应该都很熟悉了,combojiang大侠在他的rootkit hook系列文章里将的很详细了。但是combojiang文章
   中有关IDT的代码都是在单核机器中实现的,如果你有个双核的机子,你正好又学习了combojiang大大的文章,你就会发现出
   问题了。因为每个CPU 都有自己的中断向量表。在多核的机子上,如果你修改了CPU 1的中断向量表,如果应用程序不是运行
   在CPU 1上,而是在别的CPU上,这时候就会出现问题了。
      在多核的 CPU 上添加新中断,我想方法有两种。一种是让应用程序运行在修改中断向量表的那个CPUS上,另一个是将所有
   的CPU的中断向量表都修改,这样应用层就不用管自己运行在那个CPU上了,中断都不会导致系统的崩溃。
      让某个程序运行在某个CPU上,那就要设置程序的亲和性了,在应用层设置进程和线程的亲和性的函数是
   SetProcessAffinityMask/SetThreadAffinityMask。那么在内核呢?google了下,发现了diyhack 提到了个函数
   KeSetSystemAffinityThread。
  
      KeSetSystemAffinityThread是个内核导出的函数,但在DDK头文件中没有发现他的定义,帮助中也没有看见有文字介绍,
   于是就直奔WRK。在WRK中找到了这个函数。
  
   VOID
   KeSetSystemAffinityThread (
       __in KAFFINITY Affinity
       )
  
   /*++
   Routine Description:
       This function set the system affinity of the current thread
   Arguments:
       Affinity - Supplies the new of set of processors on which the thread can run.
   Return Value:
       None.
   --
*/
  
      KeSetSystemAffinityThread 设置当前线程的系统亲和性。在wrk和google的帮助下,实现了在多核下修改IDT比较稳定的
   方法。
  
   #include "ntddk.h"
   #include "string.h"
   #include "stdio.h"
   #define ADDINT                 0x22
  
   #define MAX_NUM_PROCESSER    8
  
   extern VOID KeSetSystemAffinityThread(KAFFINITY Affinity);    //函数声明下
  
   #pragma pack(1)
   typedef struct
   {
       unsigned short LowOffset;
       unsigned short selector;
       unsigned char unused_lo;
       unsigned char segment_type:4;          //0x0E is an interrupt gate
       unsigned char system_segment_flag:1;
       unsigned char DPL:2;           // descriptor privilege level
       unsigned char P:1;           // present
       unsigned short HiOffset;
   } IDTENTRY;
  
  
   typedef struct
   {
       unsigned short IDTLimit;
       union
       {
           unsigned long IDTbase;
       };
   } IDTINFO;
   #pragma pack(1)
  
   IDTENTRY OldIdtEntry[MAX_NUM_PROCESSER]={ 0 };
   IDTINFO idt_info[MAX_NUM_PROCESSER]={ 0 };
   ULONG orgcr0;
  
   void __declspec (naked) InterruptHandler()  
   {
       _asm iretd
      
   }
  
   VOID DisableWriteProtect(PULONG pOldAttr)
   {
     ULONG uAttr;
     _asm
     {
       push eax
       mov eax, cr0
       mov uAttr, eax
       and eax, 0FFFEFFFFh // CR0 16 BIT = 0
       mov cr0, eax
       pop eax
     };
     *pOldAttr = uAttr; //保存原有的 CRO 属性  
   }
  
   VOID EnableWriteProtect(ULONG uOldAttr )
   {
     _asm
     {
       push eax
       mov eax, uOldAttr //恢复原有 CR0 属性
       mov cr0, eax
       pop eax
     };  
   }
  
   VOID AddInterrupt(LONG dwIndex)
   {  
     IDTENTRY* idt_entries;  
     IDTINFO idt_infoTmp;
  
     __asm sidt idt_infoTmp;
  
     idt_info[dwIndex]=idt_infoTmp;
       idt_entries = (IDTENTRY*)idt_info[dwIndex].IDTbase;
  
     DbgPrint("idt_entries=%x",idt_entries);
  
       if ((idt_entries[ADDINT].LowOffset != 0) || (idt_entries[ADDINT].HiOffset != 0))
       return;
  
       DisableWriteProtect(&orgcr0);
       memcpy(&OldIdtEntry[dwIndex], &idt_entries[ADDINT], sizeof(IDTENTRY));
       idt_entries[ADDINT].LowOffset = (unsigned short)InterruptHandler;
       idt_entries[ADDINT].selector = 8;
       idt_entries[ADDINT].unused_lo = 0;
       idt_entries[ADDINT].segment_type = 0xE;
       idt_entries[ADDINT].system_segment_flag = 0;
       idt_entries[ADDINT].DPL = 3;
       idt_entries[ADDINT].P = 1;
       idt_entries[ADDINT].HiOffset = (unsigned short)((unsigned int) InterruptHandler>>16);
       EnableWriteProtect(orgcr0);
  
     return;
   }
  
   void RemoveInterrupt(LONG dwIndex)
   {
       IDTENTRY* idt_entries;
       idt_entries = (IDTENTRY*)idt_info[dwIndex].IDTbase;
  
       DbgPrint("idt_entries=%x",idt_entries);
    
       DisableWriteProtect(&orgcr0);
        memcpy(&idt_entries[ADDINT], &OldIdtEntry[dwIndex], sizeof(IDTENTRY));
       EnableWriteProtect(orgcr0);
   }
  
   void DriverUnload (IN PDRIVER_OBJECT pDriverObject)
   {
           KAFFINITY      ActiveProcessors, CurrentAffinity;
           LONG   dwTmp=0;
           ActiveProcessors=KeQueryActiveProcessors();
  
     DbgPrint("KeActiveProcessors=%d",ActiveProcessors);
  
      for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1)
       {
                   if (ActiveProcessors & CurrentAffinity)
        {
                       ActiveProcessors &= ~CurrentAffinity;
                       KeSetSystemAffinityThread(CurrentAffinity);
           RemoveInterrupt(dwTmp);  
           dwTmp++;
       }
      }
   }
  
   NTSTATUS
   DriverEntry(
     IN PDRIVER_OBJECT     DriverObject,
     IN PUNICODE_STRING     RegistryPath
     )
   {
     NTSTATUS       status = STATUS_SUCCESS;
     KAFFINITY      ActiveProcessors, CurrentAffinity;
     LONG         dwTmp=0;
     ActiveProcessors=KeQueryActiveProcessors();
     DbgPrint("KeActiveProcessors=%d",ActiveProcessors);
           for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1)
     {
                  if (ActiveProcessors & CurrentAffinity)
        {
                     ActiveProcessors &= ~CurrentAffinity;
                     KeSetSystemAffinityThread(CurrentAffinity);
           AddInterrupt(dwTmp);
           dwTmp++;
       }
     }  
     DriverObject->DriverUnload = DriverUnload;
     return status;
   }
  
--------------------------------------------------------------------------------

   如有错误之处,还请大家指出!酷睿双核 windows xp sp2 下测试通过
  
--------------------------------------------------------------------------------
 
技术 | 阅读 2371 次
文章评论,共0条
游客请输入验证码
浏览1970460次