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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

一种User Mode下访问物理内存及Kernel Space的简单实现

發布時間:2023/12/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一种User Mode下访问物理内存及Kernel Space的简单实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一種User Mode下訪問物理內存及Kernel Space的實現

一.背景

?????? WinCE發展到6.0之后,內存結構和管理方法進行了完善。對應用程序影響比較大的有Virtual Memory Layout的變化,如每個進程的虛擬內存空間擴展為2GB。對驅動程序影響比較大的有PointerShare Memory,這一點在DriverOS接口部分對指針和內存的保護方法中可以看到。對OAL影響比較大的有,系統Boot Process的改變。

?????? 另外,6.0上廢除了Full Kernel Mode的不合理設計,將Kernel ModeUser Mode進行了細分。由此帶來了本文中要討論的問題,就是如何在User Mode下操作Kernel Mode下的內存空間。

?????? 大家一定想到了,簡單的在User Mode下訪問Kernel Mode下才有權限訪問的內存肯定是行不通,可以間接的通過Kernel下的Driver或者其它與Kernel中的代碼進行通信的方法來訪問。

?????? 本文先討論一下第一種方法實現中要解決的問題,最后會將主要代碼實現粘貼出來。

二.需要解決的幾個問題

?????? 前面已經提到主要的實現思路,需要解決的問題是如何加載該驅動,以及如何保證Driver運行在Kernel Mode下,以及如何將DriverExe組合到一起。

1.用戶模式下Driver的加載

?????? 為了方便實現User ModeDriver的動態加載,將這支在User ModeKernel Mode下做轉換的Driver做成流驅動。

?????? User Mode下加載Driver,只需兩個步驟:首先將Driver拷貝到對象存儲下的Windows目錄下,然后調用Device ManagerAPI ActivateDevice()來實現動態的加載。

?????? 函數ActivateDevice()的使用非常簡單,其聲明如下:

This function loads a device driver. For additional functionality, use the ActivateDeviceEx function.

HANDLE ActivateDevice( ? LPCWSTR lpszDevKey, ??DWORD dwClientInfo );

Parameters

lpszDevKey

[in] Pointer to a string that identifies the location under the HKEY_LOCAL_MACHINE registry subtree where the Driver registry subkey for the device resides. A driver registry subkey contains the dynamic-link library (DLL) name, device prefix, friendly name, and other device information.

dwClientInfo

[in] Data to store in the Active registry subkey for the device in the ClientInfo registry entry. The registry path to the Active registry subkey for the device is passed in as the context parameter to the device's XXX_Init (Device Manager) function. After the value in dwClientInfo is stored in the registry under HKEY_LOCAL_MACHINE/Drivers/Active, the Device Manager calls XXX_Init. Devload.h defines DEVLOAD_CLIENTINFO_VALNAME and DEVLOAD_CLIENTINFO_VALTYPE to facilitate access to the ClientInfo key.

?????? 可以看到,第一個參數用來指定Driver的注冊表路徑,而第二個參數用來寫入到Active Key下,如果不需要寫入的話,可以置為NULL?

2.如何保證加載的Driver處于Kernel Mode

?????? 6.0下引入了Group的概念,通過注冊表可以去定義一個Group,一個簡單的Group定義如下:

[HKEY_LOCAL_MACHINE/Drivers/ProcGroup_0002]

??? "ProcName"="servicesd.exe"

??? "ProcVolPrefix"="$services"

??? "ProcTimeout"=dword:20000

?

[HKEY_LOCAL_MACHINE/Drivers/ProcGroup_0003]

??? "ProcName"="udevice.exe"

??? "ProcVolPrefix"="$udevice"

?????? 其實,簡單點理解Group就是將Driver的加載方式進行細分,方便不同的Driver使用不同的系統組件進行加載。

?????? Driver的注冊表項可以用來指定加載自己的Group,如下:

[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/Ethman]

"Prefix"="ETM"

"Dll"="ethman.dll"

"Index"=dword:1

; WZCSVC must be started before ethman

"Order"=dword:2A

; Flags==12 is DEVFLAGS_LOADLIBRARY and DEVFLAGS_LOAD_AS_USERPROC

"Flags"=dword:12

"UserProcGroup"=dword:3 ; // default to group 3

?

[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/SIP]

"Prefix"="SIP"

"Dll"="softkb.DLL"

"Order"=dword:1

"Index"=dword:0

;Flags==10 is DEVFLAGS_LOAD_AS_USERPROC

"Flags"=dword:10

"UserProcGroup"=dword:3 ; // default to group 3

?????? 對于指定通過某個Group進行加載的Driver,系統中進行加載的時候會引入Reflect機制。該機制主要用來對檢察注冊表項中的IoLenIoBase值,當檢察到Driver中訪問了不在IoLenIoBase指定區域的物理內存時,將會出現系統異常。

?????? 對于那些沒有指定使用Group進行加載的驅動,WinCE6.0中將其加載到Kernel Mode下。也就是說,它們具有了訪問整個4GB空間的權限。

?????? 要保證User Mode下加載的Driver處于Kernel Mode,只需要在注冊表中不去指定User Group就可以了。????

3.如何將Driver DLLExe 做成一個文件

?????? 之所以將DriverEXE組合成一個文件,是為了用戶使用的方便。想象一下,如果不把兩者做成一個文件的話,一個簡單的訪問物理內存的應用程序就變成了兩個文件,那是多么不美觀的事情。

?????? 其實實現將Driver DLLEXE做成一個文件有兩個方法。方法一,由于DLLEXE都是PE結構的,可以使用網上的加殼工具將其組合成一個PE文件,而在運行的時候自動去殼即可。方法二,將DLL中的信息提取出來放到EXEData Section,然后在運行的時候,將這些數據重新組合成一個DLL

?????? 這里我采用了第二種方法來實現組合DriverEXE文件。

三.代碼實現

1.將Driver注冊表的操作簡化

?????? 操作過CE下注冊表的兄弟們都知道,微軟設計的注冊表非常簡單,可是操作API實在是不那么友好。

?????? 我這里使用了PB6.0源文件PUBLIC/WCESHELLFE/OAK/CTLPNL/CPLMAIN/cplmacro.h中的類CReg來實現對Driver注冊表項的讀寫動作。

?????? 該注冊表類主要封裝了注冊表的Open/Read/Write API,為用戶提供了一種更加友好的注冊表操作接口。

?????? 該類的定義和實現如下:

class CReg

{

private:

???? HKEY m_hKey;

???? int????? m_Index;

???? LPBYTE?? m_lpbValue; // last value read, if any

?

public:

???? BOOL Create(HKEY hkRoot, LPCTSTR pszKey) {

???????? DWORD dwDisp;

???????? return ERROR_SUCCESS==RegCreateKeyEx(hkRoot, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hKey, &dwDisp);

???? }

?

???? BOOL Open(HKEY hkRoot, LPCTSTR pszKey, REGSAM sam=KEY_READ) {

???????? return ERROR_SUCCESS==RegOpenKeyEx(hkRoot, pszKey, 0, sam, &m_hKey);

???? }

?

???? CReg(HKEY hkRoot, LPCTSTR pszKey) {

???????? m_hKey = NULL;

???????? m_Index = 0;

???????? m_lpbValue = NULL;

???????? Open(hkRoot, pszKey);

???? }

?

???? CReg() {

???????? m_hKey = NULL;

???????? m_Index = 0;

???????? m_lpbValue = NULL;

???? }

?

???? ~CReg() {

???????? if(m_hKey) RegCloseKey(m_hKey);

???????? MyFree(m_lpbValue);

???? }

?

???? void Reset() {

???????? if(m_hKey) RegCloseKey(m_hKey);

???????? MyFree(m_lpbValue);

???????? m_hKey = NULL;

???????? m_Index = 0;

???????? m_lpbValue = NULL;

???? }

?

???? operator HKEY() { return m_hKey; }

?

???? BOOL IsOK(void) { return m_hKey!=NULL; }

?

?

???? BOOL EnumKey(LPTSTR psz, DWORD dwLen) {

???????? if(!m_hKey) return FALSE;

???????? return ERROR_SUCCESS==RegEnumKeyEx(m_hKey, m_Index++, psz, &dwLen, NULL, NULL, NULL, NULL);

???? }

?

???? BOOL EnumValue(LPTSTR pszName, DWORD dwLenName, LPTSTR pszValue, DWORD dwLenValue) {

???????? DWORD dwType;

???????? if(!m_hKey) return FALSE;

???????? dwLenValue *= sizeof(TCHAR); // convert length in chars to bytes

???????? return ERROR_SUCCESS==RegEnumValue(m_hKey, m_Index++, pszName, &dwLenName, NULL, &dwType, (LPBYTE)pszValue, &dwLenValue);

???? }

?

???? BOOL ValueSZ(LPCTSTR szName, LPTSTR szValue, DWORD dwLen) {

???????? if(!m_hKey) return FALSE;

???????? dwLen *= sizeof(TCHAR); // convert length in chars to bytes

???????? return ERROR_SUCCESS==RegQueryValueEx(m_hKey, szName, NULL, NULL, (LPBYTE)szValue, &dwLen);

???? }

?

???? DWORD ValueBinary(LPCTSTR szName, LPBYTE lpbValue, DWORD dwLen) {

???????? if(!m_hKey) return FALSE;

???????? DWORD dwLenWant = dwLen;

???????? if(ERROR_SUCCESS==RegQueryValueEx(m_hKey, szName, NULL, NULL, lpbValue, &dwLen))

????????????? return dwLen;

???????? else

????????????? return 0;

???? }

?

???? LPCTSTR ValueSZ(LPCTSTR szName);

?

???? LPBYTE ValueBinary(LPCTSTR szName) {

???????? return (LPBYTE)ValueSZ(szName);

???? }

?

???? DWORD ValueDW(LPCTSTR szName, DWORD dwDefault=0) {

???????? if(!m_hKey) return FALSE;

???????? DWORD dwValue = dwDefault;

???????? DWORD dwLen = sizeof(DWORD);

???????? RegQueryValueEx(m_hKey, szName, NULL, NULL, (LPBYTE)&dwValue, &dwLen);

???????? return dwValue;

???? }

?

???? BOOL SetSZ(LPCTSTR szName, LPCTSTR szValue, DWORD dwLen) {

???????? //Prefix

???????? if(!m_hKey) return FALSE;

???????? //

???????? return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_SZ, (LPBYTE)szValue, sizeof(TCHAR)*dwLen);

???? }

?

???? BOOL SetSZ(LPCTSTR szName, LPCTSTR szValue) {

???????? return SetSZ(szName, szValue, 1+lstrlen(szValue));

???? }

?

???? BOOL SetDW(LPCTSTR szName, DWORD dwValue) {

???????? //Prefix

???????? if(!m_hKey) return FALSE;

???????? //

???????? return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));

???? }

?

???? BOOL SetBinary(LPCTSTR szName, LPBYTE lpbValue, DWORD dwLen) {

???????? //Prefix

???????? if(!m_hKey) return FALSE;

???????? //

???????? return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_BINARY, lpbValue, dwLen);

???? }

?

???? BOOL SetMultiSZ(LPCTSTR szName, LPCTSTR lpszValue, DWORD dwLen) {

???????? return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_MULTI_SZ, (LPBYTE)lpszValue, sizeof(TCHAR)*dwLen);

???? }

?

???? BOOL DeleteValue(LPCTSTR szName) {

???????? //Prefix

???????? if(!m_hKey) return FALSE;

???????? //

???????? return ERROR_SUCCESS==RegDeleteValue(m_hKey, szName);

???? }

?

???? BOOL DeleteKey(LPCTSTR szName) {

???????? if(!m_hKey) return FALSE;

???????? return ERROR_SUCCESS==RegDeleteKey(m_hKey, szName);

???? }

};

?????? 具體的使用方法可參照后面代碼中LoadMemDrv()的實現。

2DriverDLL合并與解壓

?????? 合并方法很簡單。首先,我將DLL中的每個字節的數據提取出來組合成一個數組,然后在AP中引用該數組。

?????? 解壓的時候,直接將該數組組合成DriverDLL就行了,如下:

// 從靜態變量區提取MEM_DRV_NAME驅動的內容,并將其組合成為一個Driverdll

{

???? HANDLE?? hTempFile = INVALID_HANDLE_VALUE;

???? DWORD??? dwBytesReturned = 0;

???? TCHAR??? szFileName[MAX_PATH/2] = {0,};

?

???? wsprintf(szFileName, L"%s%s", TEXT("//"), MEM_DRV_NAME);

?

???? hTempFile = CreateFile(

???????? szFileName,

???????? GENERIC_READ|GENERIC_WRITE,

???????? FILE_SHARE_WRITE|FILE_SHARE_READ,

???????? NULL,

???????? CREATE_ALWAYS,

???????? FILE_ATTRIBUTE_NORMAL,

???????? NULL

???????? );

?

???? if (INVALID_HANDLE_VALUE == hTempFile)

???? {

???????? LogMessage(TEXT("[ERR] Faild to create file. File name %s"), szFileName);

???? }

???? else

???? {????????????

???????? // DllFile就是DLL變量數組的名字

???????? // 這里將DLL的內容寫入到前面創建的文件L"MyMemoryDrv.dll"

???????? if (!WriteFile(hTempFile, DllFile, sizeof(DllFile), &dwBytesReturned, NULL))

???????? {

????????????? LogMessage(TEXT("[ERR] Faild to write file.? Error code 0x%x"), GetLastError());

???????? }

???????? else

???????? {?????????????????

????????????? LogMessage(TEXT("Create driver %s successfully"), szFileName);

???????? }

?

???????? CloseHandle(hTempFile);

????????

???????? DeleteFile(MEM_DRV_DST_PATH);

?

???????? //if (!CopyFile(szFileName, L"//me.dat", 0))

???????? if (!CopyFile(szFileName, MEM_DRV_DST_PATH, FALSE))

???????? {

????????????? LogMessage(L"[ERR] Copy memory driver from %s to %s failed, Error code 0x%x!", szFileName, MEM_DRV_DST_PATH, GetLastError());

???????? }

???? }???????

}

3Driver的實現

?????? 由于該Driver的功能僅僅是在User ModeKernel Mode下的內存之間做轉換,所以只需要簡單的實現一下DeviceIoControl就可以了,其它的流接口除了OpenInit直接為空就行了。

?????? 如下:

/*

* make use of MEM_IOControl to control memory address space conversion

* Para:

*??? pInBuf:?????? physical or virtual memory address

*??? nInBufSize:?? 4

*??? pOutBuf:????? user buffer used to store data

*??? nOutBufSize:? size of data the user wanted in bytes [note********************]

*/

DWORD MEM_IOControl(DWORD Handle, DWORD dwIoControlCode, PBYTE pInBuf,

?????????????????????? DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)

{

???? DWORD bRetVal = ERROR_SUCCESS;

???? PBYTE pMemBuffer = NULL;

????

???? NKDbgPrintfW(L"MEM_IOControl(). Handle 0x%x, Code 0x%x, pInBuf 0x%8x, InSize 0x%x, OutSize 0x%x/r/n", Handle, dwIoControlCode, *(DWORD *)pInBuf, nInBufSize, nOutBufSize);

????

??? switch(dwIoControlCode) {

???? case IOCTL_MEM_GET_PHYSICAL_RAM:

???????? NKDbgPrintfW(TEXT("IOCTL_MEM_GET_PHYSICAL_RAM/r/n"));

???????? break;

???? case IOCTL_MEM_GET_VIRTUAL_RAM:

???????? NKDbgPrintfW(TEXT("IOCTL_MEM_GET_VIRTUAL_RAM/r/n"));

???????? break;

???? default:

???????? NKDbgPrintfW(TEXT("**UNKNOWN**/r/n"));

???????? break;

??? }

????

????

??? switch(dwIoControlCode) {

???? case IOCTL_MEM_GET_PHYSICAL_RAM:

???????? {????????????

????????????? do

????????????? {?????????????????

?????????????????? if (pInBuf == NULL || nInBufSize != sizeof(DWORD) || pOutBuf == NULL || nOutBufSize == 0)

?????????????????? {

??????????????????????

?????????????????????? NKDbgPrintfW((_T("MEM_IOControl: IOCTL_MEM_GET_PHYSICAL_RAM - invalid paramter/n/r")));

?????????????????????? bRetVal = ERROR_INVALID_PARAMETER;

?????????????????????? break;

?????????????????? }

??????????????????

?????????????????? pMemBuffer = (PBYTE)VirtualAlloc(NULL, nOutBufSize, MEM_RESERVE, PAGE_NOACCESS);

??????????????????

?????????????????? if (NULL != pMemBuffer)

?????????????????? {

??????????????????????

?????????????????????? if (!VirtualCopy((void *)pMemBuffer, (void *)((*(DWORD *)pInBuf)>>8), nOutBufSize, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))

?????????????????????? {

??????????????????????????? NKDbgPrintfW((_T("[MEMDRV] MEM_IOControl() : pMemBuffer VirtualCopy() Failed /n/r")));

??????????????????????????? bRetVal = ERROR_INVALID_PARAMETER;

?????????????????????? }

?????????????????????? else

?????????????????????? {

???????????????????????????

??????????????????????????? __try

??????????????????????????? {???

???????????????????????????????? NKDbgPrintfW(L"Physical Add: 0x%8x, Virtual Add: 0x%8x/r/n", *(DWORD *)pInBuf, *(DWORD*)pMemBuffer);

???????????????????????????????? memcpy(pOutBuf, pMemBuffer, nOutBufSize);

??????????????????????????? }

??????????????????????????? __except(EXCEPTION_EXECUTE_HANDLER)

??????????????????????????? {

???????????????????????????????? NKDbgPrintfW((L"[ERR] Throw out exception in MEMDRV: MEM_IOControl()"));

???????????????????????????????? bRetVal = ERROR_INVALID_PARAMETER;

??????????????????????????? }

?????????????????????? }

??????????????????????

?????????????????????? VirtualFree(pMemBuffer, 0, MEM_RELEASE);

?????????????????? }???

?????????????????? else

?????????????????? {

?????????????????????? NKDbgPrintfW((_T("[MEMDRV] MEM_IOControl() : pMemBuffer VirtualCopy() Failed /n/r")));

?????????????????????? bRetVal = ERROR_INVALID_PARAMETER;?????????????????????

?????????????????? }

????????????? }

????????????? while(0);?????????

?????????????

???????? }

???????? break;

???? case IOCTL_MEM_GET_VIRTUAL_RAM:

???????? {????????????

????????????? NKDbgPrintfW(TEXT("IOCTL_MEM_GET_VIRTUAL_RAM/r/n"));

????????????? __try

????????????? {???

?????????????????? // copy data from pInBuf to pOutBuf

?????????????????? memcpy(pOutBuf, &pInBuf, nOutBufSize);???

????????????? }

????????????? __except(EXCEPTION_EXECUTE_HANDLER)

????????????? {

?????????????????? NKDbgPrintfW((L"[ERR] Throw out exception in MEMDRV: MEM_IOControl()"));

?????????????????? bRetVal = ERROR_INVALID_PARAMETER;

????????????? }

???????? }

???????? break;

???? default:

???????? NKDbgPrintfW(TEXT("**UNKNOWN**/r/n"));

???????? bRetVal = ERROR_INVALID_PARAMETER;

???????? break;

??? }

????

???? return (ERROR_SUCCESS == bRetVal);

}

4Driver的加載????

?????? Driver的加載包括兩個過程。首先將Driver相關的注冊表項寫入到注冊表中,然后調用API ActivateDevice()來實現動態的加載。

?????? 代碼如下:

/*

?

[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MEM]

"Dll"="MyMemoryDrv.dll"

"Prefix"="MEM"

"Index"=dword:1

"Order"=dword:0

"FriendlyName"="MEM driver"

?

*/

#define MEM_DRV_NAME???????????? L"MEM1:"

bool? LoadMemDrv(void)

{

???? BOOL bRetVal = false;

?

???? // Step1: modify the registry

???? class CReg MemDrvReg;

?

???? bRetVal = MemDrvReg.Create(HKEY_LOCAL_MACHINE, MEM_DRV_PATH);

???? bRetVal= MemDrvReg.SetSZ(L"Dll", L"MyMemoryDrv.dll");//, sizeof(L"MyMemoryDrv.dll")/sizeof(TCHAR));

???? MemDrvReg.SetSZ(L"Prefix", L"MEM");//, sizeof(L"MEM")/sizeof(TCHAR));

???? MemDrvReg.SetDW(L"Order", 0);

???? MemDrvReg.SetDW(L"Index", 1);

???? MemDrvReg.SetDW(L"Index", 1);

???? MemDrvReg.SetSZ(L"FriendlyName", L"MEM driver");//, sizeof(L"MEM driver")/sizeof(TCHAR));

?

???? // Step2: load driver unsing device manager

???? hActiveMemDrv = INVALID_HANDLE_VALUE;

?

???? hActiveMemDrv = ActivateDevice(MEM_DRV_PATH, 0);

???? if (INVALID_HANDLE_VALUE == hActiveMemDrv)

???? {

???????? LogMessage(L"[ERR]Load driver %s failed", MEM_DRV_FULL_PATH);

???????? goto EXIT;

???? }

?

???? // Step3: Open stream driver????

???? hFile = INVALID_HANDLE_VALUE;

???? hFile = CreateFile(MEM_DRV_NAME,

???????? GENERIC_READ|GENERIC_WRITE,

???????? 0,

???????? NULL,

???????? OPEN_EXISTING,

???????? FILE_ATTRIBUTE_NORMAL,

???????? NULL);

????

???? if (INVALID_HANDLE_VALUE == hFile)

???? {

???????? LogMessage(L"[ERR] Open stream driver %s failed. Error code 0x%8x", MEM_DRV_NAME, GetLastError());

???????? goto EXIT;

???? }

?

???? bIsDrvLoad = true;

???? bRetVal = TRUE;

?

EXIT:???

???? return (bRetVal == TRUE);

}

附:

具體的實現代碼可以到我的資源中下載。

總結

以上是生活随笔為你收集整理的一种User Mode下访问物理内存及Kernel Space的简单实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日本69少妇 | 五月婷在线观看 | 国产精品久久久影院 | jizz在亚洲 | 国产肉体ⅹxxx137大胆 | 中文字幕人妻一区二区三区 | 大桥未久在线视频 | 色婷婷yy | 黄色在线免费网站 | 国产又色又爽又黄又免费 | 99成人精品 | 国产特级黄色片 | 精品自拍视频在线观看 | 欧美美女视频 | 久久天堂av综合合色蜜桃网 | 99热国产在线观看 | 97久久久久久久 | 国产成人精品一区二区三区网站观看 | 日韩欧美一二三四区 | 婷婷激情五月 | 欧美日韩一二三四区 | 久久人人爽人人爽人人片av免费 | 久久久久国产精品视频 | 免费搞黄网站 | 日本黄色一级 | 国产女人在线 | 免费成人深夜夜 | 欧美一区二区三区免费在线观看 | 在线中文字幕日韩 | 日韩欧美亚洲精品 | 欧美专区日韩专区 | 国产一区伦理 | 国产色无码精品视频 | 黄色不打码视频 | 久久久777| 久久久99精品 | 国产精品黄色在线观看 | 国产自产21区 | 一本色道久久综合精品婷婷 | 2019中文字幕在线免费观看 | www.久久网| 四虎在线观看 | 国产av一区不卡 | 在线免费看污网站 | 免费久久久久 | 日韩卡一卡二 | 牛牛免费视频 | 一区二区成人av | 国产xxxx18 | 人妻熟人中文字幕一区二区 | 美女扒开尿口给男人看 | 91成人观看 | 国产日韩激情 | 91精品看片 | 色欲无码人妻久久精品 | 免费av在线播放 | 中文高清av| 91大神视频在线播放 | 国产一区二区三区在线免费观看 | 一区精品二区国产 | 玖玖伊人 | 国产三级成人 | 丰满人妻av一区二区三区 | 国产无遮挡又黄又爽在线观看 | 色婷婷综合久久久久中文 | 99久久国产宗和精品1上映 | 亚洲成人天堂 | 国产免费观看视频 | 欧美变态另类刺激 | 日韩免费三级 | wwww日本60 | 日本高清视频免费观看 | 和漂亮岳做爰3中文字幕 | 国产日韩一区二区三区在线观看 | 青青草国产成人99久久 | 天堂网av2018| 99久久综合国产精品二区 | 日韩美女做爰高潮免费 | 青青视频免费看 | 大屁股一区二区三区 | 亚洲人成网站999久久久综合 | 超碰97免费 | 亚洲综合成人亚洲 | 亚洲五十路| 色片网站在线观看 | 中文字幕第31页 | 精品国产999 | 88av在线播放 | 男人操女人的视频 | 特黄老太婆aa毛毛片 | 深夜视频免费在线观看 | 国产精品500部 | 91高清在线视频 | 一区二区三区视频免费视 | 美女又黄又免费的视频 | 少妇的性事hd | 壮汉被书生c到合不拢腿 | 日韩一级影片 | 99香蕉网 |