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

小默

(zz)逆向RING0程序從這里開始

標 題: 逆向RING0程序從這里開始
作 者: 笨笨雄
時 間: 2006-12-06 21:41
鏈 接: http://bbs.pediy.com/showthread.php?threadid=35999
詳細信息:

【文章標題】: 逆向RING0程序從這里開始
【文章作者】: 笨笨雄
【作者郵箱】: nemo314@gmail.com
【使用工具】: IDA

接觸RING 0之前,以為得學很多東西,一大堆驅動開發的知識。不過后來想了想,驅動殼等其他不直接訪問硬件的程序為了兼容性,不可能真的直接訪問硬件,也就是那些是基于硬件抽象層之上的,而且大部分使用的還是系統提供的API(RING0下使用的API稱為NATIVE API)。事情一下子變簡單了,除非你想通過逆向硬件廠商驅動,自己編寫優化硬件或者超頻程序。

雖然這是純靜態分析,但是我希望通過分析整個驅動,你會理解一些RING0下的機制,并且懂得在動態調試中應該如何下斷點定位代碼。

在開始之前,感謝rockhard的源代碼和已編譯好的驅動,這樣我就可以不必學習WINDDK的使用了。你可以在下面鏈接的附件中得到:

http://bbs.pediy.com/showthread.php?s=&threadid=35626
初步實現系統級攔截應用程序取硬盤物理序列號

Rockhard發表上述文章時的目標是通過簡單修改REGMON驅動部分的源代碼完成攔截應用程序取硬盤物理序列號的功能,難免有不足之處。個人對源代碼的不成熟評論并不針對Rockhard。

學習逆向時,我的方法是先看看高級語言代碼編譯后究竟是怎么樣的。或許最后我還是得學習WINDDK的使用,編寫代碼,編譯,反匯編,它會解答一些疑問。下面讓我來以源碼和反匯編代碼對照的形式來說明RING0下的一些機制。

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )

DriverEntry,驅動程序的入口函數,驅動的一些初始化操作,將在這里進行。象RING3那樣,程序通過堆棧訪問DriverObject和RegistryPath。而在IDA,反匯編后是這樣子:“; int __stdcall start(PDRIVER_OBJECT DriverObject,HANDLE Handle)”第二個參數的名字有點不同,不過不重要,我們知道,其實它是一樣的。

.text:000105A0                 push    7
.text:000105A2                 pop     ecx
.text:000105A3                 mov     esi, offset s_DeviceHdhook ; "\\Device\\HDHOOK"
.text:000105A8                 lea     edi, [ebp+regnameNt]
.text:000105AE                 push    9
.text:000105B0                 rep movsd
.text:000105B2                 movsw
.text:000105B4                 pop     ecx
.text:000105B5                 mov     esi, offset s_DosdevicesHdh ; "\\DosDevices\\HDHOOK"
.text:000105BA                 lea     edi, [ebp+regnameDos]
.text:000105C0                 push    206B6444h       ; Tag
.text:000105C5                 rep movsd
.text:000105C7                 movsw
.text:000105C9                 mov     esi, offset s_Start ; "Start"
.text:000105CE                 lea     edi, [ebp+SourceString]
.text:000105D1                 movsd
.text:000105D2                 movsd
.text:000105D3                 movsd
.text:000105D4                 mov     esi, [ebp+Handle]
.text:000105D7                 movzx   eax, word ptr [esi]
.text:000105DA                 inc     eax
.text:000105DB                 inc     eax
.text:000105DC                 push    eax             ; NumberOfBytes
.text:000105DD                 push    1               ; PoolType
.text:000105DF                 call    ds:ExAllocatePoolWithTag

前面一大堆代碼,都是因為下面3個局部變量的定義,編譯器會生成一段代碼,先將這些字符移進堆棧,然后再使用。

WCHAR                   deviceNameBuffer[]  = L"\\Device\\"DRIVER_NAME;
WCHAR                   deviceLinkBuffer[]  = L"\\DosDevices\\"DRIVER_NAME;
WCHAR                   startValueBuffer[] = L"Start";

從逆向的角度來看,象這種靜態字符變量,如果換成全局變量,或者可以獲得更高的運行效率和更小的程序。值得注意的是NATIVE API的調用,第一個參數入棧后的幾行代碼,仍然是局部變量的初始化,這編譯器讓我想起扭曲變形的介紹。000105D4的代碼是從堆棧中取得DriverEntry的第二參數,它是一個UNICODE_STRING結構,從MSDN中搜索到的說明(如無特別說明,一切資料都是從MSDN中搜索得到):

typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING *PUNICODE_STRING;

從000105D7處的代碼來看,該結構在反匯編是:

  WORD  Length
  WORD  MaximumLength
  DWORD  Buffer(指向字符的指針)

通過逆向RtlInitUnicodeString,可知上述結構中的 MaximumLength成員,其實就相當于Length + sizeof(UNICODE_NULL)。關于調用ExAllocatePoolWithTag的第三參數PoolType:

typedef enum _POOL_TYPE {
  NonPagedPool,
  PagedPool,
  NonPagedPoolMustSucceed,
  DontUseThisType,
  NonPagedPoolCacheAligned,
  PagedPoolCacheAligned,
  NonPagedPoolCacheAlignedMustS
} POOL_TYPE;

這里看起來跟PUSH 1好象沒有什么關系,現在看看源代碼:

    registryPath.Buffer = ExAllocatePool( PagedPool,
                                          RegistryPath->Length + sizeof(UNICODE_NULL));

這里使用的參數是PagedPool,對于enum類型的定義,每個成員代表的數字是從0開始遞增。PagedPool剛好在第二個位置,所以它是1。源代碼使用的ExAllocatePool,反匯編后的代碼使用的是ExAllocatePoolWithTag。MSDN的說法是ExAllocatePool已經被舍棄了,取代的是ExAllocatePoolWithTag(以標識申請內存)。調用API之后是對返回結果的判斷:

    if (!registryPath.Buffer) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

它對應的匯編代碼是

.text:000105E5                 mov     edi, eax
.text:000105E7                 xor     ebx, ebx
.text:000105E9                 cmp     edi, ebx
.text:000105EB                 mov     [ebp+Path], edi
.text:000105EE                 jnz     short loc_105FA
.text:000105EE
.text:000105F0                 mov     eax, 0C000009Ah
.text:000105F5                 jmp     loc_1075A

注意到000105F0,STATUS_INSUFFICIENT_RESOURCES=0C000009Ah,仍然使用EAX作為返回參數。接下來的源代碼,終于看到編譯優化了:

    registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
    registryPath.MaximumLength = registryPath.Length;

    RtlZeroMemory( registryPath.Buffer, registryPath.Length );

    RtlMoveMemory( registryPath.Buffer,  RegistryPath->Buffer,
                   RegistryPath->Length  );

    RtlZeroMemory( &paramTable[0], sizeof(paramTable));

這里本來要調用2個API的。對于前一個RtlZeroMemory調用,編譯器使用自己的代碼來代替它:

.text:000105FA                 mov     ax, [esi]
.text:000105FD                 add     ax, 2
.text:00010601                 movzx   ecx, ax
.text:00010604                 mov     edx, ecx
.text:00010606                 xor     eax, eax
.text:00010608                 shr     ecx, 2
.text:0001060B                 rep stosd
.text:0001060D                 mov     ecx, edx
.text:0001060F                 and     ecx, 3
.text:00010612                 rep stosb

先是4字節對齊的填0,然后使用AND取得除以4后的余數,繼續填0。第二次調用,編譯器同樣使用自己的代碼來實現這個功能:

.text:00010624                 add     esp, 0Ch
.text:00010627                 xor     eax, eax
.text:00010629                 lea     edi, [ebp+QueryTable]
.text:0001062F                 push    0Eh
.text:00010631                 pop     ecx
.text:00010632                 rep stosd

現在讓我們再來看看系統中RtlZeroMemory的代碼:

00402520: 57                       PUSH EDI
00402521: 8B7C2408                 MOV EDI, [ESP+08]
00402525: 8B4C240C                 MOV ECX, [ESP+0C]
00402529: 33C0                     XOR EAX, EAX
0040252B: FC                       CLD ;這一句用來保證DF=0
0040252C: 8BD1                     MOV EDX, ECX
0040252E: 83E203                   AND EDX, 00000003
00402531: C1E902                   SHR ECX, 02
00402534: F3AB                     REP STOSD 
00402536: 0BCA                     OR ECX, EDX
00402538: 7504                     JNZ 40253E;非4字節對齊,繼續填0
0040253A: 5F                       POP EDI
0040253B: C20800                   RETN 0008
0040253E: F3AA                     REP STOSB 
00402540: 5F                       POP EDI
00402541: C20800                   RETN 0008

高級語言似乎不提供修改標志寄存器的功能,CLD可以省掉。在編譯過程中比較需要填0的內存是否4字節對齊,把比較語句也省了。這里的代碼沒有以函數的形式出現,當然連傳遞參數和保存環境的代碼也省了。至于RtlMoveMemory,編譯器用下面代碼代替:

.text:00010614                 movzx   eax, word ptr [esi]
.text:00010617                 push    eax             ; size_t
.text:00010618                 push    dword ptr [esi+4] ; void *
.text:0001061B                 push    [ebp+Path]      ; void *
.text:0001061E                 call    ds:memmove

選擇使用MEMMOVE而不是RtlMoveMemory。簡單分析了一下,前者為每種情況都準備了一個獨立的處理例程,通過跳轉表的形式來實現,后者則是使用了不少比較命令。由于代碼量較多,有興趣的可以自己看看。
編譯出來的程序,至少在代碼段,看起來跟RING 3沒有什么區別,同樣可以通過程序實現的功能和驅動導入表,估計程序用了什么API,下斷,并最終定位目標功能代碼。我們需要做的事,只是熟悉這些API和一些常用的RING0機制,然后就可以象分析RING 3程序一樣分析RING 0了。下面我將把重點放在API的解釋。程序下一個調用的API是RtlQueryRegistryValues,MSDN可以查得該函數的功能是訪問注冊表。其中一個參數的結構如下:

typedef struct _RTL_QUERY_REGISTRY_TABLE {
    PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
    ULONG Flags;
    PWSTR Name;
    PVOID EntryContext;
    ULONG DefaultType;
    PVOID DefaultData;
    ULONG DefaultLength;
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;

關于Flags標記,可用的常量如下:

RTL_QUERY_REGISTRY_SUBKEY 
RTL_QUERY_REGISTRY_TOPKEY 
RTL_QUERY_REGISTRY_REQUIRED 
RTL_QUERY_REGISTRY_NOVALUE 
RTL_QUERY_REGISTRY_NOEXPAND 
RTL_QUERY_REGISTRY_DIRECT 
RTL_QUERY_REGISTRY_DELETE

對于這類型常量定義,從1(二進制)開始,第二個是10(二進制),第三個是100(二進制),如此類推。源代碼中使用的是RTL_QUERY_REGISTRY_DIRECT,所以有如下代碼:

.text:0001064F                 mov     [ebp+QueryTable.Flags], 20h

這里有點想不明白,在此API調用之前的大段代碼和幾個API的調用,都是為了初始化此API的Path參數。為什么不能直接使用入口參數RegistryPath的BUFFER,而要另外分配內存,轉移數據在作為傳入參數?另外在此API的注釋中看到這一句話“The table must be allocated from nonpaged pool.”。程序沒有申請一塊nonpaged內存存放QueryTable結構,而是直接使用堆棧。難道RING 0下的堆棧都是nonpaged的?此外程序此后并沒有對該API的返回值或者返回數據作任何處理。這里大膽假設一下到目前為止的代碼都是垃圾代碼。另外我注意到編譯器的對于每行代碼幾乎都是很機械的編譯,下面源代碼:

    paramTable[0].EntryContext = &startType;
    paramTable[0].DefaultType = REG_DWORD;
    paramTable[0].DefaultData = &startType;

對應的反匯編代碼:

.text:00010634                 lea     eax, [ebp+var_4]
.text:00010637                 push    4
.text:00010639                 mov     [ebp+QueryTable.EntryContext], eax
.text:0001063C                 lea     eax, [ebp+var_4]
.text:0001063F                 pop     edi
.text:00010640                 mov     [ebp+QueryTable.DefaultData], eax

編譯器將相同的賦值語句歸類了,但是卻對EAX重復賦值,顯然0001063C處的代碼可以省略。接下來是ZwOpenKey。根據NTSTATUS的定義(詳見WINDDK中的ntstatus.h),最高位有如下定義:

//          00 – Success      ;對應的16進制最高位0
//          01 – Informational    ;4
//          10 – Warning      ;8
//          11 – Error        ;c

比較是否成功調用的代碼是:

.text:0001069D                 test    eax, eax
.text:0001069F                 jl      short loc_106CF;最高位為1(調用失敗),跳

在RING 3下API調用失敗返回的是-1,NATIVE API則是以返回值的最高位來判斷調用是否成功。

.text:00010675                 lea     eax, [ebp+Handle]
.text:00010678                 push    20006h          ; DesiredAccess
.text:0001067D                 push    eax             ; KeyHandle
.text:0001067E                 mov     [ebp+ObjectAttributes.RootDirectory], ebx
.text:00010681                 mov     [ebp+ObjectAttributes.Attributes], 40h
.text:00010688                 mov     [ebp+ObjectAttributes.ObjectName], esi
.text:0001068B                 mov     [ebp+ObjectAttributes.SecurityDescriptor], ebx
.text:0001068E                 mov     [ebp+ObjectAttributes.SecurityQualityOfService], ebx
.text:00010691                 call    ds:ZwOpenKey

由上面代碼可知,該API的KeyHandle參數,使用的就是DriverEntry的第二個參數。也就是說KeyHandle其實就是一個UNICODE_STRING結構。搞不懂micro$oft,一樣的東西搞這么多概念干什么。另外想不明白的是,假如該API調用成功,將會在注冊表寫入一些數據。但是對程序的運行沒有影響。ZwOpenKey調用失敗了反而省了幾行代碼。隨后是IoCreateDevice和IoCreateSymbolicLink建立驅動對象和符號連接,API調用失敗則把建立的對象和符號連接刪除。為IRP_MJ_SHUTDOWN,IRP_MJ_CREATE,IRP_MJ_CLOSE和IRP_MJ_DEVICE_CONTROL分派處理例程。分別有下面對應關系:

       名稱                                    描述                            調用的API
IRP_MJ_CREATE                       請求一個句柄                           CreateFile 
IRP_MJ_CLOSE                       關閉句柄                             CloseHandle 
IRP_MJ_DEVICE_CONTROL        控制操作(利用IOCTL宏)        DeviceIoControl 
IRP_MJ_SHUTDOWN                   系統關閉                                InitiateSystemShutdown

當RING 3程序調用上述API對驅動進行操作時,系統會查找該IRP對應的處理例程地址,并調用該例程。

.text:0001071B                 mov     eax, offset sub_104B4
.text:00010720                 cmp     edi, ebx
.text:00010722                 mov     [esi+70h], eax
.text:00010725                 mov     [esi+40h], eax
.text:00010728                 mov     [esi+38h], eax
.text:0001072B                 mov     [esi+78h], eax

此處ESI指向的是DriverEntry的第一個參數DriverObject。+38h是IRP_MJ_CREATE,+40h是IRP_MJ_CLOSE。具體請查閱WINDDK中的wdm.h。

.text:0001074E                 mov     eax, ds:KeServiceDescriptorTable
.text:00010753                 mov     dword_1080C, eax

執行完這兩行代碼,把SSDT存到全局變量中便結束了DriverEntry例程,也就是說驅動的初始化完畢了。實現驅動功能的代碼在IRP例程中,這讓我想起RING 3下的消息環。下面來看看sub_104B4:

.text:000104B4 sub_104B4       proc near               ; DATA XREF: start+187 o
.text:000104B4                  ;按照IRPDispatch例程的定義
.text:000104B4 arg_0           = dword ptr  8      ;DeviceObject
.text:000104B4 arg_4           = dword ptr  0Ch    ;pIrp

關于pIrp結構,MSDN中的定義不完整。對照源代碼可知:

+0ch    DWORD    AssociatedIrp.SystemBuffer
+18h    DWORD    IoStatus.Status
+1Ch    DWORD    IoStatus.Information
+3ch    DWORD    UserBuffer
+60h    DWORD    irpStack

irpStack:

+00h    BYTE    MajorFunction ,查詢WINDDK中的WDM.h可知

#define IRP_MJ_CREATE                      0x00
#define IRP_MJ_CLOSE                      0x02
#define IRP_MJ_DEVICE_CONTROL           0x0e
#define IRP_MJ_SHUTDOWN                 0x10

+04h    DWORD    Parameters.DeviceIoControl.OutputBufferLength
+08h    DWORD    Parameters.DeviceIoControl.InputBufferLength
+0ch    DWORD    Parameters.DeviceIoControl.IoControlCode
+18h    DWORD    FileObject

該函數根據不同的IRP消息,進入不同的流程。其中從IRP_MJ_DEVICE_CONTROL的處理流程可知,當IoControlCode的低3位為111(二進制,即METHOD_NEITHER)時,驅動程序使用UserBuffer返回數據,反之則使用SystemBuffer。現在來看看sub_103DA,即是源代碼中的HDHookDeviceControl函數:

.text:000103EB                 cmp     ecx, 83050000h
.text:000103F1                 jz      loc_104A7
.text:000103F1
.text:000103F7                 cmp     ecx, 83050004h
.text:000103FD                 jz      loc_104A0
.text:000103FD
.text:00010403                 cmp     ecx, 83050008h
.text:00010409                 jz      short loc_1047E
.text:00010409
.text:0001040B                 cmp     ecx, 8305000Ch
.text:00010411                 jz      short loc_10452
.text:00010411
.text:00010413                 cmp     ecx, 83050010h
.text:00010419                 jz      short loc_10426

函數將IoControlCode保存在ECX中,經過對比跳轉到相關代碼中。在用戶態程序中,通過下面API與驅動進行通信:

BOOL DeviceIoControl(

    HANDLE hDevice,  // handle to device of interest
    DWORD dwIoControlCode,  // control code of operation to perform
    LPVOID lpInBuffer,  // pointer to buffer to supply input data
    DWORD nInBufferSize,  // size of input buffer
    LPVOID lpOutBuffer,  // pointer to buffer to receive output data
    DWORD nOutBufferSize,  // size of output buffer
    LPDWORD lpBytesReturned,  // pointer to variable to receive output byte count
    LPOVERLAPPED lpOverlapped   // pointer to overlapped structure for asynchronous operation
   );

也就是說,攔截該API,取得dwIoControlCode,在IRP分派例程的入口下條件斷點。然后便可以定位驅動中相關的功能代碼。我想看到這里,大家都大概了解RING 0的一些機制,并且能嘗試動態調試一些程序了。該程序大部分代碼的功能Rockhard在他的貼里已經講得很清楚了,除了如何取得系統調用號。我們知道系統調用號隨著系統版本,甚至SP之間也會有所不同,如何兼容各版本?我對此很感興趣,先看看源代碼:

VOID HookStart( void )
{
    if( !IsHooked ) {
        RealZwDeviceIoControlFile = SYSCALL( ZwDeviceIoControlFile );
        SYSCALL( ZwDeviceIoControlFile ) = (PVOID) HookZwDeviceIoControlFile;
        IsHooked = TRUE;
    }
}

你能想象這樣的代碼能取得ZwDeviceIoControlFile在SSDT中的位置嗎?現在再讓我們看看反匯編代碼:

.text:00010381                 mov     eax, ds:ZwDeviceIoControlFile
.text:00010386                 mov     ecx, ssdt
.text:0001038C                 push    esi
.text:0001038D                 mov     edx, [eax+1];這里有點奇怪,取函數的機械碼?
.text:00010390                 mov     esi, [ecx]
.text:00010392                 mov     edx, [esi+edx*4]
.text:00010395                 pop     esi
.text:00010396                 mov     dword_10814, edx
.text:0001039C                 mov     eax, [eax+1]
.text:0001039F                 mov     ecx, [ecx]
.text:000103A1                 mov     dword ptr [ecx+eax*4], offset sub_1030E

現在讓我們來看看ZwDeviceIoControlFile的代碼:

00400BC6: B838000000               MOV EAX, 00000038
00400BCB: 8D542404                 LEA EDX, [ESP+04]
00400BCF: CD2E                     INT 2E
00400BD1: C22800                   RETN 0028

入口點加1,便是系統調用號。最后感謝所有看到這里的人

posted on 2010-02-05 23:47 小默 閱讀(549) 評論(0)  編輯 收藏 引用 所屬分類: Language

導航

統計

留言簿(13)

隨筆分類(287)

隨筆檔案(289)

漏洞

搜索

積分與排名

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美激情久久久久久| 欧美xart系列高清| 欧美激情精品久久久久久黑人 | 亚洲视频一二三| 国产欧美日韩视频| 欧美成人国产| 午夜亚洲福利在线老司机| 美女视频黄a大片欧美| 亚洲视频一区二区| 国内外成人免费激情在线视频网站 | 亚洲午夜激情免费视频| 久久福利精品| 亚洲伦理自拍| 激情欧美一区二区三区在线观看 | 亚洲午夜久久久久久久久电影院| 国产综合欧美在线看| 亚洲国产黄色| 在线观看成人av| 国产精品成人在线观看| 欧美黄在线观看| 久久久久高清| 欧美在线3区| 欧美成人精品在线| 欧美黄污视频| 欧美精品一区二区三区久久久竹菊| 久久久亚洲影院你懂的| 欧美一区午夜视频在线观看| 亚洲视频每日更新| 另类激情亚洲| 亚洲精品综合精品自拍| 一本综合久久| 亚洲一区二区3| 亚洲影院一区| 亚洲美女在线视频| 夜夜嗨av一区二区三区中文字幕| 欧美成ee人免费视频| 欧美激情第1页| 91久久精品日日躁夜夜躁欧美 | 国产精品乱码一区二三区小蝌蚪| 蜜桃久久av一区| 乱人伦精品视频在线观看| 久久亚洲国产成人| 久久夜色精品国产欧美乱| 小黄鸭精品密入口导航| 亚洲国产小视频| 国产一区二区三区无遮挡| 99精品99久久久久久宅男| 亚洲精品免费在线播放| 欧美在线亚洲一区| 亚洲在线一区| 久久九九电影| 欧美激情一区二区久久久| 美女黄网久久| 亚洲高清激情| 亚洲一区二区在线| 久久久999精品免费| 欧美精品在线看| 在线成人免费视频| 一卡二卡3卡四卡高清精品视频| 亚洲一区二区三区精品动漫| 亚洲视频在线观看网站| 久久久国产精彩视频美女艺术照福利 | 日韩视频二区| 亚洲精品欧美激情| 欧美成人免费播放| 日韩亚洲欧美成人一区| 亚洲大片一区二区三区| 国产欧美精品xxxx另类| 免费观看成人www动漫视频| 亚洲在线成人| 一区二区三区国产精品| 一区二区三区国产在线| 欧美午夜www高清视频| 欧美黄色小视频| 久久久亚洲精品一区二区三区| 午夜精品久久久久久久白皮肤| 国产亚洲一区精品| 国产日韩欧美不卡| 国产亚洲va综合人人澡精品| 欧美日韩综合在线免费观看| 欧美日韩精品在线播放| 欧美精品www在线观看| 欧美日韩一区免费| 国产精品日本一区二区| 精品999日本| 9色精品在线| 欧美日韩在线播放三区| 欧美日韩不卡一区| 久久美女艺术照精彩视频福利播放| 国产日本欧美一区二区三区在线| 亚洲精品国产品国语在线app| 日韩一区二区久久| 亚洲香蕉成视频在线观看 | 国产欧美日本| …久久精品99久久香蕉国产| 亚洲三级影院| 欧美与欧洲交xxxx免费观看| 欧美jizz19性欧美| 亚洲欧美久久久久一区二区三区| 亚洲免费在线观看| 欧美sm极限捆绑bd| 国产午夜亚洲精品不卡| 亚洲一区二区三区午夜| 另类酷文…触手系列精品集v1小说| 日韩午夜在线播放| 久久综合狠狠综合久久综合88| 欧美精品在线观看播放| 亚洲第一天堂av| 欧美www视频| 久久精品国产精品亚洲综合| 欧美视频在线播放| 亚洲日韩欧美视频| 欧美成人情趣视频| 欧美中文日韩| 亚洲高清资源| 亚洲人成网站在线观看播放| 久久综合成人精品亚洲另类欧美| 樱花yy私人影院亚洲| 久久久精品性| 久久在线精品| 亚洲精品国产视频| 亚洲高清视频一区| 国产精品一区二区女厕厕| 亚洲影院高清在线| 久久久国产精品一区二区中文| 国产在线视频欧美一区二区三区| 久久艳片www.17c.com| 欧美aⅴ一区二区三区视频| 欧美激情精品久久久久久蜜臀 | 亚洲欧洲中文日韩久久av乱码| 久久成人免费日本黄色| 亚洲人体偷拍| 国产精品永久免费观看| 久久精品一区二区三区不卡| 久久中文在线| 亚洲午夜国产成人av电影男同| 久久精品毛片| 中文国产成人精品| 欧美亚洲系列| 亚洲欧美激情一区二区| 欧美成人午夜免费视在线看片| 欧美一区二区福利在线| 欧美成人一区二区| 久久一综合视频| 国产精品视频久久久| 国产精品99久久99久久久二8 | 韩日精品视频一区| 一区二区高清| 日韩视频一区二区在线观看 | 久久美女性网| 亚洲欧美日韩在线综合| 久久综合成人精品亚洲另类欧美| 午夜精品福利电影| 欧美大香线蕉线伊人久久国产精品| 亚洲欧美成人综合| 免费欧美在线| 亚洲自拍电影| 欧美国产高清| 欧美韩日一区| 亚洲精品资源| 欧美午夜精品久久久久久久| 亚洲电影免费观看高清完整版在线观看 | 久久精品国产999大香线蕉| 欧美午夜精品理论片a级按摩| 亚洲欧洲在线看| 日韩亚洲国产欧美| 国产精品久久久久久久久久三级| 麻豆精品精华液| 亚洲电影中文字幕| 欧美老女人xx| 亚洲一区在线观看视频| 久久女同互慰一区二区三区| 亚洲国产精品久久久久婷婷老年| 欧美va亚洲va国产综合| 在线亚洲高清视频| 久久综合色婷婷| 亚洲男人的天堂在线观看| 国产亚洲成精品久久| 欧美激情在线狂野欧美精品| 亚洲制服av| 欧美国产精品一区| 欧美一区二区三区免费看| 91久久精品国产| 国产精品午夜电影| 欧美激情第8页| 久久久一区二区三区| 亚洲毛片av| 久久综合久久综合这里只有精品| 一本色道久久综合亚洲精品小说| 国产日韩欧美一区二区| 欧美日韩三级| 裸体女人亚洲精品一区| 亚洲尤物在线视频观看| 午夜精品一区二区三区电影天堂 | 一区二区三区.www| 久久久一区二区| 久久精品国产成人| 久久免费视频这里只有精品| 免费久久精品视频| 日韩午夜精品视频|