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

S.l.e!ep.¢%

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

利用鉤子技術控制進程創建

Posted on 2009-10-27 18:51 S.l.e!ep.¢% 閱讀(304) 評論(0)  編輯 收藏 引用 所屬分類: RootKit
? 收藏的一些書 [轉載]從源碼看下載者生成器 ?

[轉載]利用鉤子技術控制進程創建

信息來源:新浪網

一、 簡介

  最近,我了解到一個叫做Sanctuary的相當有趣的安全產品。它能夠阻止任何程序的運行-這些程序沒有顯示在軟件列表中-該表中的程序被允許在一個特定的機器上運行。結果,PC用戶得到保護而免于各種插件間諜軟件、蠕蟲和特洛伊木馬的侵襲-就算能夠進入他/她的計算機,它們也沒有機會執行,并因此沒有機會對該機器造成任何損害。當然,我覺得這個特征相當有趣;并且,在稍作思考以后,我就有了一個自己的實現。因此,本文將描述如何通過鉤住本機API的方式來實現監控一個進程的創建并在系統級上對之進行控制。

  本文大膽假設,目標進程是以一種用戶模式(外殼函數,CreateProcess(),用一系列的本機API調用的手工的進程創建,等等)創建的。盡管從理論上,一個進程能夠以內核方式啟動;不過從實際來看,如此的可能性是可以忽略不計的,因此我們不必為此擔心。為什么?請邏輯地思考一下-為了以內核方式啟動一個進程,用戶必須裝載一個驅動程序,該驅動程序反過來首先要暗示某種用戶模式代碼的執行。因此,為了防止未被授權程序的執行,我們可以安全地在系統級上以用戶模式限制我們自己控制的進程的創建。

  二、 定義策略

  首先讓我們明確,之所以這樣做的目的是為了在系統級上監視和控制進程創建。

  進程創建是一件相當復雜的事情-它包含相當多的工作(如果你不相信我,可以反匯編CreateProcess(),這樣你就會親眼看到這點)。為了啟動一個進程,可以使用下列步驟:

  1.可執行文件必須被以FILE_EXECUTE存取方式打開。

  2.可執行映像必須被裝載進RAM。

  3.必須建立進程執行對象(EPROCESS,KPROCESS和PEB結構)。

  4.必須為新建進程分配地址空間。

  5.必須建立進程的主線程的線程執行對象(ETHREAD,KTHREAD和TEBstructures)。

  6.必須為主線程分配堆棧。

  7.必須建立進程的主線程的執行上下文。

  8.必須通知Win32子系統有關該新進程的創建情況。

  為確保這些步驟中的任何一步的成功,所有其前面的步驟必須是成功執行的(你不能夠在沒有一個可執行區句柄的情況下建立一個可執行進程對象;沒有文件句柄的情況下你無法映射一個可執行區,等等)。因此,如果我們決定退出任何這些步驟,所有后面的步驟也會失敗,以至于整個進程創建會失敗。上面所有的步驟都可以通過調用某些本機API函數的方式來實現,這是可以理解的。因此,為了監視和控制進程創建,我們所有要做的就是鉤住這些API函數-它們無法旁路掉要創建一新進程所要執行的代碼。

  我們應該鉤住哪些本機API函數呢?盡管NtCreateProcess()似乎是問題的最顯然的答案,但是,這個答案是錯誤的-有可能不需要調用這個函數也可以創建一個新的進程。例如,CreateProcess()可以創建與進程相關的內核模式結構而不是調用NtCreateProcess()。因此,這樣以來鉤住NtCreateProcess()對我們毫無幫助。

  為了監視進程的創建,我們必須或者鉤住NtCreateFile()和NtOpenFile(),或者鉤住NtCreateSection()-不經調用這些API是絕對無法運行任何可執行文件的。如果我們決定監視對NtCreateFile()和NtOpenFile()的調用,那么我們必須區別開進程創建和常規的文件IO操作。這項任務并不總是那么容易。例如,如果一些可執行文件正在被以FILE_ALL_ACCESS存取方式打開,我們該怎么辦?這僅是一個IO操作還是一個進程創建的一部分?在這點上,是很難判斷的-我們需要了解調用線程下一步要干什么。因此,鉤住NtCreateFile()和NtOpenFile()不是最好的可能性選擇。

  鉤住NtCreateSection()是更為合理的-如果我們想攔截對NtCreateSection()的調用,發出的請求是作為一個映像(SEC_IMAGE屬性)映射可執行文件(SEC_IMAGE屬性),同時請求允許執行的頁面保護;那么,我們可以確信該進程將要被啟動。在這一點上,我們是能夠作出決定的,并且在我們不想要創建該進程的情況下,讓NtCreateSection()返回STATUS_ACCESS_DENIED。因此,為了完全控制目標機器上的進程創建,所有我們要做的是在系統級上鉤住NtCreateSection()。

  象來自于ntdll.dll中的任何其它代理一樣,NtCreateSection()用服務索引加載EAX,使EDX指向函數參數,并且把執行權傳遞到KiDispatchService()內核模式例程(這是通過Windows NT/2000中的INT 0x2E指令或者Windows XP下的SYSENTER指令實現的)。在校驗完函數參數之后,KiDispatchService()把執行權傳遞到服務的實際實現部分-它的地址可用于服務描述表(指向這個表的指針由ntoskrnl.exe作為KeServiceDescriptorTable變量所輸出,所以它對于內核模式驅動程序是可用的)中。服務描述表通過下列結構所描述:
Copy code

  struct SYS_SERVICE_TABLE {

  void **ServiceTable;

  unsigned long CounterTable;

  unsigned long ServiceLimit;

  void **ArgumentsTable;

  };

  這個結構中的ServiceTable字段指向一個數組-它擁有所有實現系統服務的函數的地址。因此,為了在系統級上鉤住任何本機API函數,所有我們必須做的是把我們的代理函數的地址寫入被KeServiceDescriptorTable的ServiceTable字段所指向的數組的第i個入口(i是服務索引)。

  至此,看起來我們已了解了在系統級上監視和控制進程創建的一切?,F在讓我們開始實際的工作。


? 三、 控制進程創建

  我們的解決方案由一個內核模式驅動程序和一個用戶模式應用程序組成。為了開始監視進程創建,我們的應用程序要把服務索引(相應于NtCreateSection())以及交換緩沖區的地址傳遞到我們的驅動程序。這是由下列代碼所完成的:
Copy code

//打開設備
device=CreateFile("\\.\PROTECTOR",GENERIC_READ|GENERIC_WRITE,
0,0,OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0);
//得到NtCreateSection的索引并把它連同輸出緩沖區的地址傳遞給設備
DWORD * addr=(DWORD *)
(1+(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtCreateSection"));
ZeroMemory(outputbuff,256);
controlbuff[0]=addr[0];
controlbuff[1]=(DWORD)&outputbuff[0];
DeviceIoControl(device,1000,controlbuff,256,controlbuff,256,&dw,0);


  此代碼是顯然的-唯一需要注意的是我們得到服務索引的方式。所有來自于ntdll.dll的代理都從一行代碼MOV EAX,ServiceIndex開始-它可以適用于任何版本和風味的Windows NT。這是一條5字節長的指令,以MOV EAX操作碼作第一字節,服務索引作為留下的4字節。因此,為了得到相應于一些特別的本機API函數的服務索引,所有你要做的是從該地址讀取4個字節,-位于從這個代理開始1字節距離的地方。

  現在讓我們看一下我們的驅動程序做什么,當它收到來自我們的應用程序的IOCTL時:

Copy code

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT device,IN PIRP Irp)
{
 UCHAR*buff=0; ULONG a,base;
 PIO_STACK_LOCATION loc=IoGetCurrentIrpStackLocation(Irp);
 if(loc->Parameters.DeviceIoControl.IoControlCode==1000)
 {
  buff=(UCHAR*)Irp->AssociatedIrp.SystemBuffer;
  //鉤住服務調度表
  memmove(&Index,buff,4);
  a=4*Index+(ULONG)KeServiceDescriptorTable->ServiceTable;
  base=(ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a),4,0);
  a=(ULONG)&Proxy;
  _asm
  {
   mov eax,base
   mov ebx,dword ptr[eax]
   mov RealCallee,ebx
   mov ebx,a
   mov dword ptr[eax],ebx
  }
  MmUnmapIoSpace(base,4);
  memmove(&a,&buff[4],4);
  output=(char*)MmMapIoSpace(MmGetPhysicalAddress((void*)a),256,0);
 }
 Irp->IoStatus.Status=0;
 IoCompleteRequest(Irp,IO_NO_INCREMENT);
 return 0;
}



  正如你所見,這里沒有什么特別的-我們只是通過MmMapIoSpace()來把交換緩沖區映射到內核中,另外把我們的代理函數的地址寫到服務表(當然,我們這是在把實際的服務執行的地址保存到全局變量RealCallee以后這樣做的)。為了改寫服務表的適當入口,我們通過MmMapIoSpace()來映射目標地址。為什么我們要這樣做?不管怎么說,我們已經可以存取服務表了,不是嗎?問題是,服務表可能駐留在一段只讀內存中。因此,我們必須檢查一下是否我們有對目標空間寫的權限,而如果我們沒有這個權限,那么在改寫服務表之前,我們必須改變頁面保護。你不認為這樣以來工作太多了嗎?因此,我們僅用MmMapIoSpace()來映射我們的目標地址,這樣以來,我們就不必擔心任何的頁面保護問題了-從現在開始,我們假定已有到目標頁面寫的權限了?,F在讓我們看一下我們的代理函數:

Copy code

//這個函數用來確定是否我們應該允許NtCreateSection()調用成功
ULONG __stdcall check(PULONG arg)
{
 HANDLE hand=0;PFILE_OBJECT file=0;
 POBJECT_HANDLE_INFORMATION info;ULONG a;char*buff;
 ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;
 //檢查標志。如果所要求的存取方式不是PAGE_EXECUTE,
 //這并不要緊
 if((arg[4]&0xf0)==0)return 1;
 if((arg[5]&0x01000000)==0)return 1;
 //經由文件句柄得到文件名
 hand=(HANDLE)arg[6];
 ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,&info);
 if(!file)return 1;
  RtlUnicodeStringToAnsiString(&str,&file->FileName,1);
  a=str.Length;buff=str.Buffer;
  while(1)
  {
   if(buff[a]=='.'){a++;break;}
   a--;
  }
  ObDereferenceObject(file);
  //如果它是不可執行的,這也不要緊
  //返回1
  if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}
   //現在,我們要詢問用戶的選擇。
   //把文件名寫入緩沖區,并等待直到用戶顯示響應
   //(第一個DWORD為1意味著我們可以繼續)
   //同步存取該緩沖區
   KeWaitForSingleObject(&event,Executive,KernelMode,0,0);
   //把緩沖區的前兩個DWORD置為0,
   //把字符串復制到該緩沖區中,并循環下去,直到用戶把每一個
   //DWORD置為1.
   //第二個DWORD的值指明用戶的響應
  strcpy(&output[8],buff);
  RtlFreeAnsiString(&str);
  a=1;
  memmove(&output[0],&a,4);
  while(1)
  {
   KeDelayExecutionThread(KernelMode,0,&li);
   memmove(&a,&output[0],4);
   if(!a)break;
  }
  memmove(&a,&output[4],4);
  KeSetEvent(&event,0,0);
  return a;
 }
 //僅保存執行上下文并調用check()
 _declspec(naked) Proxy()
 {
  _asm{
   //保存執行上下文并調用check()
   //-后面的依賴于check()所返回的值
   // 如果返回值是1,繼續實際的調用。
   //否則,返回STATUS_ACCESS_DENIED
   pushfd
   pushad
   mov ebx,esp
   add ebx,40
   push ebx
   call check
   cmp eax,1
   jne block
   //繼續實際的調用
   popad
   popfd
   jmp RealCallee
   //返回STATUS_ACCESS_DENIED
   block:popad
   mov ebx, dword ptr[esp+8]
   mov dword ptr[ebx],0
   mov eax,0xC0000022L
   popfd
   ret 32
  }
 }



  Proxy()保存寄存器和標志,把一個指向服務參數的指針壓入棧中并調用check()。其它的依賴于check()所返回的值。如果check()返回TRUE(也就是,我們想要繼續請求),那么,Proxy()將恢復寄存器和標志,并且把控制權交給服務實現部分。否則,Proxy()將把STATUS_ACCESS_DENIED寫入EAX,恢復ESP并返回-從調用者的觀點來看,這就象對NtCreateSection()的調用失敗一樣-以錯誤狀態STATUS_ACCESS_DENIED返回。


? check()函數是怎樣做出決定的?一旦它收到一個指向服務參數的指針參數,它就可以檢查這些參數。首先,它檢查標志和屬性-如果有一部分沒有被要求作為一個可執行映像映射,或如果要求的頁面保護不允許執行,那么我們可以確定NtCreateSection()調用與進程創建毫無關系。在這種情況下,check()直接返回TRUE。否則,它將檢查該潛在文件的擴展-畢竟,SEC_IMAGE屬性和允許執行的頁面保護可能被要求來映射某個DLL文件。如果該潛在文件不是一個.exe文件,那么,check()將返回TRUE。否則,它給用戶模式代碼一個作出決定的機會。因此,它僅把文件名和路徑寫到交換緩沖區,并且對它循環查詢,直到它得到響應為止。

  在打開我們的驅動程序前,我們的應用程序創建一個運行下面函數的線程:

Copy code

void thread()
{
 DWORD a,x; char msgbuff[512];
 while(1)
 {
  memmove(&a,&outputbuff[0],4);
  //如果什么也沒有,Sleep() 10毫秒并再檢查
  if(!a){Sleep(10);continue;}
  //看起來象我們的權限被詢問。
  //如果被懷疑的文件已經存在于空白列表中,
  // 則給出一個積極的響應。
  char*name=(char*)&outputbuff[8];
  for(x=0;x<stringcount;x++)
  {
   if(!stricmp(name,strings[x])){a=1;goto skip;}
  }
  //要求用戶允許運行該程序
  strcpy(msgbuff, "Do you want to run ");
  strcat(msgbuff,&outputbuff[8]);
  //如果用戶的答復是積極的,那么把這個程序添加到空白列表中
  if(IDYES==MessageBox(0, msgbuff,"WARNING",MB_YESNO|MB_ICONQUESTION|0x00200000L))
   {a=1; strings[stringcount]=_strdup(name);stringcount++;}
  else a=0;
  // 把響應寫入緩沖區中,而由驅動程序之后取回它
  skip:memmove(&outputbuff[4],&a,4);
  //告訴驅動程序繼續
  a=0;
  memmove(&outputbuff[0],&a,4);
 }
}


  這段代碼是顯然的-我們的線程每10毫秒查詢交換緩沖區。如果它發現我們的驅動程序已經把它的請求寄到了該緩沖區中,它就檢查被允許在本機上運行的程序列表中的文件的文件名和路徑。如果發現匹配,它直接給出一個OK響應。否則,它顯示一個消息窗口,詢問用戶是否允許有問題的程序執行。如果響應是積極的,我們就把有問題的程序添加到允許在本機上運行的軟件列表中。最后,我們把用戶響應寫入緩沖區,也就是說,把它傳遞到我們的驅動程序。因此,該用戶就能完全控制它的PC上的進程的創建-只要我們的程序運行,在沒有用戶所給予權限的情況下,絕對沒有辦法來啟動該PC上的任何進程。

  正如你所見,我們讓內核方式代碼等待用戶反應。這是否是一種聰明的舉措呢?為了回答這個問題,你必須問你自己你是否正在堵住任何關鍵的系統資源-一切都依賴于具體的情況。在我們的情況下,一切發生在IRQLPASSIVE_LEVEL級上,并沒有包含對IRPs的處理,并且必須等待用戶響應的線程并不十分重要。因此,在我們的情況下,一切工作正常。然而,本例僅為演示之目的而編寫。為了實際地使用它,以一個自動啟動的服務的方式來重寫我們的應用程序是很重要的。在這種情況下,我建議我們解除LocalSystem帳戶,并且,在NtCreateSection()被用LocalSystem帳戶特權在一個線程的上下文中調用的情況下,可以繼續實際的服務實現而不施行任何檢查-不管怎么說,LocalSystem帳戶僅運行那些在注冊表中指定的可執行程序。因此,這樣的一種解除不會是與我們的安全相妥協的。

  四、 結論

  最后,我必須指出,鉤住本機API很明顯是現已存在的最強有力的編程技術之一。本文通過一個例子向你展示通過鉤住本機API可以實現的能力-正如你所見,我們已設法防止未被授權的程序的執行-這可以通過鉤住單一的本機API函數來實現。你可以進一步擴展這個方法,并且獲得對硬件設備、文件IO操作、網絡流量等等的完全控制。然而,我們現在的解決方案并不是準備為內核模式API調用者所用-一旦內核模式代碼被允許直接調用ntoskrnl.exe的輸出,則這些調用就不需要經由系統服務發送者進行了。

  本文源碼在運行Windows XP SP2的若干機器上成功地測試過。盡管我還沒在任何另外的環境下面測試它,我相信它應該到處工作正常-不管怎么說,它從未使用任何系統特定的結構。為了運行這個示例,所有你要做的是放置protector.exe和protector.sys到相同的目錄下,并且運行protector.exe。直到protector.exe的應用程序窗口被關閉為止;否則,每次你都會被提示你試圖運行任何可執行程序。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            日韩视频在线免费| 亚洲精品乱码视频| 久久久国产亚洲精品| 亚洲视屏在线播放| 亚洲网站在线观看| 亚洲图片激情小说| 亚洲一区二区三区影院| 亚洲一区二区视频在线| 午夜影院日韩| 久久综合网hezyo| 麻豆9191精品国产| 蜜桃av综合| 欧美国产日韩精品| 亚洲精品视频在线看| 一区二区三区 在线观看视频| 亚洲精品视频啊美女在线直播| 99re这里只有精品6| 亚洲影院色无极综合| 欧美成人免费观看| 久久免费精品视频| 欧美成人精品一区二区三区| 欧美激情精品| 国产九九视频一区二区三区| 精品1区2区| 亚洲精品看片| 午夜欧美精品久久久久久久| 欧美成人一品| 亚洲一区视频在线观看视频| 久久青草欧美一区二区三区| 欧美日韩和欧美的一区二区| 韩国福利一区| 亚洲一区二区精品在线| 欧美一级在线播放| 欧美mv日韩mv国产网站| 亚洲一区二区在线视频| 久久国产精品久久久久久| 亚洲激情av在线| 亚洲国产精品久久91精品| 亚洲国产精品成人综合色在线婷婷| 午夜伦欧美伦电影理论片| 免费人成精品欧美精品| 欧美三级中文字幕在线观看| 国产欧亚日韩视频| 亚洲精品永久免费| 国产精品红桃| 欧美色图一区二区三区| 国产精品扒开腿做爽爽爽软件 | 亚洲大片免费看| 99热这里只有成人精品国产| 欧美亚洲在线视频| 欧美日在线观看| 亚洲国产另类久久精品| 99成人在线| 久久综合给合久久狠狠色| 一区二区三区成人| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产精品成人aaaaa网站| 在线观看亚洲a| 欧美一区二区在线播放| av成人免费| 一区二区毛片| 猛男gaygay欧美视频| 国产精品一级在线| 正在播放欧美视频| 欧美黄色大片网站| 99精品国产在热久久婷婷| 亚洲视频 欧洲视频| 亚洲成色www8888| 久久青草久久| 国产综合色产| 先锋资源久久| 夜夜嗨av色综合久久久综合网| 免费在线观看成人av| 国内欧美视频一区二区| 亚洲综合色婷婷| 亚洲美女网站| 欧美日韩视频在线| 亚洲午夜激情| 亚洲九九九在线观看| 欧美一区永久视频免费观看| 国产精品久久久久久久久久尿| 99国产精品国产精品毛片| 欧美黑人国产人伦爽爽爽| 免费看成人av| 亚洲欧洲视频| 亚洲欧洲一区二区天堂久久 | 亚洲综合三区| 亚洲一区二区在线免费观看| 欧美性jizz18性欧美| 亚洲午夜精品久久| 一卡二卡3卡四卡高清精品视频| 欧美精品一区二区三| 在线精品国精品国产尤物884a| 午夜精品国产更新| 欧美高清视频在线播放| 亚洲视频图片小说| 欧美激情二区三区| 一区二区久久久久久| 极品av少妇一区二区| 欧美成人一区二免费视频软件| 久久综合九色综合网站| 亚洲精品在线二区| 亚洲特色特黄| 伊人成综合网伊人222| 欧美专区在线| 免费在线观看成人av| 亚洲伊人网站| 欧美尤物一区| 亚洲三级毛片| 亚洲视频中文字幕| 在线观看亚洲专区| 日韩网站在线观看| 国产亚洲一区二区三区在线播放| 麻豆乱码国产一区二区三区| 欧美伦理91| 国产精品一级在线| 亚洲精选在线| 亚洲一区二区三区在线观看视频| 国产在线观看91精品一区| 亚洲国产三级网| 国产欧美一区二区三区在线老狼 | 亚洲欧美精品在线观看| 国内精品久久久久久影视8| 亚洲第一中文字幕在线观看| 国产精品扒开腿爽爽爽视频| 欧美成人激情在线| 国产精品久久国产精品99gif| 久久夜色精品一区| 欧美三级免费| 亚洲第一在线| 亚洲第一区色| 午夜精品久久久久久久男人的天堂 | 欧美香蕉大胸在线视频观看| 你懂的网址国产 欧美| 国产精品久久久久免费a∨大胸| 欧美成人精品一区二区| 国产精品免费观看视频| 亚洲日本无吗高清不卡| 在线观看日韩av| 久久国产精品亚洲va麻豆| 亚洲欧美在线看| 欧美日韩国产二区| 亚洲电影免费观看高清完整版在线 | 久久综合婷婷| 欧美在线影院在线视频| 国产精品对白刺激久久久| 亚洲国产综合91精品麻豆| 亚洲国产91| 久久综合伊人77777尤物| 久久伊人亚洲| 国产亚洲欧美aaaa| 先锋影音网一区二区| 亚洲欧美成人| 欧美色欧美亚洲高清在线视频| 亚洲第一页中文字幕| 亚洲日本电影| 欧美经典一区二区三区| 亚洲大胆在线| 在线视频欧美日韩| 欧美日韩免费| 免费不卡在线观看| 一色屋精品视频在线看| 久久久无码精品亚洲日韩按摩| 久久亚洲不卡| 尤物精品在线| 免费在线成人av| 亚洲男人的天堂在线观看| 欧美伊人影院| 久久亚洲春色中文字幕| 亚洲电影观看| 欧美成人小视频| 日韩一级大片在线| 亚洲一区欧美二区| 国产乱肥老妇国产一区二| 亚洲视频在线免费观看| 久久精品国产亚洲aⅴ| 好吊一区二区三区| 免费在线成人| 亚洲最新色图| 久久久久久精| 亚洲国产精品悠悠久久琪琪 | 亚洲精品国产系列| 欧美另类极品videosbest最新版本| 亚洲免费成人| 久久精品av麻豆的观看方式| 狠狠色2019综合网| 欧美日韩99| 亚洲国产精品久久| 一区二区三区四区五区精品| 国产精品看片你懂得| 欧美一级艳片视频免费观看| 欧美激情在线播放| 性欧美长视频| 亚洲精品欧美激情| 国产欧美精品在线| 欧美成人精品不卡视频在线观看 | 欧美午夜精品一区| 久久嫩草精品久久久精品一| 一本色道久久综合亚洲二区三区| 久久久久免费视频|