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

elva

玩轉ptrace(一)

by Pradeep Padala
Created 2002-11-01 02:00
翻譯: Magic.D E-mail: adamgic@163.com
譯者序:在開發(fā)Hust Online Judge的過程中,查閱了不少資料,關于調試器技術的資料在網(wǎng)上是很少,即便是UNIX編程巨著《UNIX環(huán)境高級編程》中,相關內容也不多,直到我在http://www.linuxjournal.com上找到這篇文章,如獲至寶,特翻譯之,作為鄙人翻譯技術文檔的第一次嘗試,必定會有不少蹩腳之處,各位就將就一下吧,歡迎大力拍磚。

你想過怎么實現(xiàn)對系統(tǒng)調用的攔截嗎?你嘗試過通過改變系統(tǒng)調用的參數(shù)來愚弄你的系統(tǒng)kernel嗎?你想過調試器是如何使運行中的進程暫停并且控制它嗎?
你 可能會開始考慮怎么使用復雜的kernel編程來達到目的,那么,你錯了。實際上Linux提供了一種優(yōu)雅的機制來完成這些:ptrace系統(tǒng)函數(shù)。 ptrace提供了一種使父進程得以監(jiān)視和控制其它進程的方式,它還能夠改變子進程中的寄存器和內核映像,因而可以實現(xiàn)斷點調試和系統(tǒng)調用的跟蹤。
使用ptrace,你可以在用戶層攔截和修改系統(tǒng)調用(sys call)
在這篇文章中,我們將學習如何攔截一個系統(tǒng)調用,然后修改它的參數(shù)。在本文的第二部分我們將學習更先進的技術:設置斷點,插入代碼到一個正在運行的程序中;我們將潛入到機器內部,偷窺和纂改進程的寄存器和數(shù)據(jù)段。
 
基本知識
操 作系統(tǒng)提供了一種標準的服務來讓程序員實現(xiàn)對底層硬件和服務的控制(比如文件系統(tǒng)),叫做系統(tǒng)調用(system calls)。當一個程序需要作系統(tǒng)調用的時候,它將相關參數(shù)放進系統(tǒng)調用相關的寄存器,然后調用軟中斷0x80,這個中斷就像一個讓程序得以接觸到內核 模式的窗口,程序將參數(shù)和系統(tǒng)調用號交給內核,內核來完成系統(tǒng)調用的執(zhí)行。
 
在i386體系中(本文中所有的代碼都是面向i386體系),系統(tǒng)調用號將放入%eax,它的參數(shù)則依次放入%ebx, %ecx, %edx, %esi 和 %edi。 比如,在以下的調用
 
       Write(2, “Hello”, 5)
 
的匯編形式大概是這樣的


    movl $4, %eax
    movl $2, %ebx
    movl $hello, %ecx
    movl $5, %edx
    int $0x80
 

這里的$hello指向的是標準字符串”Hello”。
 
那么,ptrace會在什么時候出現(xiàn)呢?在執(zhí)行系統(tǒng)調用之前,內核會先檢查當前進程是否處于被“跟蹤”(traced)的狀態(tài)。如果是的話,內核暫停當前進程并將控制權交給跟蹤進程,使跟蹤進程得以察看或者修改被跟蹤進程的寄存器。
 
讓我們來看一個例子,演示這個跟蹤程序的過程

 

#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
  #include <linux/user.h> /* For constants
                                    ORIG_EAX etc */

 int main()
  {
    pid_t child;
     long orig_eax;
     child = fork();
      if(child == 0) {
         ptrace(PTRACE_TRACEME, 0, NULL, NULL);
         execl("/bin/ls", "ls", NULL);
     }
      else {
         wait(NULL);
         orig_eax = ptrace(PTRACE_PEEKUSER,
                           child, 4 * ORIG_EAX,
                           NULL);
         printf("The child made a "
                "system call %ld ", orig_eax);
         ptrace(PTRACE_CONT, child, NULL, NULL);
     }
     return 0;
 }

運行這個程序,將會在輸出ls命令的結果的同時,輸出:
 
The child made a system call 11
 
說明:11是execve的系統(tǒng)調用號,這是該程序調用的第一個系統(tǒng)調用。
想知道系統(tǒng)調用號的詳細內容,察看 /usr/include/asm/unistd.h。
 
在 以上的示例中,父進程fork出了一個子進程,然后跟蹤它。在調用exec函數(shù)之前,子進程用PTRACE_TRACEME作為第一個參數(shù)調用了 ptrace函數(shù),它告訴內核:讓別人跟蹤我吧!然后,在子進程調用了execve()之后,它將控制權交還給父進程。當時父進程正使用wait()函數(shù) 來等待來自內核的通知,現(xiàn)在它得到了通知,于是它可以開始察看子進程都作了些什么,比如看看寄存器的值之類。
 
出現(xiàn)系統(tǒng)調用之后,內核會將eax中的值(此時存的是系統(tǒng)調用號)保存起來,我們可以使用PTRACE_PEEKUSER作為ptrace的第一個參數(shù)來讀到這個值。
我們察看完系統(tǒng)調用的信息后,可以使用PTRACE_CONT作為ptrace的第一個參數(shù),調用ptrace使子進程繼續(xù)系統(tǒng)調用的過程。
 
ptrace函數(shù)的參數(shù)
 
Ptrace有四個參數(shù)
long ptrace(enum __ptrace_request request,
            pid_t pid,
            void *addr,
            void *data);
 
第一個參數(shù)決定了ptrace的行為與其它參數(shù)的使用方法,可取的值有:
PTRACE_ME
PTRACE_PEEKTEXT
PTRACE_PEEKDATA
PTRACE_PEEKUSER
PTRACE_POKETEXT
PTRACE_POKEDATA
PTRACE_POKEUSER
PTRACE_GETREGS
PTRACE_GETFPREGS,
PTRACE_SETREGS
PTRACE_SETFPREGS
PTRACE_CONT
PTRACE_SYSCALL,
PTRACE_SINGLESTEP
PTRACE_DETACH
在下文中將對這些常量的用法進行說明。
 
讀取系統(tǒng)調用的參數(shù)
 
通過將PTRACE_PEEKUSER作為ptrace 的第一個參數(shù)進行調用,可以取得與子進程相關的寄存器值。
 
先看下面這個例子

#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/user.h>
  #include <sys/syscall.h> /* For SYS_write etc */
 
 int main()
  {
     pid_t child;
     long orig_eax, eax;
     long params[3];
     int status;
     int insyscall = 0;
     child = fork();
      if(child == 0) {
         ptrace(PTRACE_TRACEME, 0, NULL, NULL);
         execl("/bin/ls", "ls", NULL);
     }
      else {
         while(1) {
           wait(&status);
           if(WIFEXITED(status))
               break;
           orig_eax = ptrace(PTRACE_PEEKUSER,
                      child, 4 * ORIG_EAX, NULL);
            if(orig_eax == SYS_write) {
               if(insyscall == 0) {
                  /* Syscall entry */
                 insyscall = 1;
                 params[0] = ptrace(PTRACE_PEEKUSER,
                                    child, 4 * EBX,
                                    NULL);
                 params[1] = ptrace(PTRACE_PEEKUSER,
                                    child, 4 * ECX,
                                    NULL);
                 params[2] = ptrace(PTRACE_PEEKUSER,
                                    child, 4 * EDX,
                                    NULL);
                 printf("Write called with "
                        "%ld, %ld, %ld ",
                        params[0], params[1],
                        params[2]);
                 }
            else { /* Syscall exit */
                 eax = ptrace(PTRACE_PEEKUSER,
                              child, 4 * EAX, NULL);
                     printf("Write returned "
                            "with %ld ", eax);
                     insyscall = 0;
                 }
             }
             ptrace(PTRACE_SYSCALL,
                    child, NULL, NULL);
         }
     }
     return 0;
 }

這個程序的輸出是這樣的
 
ppadala@linux:~/ptrace > ls
a.out dummy.s ptrace.txt
libgpm.html registers.c syscallparams.c
dummy ptrace.html simple.c
ppadala@linux:~/ptrace > ./a.out
Write called with 1, 1075154944, 48
a.out dummy.s ptrace.txt
Write returned with 48
Write called with 1, 1075154944, 59
libgpm.html registers.c syscallparams.c
Write returned with 59
Write called with 1, 1075154944, 30
dummy ptrace.html simple.c
Write returned with 30
 

以上的例子中我們跟蹤了write系統(tǒng)調用,而ls命令的執(zhí)行將產生三個write系統(tǒng)調用。使用PTRACE_SYSCALL作為ptrace的 第一個參數(shù),使內核在子進程做出系統(tǒng)調用或者準備退出的時候暫停它。這種行為與使用PTRACE_CONT,然后在下一個系統(tǒng)調用/進程退出時暫停它是等 價的。
 
在前一個例子中,我們用PTRACE_PEEKUSER來察看write系統(tǒng)調用的參數(shù)。系統(tǒng)調用的返回值會被放入%eax。
 
wait函數(shù)使用status變量來檢查子進程是否已退出。它是用來判斷子進程是被ptrace暫停掉還是已經運行結束并退出。有一組宏可以通過status的值來判斷進程的狀態(tài),比如WIFEXITED等,詳情可以察看wait(2) man。
 
讀取寄存器的值
 
如果你想在系統(tǒng)調用或者進程終止的時候讀取它的寄存器,使用前面那個例子的方法是可以的,但是這是笨拙的方法。使用PRACE_GETREGS作為ptrace的第一個參數(shù)來調用,可以只需一次函數(shù)調用就取得所有的相關寄存器值。
獲得寄存器值得例子如下:

 

#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/user.h>
 #include <sys/syscall.h>
 
 int main()
  {
     pid_t child;
     long orig_eax, eax;
     long params[3];
     int status;
     int insyscall = 0;
     struct user_regs_struct regs;
     child = fork();
      if(child == 0) {
         ptrace(PTRACE_TRACEME, 0, NULL, NULL);
         execl("/bin/ls", "ls", NULL);
     }
      else {
         while(1) {
           wait(&status);
           if(WIFEXITED(status))
               break;
           orig_eax = ptrace(PTRACE_PEEKUSER,
                             child, 4 * ORIG_EAX,
                             NULL);
            if(orig_eax == SYS_write) {
                if(insyscall == 0) {
                   /* Syscall entry */
                  insyscall = 1;
                  ptrace(PTRACE_GETREGS, child,
                         NULL, &regs);
                  printf("Write called with "
                         "%ld, %ld, %ld ",
                         regs.ebx, regs.ecx,
                         regs.edx);
              }
               else { /* Syscall exit */
                  eax = ptrace(PTRACE_PEEKUSER,
                               child, 4 * EAX,
                               NULL);
                  printf("Write returned "
                         "with %ld ", eax);
                  insyscall = 0;
              }
           }
           ptrace(PTRACE_SYSCALL, child,
                  NULL, NULL);
        }
    }
    return 0;
 }

這段代碼與前面的例子是比較相似的,不同的是它使用了PTRACE_GETREGS。 其中的user_regs_struct結構是在<linux/user.h>中定義的。
 
 
來點好玩的
 
現(xiàn)在該做點有意思的事情了,我們將要把傳給write系統(tǒng)調用的字符串給反轉。

 

#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/user.h>
 #include <sys/syscall.h>
 
 const int long_size = sizeof(long);
 
 void reverse(char *str)
  {
     int i, j;
     char temp;
     for(i = 0, j = strlen(str) - 2;
          i <= j; ++i, --j) {
         temp = str[i];
         str[i] = str[j];
         str[j] = temp;
     }
 }
 
 void getdata(pid_t child, long addr,
              char *str, int len)
  {
     char *laddr;
     int i, j;
      union u {
             long val;
             char chars[long_size];
     }data;
 
     i = 0;
     j = len / long_size;
     laddr = str;
      while(i < j) {
         data.val = ptrace(PTRACE_PEEKDATA,
                           child, addr + i * 4,
                           NULL);
         memcpy(laddr, data.chars, long_size);
         ++i;
         laddr += long_size;
     }
     j = len % long_size;
      if(j != 0) {
         data.val = ptrace(PTRACE_PEEKDATA,
                           child, addr + i * 4,
                           NULL);
         memcpy(laddr, data.chars, j);
     }
     str[len] = '';
 }
 
 void putdata(pid_t child, long addr,
              char *str, int len)
  {
     char *laddr;
     int i, j;
      union u {
             long val;
             char chars[long_size];
     }data;
 
     i = 0;
     j = len / long_size;
     laddr = str;
      while(i < j) {
         memcpy(data.chars, laddr, long_size);
         ptrace(PTRACE_POKEDATA, child,
                addr + i * 4, data.val);
         ++i;
         laddr += long_size;
     }
     j = len % long_size;
      if(j != 0) {
         memcpy(data.chars, laddr, j);
         ptrace(PTRACE_POKEDATA, child,
                addr + i * 4, data.val);
     }
 }
 
 int main()
  {
    pid_t child;
    child = fork();
     if(child == 0) {
       ptrace(PTRACE_TRACEME, 0, NULL, NULL);
       execl("/bin/ls", "ls", NULL);
    }
     else {
       long orig_eax;
       long params[3];
       int status;
       char *str, *laddr;
       int toggle = 0;
        while(1) {
          wait(&status);
          if(WIFEXITED(status))
              break;
          orig_eax = ptrace(PTRACE_PEEKUSER,
                            child, 4 * ORIG_EAX,
                            NULL);
           if(orig_eax == SYS_write) {
              if(toggle == 0) {
                toggle = 1;
                params[0] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * EBX,
                                   NULL);
                params[1] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * ECX,
                                   NULL);
                params[2] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * EDX,
                                   NULL);
                str = (char *)calloc((params[2]+1)
                                  * sizeof(char));
                getdata(child, params[1], str,
                        params[2]);
                reverse(str);
                putdata(child, params[1], str,
                        params[2]);
             }
              else {
                toggle = 0;
             }
          }
       ptrace(PTRACE_SYSCALL, child, NULL, NULL);
       }
    }
    return 0;
 }
輸出是這樣的:
 
ppadala@linux:~/ptrace > ls
a.out dummy.s ptrace.txt
libgpm.html registers.c syscallparams.c
dummy ptrace.html simple.c
ppadala@linux:~/ptrace > ./a.out
txt.ecartp s.ymmud tuo.a
c.sretsiger lmth.mpgbil c.llacys_egnahc
c.elpmis lmth.ecartp ymmud

這個例子中涵蓋了前面討論過的所有知識點,當然還有些新的內容。這里我們用PTRACE_POKEDATA作為第一個參數(shù),以此來改變子進程中的變量值。它以與PTRACE_PEEKDATA相似的方式工作,當然,它不只是偷窺變量的值了,它可以修改它們。
 
單步
 
ptrace 提供了對子進程進行單步的功能。 ptrace(PTRACE_SINGLESTEP, …) 會使內核在子進程的每一條指令執(zhí)行前先將其阻塞,然后將控制權交給父進程。下面的例子可以查出子進程當前將要執(zhí)行的指令。為了便于理解,我用匯編寫了這個 受控程序,而不是讓你為c的庫函數(shù)到底會作那些系統(tǒng)調用而頭痛。
 
以下是被控程序的代碼 dummy1.s,使用gcc  –o dummy1 dummy1.s來編譯

 

.data
hello:
    .string "hello world\n"
.globl main
main:
    movl $4, %eax
    movl $2, %ebx
    movl $hello, %ecx
    movl $12, %edx
    int $0x80
    movl $1, %eax
    xorl %ebx, %ebx
    int $0x80
    ret

以下的程序則用來完成單步:

 

#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/user.h>
 #include <sys/syscall.h>
 int main()
  {
     pid_t child;
     const int long_size = sizeof(long);
     child = fork();
      if(child == 0) {
         ptrace(PTRACE_TRACEME, 0, NULL, NULL);
         execl("./dummy1", "dummy1", NULL);
     }
      else {
         int status;
          union u {
             long val;
             char chars[long_size];
         }data;
         struct user_regs_struct regs;
         int start = 0;
         long ins;
          while(1) {
             wait(&status);
             if(WIFEXITED(status))
                 break;
             ptrace(PTRACE_GETREGS,
                    child, NULL, &regs);
              if(start == 1) {
                 ins = ptrace(PTRACE_PEEKTEXT,
                              child, regs.eip,
                              NULL);
                 printf("EIP: %lx Instruction "
                        "executed: %lx ",
                        regs.eip, ins);
             }
              if(regs.orig_eax == SYS_write) {
                 start = 1;
                 ptrace(PTRACE_SINGLESTEP, child,
                        NULL, NULL);
             }
             else
                 ptrace(PTRACE_SYSCALL, child,
                        NULL, NULL);
         }
     }
     return 0;
 }

程序的輸出是這樣的:
你可能需要察看Intel的用戶手冊來了解這些指令代碼的意思。
更復雜的單步,比如設置斷點,則需要很仔細的設計和更復雜的代碼才可以實現(xiàn)。
 
 
在第二部分,我們將會看到如何在程序中加入斷點,以及將代碼插入到已經在運行的程序中

posted on 2009-07-25 17:45 葉子 閱讀(1593) 評論(5)  編輯 收藏 引用 所屬分類: Unix

Feedback

# re: 玩轉ptrace(一)[未登錄] 2012-05-07 17:27 along

good job, guys  回復  更多評論   

# re: 玩轉ptrace(一) 2012-06-27 17:41 KIMBERLEYCRAWFORD

Do you understand that this is correct time to receive the <a href="http://goodfinance-blog.com">loan</a>, which can help you.   回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            91久久国产综合久久| 国产精品一区二区a| 黑丝一区二区三区| 欧美一区激情| 亚洲午夜精品网| 欧美午夜在线一二页| 一本大道久久a久久精二百| 亚洲高清网站| 欧美成人一品| 99精品久久免费看蜜臀剧情介绍| 欧美高清成人| 欧美岛国激情| 在线一区日本视频| 99精品欧美一区二区三区| 欧美日韩中文在线观看| 亚洲欧美国产日韩天堂区| 亚洲午夜羞羞片| 国产精品一页| 久久综合给合久久狠狠色| 久久综合精品国产一区二区三区| 亚洲国产精品久久久久秋霞不卡| 欧美激情国产日韩| 欧美日韩国产123区| 亚洲一区在线免费观看| 午夜在线观看欧美| 亚洲国产日日夜夜| 一区二区三区黄色| 国产性做久久久久久| 久久综合999| 欧美韩国日本综合| 亚洲欧美中文日韩在线| 久久国产日韩欧美| 99视频国产精品免费观看| 亚洲视频精品在线| 伊人成人在线视频| 日韩一级在线观看| 国模叶桐国产精品一区| 欧美激情精品久久久久久蜜臀| 欧美日韩国产另类不卡| 久久成人精品电影| 免费亚洲网站| 香蕉尹人综合在线观看| 麻豆精品91| 欧美一区二区三区免费观看视频| 久久久久在线观看| 亚洲一区二区免费视频| 欧美日韩中文字幕在线视频| 一区二区免费在线观看| 欧美一区二区三区在线视频| 亚洲精品国产精品国产自| 亚洲一区欧美| 亚洲欧洲一区二区在线观看| 亚洲综合大片69999| 一区二区欧美国产| 国内激情久久| 国产精品99久久久久久人 | 免费一级欧美片在线播放| 日韩亚洲欧美中文三级| 欧美一区观看| 亚洲永久精品大片| 欧美sm视频| 久久色在线观看| 国产精品嫩草99av在线| 亚洲国产另类久久精品| 狠狠色狠狠色综合日日91app| 99pao成人国产永久免费视频| 在线免费观看一区二区三区| 亚洲欧美久久久久一区二区三区| 99精品视频网| 免费不卡在线视频| 美女精品自拍一二三四| 国产日本欧美一区二区三区在线| 亚洲麻豆视频| 99国产精品视频免费观看一公开| 麻豆成人av| 免费一级欧美片在线播放| 国产一区二区日韩精品| 亚洲欧美成人一区二区在线电影| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 中文国产成人精品久久一| 久久夜色精品亚洲噜噜国产mv| 欧美在线免费观看亚洲| 国产精品毛片在线看| 日韩系列欧美系列| 在线午夜精品自拍| 欧美日韩免费一区二区三区| 亚洲级视频在线观看免费1级| 亚洲国产精品123| 麻豆精品在线视频| 亚洲大片在线| 99热免费精品| 欧美日韩一区二区三| 一区二区日韩| 西瓜成人精品人成网站| 国产精品一级二级三级| 午夜国产精品影院在线观看| 欧美亚洲一区二区在线观看| 国产日本欧洲亚洲| 久久国产夜色精品鲁鲁99| 久久综合九色欧美综合狠狠| 亚洲盗摄视频| 欧美日韩成人在线| 亚洲天堂网站在线观看视频| 欧美一区二区视频网站| 国产一本一道久久香蕉| 久久久久国色av免费看影院 | 欧美一区二区三区精品电影| 久久久一二三| 亚洲人成在线观看网站高清| 欧美男人的天堂| 亚洲午夜精品视频| 老司机免费视频久久| 亚洲精品专区| 国产精品亚洲片夜色在线| 久久国产精品一区二区| 欧美成人在线网站| 亚洲香蕉视频| 精东粉嫩av免费一区二区三区| 欧美顶级大胆免费视频| 亚洲午夜一区二区三区| 米奇777在线欧美播放| 99热免费精品在线观看| 国产日韩视频一区二区三区| 免费成人激情视频| 亚洲一区二区三区精品在线观看 | 久久偷看各类wc女厕嘘嘘偷窃| 亚洲激情在线观看视频免费| 亚洲欧美日本视频在线观看| 一区二区视频免费完整版观看| 欧美日本在线看| 久久久国产精品一区二区三区| 亚洲日韩中文字幕在线播放| 久久久99精品免费观看不卡| 亚洲免费大片| 精品91久久久久| 国产精品mm| 欧美成人精品影院| 欧美在线免费视频| 在线视频欧美精品| 欧美国产高潮xxxx1819| 午夜亚洲精品| 99精品国产福利在线观看免费| 国模精品一区二区三区| 国产精品扒开腿做爽爽爽视频| 老牛影视一区二区三区| 校园激情久久| 亚洲一区免费在线观看| 亚洲人体影院| 亚洲电影免费观看高清| 久久人人爽人人爽爽久久| 午夜宅男久久久| 亚洲免费影视| 亚洲自拍偷拍色片视频| 一级日韩一区在线观看| 亚洲国内欧美| 亚洲成人直播| 激情综合久久| 黑丝一区二区三区| 国内伊人久久久久久网站视频| 国产精品一区二区黑丝| 欧美午夜电影在线| 欧美日韩成人综合在线一区二区| 欧美sm视频| 欧美激情a∨在线视频播放| 免费成年人欧美视频| 麻豆精品视频在线观看视频| 久久久一二三| 久久综合综合久久综合| 另类图片综合电影| 美日韩免费视频| 欧美国产精品一区| 欧美经典一区二区三区| 欧美激情亚洲一区| 欧美国产大片| 欧美日本一区二区三区| 欧美区一区二区三区| 欧美精品日韩www.p站| 欧美激情在线播放| 欧美日韩亚洲91| 国产精品久久久久久妇女6080 | 亚洲精品永久免费精品| 日韩视频在线一区二区| 一本色道久久综合| 亚洲无亚洲人成网站77777| 亚洲一区在线免费| 欧美在线网址| 欧美阿v一级看视频| 亚洲国产成人av| 99国产精品| 午夜精品免费视频| 久久久久久久久一区二区| 欧美xart系列高清| 国产精品va| 国产主播精品在线| 亚洲精品一级| 香蕉国产精品偷在线观看不卡| 久久久久久久久久久成人| 欧美成人精品激情在线观看| 亚洲日本激情| 午夜精品在线看|