999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于自修改字節碼的Android軟件保護技術研究

2016-05-09 07:07:40劉克勝邱世萬
計算機應用與軟件 2016年4期
關鍵詞:結構分析方法

高 琦 劉克勝 常 超 邱世萬

基于自修改字節碼的Android軟件保護技術研究

高 琦 劉克勝 常 超 邱世萬

(合肥電子工程學院 安徽 合肥 230037)

隨著侵權現象的不斷發生,加強Android軟件的保護已成為一個研究熱點。對軟件逆向工程及其對抗措施進行分析和評價,指出重點的研究領域;針對Android軟件逆向工程,在研究APK安裝原理及dex文件格式的基礎上,采取軟件運行時自修改dalvik字節碼的方案有效改變了代碼的執行流程,增加了代碼的迷惑性。通過實驗實現對軟件關鍵模塊的隱藏,使分析者無法得到正確的代碼流程,證明了該方法在軟件保護領域具有可行性,為軟件保護提供了新的思路。

Android 軟件保護 字節碼 dex文件 代碼自修改

0 引 言

Android軟件市場發展十分迅猛,根據360公司2014年的統計數據[1],僅國內37個大型市場中,軟件數達50萬以上的就有6個,其中3個市場的軟件數超百萬。但市場繁榮的背后隱藏著嚴重的版權保護問題,如游戲廠商“Dead Trigge”因軟件盜版而被迫免費出售軟件的案例曾引起廣泛熱議[2],給開發商帶來巨大損失。更為嚴重的問題是,軟件破解的方法被大量用于惡意代碼的編寫,如偽裝成合法應用竊取用戶敏感信息的惡意軟件[3],不但侵犯了開發者的版權,更損害了用戶的利益和個人隱私。文獻[4]詳細說明了這種惡意軟件從合法逆向、代碼分析、惡意篡改到重打包生成APK并發布的整個過程。

程序自修改(SMC)是一種允許代碼在運行時對自身進行修改的技術手段,最早由日本研究者于2003年提出[5],現在已比較成熟[6],相關文獻[7,8]將此方法進行改進以應對動態分析技術的發展,取得了理想效果。2013年,Bluebox Scurity網站的一篇文章[9]為自修改技術在Android移動端的應用提供了啟示。本文在分析Android軟件靜態分析技術的基礎上,重點研究了APK在系統中的安裝及APK的可執行文件格式,掌握了dalvik字節碼在系統中的存放形式,并將SMC技術原理與Android系統架構和軟件格式相結合,提出了一種基于自修改dalvik字節碼的Android軟件保護方案,并編寫實例進行了測試。一方面,將SMC技術用于Android系統,擴展了其應用范圍,另一方面,本文實現的方法可以有效地提高Android平臺軟件對抗逆向工程的能力。

1 Android軟件逆向及對抗方法

1.1 Android軟件逆向工程

逆向工程,通常也稱之為Android靜態分析,指的是采用詞法分析、語法分析等手段生成軟件的反匯編代碼,分析員通過閱讀代碼掌握程序功能的一類技術。在實際操作中,分析員通常會采用動靜結合的方法開展分析,但靜態分析仍在其中起主要作用。靜態分析的基本方法是代碼的反匯編和語法分析,通過分析代碼獲取目標軟件各功能模塊及其實現方法。

Android平臺軟件通常基于Java語言編寫,經.class文件轉化成.dex文件,并被dalvik虛擬機所解釋。反匯編程序基于dex文件格式編寫,將Java代碼反匯編生成一種smali格式的語言文件,該文件分別為程序的每一個抽象類、普通類、內部類或接口生成一個對應的smali文件,按原代碼的組織形式呈現在用戶面前。常用的反匯編工具是baksmali、apktool和dex2jar。

1.2 對抗逆向工程的Android軟件保護技術

如何有效保護軟件版權一直是開發商關注的重點,圍繞該問題業界提出了大量解決方案。目前,對抗逆向分析的方法大致可以歸為以下幾類:

(1) 核心模塊隱藏:修改dex文件特殊字段的值可以實現關鍵方法的隱藏,但字段值的改變很容易被有經驗的分析者發現;動態加載函數也允許將部分代碼以資源形式隱藏在本地或云端,但與云端的交互受網絡條件和用戶資費承受能力的制約;利用Java語言的反射機制[10]實現函數功能也能隱藏代碼意圖,但通常仍不可避免地需要將相關參數存儲于云端。

(2) 軟件完整性校驗:對dex文件或整個APK計算hash值,結果存儲于云端或資源文件中,每次運行時都計算該hash值,與存儲的值進行比較。但是這種方法可以通過修改代碼邏輯使之失效。

(3) 破壞代碼可讀性: “append”函數允許逐個字符地產生字符串數組,以增大分析者提取關鍵字段的難度;也可以通過使用goto指令實現代碼的亂序;dexguard或proguard等工具對軟件進行的處理,隱藏了類和方法的名稱,使分析者無法直接判斷代碼作用。

(4) 使用NDK:原生代碼的逆向分析難度遠遠大于Java層代碼,因此軟件的核心功能通過C代碼實現可以增強保護。

(5) 加殼:對關鍵代碼進行加密處理。

(6) 逆向工具對抗:對逆向工具進行分析,尋找其缺陷,有針對性地破壞其功能。Manifest欺騙通過在AndroidManifest文件的節點加入未知id,破壞apktool工具的重打包過程;偽加密則利用Android系統解壓縮zip文件的缺陷,將general purpose bit flags字段的第0位置1,干擾apktool工具對文件的解析。

綜合對上述六種方法的分析,目前逆向工程的對抗技術主要存在兩點不足:

一是代碼閱讀的難度雖然增大,但執行流程沒有改變,有經驗的分析者完全有能力克服閱讀上的障礙,因此,需要在提高代碼不可讀性、改變代碼執行流程方面加以研究;

二是針對逆向工具對抗的方法具有時效性,隨著分析技術的不斷發展,對抗方法也需要不斷改進,因此,軟件保護的重點應當是對代碼本身的保護。

基于此分析,本文主要研究通過軟件運行時修改代碼執行流程的方法保護代碼。

2 APK安裝及其在系統中的運行

APK是Android平臺的軟件安裝包,DEX文件是可執行的Android程序。本節結合Android4.0版本源代碼研究了系統對APK安裝包進行的處理過程,并分析了dex文件格式,為自修改dalvik字節碼提供了理論基礎。

2.1 APK的安裝過程

分析APK文件的安裝過程,重點研究APK安裝后代碼及數據的存放,梳理軟件在系統中的運行模式,為正確定位dalvik字節碼的內存地址提供理論支撐。

系統軟件包packageinstaller.apk接收到系統的Intent后開始軟件的安裝。分析源碼發現這一過程的最終落腳點是frameworksasecmdinstalldcommands.c中的方法install(),該方法執行完畢后通過socket向系統上層報告軟件安裝信息。

APK文件本質是一個壓縮包,包含META-INF(簽名信息)、res(資源文件)、AndroidManifest.xml(配置文件)、classes.dex(Dalvik字節碼)、resources.arsc(二進制資源文件)、lib(原生庫)等內容。APK安裝時,系統首先將APK復制于/data/app目錄下,然后分別將APK的數據部分和dex可執行程序文件部分存于/data/data和/data/ dalvik-cache目錄,其中數據部分包括databases數據庫目錄、cache緩存數據目錄、file應用程序控制的文件目錄、lib庫目錄。Android程序首次啟動時,Dalvik虛擬機通過依存關系樹優化程序代碼,包括將APK中dex格式優化為odex格式,并刪除原dex文件。odex文件是Android平臺的可運行文件,比dex文件體積小。這種優化可以加快軟件啟動速度,減少對RAM的占用。

2.2 dex文件與odex文件的格式

Dex文件是軟件的可執行程序在內存中的存放形式,修改dalvik字節碼的本質是對dex文件的修改,研究該文件格式,重點是研究函數的字節碼在文件中的存放位置和存放格式,為自修改dalvik字節碼的實現提供框架支撐。

Android4.1以前版本的源碼的文檔dex-format.html記錄了dex的文件格式,本文主要結合Android4.0版本源碼對相關內容進行分析和梳理。

Odex文件被視為dex文件的超集,其文件結構如圖1所示。

圖1 Odex文件結構

綜合代碼中對odex文件的敘述,可以用如下的結構對其進行定義,其中header是文件頭,dexfile是dex文件。

struct ODEXFile{

DexOptHeader header;

//文件頭

DEXFile dexfile ;

//dex文件

Dependences dependlib ;

//庫

ChunkDexClassLookup classlook;

//輔助數據

ChunkRegisterMapPool Registerpool;

//輔助數據

ChundEnd end;

//文件結束

}

源碼中的dalvik/libdex/DexFile.h文件對該結構體的各個要素在dalvik虛擬機中的映射作了定義。文件頭結構DexOptHeader中,dexOffset代表dex文件頭偏移,dexLength代表dex文件總長度。

struct DexOptHeader {

//odex文件頭

u1 magic[8];

/* includes version number */

u4 dexOffset;

/* file offset of DEX header */

u4 dexLength;

u4 depsOffset;

/* offset of optimized DEX dependency table */

u4 depsLength;

u4 optOffset;

/* file offset of optimized data tables */

u4 optLength;

u4 flags;

/* some info flags */

u4 checksum;

/* adler32 checksum covering deps/opt */

};

結構體的dexOffset字段記錄了dex的基地址偏移。

Android系統對dex文件結構的定義如圖2所示。

圖2 Dex文件結構

Dalvik虛擬機在源碼中將文件映射為DexFile結構體:

struct DexFile {

/* directly-mapped ″opt″ header */

const DexOptHeader* pOptHeader;

/* pointers to directly-mapped structs and arrays in base DEX */

const DexHeader* pHeader;

const DexStringId* pStringIds;

const DexTypeId* pTypeIds;

const DexFieldId* pFieldIds;

const DexMethodId* pMethodIds;

const DexProtoId* pProtoIds;

const DexClassDef* pClassDefs;

const DexLink* pLinkData;

……

}

其中DexHeader是文件頭,它的methodIdsSize、mehtodIdsOff、classDefsSize、classDefsOff指針分別代表DexMethodId(方法結構體)及DexClassDef(類結構體)字段的大小和偏移。

struct DexHeader {

//dex文件頭

u1 magic[8];

/* includes version number */

u4 checksum;

/* adler32 checksum */

u1 signature[kSHA1DigestLen];

/* SHA-1 hash */

u4 fileSize;

/* length of entire file */

u4 headerSize;

/* offset to start of next section */

u4 endianTag;

u4 linkSize;

u4 linkOff;

u4 mapOff;

u4 stringIdsSize;

u4 stringIdsOff;

u4 typeIdsSize;

u4 typeIdsOff;

u4 protoIdsSize;

u4 protoIdsOff;

u4 fieldIdsSize;

u4 fieldIdsOff;

u4 methodIdsSize;

u4 methodIdsOff;

u4 classDefsSize;

u4 classDefsOff;

u4 dataSize;

u4 dataOff;

};

DexClassDef有一個classDataOff字段,指向一個DexClassData結構體,該結構體的directMethods字段又指向一個描述程序中調用的方法的DexMethod結構體,聲明如下:

struct DexMethod{

//方法信息

u4 methodIdx;

u4 accessFlags;

u4 codeOff;

}

codeOff字段指向DexCode結構體,它的定義為:

struct DexCode {

//方法的實現代碼

u2 registersSize;

u2 insSize;

u2 outsSize;

u2 triesSize;

u4 debugInfoOff;

/* file offset to debug info stream */

u4 insnsSize;

/* size of the insns array, in u2 units */

u2 insns[1];

}

其中insns字段內存儲了該方法的dalvik字節碼,進行字節碼修改,主要就是尋找這個字段,并修改該字段的內容。

2.3 Android原生程序及其調用

原生代碼運行在系統庫層,對dalvik字節碼的修改只能通過原生代碼實現, 通過Java語言的JNI調用與原生庫進行交互,利用NDK編程生成動態鏈接文件實現對字節碼的修改。

NDK(native development kit)是Android平臺對C和C++代碼的支持,Android自誕生起就表達了對C代碼的支持,NDK將這種支持加以具體實現。它包含一系列動態庫開發工具,集成交叉編譯,通過mk文件對CPU、平臺等硬件條件進行透明化處理,生成.so文件并與Java層生成的文件隨應用一起打包入APK壓縮包,向市場發布。但Andoid明確表示NDK只支持部分功能,無法實現全C代碼的Android軟件。NDK編程的優點在于代碼重用和代碼保護,可以增加代碼跨硬件的可移植性,或增大分析者逆向獲取源代碼結構的難度;它的缺點在于代碼復雜度的大幅增加,可能給開發者帶來不便和風險。因此,編程人員往往只對關鍵代碼或對系統性能有較高要求的部分才使用C代碼實現,如涉及顯示器的操作[11,12]。

Java本地調用JNI是Java語言平臺的組成部分,它提供了對C代碼的支持,使得原生庫像普通Java方法一樣為主程序所調用,同時JNI也提供了原生代碼對java代碼的調用方案。它有一套與Java語言相對的數據類型、數據結構及函數標記。在JNI平臺的支持下,Android應用可以通過靈活地調用C代碼實現更多功能。如圖3所示。

圖3 JNI調用示意圖

JNI的書寫步驟包括:

(1) 編寫帶native聲明方法的Java類;

(2) 使用Javac編譯Java類;

(3) 使用Javah+Java生成頭文件;

(4) 跟據頭文件,實現本地代碼;

(5) 編譯生成動態連接庫。

3 基于自修改字節碼實現關鍵代碼隱藏

本節設計了一段示例代碼,該示例軟件的作用是對數據進行簡單加密,即把用戶輸入的數據按1.8倍輸出,用以加密數據。同時,在逆向分析時,攻擊者通過靜態分析得出的結論卻是用戶輸入的數據被直接輸出,未進行乘法處理,從而無法分析出軟件的真實流程。圖4是示例軟件的設計思路。

圖4 軟件設計

為了更加清晰地展示實驗內容,該軟件只實現了關鍵代碼,修飾性的代碼全部去除。

3.1 執行流程

(1) Java層主函數代碼設計

創建包com.tim.parsetest,涉及的具體操作的實現代碼在類文件SetDataMethod中實現;

設計一個方法setdata(),供主函數調用;

設計一個方法setdatahidden(),作為調用setdata ()時,軟件實際運行的代碼;

在主界面MainActivity中調用方法setdata();

本實驗中,為了使實驗內容更加直觀,為輸入數據賦值“1.0”,直接在界面輸出結果值。

(2) 啟動C層代碼

Android系統通過System.loadlibrary()函數調用動態鏈接庫.so文件,并首先執行JNI_Onload()函數。該函數主要目的是進行JNI版本的聲明和代碼初始化,相當于一個初始化函數。

本實驗在JNI_Onload()函數內調用動態鏈接庫parsingdex. so,該動態鏈接庫的作用是在C層完成字節碼的修改和替換。確保在軟件調用動態鏈接庫時,setdatahidden()對setdata()的替換可以在C層代碼初始化期間完成,不需要顯性地在Java層調用該方法,從而確保了setdatahidden()函數在代碼執行路徑中不出現。

(3) 尋找對應方法的DexCode結構體

由上文2.2節的分析,DexCode結構體中存儲了方法對應的字節碼,因此代碼執行替換操作之前必須正確尋找和定位setdata()與setdatahidden()對應的的DexCode結構體。

第一步,定位odex文件,獲取odex文件的基地址odexbase。先是跟據odex文件在系統中的存諸路徑及格式構造odex文件名:

odexname=/data/dalvik-cache/data@app@com.tim.parsetest-%d.apk@classes.d

然后調用getmodulebase()方法搜索本進程的proc/self/ maps文件獲取odex的基地址。

第二步,獲取odex內存塊大小odexsize。通過getmodulesize()方法獲取系統maps文件內odex所占內存的起始值和結束值,它們的差值就是odex的大小。

第三步,獲取dex文件位置dexbase。調用getdexstart()方法,在odex文件頭讀取dex文件偏移字段dexoffset的值,采用odexbase+dexoffset的方法得到dex內存塊基址。讀取maps文件的偽代碼可如下所示:

fp=fopen(proc/self/maps);

while(fgets(line,fp)=1){

if(strstr(line,odex文件名)=1){

讀取該行地址信息;

}

}

fclose;

第四步,解析dex文件頭。對DexFile結構體的關鍵字段賦值,方便下一步操作。

第五步,調用getmethod()方法,尋找DexCode結構體。在系統中搜索該結構體的流程如圖5所示。

圖5 DexCode結構體的確定過程

通過枚舉類結構DexClassDef,確定對應SetDataMethod類的DexClassDef結構體,同理,枚舉DexMethod確定setdata()與setdatahidden()方法的DexMethod結構體。

(4) 修改讀寫權限

要想隱性地修改setdata()方法的dalvik字節碼,必須調用mprotect()函數為相應內存區間增加PROT_WRITE聲明,賦予軟件將字節碼寫入setdata()的權限。

(5) 實現字節碼的寫入

以字符串數組的形式逐個替換setdata()方法的insns[]字段。可用如下偽代碼表示:

mprotect(dex,PROT_READ|PROT_WRITE|PROT|EXEC);

for(i=0;i

insns_setdata[i] = insns_setdatahidden[i];

}

mprotect(dex,PROT_READ|PROT_WRITE);

//恢復權限的目的是防止軟件在運行時出現不可預知的錯誤

3.2 實驗結果

對代碼進行編譯和組建,生成dalvikmodifytest.apk文件。

利用工具ApkIDE對文件進行逆向,分析其軟件功能。為了直觀地展現結果,APK文件在組建時未做任何混淆。

(1) 靜態分析

對軟件進行逆向,發現主程序調用了setdata()方法,參數1.0,逆向代碼如下:

invoke-virtual {v0, v2, v3}, Lcom/tim/parsetest/SetDataMethod;-> setdata(D)V

Setdata()方法中,輸入的參數1.0被直接存入data域,此時,data=1.0,逆向代碼為:

iput-object v0, p0, Lcom/tim/parsetest/SetDataMethod;->data:Ljava/jang/ Double;

隨后getdata()方法將data值直接輸出:

iget-object v0, p0, Lcom/tim/parsetest/SetDataMethod;->data:Ljava/jang/ Double;

return v0;

從逆向分析判斷,軟件將1.0存入data域后,通過getdata()直接輸出,其結果應與輸入參數一致,為1.0。從分析過程來看,setdatahidden()方法并未被調用。

(2) 實際運行

在Android 4.0版本系統中運行該APK,界面中輸出了getdata()函數的運行結果如圖6所示。

圖6 真實的實驗結果與逆向分析結果不符

按照逆向工程的步驟得出的結果是1.0,但實際運行的卻是輸入數據1.8倍的結果1.8,說明該軟件并未執行setdata()方法,而是在調用setdata()方法時,執行了setdatahidden()方法的字節碼。因此,軟件的關鍵加密模塊setdatahidden()被隱藏,受到了保護。

本實驗成功地迷惑了逆向分析者,實現了對dalvik字節碼的自修改,更改了代碼的執行流程,增加了代碼的迷惑性,證實了該方法在軟件保護領域對抗逆向工程的可行性。

4 結 語

本文分析了軟件逆向工程及其對抗,將研究點關注于增加代碼迷惑性和改變代碼執行流程,在研究了APK安裝過程、dex文件結構及JNI調用的基礎上,編寫了一個簡單的示例代碼實現了自修改dalvik字節碼,并證實了該方案在軟件保護上的可用性和廣闊前景。

下一步主要有兩個方面的工作,一是采用更加成熟的方法實現字節碼寫入,以防止可能出現的內存塊溢出;二是進一步研究該方法在對抗軟件動態分析方面的可行性。

[1] 360互聯網中心.2013年中國手機安全狀況報告[EB/OL].(2014-02-11).[2014-09-11].http://awhzfien7r.l5.yunpan.cn/lkl QPERX j6bcPGgA.

[2] Android Police.Just How Bad Is App Piracy On Android Anyway? Hint: We’re Asking The Wrong Question[EB/OL].(2012-07-31).[2014-09-11].http://www.androidpolice.com/2012/07/31/editorial-just-how-bad-is-app-piracy-on-android-anyways-hint-were-asking-the-wrong-question/.

[3] 360互聯網中心.2014年第一期中國移動支付安全報告[EB/OL].(2014 -03-11).[2014-9-11].http://aqvs9knlja.l5.yanpan.cn/lk/Q4VgpLKMLV9Xq.

[4] 伍景珠.基于Android平臺的軟件保護方案的研究與實現[D].北京:北京郵電大學,2013.

[5] Kanzaki Y,Monden A.Computer Software and Applications Conference[C].Dallas,USA:COMPSAC,2003.

[6] 徐江凌.基于反跟蹤和自修改代碼技術的軟件保護系統設計[D].成都:電子科技大學,2010.

[7] 王祥根,司端鋒,馮登國.一種基于自修改代碼技術的軟件保護方法[J].中國科學院研究生院學報,2009,26(5):688-694.

[8] 高兵,林果園,王瑩.基于代碼自修改的軟件反跟蹤技術結構[J].信息網絡安全,2014(5):46-51.

[9] Patrick Schulz.Android Security Analysis Challenge Tampering Dalvik Bytecode During Runtime[EB/OL].(2013-03-25).[2014-09-11].http://blog.bluebox.com/2013/03/25/android-security-analysis-challenge-tampering-dalvik-bytecode-during-runtime/.

[10] 李興華.Java開發實戰經典[M].北京:清華大學出版社,2009:576-606.

[11] 馬建設,趙雪紅,蘇萍,等.基于Android系統的視頻播放器開發[J].計算機應用與軟件,2013,30(11):136-137,175.

[12] 楊倩,楊明趙.Android顯示服務器——SurfaceFlinger研究[J].計算機應用與軟件,2014,31(6):324-326.

RESEARCH ON ANDROID SOFTWARE PROTECTION BASED ON SELF-MODIFYING BYTE CODE

Gao Qi Liu Kesheng Chang Chao Qiu Shiwan

(HefeiElectronicEngineeringInstitution,Hefei230037,Anhui,China)

Along with the copyright infringement occurs continuously, to strengthen the protection of Android software has become a hot research topic. In this paper we carry out analysis and comment on software reverse engineering as well as its countermeasures, and point out the research focus. Aiming at reverse engineering of Android software, after studying APK installation principle and the format of DEX file, we employ the scheme of self-modifying Dalvik byte code during the operation of software to have effectively changed code execution process, and increased the perplexity of code. Through the experiment we realise the concealment of key software modules, and lead to the analyser failed in finding the correct code flow, this proves that the method has the feasibility in software protection field, and provides a new idea for software protection.

Android Software protection Byte code Dex file Code self-modifying

2014-10-21。高琦,碩士生,主研領域:信息安全。劉克勝,教授。常超,博士生。邱世萬,碩士生。

TP311.54

A

10.3969/j.issn.1000-386x.2016.04.054

猜你喜歡
結構分析方法
《形而上學》△卷的結構和位置
哲學評論(2021年2期)2021-08-22 01:53:34
隱蔽失效適航要求符合性驗證分析
論結構
中華詩詞(2019年7期)2019-11-25 01:43:04
電力系統不平衡分析
電子制作(2018年18期)2018-11-14 01:48:24
電力系統及其自動化發展趨勢分析
論《日出》的結構
用對方法才能瘦
Coco薇(2016年2期)2016-03-22 02:42:52
四大方法 教你不再“坐以待病”!
Coco薇(2015年1期)2015-08-13 02:47:34
捕魚
創新治理結構促進中小企業持續成長
現代企業(2015年9期)2015-02-28 18:56:50
主站蜘蛛池模板: 国内精品免费| 国产成人免费视频精品一区二区| 欧美一区日韩一区中文字幕页| 一级一毛片a级毛片| 亚洲成人动漫在线观看 | 欧美精品在线观看视频| 国产福利免费视频| 国产自在线播放| 91精品国产综合久久不国产大片| 无码'专区第一页| 久久精品人人做人人爽| 国产菊爆视频在线观看| 亚洲V日韩V无码一区二区| 国产一级视频久久| 亚洲欧美一区二区三区蜜芽| 婷婷五月在线视频| 亚洲AV无码精品无码久久蜜桃| 人妻精品全国免费视频| 国产流白浆视频| 91高清在线视频| 日韩一区二区三免费高清| 在线国产资源| 国产制服丝袜无码视频| 3D动漫精品啪啪一区二区下载| 婷婷色一二三区波多野衣| 国产幂在线无码精品| 91口爆吞精国产对白第三集| 日韩性网站| 欧美精品1区| 免费在线成人网| 欧美另类图片视频无弹跳第一页| 九九视频免费在线观看| 亚洲欧美在线精品一区二区| 无码精品国产dvd在线观看9久| 无码精油按摩潮喷在线播放| 91国内外精品自在线播放| 日本三级黄在线观看| 久久久久青草大香线综合精品| 丝袜国产一区| 国产亚洲视频免费播放| 男人天堂伊人网| 国产午夜福利片在线观看| 国产白丝av| 免费AV在线播放观看18禁强制| 无码国内精品人妻少妇蜜桃视频| 热99re99首页精品亚洲五月天| 欧美在线综合视频| 亚洲男人的天堂久久香蕉| 萌白酱国产一区二区| 精品无码一区二区在线观看| 日韩午夜伦| 91免费在线看| 无码网站免费观看| 日本少妇又色又爽又高潮| 亚洲三级视频在线观看| 91网址在线播放| 97精品久久久大香线焦| 毛片免费在线视频| 国产熟女一级毛片| 国产精品hd在线播放| 亚洲国产中文在线二区三区免| 巨熟乳波霸若妻中文观看免费| 国产成人AV男人的天堂| 无码丝袜人妻| 欧美亚洲网| 欧美激情第一欧美在线| 国产特级毛片| 欧美国产视频| 原味小视频在线www国产| 国产免费福利网站| 伊人成色综合网| 久久精品无码中文字幕| 亚洲视频在线观看免费视频| 日韩第九页| 亚洲无码高清视频在线观看| 国产一区亚洲一区| 久久a毛片| 制服无码网站| 久久精品这里只有国产中文精品| 97视频精品全国免费观看| 午夜啪啪网| 六月婷婷激情综合|