日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

简单Hook SYSENTER

發布時間:2024/4/11 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单Hook SYSENTER 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

其實所有的HOOK,都基本是一樣道理。就是勾住你的目標函數,實現你自己的功能。只要你掌握了,HOOK的原理。剩下的就是尋找目標函數了。

?????今天回憶一下 HOOK SYSENTER,目的當然還是繼續充實自己的BLOG,繼續灌水。

一:認識SYSENTER

???SYSENTER是一個東西?大家都知道調用門,陷阱門,任務門(這里沒有照片!_!).。通過他們我們可以從R3到達R0。簡單的說SYSENTER就是他們的替代品。SYSENTER是一個入的

過程,SYSEXIT是他的反過程。

我們以OpenProcess為例,看看他是怎么從R3-R0

kernel32!OpenProcess -> ntdll!ZwOpenProcess -> ntdll!KiFastSystemCall -> sysenter -> nt!KiFastCallEntry -> nt!NtOpenProcess -> nt!KiFastCallEntry> nt!

KiServiceExit -> sysexit -> ntdll!KiFastSystemCallRet -> kernel32!OpenProcess

現在來看看SYSENTER是怎么樣處理的。

R3-R0需要把相關的工作交給R0層的。包括:設置CS,IP,SS,SP。SYSENTER有三個特殊的寄存器(MSR)來幫助我們完成。

SYSENTER_CS_MSR

SYSENTER_ESP_MSR

SYSENTER_EIP_MSR

他們的地址分別是:0x174,0x175,0x176。我們可以通過指令rdmsr/wrmsr。來讀寫這三個寄存器。相關代碼如下:

_asm
{


mov ecx,0x176
????rdmsr
????mov OldKiFastCallEntry,eax

}

我們來看看SYSENTER的工作流程。

1. 裝載SYSENTER_CS_MSR 到CS 寄存器,設置目標代碼段
2. 裝載SYSENTER_EIP_MSR到 EIP寄存器,設置目標指令
3. SYSENTER_CS_MSR+8 裝載到SS寄存器 ,設置棧段
4. 裝載SYSENTER_ESP_MSR 到ESP寄存器,設置棧幀
5. 切換RING0.
6. 清除 EFLAGS的 VM標志
7. 執行RING0例程

SYSEXIT的工作流程

1. SYSENTER_CS_MSR+16裝載到 CS寄存器
2. 將EDX的值送入EIP
3. SYSENTER_CS_MSR+24 裝載到SS寄存器
4. 將ECX的值送入ESP
5. 切換回RING3
6. 執行EIP處的RING3指令

這樣就完成了R3-RO-R3的過程。


二:相關代碼

//
// Hook SysEnter.cpp文件


extern "C"
{
#include <ntddk.h>
}


VOID UnloadDriver(PDRIVER_OBJECT pDriverObj);


ULONG OldKiFastCallEntry;


VOID NewKiFastCallEntry()
{
DbgPrint("一個系統調用...\n");
_asm
{
???jmp DWORD PTR[OldKiFastCallEntry]

}
}

// 驅動程序加載時調用DriverEntry例程
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
pDriverObj->DriverUnload = UnloadDriver;
//
_asm
{
???mov ecx,0x176
???rdmsr
???mov OldKiFastCallEntry,eax
???mov eax,NewKiFastCallEntry
???wrmsr
}

// 請視情況返回DriverEntry例程執行結果
return STATUS_SUCCESS;
}


VOID UnloadDriver(PDRIVER_OBJECT pDriverObj)
{
_asm
{
???mov ecx,0x176
???xor edx,edx
???mov eax,OldKiFastCallEntry
???wrmsr

}

}

=============================================================================================

呵呵,今天這篇內容少,比較簡單。

SYSENETER是一條匯編指令,它是在Pentium? II 處理器及以上處理器中提供的,是快速系統調用的一部分。SYSENTER/SYSEXIT這對指令專門用于實現快速調用。在這之前是采用INT 0x2E來實現的。INT 0x2E在系統調用的時候,需要進行棧切換的工作。由于Interrupt/Exception Handler的調用都是通過 call/trap/task這一類的gate來實現的,這種方式會進行棧切換,并且系統棧的地址等信息由TSS提供。這種方式可能會引起多次內存訪問 (來獲取這些切換信息),因此,從PentiumII開始,IA-32引入了新指令:SYSENTER/SYSEXIT。 有了這兩條指令,
從用戶級到特權級的堆棧以及指令指針的轉換,可以通過這一條指令來實現,并且,需要切換到的新堆棧的地址,以及相應過程的第一條指令的位置,都有一組特殊寄存器來實現,這類特殊寄存器在IA-32中稱為MSR(Model Specific Register)。這里牽涉到3個特殊寄存器:?
SYSENTER_CS_MSR: New code segment selector? ?0x174?
SYSENTER_ESP_MSR: New Stack Pointer? ?? ?? ?? ?? ? 0x175?
SYSENTER_EIP_MSR: New Instruction Pointer? ?? ???0x176?
這里標出的3個16進制數分別對應這3個寄存器的地址,該地址用于Kernel debug時,通過rdmsr/wrmsr指令來讀/寫這3個寄存器。步驟如下:

1. 裝載SYSENTER_CS_MSR 到CS 寄存器,設置目標代碼段
2. 裝載SYSENTER_EIP_MSR到 EIP寄存器,設置目標指令?
3. SYSENTER_CS_MSR+8 裝載到SS寄存器 ,設置棧段
4. 裝載SYSENTER_ESP_MSR 到ESP寄存器,設置棧幀?
5. 切換RING0.?
6. 清除 EFLAGS的 VM標志?
7. 執行RING0例程?


1. SYSENTER_CS_MSR+16裝載到 CS寄存器?
2. 將EDX的值送入EIP?
3. SYSENTER_CS_MSR+24 裝載到SS寄存器?
4. 將ECX的值送入ESP?
5. 切換回RING3?
6. 執行EIP處的RING3指令?

我們在windbg中可以看看這個三個寄存器的情況,這個是我機器里的情況。
lkd> rdmsr 176
msr[176] = 00000000`8053dad0
lkd> rdmsr 175
msr[175] = 00000000`ba4e0000
lkd> rdmsr 174
msr[174] = 00000000`00000008

可以看到,我的機器里面當前SYSENTER_EIP_MSR,SYSENTER_ESP_MSR,SYSENTER_CS_MSR這三個寄存器的值。

我們在微軟公開的內核WRK中發現關于這三個寄存器的設置,其中SYSENTER_EIP_MSR設置的值是KiFastCallEntry。
代碼如下:
VOID
KiLoadFastSyscallMachineSpecificRegisters(
? ? IN PLONG Context
? ? )

/*++

Routine Description:

? ? Load MSRs used to support Fast Syscall/return.??This routine is
? ? run on all processors.

Arguments:

? ? None.

Return Value:

? ? None.

--*/

{
? ? PKPRCB Prcb;

? ? UNREFERENCED_PARAMETER (Context);

? ? if (KiFastSystemCallIsIA32) {

? ?? ???Prcb = KeGetCurrentPrcb();

? ?? ???//
? ?? ???// Use Intel defined way of doing this.
? ?? ???//

? ?? ???WRMSR(MSR_SYSENTER_CS,??KGDT_R0_CODE);
? ?? ???WRMSR(MSR_SYSENTER_EIP, (ULONGLONG)(ULONG)KiFastCallEntry);
? ?? ???WRMSR(MSR_SYSENTER_ESP, (ULONGLONG)(ULONG)Prcb->DpcStack);

? ? }
}

看看我電腦的情況如下:
lkd> rdmsr 176
msr[176] = 00000000`8053dad0
lkd> u 8053dad0
nt!KiFastCallEntry:
8053dad0 b923000000? ?? ?mov? ???ecx,23h
8053dad5 6a30? ?? ?? ?? ?push? ? 30h
8053dad7 0fa1? ?? ?? ?? ?pop? ???fs
8053dad9 8ed9? ?? ?? ?? ?mov? ???ds,cx
8053dadb 8ec1? ?? ?? ?? ?mov? ???es,cx
8053dadd 8b0d40f0dfff? ? mov? ???ecx,dword ptr ds:[0FFDFF040h]
8053dae3 8b6104? ?? ?? ? mov? ???esp,dword ptr [ecx+4]
8053dae6 6a23? ?? ?? ?? ?push? ? 23h

下面是rootkit.com上的一個例子,這個例子有點不厚道,在你卸載的時候會bsod.我簡單修改了下,貼代碼如下:
#include "ntddk.h"

ULONG d_origKiFastCallEntry; // Original value of ntoskrnl!KiFastCallEntry

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
? ? ? ?? ?_asm
? ? ? ?? ?{
? ? ? ?? ?? ?? ?mov ecx, 0x176
? ? ? ? ? ? ? ?? ???xor edx,edx
? ? ? ? ? ? ? ?? ???mov eax, d_origKiFastCallEntry? ???// Hook function address
? ? ? ?? ???? ? ? ? wrmsr? ?? ?? ?? ?? ?? ?? ?? ?// Write to the IA32_SYSENTER_EIP register
? ? ? ?? ???}
}

// Hook function
__declspec(naked) MyKiFastCallEntry()
{
? ? ? ? __asm {
? ? ? ? ? ? ? ? jmp [d_origKiFastCallEntry]
? ? ? ? }
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
? ? ? ? theDriverObject->DriverUnload??= OnUnload;?

? ? ? ? __asm {
? ?? ?? ?? ?mov ecx, 0x176
? ? ? ? ? ? ? ?? ???rdmsr? ?? ?? ?? ?? ???// read the value of the IA32_SYSENTER_EIP register
? ? ? ? ? ? ? ?? ???mov d_origKiFastCallEntry, eax
? ? ? ? ? ? ? ?? ???mov eax, MyKiFastCallEntry? ???// Hook function address
? ? ? ?? ???? ? ? ? wrmsr? ?? ?? ?? ?? ?? ?? ?? ?// Write to the IA32_SYSENTER_EIP register
? ? ? ? }

? ? ? ? return STATUS_SUCCESS;
}

注意一點,大家用windbg的時候,配置symbol path,如圖:


后面貼上一篇墮落天才寫的文章鏈接:http://bbs.pediy.com/showthread.php?t=42705,
他inline hook 了KiFastCallEntry,采用detour方式,寫得很不錯。

總結

以上是生活随笔為你收集整理的简单Hook SYSENTER的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。