久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

《Undocumented Windows 2000 Secrets》翻譯 --- 第五章(2)

瀏覽:139日期:2023-08-27 18:46:02

第五章 監控 Native API 調用

翻譯: Kendiv( fcczj@263.net )

更新: Thursday, February 24, 2005

聲明:轉載請注明出處,并保證文章的完整性,本人保留譯文的所有權利。

匯編語言的救援行動

通用解決方案的主要障礙是 C 語言的典型參數傳遞機制。就像你知道的, C 通常在調用函數的入口點之前會將函數參數傳遞到 CPU 堆棧中。根據函數需要的參數數量,參數堆棧的大小將有很大的差別。 Windows 2000 的 248 個 Native API 函數需要的參數堆棧的大小位于 0 到 68 字節。這使得編寫一個唯一的 hook 函數變得非常困難。微軟的 Visual C/C++ 提供了一個完整的匯編( ASM )編譯器,該編譯器可處理復雜度適中的代碼。具有諷刺意味的是,在我的解決方案中所使用的匯編語言的優點正是通常被認為是其最大缺點的特性:匯編語言不提供嚴格的類型檢查機制。只要字節數正確就一切 OK 了,你可以在任何寄存器中存儲幾乎所有的東西,而且你可以調用任何地址,而不需要關心當前堆棧的內容是什么。盡管這在應用程序開發中是一種很危險的特性,但這確實最容易獲取的:在匯編語言中,很容易以不同的參數堆棧調用同一個普通的入口點,稍后將介紹的 API hook Dispatcher 將采用這一特性。

通過將匯編代碼放入以關鍵字 __asm 標記的分隔塊中就可調用 Microsoft Visual C/C++ 嵌入式匯編程序。嵌入式匯編缺少宏定義以及 Microsoft's big Macro Assembler ( MASM )的評估能力,但這些并沒有嚴重的限制它的可用性。嵌入式匯編的最佳特性是:它可以訪問所有的 C 變量和類型定義,因此很容易混合 C 和 ASM 代碼。不過,當在 C 函數中包含有 ASM 代碼時,就必須遵守 C 編譯器的某些重要的基本約定,以避免和 C 代碼的沖突:

l C 函數調用者假定 CPU 寄存器 EBP 、 EBX 、 ESI 和 EDI 已經被保存了。

l 如果在單一函數中,將 ASM 代碼和 C 代碼混合在一起,則需要小心的保存 C 代碼可能保存在寄存器中的中間值。總是保存和恢復在 __asm 語句中使用的所有寄存器。

l 8 位的函數結果( CHAR , BYTE 等)由寄存器 AL 返回。

l 16 位的函數結果( SHORT , Word 等)由寄存器 AX 返回。

l 32 位的函數結果( INT , LONG , DWORD 等)由寄存器 EAX 返回。

l 64 位的函數結果( __int64 , LONGLONG , DWORDLONG 等)由寄存器對 EDX : EAX 返回。寄存器 EAX 包含 0 到 31 位, EDX 保存 32 到 63 位。

l 有確定參數的函數通常按照 __stdcall 約定進行參數的傳遞。從調用者的角度來看,這意味著在函數調用之前參數必須以相反的順序壓入堆棧中,被調用的函數負責在返回前從堆棧中移除它們。從被調用的函數的角度來看,這意味著堆棧指針 ESP 指向調用者的返回地址,該地址緊隨最后一個參數(按照原始順序)。( 譯注 :這意味著,最先被壓入堆棧的是函數的返回地址 )參數的原始順序被保留下來,因為堆棧是向下增長的,從高位線性地址到低位線性地址。因此,調用者壓入堆棧的最后一個參數(即,參數 #1 )將是由 ESP 指向的數組中的第一個參數。

l 某些有確定參數的 API 函數,如著名的 C 運行時庫函數(由 ntdll.dll 和 ntoskrnl.exe 導出),通常使用 __cdecl 調用約定,該約定采用與 __stdcall 相同的參數順序,但強制調用者清理參數堆棧。

l 由 __fastcall 修飾的函數聲明,則希望前兩個參數位于 CPU 寄存器 ECX 和 EDX 中。如果還需要更多的參數,它們將按照相反的順序傳入堆棧,最后由被調用者清理堆棧,這和 __stdcall 相同。

this is the function's prologue

push ebp ; save current value ebp

mov ebp, esp ; set stack frame base address

sub esp, SizeOfLocalStorage ; create local storage area

this is the function's epilogue

mov esp, ebp ; destroy local storage area

pop ebp ; restore value of ebp

ret

列表 5-2. 堆棧幀,序言和尾聲

l 很多 C 編譯器在進入函數后,會立即針對函數參數構建一個堆棧幀,這需要使用 CPU 的基地址指針寄存器 EBP 。 列表 5-2 給出了此代碼,這通常被稱為函數的“序言”和“尾聲”。有些編譯器采用更簡潔的 i386 的 ENTER 和 LEAVE 操作符,在“序言被執行后,堆棧將如 5-3 所示。 EBP 寄存器作為一分割點將函數的參數堆棧劃分為兩部分:( 1 )局部存儲區域,該區域中包含所有定義于函數范圍內的局部變量( 2 )調用者堆棧,其中保存有 EBP 的備份和返回地址。注意,微軟的 Visual C/C++ 的最新版中默認不使用堆棧幀。替代的是,代碼通過 ESP 寄存器訪問堆棧中的值,不過這需要指定變量相對于當前棧頂的偏移量。這種類型的代碼非常難以閱讀,因為每個 PUSH 和 POP 指令都會影響 ESP 的值和所有參數的偏移量。在此種情況下不再需要 EBP ,它將作為一個附加的通用寄存器。

l 在訪問 C 變量時必須非常小心。經常出現在嵌入式 ASM 中的 bug 是:你將一個變量的地址而不是它的值加載到了寄存器中。使用 ptr 和 offset 地址操作符存在潛在的二義性。例如,指令: mov eax , dword ptr SomeVariable 將加載 DWORD 類型的 SomeVariable 變量的值到 EAX 寄存器,但是, mov eax , offset SomeVariable 將加載它的線性地址到 EAX 中。

圖 5-3. 堆棧幀的典型布局

Hook 分派程序(Hook Dispatcher)

這部分的代碼將較難理解。編寫它們花費了我很多時間,而且在這一過程中我還欣賞了無數的藍屏。我最初的方法是提供一個完全用匯編語言編寫的模塊。不過,這個方法在鏈接階時帶來了很大的麻煩,因此,我改為在 C 模塊中使用嵌入式匯編。為了避免創建另一個內核模式的驅動程序,我決定將 hook 代碼整合到 Spy 設備驅動程序中。還記得在 4-2 底部列出的形如 SPY_IO_HOOK_* 的 IOCTL 函數嗎?現在我們將和它們來一次親密接觸。后面的示列代碼來自 w2k_spy.c 和 w2k_spy.h ,可以在隨書 CD 的 srcw2k_spy 中找到它們。

列表 5-3 的核心部分是 Native API Hook 機制的實現代碼。該列表開始處是一對常量和結構體定義,后面的 aSpyHooks[] 需要它們。緊隨這個數組的是一個宏,該宏實際上是三行嵌入式匯編語句,這三行匯編語句非常重要,稍后我將介紹它們。 列表 5-3 的最后一部分用來建立 SpyHookInitializeEx() 函數。猛地一看,這個函數的功能似乎很難理解。該函數組合了一下兩個功能:

1. SpyHookInitializeEx() 的表面部分包括一段用來設置 aSpyHooks[] 數組的 C 代碼,這部分代碼用 Spy 設備的 Hook 函數指針以及與之相關聯的字符串格式協議來初始化 aSpyHooks[] 數組。 SpyHookInitializeEx() 函數可被分割為兩部分:第一部分到第一個 __asm 語句后的 jmp SpyHook9 指令。第二部分顯然是從 ASM 標簽 ----SpyHook9 開始,該部分位于第二個 __asm 語句塊的最后。

2. SpyHookInitializeEx() 的內部部分包括位于兩塊 C 代碼段之間的所有代碼。這部分在一開始大量使用了 SpyHook 宏,緊隨其后的是一大塊復雜的匯編代碼。可能你已經猜到了,這些匯編代碼就是前面提到的通用 Hook 例程。

#define SPY_CALLS 0x00000100 // max api call nesting level

#define SDT_SYMBOLS_NT4 0xD3

#define SDT_SYMBOLS_NT5 0xF8

#define SDT_SYMBOLS_MAX SDT_SYMBOLS_NT5

// -----------------------------------------------------------------

typedef struct _SPY_HOOK_ENTRY

{

NTPROC Handler;

PBYTE pbFormat;

}

SPY_HOOK_ENTRY, *PSPY_HOOK_ENTRY, **PPSPY_HOOK_ENTRY;

#define SPY_HOOK_ENTRY_ sizeof (SPY_HOOK_ENTRY)

// -----------------------------------------------------------------

typedef struct _SPY_CALL

{

BOOL fInUse; // set if used entry

HANDLE hThread; // id of calling thread

PSPY_HOOK_ENTRY pshe; // associated hook entry

PVOID pCaller; // caller's return address

DWORD dParameters; // number of parameters

DWORD adParameters [1+256]; // result and parameters

}

SPY_CALL, *PSPY_CALL, **PPSPY_CALL;

#define SPY_CALL_ sizeof (SPY_CALL)

// -----------------------------------------------------------------

SPY_HOOK_ENTRY aSpyHooks [SDT_SYMBOLS_MAX];

// -----------------------------------------------------------------

// The SpyHook macro defines a hook entry point in inline assembly

// language. The common entry point SpyHook2 is entered by a call

// instruction, allowing the hook to be identifIEd by its return

// address on the stack. The call is executed through a register to

// remove any degrees of freedom from the encoding of the call.

#define SpyHook

__asm push eax

__asm mov eax, offset SpyHook2

__asm call eax

// -----------------------------------------------------------------

// The SpyHookInitializeEx() function initializes the aSpyHooks[]

// array with the hook entry points and format strings. It also

// hosts the hook entry points and the hook dispatcher.

// -----------------------------------------------------------------

// The SpyHookInitializeEx() function initializes the aSpyHooks[]

// array with the hook entry points and format strings. It also

// hosts the hook entry points and the hook dispatcher.

void SpyHookInitializeEx (PPBYTE ppbSymbols,

PPBYTE ppbFormats)

{

DWORD dHooks1, dHooks2, i, j, n;

__asm

{

jmp SpyHook9

ALIGN 8

SpyHook1: ; start of hook entry point section

}

// the number of entry points defined in this section

// must be equal to SDT_SYMBOLS_MAX (i.e. 0xF8)

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //08

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //10

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //18

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //20

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //28

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //30

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //38

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //40

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //48

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //50

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //58

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //60

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //68

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //70

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //78

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //80

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //88

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //90

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //98

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A8

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B8

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C8

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D8

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E8

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F0

SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F8

__asm

{

SpyHook2: ; end of hook entry point section

pop eax ; get stub return address

pushfd

push ebx

push ecx

push edx

push ebp

push esi

push edi

sub eax, offset SpyHook1 ; compute entry point index

mov ecx, SDT_SYMBOLS_MAX

mul ecx

mov ecx, offset SpyHook2

sub ecx, offset SpyHook1

div ecx

dec eax

mov ecx, gfSpyHookPause ; test pause flag

add ecx, -1

sbb ecx, ecx

not ecx

lea edx, [aSpyHooks + eax * SIZE SPY_HOOK_ENTRY]

test ecx, [edx.pbFormat] ; format string == NULL?

jz SpyHook5

push eax

push edx

call PsGetCurrentThreadId ; get thread id

mov ebx, eax

pop edx

pop eax

cmp ebx, ghSpyHookThread ; ignore hook installer

jz SpyHook5

mov edi, gpDeviceContext

lea edi, [edi.SpyCalls] ; get call context array

mov esi, SPY_CALLS ; get number of entries

SpyHook3:

mov ecx, 1 ; set in-use flag

xchg ecx, [edi.fInUse]

jecxz SpyHook4 ; unused entry found

add edi, SIZE SPY_CALL ; try next entry

dec esi

jnz SpyHook3

mov edi, gpDeviceContext

inc [edi.dMisses] ; count misses

jmp SpyHook5 ; array overflow

SpyHook4:

mov esi, gpDeviceContext

inc [esi.dLevel] ; set nesting level

mov [edi.hThread], ebx ; save thread id

mov [edi.pshe], edx ; save PSPY_HOOK_ENTRY

mov ecx, offset SpyHook6 ; set new return address

xchg ecx, [esp+20h]

mov [edi.pCaller], ecx ; save old return address

mov ecx, KeServiceDescriptorTable

mov ecx, [ecx].ntoskrnl.ArgumentTable

movzx ecx, byte ptr [ecx+eax] ; get argument stack size

shr ecx, 2

inc ecx ; add 1 for result slot

mov [edi.dParameters], ecx ; save number of parameters

lea edi, [edi.adParameters]

xor eax, eax ; initialize result slot

stosd

dec ecx

jz SpyHook5 ; no arguments

lea esi, [esp+24h] ; save argument stack

rep movsd

SpyHook5:

mov eax, [edx.Handler] ; get original handler

pop edi

pop esi

pop ebp

pop edx

pop ecx

pop ebx

popfd

xchg eax, [esp] ; restore eax and...

ret ; ...jump to handler

SpyHook6:

push eax

pushfd

push ebx

push ecx

push edx

push ebp

push esi

push edi

push eax

call PsGetCurrentThreadId ; get thread id

mov ebx, eax

pop eax

mov edi, gpDeviceContext

lea edi, [edi.SpyCalls] ; get call context array

mov esi, SPY_CALLS ; get number of entries

SpyHook7:

cmp ebx, [edi.hThread] ; find matching thread id

jz SpyHook8

add edi, SIZE SPY_CALL ; try next entry

dec esi

jnz SpyHook7

push ebx ; entry not found ?!?

call KeBugCheck

SpyHook8:

push edi ; save SPY_CALL pointer

mov [edi.adParameters], eax ; store NTSTATUS

push edi

call SpyHookProtocol

pop edi ; restore SPY_CALL pointer

mov eax, [edi.pCaller]

mov [edi.hThread], 0 ; clear thread id

mov esi, gpDeviceContext

dec [esi.dLevel] ; reset nesting level

dec [edi.fInUse] ; clear in-use flag

pop edi

pop esi

pop ebp

pop edx

pop ecx

pop ebx

popfd

xchg eax, [esp] ; restore eax and...

ret ; ...return to caller

SpyHook9:

mov dHooks1, offset SpyHook1

mov dHooks2, offset SpyHook2

}

n = (dHooks2 - dHooks1) / SDT_SYMBOLS_MAX;

for (i = j = 0; i < SDT_SYMBOLS_MAX; i++, dHooks1 += n)

{

if ((ppbSymbols != NULL) && (ppbFormats != NULL) &&

(ppbSymbols [j] != NULL))

{

aSpyHooks [i].Handler = (NTPROC) dHooks1;

aSpyHooks [i].pbFormat =

SpySearchFormat (ppbSymbols [j++], ppbFormats);

}

else

{

aSpyHooks [i].Handler = NULL;

aSpyHooks [i].pbFormat = NULL;

}

}

return;

}

列表 5-3. Hook Dispatcher 的實現方式

SpyHook 宏實際是什么呢?在 SpyHookInitializeEx() 函數中,這個宏被重復了多大 248 ( 0xF8 )次,這正好是 Windows 2000 Native API 函數的數目。在 列表 5-3 的頂部,這個數目被定義為 SDT_SYMBOLS_MAX 常量,該宏可以使 SDT_SYMBOLS_NT4 或 SDT_SYMBOLS_NT5 。因為我打算支持 Windows NT 4.0 。回到 SpyHook 宏上來:該宏調用的匯編語句在 列表 5-4 中給出了。每個 SpyHook 都產生同樣的三行代碼:

1. 第一行,將當前 EAX 寄存器的內容保存到堆棧中。

2. 第二行,將 SpyHook2 的線性地址保存到 EAX 中。

3. 第三行,調用 EAX 中的地址(即: call eax )。

你可能會驚訝:當這個 CALL 返回時會發生什么。接下來的一組 SpyHook 代碼會被調用嗎?不 ---- 這個 CALL 并不支持返回,因為在到達 SpyHook2 之后,這個 CALL 的返回地址就會被立即從堆棧中移出, 列表 5-4 最后的 POP EAX 指令可以證明這一點。這種看上去毫無疑義的代碼在古老的匯編程序設計時代曾被廣泛的討論的一種技巧,就像今天我們討論面向對象的程序設計一樣。當 ASM 老大級人物需要構建一個數組,而此數組的每一項都有類似的進入點,但卻需要被分派到獨立的函數時,就會采用這種技巧。對所有進入點使用幾乎相同的代碼可以保證它們之間有相等的間隔,因此客戶端就可以很容易的通過 CALL 指令的返回地址計算出進入點的在數組中的索引值,數組的基地址和大小以及數組中共有多少項

SpyHook1:

push eax

mov eax, offset SpyHook2

call eax

push eax

mov eax, offset SpyHook2

call eax

244 boring repetitions cimitted

push eax

mov eax, offset SpyHook2

call eax

push eax

mov eax, offset SpyHook2

call eax

SpyHook2:

pop eax

列表 5-4. 擴充 SpyHook 宏調用

例如, 列表 5-4 中第一個 CALL EAX 指令的返回地址是其下一個語句的地址。通常,第 N 個 CALL EAX 指令的返回地址是第 N+1 個語句的地址,但最后一個除外,最后這個將返回 SpyHook2 。因此,從 0 開始的所有進入點的索引可以由 5-4 中的通用公式計算出來。這三條規則中的潛在規則是: SDT_SYMBOLS_MAX 進入點符合內存塊 SpyHook2---SpyHook1 。那么有多少個進入點符合 ReturnAddress---SpyHook1 呢?因為計算結果是位于 0 到 SDT_SYMBOLS_MAX 中的某一個數值,所以,肯定要使用該數值來獲取一個從 0 開始的索引。

圖 5-4. 通過 Hook 進入點的返回地址確定一個 Hook 進入點

圖 5-4 所示公式的實現方式可以在 列表 5-3 中找到,在匯編標簽 SpyHook2 的右邊。在 5-5 的左下角也給出了該公式的實現代碼,它展示了 Hook Dispatcher 機制的基本原理。注意, i386 的 mul 指令會在 EDX:EAX 寄存器中產生一個 64 位的結果值,這正是其后的 div 指令所期望的,因此,這里沒有整數溢出的危險。在 5-5 的左上角,是對 KiServiceTable 的描述,該表將被 SpyHook 宏生成的進入點地址修改。在圖的中部展示了展開后的宏代碼(來自 列表 5-4 中)。進入點的線性地址位于圖的右手邊。為了完全一致,每個進入點的大小都是 8 字節,因此,通過將 KiServiceTable 中每個函數的索引值乘以 8 ,然后再將乘積加上 SpyHook1 的地址就可得出進入點的地址。

事實上,每個進入點并不都是純粹的 8 字節長。我花費了大量的時間來尋找最佳的 hook 函數的實現方式。盡管按照 32 位邊界對齊代碼并不是必須的,但這從來都不是個壞主意,因為這會提高性能。當然,能提升的性能十分有限。你或許會奇怪:為什么我要通過 EAX 寄存器間接的調用 SpyHook2 ,而不是直接使用 CALL SpyHook2 指令,這不是更高效嗎?是的!不過,問題是 i386 的 CALL (還有 jmp )指令可以有多種實現方式,而且都具有相同的效果,但是產生的指令大小卻不相同。請參考: Intel's Instruction Set Reference of the Pentium CPU family ( Intel 199c )。因為最終的實現方式要由編譯器 / 匯編器來確定,這不能保證所有的進入點都會有相同的編碼。換句話說, MOV EAX 和一個 32 位常量操作數總是以相同的方式編碼,同樣的,這也適用于 CALL EAX 指令。

圖 5-5. Hook Dispatcher 的功能原理

列表 5-3 中還有一點需要澄清。讓我們從 SpyHook9 標簽后的最后一快 C 代碼段開始。緊隨 SpyHook9 之后的匯編代碼將 SpyHook1 和 SpyHook2 的線性地址保存在 dHook1 和 dHook2 變量中。接下來,變量 n 被設為每個進入點的大小(由進入點數組的大小除以進入點的個數而得出)。當然,這個值將是 8 。 列表 5-3 的剩余部分是一個循環語句,用來初始化全局數組 aSpyHooks[] 中的所有項。這個數組所包含的 SPY_HOOK_ENTRY 結構定義于列 5-3 的頂部,該數組中的每一項都對應一個 Native API 函數。要理解該結構中的 Handler 和 pbFormat 成員是如何被設置的,就必須進一步了解傳遞給 SpyHookInitializeEx() 的 ppbSymbols 和 ppbFormats 參數, 列表 5-5 給出了外包函數 SpyHookInitialize() ,該函數會選擇適合當前 OS 版本的參數來調用 SpyHookInitializeEx() 。前面已經提示過,我使用的代碼不直接測試 OS 版本或 Build Number ,而是用常量 SPY_SYMBOLS_NT4 、 SPY_SYMBOLS_NT5 和 SDT 中與 ntoskrnl.exe 相關的 ServiceLimit 成員的值進行比較。如果沒有一個匹配, Spy 設備將把 aSpyHooks[] 數組內容全部初始化為 NULL ,從而有效的禁止 Native API Hook 機制。

BOOL SpyHookInitialize (void)

{

BOOL fOk = TRUE;

switch (KeServiceDescriptorTable->ntoskrnl.ServiceLimit)

{

case SDT_SYMBOLS_NT4:

{

SpyHookInitializeEx (apbSdtSymbolsNT4, apbSdtFormats);

break;

}

case SDT_SYMBOLS_NT5:

{

SpyHookInitializeEx (apbSdtSymbolsNT5, apbSdtFormats);

break;

}

default:

{

SpyHookInitializeEx (NULL, NULL);

fOk = FALSE;

break;

}

}

return fOk;

}

列表 5-5. SpyHookInitialize() 選擇匹配當前 OS 版本的符號表

將全局數組: apbSdtSymbolsNT4[] 和 apbSdtSymbolsNT5[] 傳遞給 SpyHookInitializeEx() 函數作為其第一個參數 ppbSymbols ,這兩個數組只是簡單的字符串數組,包含 Windows NT 4.0 和 Windows 2000 的所有 Native API 函數的名稱,按照它們在 KiServiceTable 中的索引順序來存儲,最后以 NULL 結束。 列表 5-6 給出了 apbStdFormats[] 字符串數組。這個格式字符串列表也是 hook 機制中很重要的一部分,因為它確定了記錄了那個 Native API 調用,以及每個記錄項的格式。顯然,這些字符串的結構借鑒了 C 運行時庫中的 printf() 函數,但針對 Native API 經常使用的數據類型進行了修改。 5-2 列出了所有可被 API Logger 識別的格式化 ID 。

PBYTE apbSdtFormats [] =

{

'%s=NtCancelIoFile(%!,%i)',

'%s=NtClose(%-)',

'%s=NtCreateFile(%+,%n,%o,%i,%l,%n,%n,%n,%n,%p,%n)',

'%s=NtCreateKey(%+,%n,%o,%n,%u,%n,%d)',

'%s=NtDeleteFile(%o)',

'%s=NtDeleteKey(%-)',

'%s=NtDeleteValueKey(%!,%u)',

'%s=NtDeviceIoControlFile(%!,%p,%p,%p,%i,%n,%p,%n,%p,%n)',

'%s=NtEnumerateKey(%!,%n,%n,%p,%n,%d)',

'%s=NtEnumerateValueKey(%!,%n,%n,%p,%n,%d)',

'%s=NtFlushBuffersFile(%!,%i)',

'%s=NtFlushKey(%!)',

'%s=NtFsControlFile(%!,%p,%p,%p,%i,%n,%p,%n,%p,%n)',

'%s=NtLoadKey(%o,%o)',

'%s=NtLoadKey2(%o,%o,%n)',

'%s=NtNotifyChangeKey(%!,%p,%p,%p,%i,%n,%b,%p,%n,%b)',

'%s=NtNotifyChangeMultipleKeys(%!,%n,%o,%p,%p,%p,%i,%n,%b,%p,%n,%b)',

'%s=NtOpenFile(%+,%n,%o,%i,%n,%n)',

'%s=NtOpenKey(%+,%n,%o)',

'%s=NtOpenProcess(%+,%n,%o,%c)',

'%s=NtOpenThread(%+,%n,%o,%c)',

'%s=NtQueryDirectoryFile(%!,%p,%p,%p,%i,%p,%n,%n,%b,%u,%b)',

'%s=NtQueryInformationFile(%!,%i,%p,%n,%n)',

'%s=NtQueryInformationProcess(%!,%n,%p,%n,%d)',

'%s=NtQueryInformationThread(%!,%n,%p,%n,%d)',

'%s=NtQueryKey(%!,%n,%p,%n,%d)',

'%s=NtQueryMultipleValueKey(%!,%p,%n,%p,%d,%d)',

'%s=NtQueryOpenSubKeys(%o,%d)',

'%s=NtQuerySystemInformation(%n,%p,%n,%d)',

'%s=NtQuerySystemTime(%l)',

'%s=NtQueryValueKey(%!,%u,%n,%p,%n,%d)',

'%s=NtQueryVolumeInformationFile(%!,%i,%p,%n,%n)',

'%s=NtReadFile(%!,%p,%p,%p,%i,%p,%n,%l,%d)',

'%s=NtReplaceKey(%o,%!,%o)',

'%s=NtSetInformationKey(%!,%n,%p,%n)',

'%s=NtSetInformationFile(%!,%i,%p,%n,%n)',

'%s=NtSetInformationProcess(%!,%n,%p,%n)',

'%s=NtSetInformationThread(%!,%n,%p,%n)',

'%s=NtSetSystemInformation(%n,%p,%n)',

'%s=NtSetSystemTime(%l,%l)',

'%s=NtSetValueKey(%!,%u,%n,%n,%p,%n)',

'%s=NtSetVolumeInformationFile(%!,%i,%p,%n,%n)',

'%s=NtUnloadKey(%o)',

'%s=NtWriteFile(%!,%p,%p,%p,%i,%p,%n,%l,%d)',

NULL

};

列表 5-6. Native API Logger 使用的格式化字符串

這里要特別提出的是:每個格式字符串要求必須提供函數名的正確拼寫。 SpyHookInitializeEx() 遍歷它接受到的 Native API 符號列表(通過 ppbSymbols 參數),并試圖從 ppbFormats 列表中找出與函數名匹配的格式字符串。由幫助函數 SpySearchFormat() 來進行比較工作, 列表 5-3 底部的 if 語句中調用了該函數。因為要執行大量的字符串查找操作,我使用了一個高度優化的查找引擎,該引擎基于“ Shift/And ”搜索算法。如果你想更多的學習它的實現方式,請察看隨書 CD 的 srcw2k_spyw2k_spy.c 源文件中的 SpySearch*() 函數。當 SpyHookInitializeEx() 推出循環后, aSpyHooks[] 中的所有 Handler 成員都將指向適當的 Hook 進入點, pbFormat 成員提供與之匹配的格式字符串。對于 Windows NT 4.0 ,所有索引值在 0xD3---0xF8 的數組成員都將被設為 NULL ,因為在 NT4 中,它們并沒有被定義。

表 5-2. 可識別的格式控制 ID

ID

%+

句柄(登記)

將句柄和對象名寫入日志,并將其加入句柄表。

%!

句柄(檢索)

將句柄寫入日志,并從句柄表中檢索其對應的對象名。

%-

句柄(撤銷登記)

將句柄和對象名寫入日志,并將其從句柄表移除

%a

ANSI 字符串

將一個由 8 位 ANSI 字符構成的字符串寫入日志

%b

BOOLEAN

將一個 8 位的邏輯值寫入日志

%c

CLIENT_ID*

將 CLIENT_ID 結構的成員寫入日志

%d

DWORD *

將該 DWORD 所指變量的值寫入日志

%i

IO_STATUS_BLOCK *

將 IO_STATUS_BLOCK 結構的成員寫入日志

%l

LARGE_INTEGER *

將一個 LARGE_INTEGER 的值寫入日志

%n

數值 (DWORD)

將一個 32 位無符號數寫入日志

%o

OBJECT_ATTRIBUTES *

將對象的 ObjectName 寫入日志

%p

指針

將指針的目標地址寫入日志

%s

狀態 (NTSTATUS)

將 NT 狀態代碼寫入日志

%u

UNICODE_STRING *

將 UNICOD_STRING 結構的 Buffer 成員寫入日志

%w

寬字符串

將一個由 16 位字符構成的字符串寫入日志

%%

百分號轉義符

將一個“ % ”號寫入日志

標簽: Windows系統
主站蜘蛛池模板: 亚洲激情一区二区 | 最新av网址大全 | aaa在线观看 | 久久99久久久久 | 久久久国产一区二区三区四区小说 | 国产成人一区 | 亚洲人在线| 日韩日日夜夜 | 国精日本亚洲欧州国产中文久久 | 人人干在线 | 国产精品视频久久久 | 日韩欧美精品一区二区三区 | a级毛片免费高清视频 | 五月天婷婷色综合 | 国产精品久久久久久久竹霞 | 日韩欧美三区 | www.成人.com | 一区二区三区在线 | 国产精品久久久久久 | av三级| 人人99| 夜夜艹| 成人v片 | 中文字幕一区在线观看视频 | 99r精品在线 | 国产成人在线一区二区 | 电家庭影院午夜 | 亚洲一区二区三区免费在线 | 午夜免费福利在线 | 中文字幕一区二区不卡 | 亚洲美女视频 | 久久国产精品久久久久久 | 99视频免费 | 日韩欧美综合在线 | 欧美一区在线视频 | 91资源在线观看 | 久久久亚洲成人 | 国产精品成人在线视频 | 久久精品久久久 | 日韩靠逼| 国产精品一区二区三区四区 | 精品国产成人 | 蜜桃精品在线观看 | 欧美人成在线 | 欧美一级做a爰片免费视频 亚洲精品一区在线观看 | 成人做爰www免费看视频网站 | 国产精品九九九 | 亚洲中出 | 日韩看片 | 亚洲免费在线视频 | 免费一级片 | 91视频免费观看网址 | 在线视频se | 国产精品福利午夜在线观看 | 视频专区一区二区 | 欧美电影一区 | 男人的天堂亚洲 | 国产精品美女久久久久久免费 | 最新国产毛片 | 国产精品伦理一区 | 中文字幕在线一区 | 色九九 | 国产欧美日韩综合精品一区二区 | 久久国产精品一区 | 免费在线国产 | 精品在线视频观看 | 性大毛片视频 | 日韩中文字幕电影 | 国产三级在线 | av在线一区二区 | 999视频在线免费观看 | 久久国产一区二区 | 免费观看成人毛片 | 成人一级片视频 | 免费的av在线 | 亚洲欧美日韩电影 | 99久久国产 | 色婷婷在线视频观看 | 久久综合网址 | 久久99精品久久久久久噜噜 | 欧美一区二区大片 | 午夜视频福利在线观看 | 国产日韩欧美三级 | 国产乱视频网站 | 亚洲福利影院 | 精品久久久久久久 | 亚洲欧美精品久久 | 超碰在线国产 | 一级a毛片免费 | 国产 欧美 日韩 一区 | 国产高清在线观看 | 激情小说综合网 | 欧美亚洲一区二区三区 | 久久综合伊人 | 欧美一级片aaa| 亚洲日韩欧美一区二区在线 | 成人免费共享视频 | 国产精品一区二区三区四区 | 精品无人乱码一区二区三区 | 亚洲电影一区二区 | 日韩在线视频一区 | 欧美成在线观看 | 毛片视频播放 | 国产综合在线视频 | 夜夜操av| 日韩一区在线视频 | 激情网页| 凹凸日日摸日日碰夜夜 | 在线视频一区二区 | 一区二区三区视频免费在线观看 | 欧美在线视频一区二区 | 美女国产精品 | 91社区影院 | 日韩在线视频在线观看 | 先锋影音av资源站 | 亚洲免费观看视频 | 天天久久| 中文字幕av一区二区 | 亚洲精品国品乱码久久久久 | 午夜精品一区二区三区在线播放 | 日韩av视屏| 成人欧美一区二区三区白人 | 亚洲福利一区二区 | 龙珠z国语版291集全 | 欧美一级久久 | 最新中文字幕在线 | 在线观看视频一区 | 欧美日韩国产影院 | 亚洲精品乱码久久久久久花季 | 天天射天天干 | 亚洲精品成人久久久 | 日韩一区精品 | 亚洲高清视频在线 | 久久国产精品久久久久久 | 精品亚洲一区二区三区四区五区 | 黄色影片免费在线观看 | 精品1区| 亚洲午夜精品一区二区三区他趣 | 国产专区在线视频 | 最新av在线网址 | 日韩一二三区 | 精品久久久久久亚洲精品 | 农村末发育av片四区五区 | 亚洲精品成人久久久 | 国产日韩欧美在线 | 亚洲一区二区三区国产 | 国产精品乱码一区二区三区 | 午夜精品在线观看 | 激情久久av一区av二区av三区 | 国产视频一区二区三区四区 | 日韩欧美在线视频 | 国产精品一区二区三区免费 | 精品久久久久久久久久 | 国产免费一区 | 亚洲36d大奶网 | 成人黄色av | 天堂资源在线 | 91精品国产综合久久国产大片 | 欧美国产精品一区 | 一区二区欧美在线 | 欧美一级日韩 | 欧美成年黄网站色视频 | av小说在线观看 | 日本黄色片免费 | 久久久久国产一区二区三区四区 | 亚洲精品国产剧情久久9191 | 欧美久久免费观看 | 性视频网 | 99免费精品 | 国产一区二区三区在线 | 一区二区三区国产 | 久久91精品国产91久久跳 | 色无欲天天天影视综合网 | 亚洲欧美一区二区精品中文字幕 | 国产精品亚洲一区 | 成人欧美一区二区三区视频xxx | 国产精品美女久久久久久不卡 | 久久久免费电影 | 午夜精品一区二区三区免费视频 | 国产日韩欧美视频 | 视频羞羞| 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 一区二区三区四区免费观看 | 91久久精品一区 | 国产精品一区二区三 | 国产日韩欧美视频 | 91精品久久久久久久久久 | 欧美亚洲视频 | 91人人看 | 国产一区 欧美 | 成人久久久精品乱码一区二区三区 | 日韩视频一区在线观看 | 91在线一区二区 | 婷婷色视频 | 中文一区 | 99视频精品在线 | 精品美女在线 | 国产成人欧美一区二区三区的 | 精品久久久久久久久久久 | 欧美成人a∨高清免费观看 在线视频成人 | www.伊人.com | 久久久久久国产精品久久 | 久久成人国产精品 | 一级黄色大片视频 | 黑人巨大精品欧美一区免费视频 | 久久r精品| 久久av资源 | 亚洲一区二区三区久久久 | 精品无人乱码一区二区三区的优势 | 69日影院 | 青青久久网 | 一级片黄片毛片 | 99国产精品久久久久久久 | 成av人在线| 日韩手机在线观看 | 在线观看欧美成人 | 激情综合网五月婷婷 | 日韩精品一区二区三区中文字幕 | 欧美精品中文字幕久久二区 | 日韩在线成人 | 成人免费视频一区二区 | 欧美成人综合在线 | 久久久91精品国产一区二区三区 | 亚洲 中文 欧美 日韩 在线观看 | 国产亚洲精品综合一区91555 | 男人的天堂久久 | 91看片网站 | 丝袜 亚洲 另类 欧美 综合 | 国内精品在线视频 | 羞羞视频网站在线免费观看 | 成人在线免费观看 | 久久久99精品免费观看 | 精品国产乱码久久久久久密桃99 | 欧美一级在线 | av伊人网 | 国产福利91精品一区二区 | 精品1区2区 | 国产精品亚洲区 | 日韩精品视频在线播放 | 久久一区 | 久久精品亚洲一区 | 日韩一区精品视频 | 色综合免费| 久久久久久久久久久网站 | 亚洲综合区 | 97av | 国产成人精品一区二区三区视频 | 国产日韩精品视频 | 成人精品在线 | 日韩在线不卡 | 激情自拍偷拍 | 息与子猛烈交尾一区二区 | 国产精品国产三级国产aⅴ无密码 | 色av一区 | 亚洲男人网 | 日韩在线视频资源 | 亚洲精品国产a久久久久久 国产毛片毛片 | av小说在线观看 | 九九热精品免费视频 | 亚洲免费视频在线观看 | 国产精品乱码人人做人人爱 | 久久99国产精品久久99大师 | 国产精品视频yy9299一区 | 午夜久久久久 | 欧美日韩三区 | 欧美3区 | 久久久久国产 | 欧美激情一区 | 欧美日韩高清一区 | 中文字幕精品一区二区三区精品 | 国产精品色一区二区三区 | 蜜桃视频网站在线观看 | 久久精品欧美 | 免费黄色小视频 | 四虎影视网址 | 精品日韩 | 欧美日韩中文字幕在线 | 色婷综合网 | 亚洲欧美一区二区三区在线 | 99视频网 | 亚洲中国精品精华液 | 久久久网 | 亚洲精品久久久久久一区二区 | xx视频在线观看 | 日韩电影在线 | 欧美日韩一区二区在线播放 | 黄版视频在线观看 | 国产精品日韩欧美一区二区三区 | 久久久久久久久99精品 | 亚洲国产精品第一区二区 | 欧美一级一区 | 亚洲一区av | 久久国产一区二区 | 黄色在线免费观看 | 国产视频久久久久 | 黄网站色大毛片 | 精品伊人久久 | 日韩综合一区二区 | 97超碰在线免费 | 亚洲视频精品 | 青青草99 | 欧美一区二区三区电影 | 久久久久久久国产 | 九九精品在线 | 久久久久久久国产精品视频 | 日韩精品一二三区 | 日韩一区二区在线观看 | 北条麻妃99精品青青久久主播 | 麻豆精品国产传媒 | 国产一级一级国产 | 亚洲视频一区在线 | 在线观看国产wwwa级羞羞视频 | 免费黄色片一区二区 | av在线三级 | 中国国产一级毛片 | 国产欧美综合一区二区三区 | 91精品国产综合久久久久久蜜月 | 午夜寂寞少妇aaa片毛片 | 欧美日韩精品一区二区 | 亚洲欧美精品 | 午夜精品91| 亚洲精品专区 | 亚洲综合一区二区 | 国产综合久久 | 91久久精品国产亚洲a∨麻豆 | 国产欧美一区二区视频 | 日韩中文字幕在线免费 | 国产一区二区欧美 | 不卡免费视频 | а天堂中文最新一区二区三区 | 日韩欧美精品一区二区三区 | 欧美伦理一区二区 | 男女视频在线观看 | 国产精品日韩欧美一区二区三区 | 黄色片地址 | 国产黄色在线观看 | 日韩在线资源 | 午夜精品久久久久久久白皮肤 | 亚洲视频中文字幕 | 日韩三级| 九九九色 | 久久草| 超碰在线一区二区三区 | 超碰在线看 | 国产一级黄色大片 | 国产精选一区二区 | 久久国产精品免费一区二区三区 | av电影手机版 | 日韩一区二区精品 | 艹艹网| 国产91视频一区二区 | 狠狠操综合网 | 天天草草草 | 久久国产精品一区二区 | 欧美日韩免费在线 | 成人午夜精品一区二区三区 | 亚洲网站在线观看 | 青青草超碰在线 | 美女超碰在线 | 人人玩人人添人人澡97 | 久草在线观看福利视频 | 亚洲综合视频在线 | 巴西性猛交xxxx免费看久久久 | 国产精品久久久久久久久免费桃花 | 天天爽天天操 | 91麻豆精品久久久久蜜臀 | 99re视频在线观看 | 国产精品高清一区二区 | 精品自拍视频 | 国精品产品区三区 | 91视频综合 | 99爱国产| 欧美日韩一 | 欧美电影一区二区三区 | 羞羞视频网站 | 国产成人精品免高潮在线观看 | 欧美精品导航 | 国产特级毛片 | 五月天婷婷在线视频 | 综合色久 | 亚洲视频在线播放 | 在线婷婷 | 国产91网| 国产黄色播放 | 欧洲亚洲视频 | 久久精品综合 | 成人一区二区三区四区 | 国产精品久久久久影院色老大 | 国产农村妇女精品久久 | 免费国产一区二区 | 亚洲男人的天堂在线播放 | 国产精品久久久久久久久免费桃花 | 在线观看免费视频黄 | 国产猛男猛女超爽免费视频网站 | 午夜社区 | 国产欧美一区二区精品忘忧草 | 91综合视频在线观看 | 国产毛片aaa | 国产日产欧美a级毛片 | 国产一区二区三区免费视频 | 天天射影院 | 精品久久一区 | 玖玖精品在线 | 在线天堂av | 91av导航| 中文字幕视频在线免费 | 国产综合视频 | 久热九九 | 伊人精品影院 | 欧美久久综合 | 在线一区 | 米奇狠狠操 | 婷婷桃色网| 免费一级黄色电影 | 精品亚洲成人 | 亚洲精彩视频 | 亚洲不卡| 日韩免费视频 | 在线一区观看 | 97视频在线 | 成视频年人免费看黄网站 | 99精品欧美一区二区蜜桃免费 | 日韩有码在线观看 | a∨在线观看 | 这里只有精品视频 | a级毛片免费高清视频 | 国产高潮好爽受不了了夜色 | 国产一级毛片国语一级 | 蜜桃久久av | 国产91 在线播放 | 国产成人精品亚洲日本在线观看 | 一区二区三区四区在线 | 久热精品视频 | 欧美精品1区2区3区 国产女无套免费网站 | 国产特级毛片 | 久久久91精品国产一区二区三区 | 国产偷国产偷精品高清尤物 | 亚洲精品一区二区 | 亚洲视频在线看 | 久久精品免费视频观看 | 日韩午夜一级片 | 国产一区二区免费视频 | 欧美在线观看黄 | 日韩一区在线观看视频 | 国产欧美一区二区精品性色 | 香蕉大人久久国产成人av | 大香伊在人线免97 | 97国产一区二区精品久久呦 | 欧美精品一区二区三区一线天视频 | 久久亚洲国产精品 | 午夜久久久久 | 亚洲天堂成人 | 欧美午夜精品久久久 | 成人免费一区二区三区视频网站 | 韩日精品在线观看 | 91九色porny首页最多播放 | www.视频在线观看 | 欧美一区精品 | 国产精品网站在线看 | 粉嫩国产精品一区二区在线观看 | 一区影院 | 国产精品久久久久久久午夜 | 国产高清久久久 | 日本一区二区三区视频免费看 | 日日日日干干干干 | 不卡在线 | 国产在线精品一区 | 伊人av超碰久久久麻豆 | 国产免费天天看高清影视在线 | 久久久久久国产精品 | 成人免费视频7777777 | 久久久中文字幕 | 在线免费黄色 | 成人精品国产一区二区4080 | 精品国产乱码一区二区三 | 青青草免费在线视频 | 国产免费看| 婷婷伊人| 精品xxxx户外露出视频 | 亚洲精品免费观看 | 亚洲国产精品久久久 | 日本精品免费 | 日本成人在线看 | 在线99热| 成人亚洲天堂 | 国产精品毛片久久久久久久 | 视频一区二区国产 | 亚洲高清一区二区三区 | 欧美精三区欧美精三区 | 成人在线观看av | 亚洲一区二区三区高清 | 亚洲综合一二区 | 欧美黄色一区 | 精品人伦一区二区三区蜜桃视频 | 欧美黑人狂躁日本寡妇 | 国产精品视频免费看 | 成人欧美一区二区三区白人 | 天天综合天天色 | 免费在线看a | 亚洲国产精品一区二区久久 | 全黄大全大色全免费大片 | 呦一呦二在线精品视频 | 欧美日韩国产精品久久久久 | 91观看| 人人射人人 | 欧美视频精品 | 国产日韩欧美综合 | 成人精品一区二区三区电影黑人 | 久久精品视频在线播放 | 国产精品久久久久久久久免费高清 | 亚洲精品一区二区三区精华液 | 成人性生交大片免费看中文带字幕 | 激情视频在线观看免费 | 正在播放国产精品 | 国产福利在线观看视频 | 国产色视频在线观看免费 | 在线观看成人 | 一级毛片网 | 日韩高清一区 | 亚洲色图综合 | zzzzyyyy精品国产 | 欧美日韩一区二区三区在线电影 | 亚洲精品wwww | 日韩快播电影网 | 欧美综合一区二区 | 亚洲精品一区中文字幕乱码 | 成人在线视频免费观看 | 一区二区三区在线播放 | 九色在线播放 | 在线看片福利 | 99久久99 | 99成人 | 亚洲一区中文 | 欧洲精品一区 | 国产精品久久久久一区二区三区 | 日韩精品一区在线 | 国产老女人精品毛片久久 | 亚洲成人一区二区三区 | 91亚洲高清 | 国产免费观看一区二区三区 | 天天操天天碰 | 午夜电影一区 | 日本 欧美 三级 高清 视频 | 中文字幕日韩在线 | 天堂一区二区三区四区 | 伊人精品影院 | 成人a在线视频免费观看 | 91精品国产成人 | 亚洲在线免费观看 | 国产精品永久免费自在线观看 | 成人av高清在线观看 | 一区二区免费视频 | 99国产精品久久久久久久成人热 | 国产乱码精品一区二区三区手机版 | 在线观看不卡一区 | 亚洲第一福利视频 | 国产精品久久久久久吹潮 | 久久久久国产一区二区三区 | 国产网站在线播放 | 色在线免费视频 | 7777av| 国产精品人人做人人爽 | 成人免费精品视频 | 在线成人免费视频 | 亚洲永久免费 | 欧美日本精品 | 国产美女一区二区 | 91av在线播放 | 青青草久草在线 | 国产探花在线精品一区二区 | 国产精品女教师av久久 | 精品永久免费 | 久久久久综合 | 亚洲成人精品 | 韩国精品视频在线观看 | www.av在线 | 欧美日韩亚洲一区 | 欧美视频综合 | 国产精品www | 射久久| 精品中文字幕一区二区 | 亚洲日韩欧美一区二区在线 | 龙珠z普通话国语版在线观看 | 免费亚洲视频 | 精品国产欧美 | 国产伊人一区 | 国产高清免费视频 | 99精品久久久 | 国产一级片儿 | 国产精品毛片一区二区在线看 | 电影k8一区二区三区久久 | 欧美精品一区二区三区四区在线 | 日韩视频在线免费观看 | 久久国产精品视频 | 国产精品久久久久久久岛一牛影视 | 在线欧美一区 | 亚洲欧美激情精品一区二区 | 日韩在线欧美 | 日韩极品视频 | 久久亚洲一区二区 | 国产福利网站 | 午夜免费高清视频 | 午夜欧美一区二区三区在线播放 | 成人一区二区三区四区 | 久久av一区二区三区 | 亚洲久久久久久 | 亚洲国产婷婷香蕉久久久久久99 | 国产精品11 | 九色在线 | 午夜久久久 | a毛片毛片av永久免费 | 最新国产在线 | 日韩视频一区在线观看 | 亚洲欧洲日韩 | 久久国产区 |