iOS逆向深入解析Hook的原理方法和安全防護(hù)

      網(wǎng)友投稿 1678 2022-05-30

      Hook 簡(jiǎn)介

      Hook就是一種改變程序執(zhí)行流程的一種技術(shù)的統(tǒng)稱(chēng);

      一段程序的執(zhí)行流程是 A --> B --> C,現(xiàn)在我們?cè)?A 和 B 之間插入一段代碼或者直接改變 B ,這樣程序原有的執(zhí)行流程就發(fā)生了改變。如下圖所示:

      Hook的方式:Method Swizzle,fishhook,Cydia Substrate;

      Hook 原理

      利用OC的Runtime特性,動(dòng)態(tài)去改變SEL(方法編號(hào))和IMP(方法實(shí)現(xiàn))的對(duì)應(yīng)關(guān)系,達(dá)到OC方法調(diào)用流程改變的目的主要用于OC方法。

      Hook中主要用到的方法(參數(shù): Class、SEL、IMP、Method):

      // 1、方法交換 OBJC_EXPORT void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); // 2、替換方法 OBJC_EXPORT IMP _Nullable class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); // 3、setIMP & getIMP OBJC_EXPORT IMP _Nonnull method_setImplementation(Method _Nonnull m, IMP _Nonnull imp) OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); OBJC_EXPORT IMP _Nullable class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name) OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      Class 一個(gè) objc_class 類(lèi)型的結(jié)構(gòu)體指針,用于說(shuō)明對(duì)象是哪個(gè)類(lèi);

      Method 一個(gè) objc_method 類(lèi)型的結(jié)構(gòu)體指針,用于定義一個(gè)方法,在objc源碼中定義如下:

      struct objc_method { SEL _Nonnull method_name OBJC2_UNAVAILABLE; char * _Nullable method_types OBJC2_UNAVAILABLE; IMP _Nonnull method_imp OBJC2_UNAVAILABLE; } OBJC2_UNAVAILABLE;

      1

      2

      3

      4

      5

      SEL 可以發(fā)現(xiàn)在 Method 的定義中,也能看見(jiàn)SEL。在蘋(píng)果官方文檔中定義這種類(lèi)型:

      typedef struct objc_selector *SEL;

      1

      IMP 同樣在 Method 的定義中也能看到,在蘋(píng)果官方文檔的定義如下:

      id (IMP *)(id, SEL, ...)

      1

      SEL是一個(gè)C String,用于表示一個(gè)方法的名稱(chēng),IMP是一個(gè)方法實(shí)現(xiàn)首地址,默認(rèn)有兩個(gè)參數(shù) self 和 _cmd。其實(shí)SEL和IMP的關(guān)系可以類(lèi)比一本書(shū)的目錄,SEL就是目錄中的內(nèi)容標(biāo)題,IMP是后面的頁(yè)碼。一個(gè)方法調(diào)用時(shí),通過(guò)SEL找到對(duì)應(yīng)的IMP,進(jìn)而找到方法的實(shí)現(xiàn)。如下圖:

      在Hook一個(gè)OC方法時(shí),只需要改變其SEL所指向的IMP時(shí),就可以實(shí)現(xiàn)方法的交換的目的,或者使用class_replaceMethod 和 method_setImplementation 改變一個(gè)類(lèi)原有方法的實(shí)現(xiàn),原理如下圖:

      逆向中,Hook一個(gè)OC方法其實(shí)就是改變其SEL所指向的IMP,從而找到另一個(gè)實(shí)現(xiàn)地址,執(zhí)行另一個(gè)方法實(shí)現(xiàn)。但這種方法的局限在于,其只能針對(duì)OC方法進(jìn)行Hook,對(duì)于C函數(shù)則無(wú)法Hook。

      fishhook主要利用了共享緩存功能和PIC技術(shù)來(lái)實(shí)現(xiàn)hook功能。

      fishHook是由faceBook開(kāi)發(fā)的,是一個(gè)動(dòng)態(tài)修改MachO文件的工具,主要是通過(guò)修改懶加載和非懶加載表里的指針的指向來(lái)達(dá)到hook的目的,因此一般用它來(lái)hook系統(tǒng)的C函數(shù)。

      DATA區(qū)有兩個(gè)section和動(dòng)態(tài)符號(hào)鏈接相關(guān):__nl_symbol_ptr 、__la_symbol_ptr;__nl_symbol_ptr為一個(gè)指針數(shù)組,直接對(duì)應(yīng)non-lazy綁定數(shù)據(jù)。__la_symbol_ptr也是一個(gè)指針數(shù)組,通過(guò)dyld_stub_binder輔助鏈接。

      fishhook實(shí)現(xiàn):根據(jù)符號(hào)(字符)獲取系統(tǒng)函數(shù)地址;替換符號(hào)指向的地址為用戶(hù)聲明的函數(shù)地址(符號(hào)綁定);對(duì)外部聲明的指針進(jìn)行系統(tǒng)函數(shù)地址賦值。

      示例說(shuō)明

      static void (* old_log)(NSString* str); void newLog(NSString * str){ str = [str stringByAppendingString:@"\n 勾住了"]; old_log(str); } // hook rebind_symbols((struct rebinding [1]){{"NSLog",newLog,(void *)&old_log}}, 1);

      1

      2

      3

      4

      5

      6

      7

      rebind_symbols的簡(jiǎn)單邏輯

      假設(shè):

      A -> 原方法 ,B -> 新方法 ,Temp -> 中間變量

      Temp = A;

      A = B;

      hook后需要調(diào)用原方法就調(diào)用Temp

      具體如下:

      1?? 首先,MachO文件是被dyld(dynamic load)動(dòng)態(tài)加載的,也就是說(shuō),MachO文件被加載到內(nèi)存的時(shí)候是不固定的,它有一個(gè)ASLR隨機(jī)值;

      2?? 同樣,依賴(lài)的系統(tǒng)庫(kù)的加載也是隨機(jī)的,因此,當(dāng)MachO文件加載到內(nèi)存之前根本不知道系統(tǒng)庫(kù)在哪;

      3?? 因此 ,蘋(píng)果采用了PIC技術(shù)(位置代碼獨(dú)立,位置和代碼無(wú)關(guān));

      假設(shè)要調(diào)用NSLog函數(shù):首先會(huì)在映射表中增加一個(gè)間接指針,指向外部的NSLog函數(shù);然后dyld會(huì)動(dòng)態(tài)的去綁定,將指針指向外部的函數(shù)地址。

      machO符號(hào)表中有懶加載表(_la_symbol_ptr)和非懶加載表(_nl_symbol_ptr)的_data段,在表中存放著與外部綁定的函數(shù)指針,在懶加載端有offset地址,如下:

      右邊紅色方框中的都是我們熟悉的名稱(chēng),這些函數(shù)的使用是需要進(jìn)行懶加載綁定的;

      左邊的offset提供了相對(duì)于MachO起始地址的偏移量offset,實(shí)際地址即是系統(tǒng)函數(shù)所在的內(nèi)存地址;

      我們觀察NSLog函數(shù),記住對(duì)應(yīng)的offset=0x8018這個(gè)偏移量;

      使用fishHook的rebind_symbols庫(kù)函數(shù)交換系統(tǒng)NSLog函數(shù):

      #pragma mark - 交換NSLog - (void)exchangeLog { // 加載出來(lái)NSLog函數(shù),生成內(nèi)存地址(因?yàn)镹SLog是Lazy Symbol Pointers) NSLog(@"我來(lái)了"); // hook NSLog函數(shù) struct rebinding imp; imp.name = "NSLog"; imp.replacement = my_NSLog; imp.replaced = &sys_nslog; // 存放rebinding結(jié)構(gòu)體數(shù)組,一次可以交換多個(gè)函數(shù) struct rebinding rebs[1] = {imp}; rebind_symbols(rebs, 1); NSLog(@"點(diǎn)擊了屏幕"); } // 實(shí)現(xiàn)一個(gè)函數(shù)來(lái)替換原有函數(shù)-函數(shù)名稱(chēng)即是函數(shù)的指針 void my_NSLog(NSString *format, ...) { printf("攔截打印\n"); sys_nslog(format); } // 定義指針來(lái)接收原始函數(shù)的指針 static void (*sys_nslog)(NSString *format,...);

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      然后運(yùn)行輸出,點(diǎn)擊屏幕,查看控制臺(tái)打印輸出,可以看到方法已被攔截,說(shuō)明NSLog函數(shù)已被替換;

      所有的函數(shù)地址在編譯后都是確定,在OC中能夠交換方法是因?yàn)橛衧el和imp的連接過(guò)程,函數(shù)與用戶(hù)之間有一個(gè)中間者,那么fishhook應(yīng)該也是如此,修改了中間者的imp指向,否則直接調(diào)用函數(shù),就沒(méi)有交換的可能,在MachO中這個(gè)中間者叫符號(hào)。

      在rebind_symbols(rebs, 1);調(diào)用前打斷點(diǎn),在控制臺(tái)執(zhí)行image list獲取模塊列表(image就是一個(gè)個(gè)模塊,一個(gè)個(gè)MachO文件),如下:

      上面的紅色標(biāo)志就是應(yīng)用程序加載的起始地址(在程序運(yùn)行期間是固定,重新啟動(dòng)該地址則會(huì)隨機(jī)變化),然后根據(jù)這個(gè)地址去找NSLog函數(shù)的地址(偏移offset=0x8018),即在控制臺(tái)繼續(xù)輸入:x 0x000000010453c000+0x8018

      上圖中的74 39 59 84 01 00 00 00即為NSLog函數(shù)所對(duì)應(yīng)的值,由于CPU的小端模式,因此需要從右往左取值: 0x0184593074就是NSLog的內(nèi)存地址;然后dis -s 0x0184593074:

      繼續(xù)讓斷點(diǎn)往下多執(zhí)行一步,重復(fù)上面的操作,就可以看到fishhook對(duì)系統(tǒng)NSLog函數(shù)的替換:

      fishHook官方說(shuō)明示意圖

      回到MachO文件,來(lái)看看Lazy Symbol、Dynamic Symbol Table、Symbol Table、String Table表關(guān)系:

      ① Lazy Symbol和Dynamic Symbol Tabel一一對(duì)應(yīng)(在數(shù)組的下標(biāo)一致)這兩個(gè)表包含了所有與動(dòng)態(tài)庫(kù)相關(guān)的符號(hào);

      ② Dynamic Symbol Tabel和Symbol Table關(guān)聯(lián),Dynamic Symbol Table中的Data字段是Symbol Table數(shù)組的下標(biāo);

      ③ Symbol Table中的data字段地址 + String Table表的起始地址,就是目標(biāo)函數(shù)對(duì)應(yīng)字符的位置。

      首先在Lazy Symbol Pointers中找到NSLog函數(shù),它處于表中第一個(gè)元素;

      找到indirect Symbols表中的NSLog項(xiàng),它也處于表中第一個(gè)元素;

      在上圖中找到NSLog的Data地址0x94,等于十進(jìn)制148,即為Symbol Table表中NSLog對(duì)應(yīng)的下標(biāo),如下:

      通過(guò)下標(biāo)找到了對(duì)應(yīng)的符號(hào),主要上面的標(biāo)注0xBA為String Table中的偏移量,表的起始地址加上偏移量即是函數(shù)名所在的位置;

      通過(guò)首地址獲取最終函數(shù)名,0xBA + 0x6180 = 0x623A,找到0x623A地址處,如下:

      最終找到系統(tǒng)的函數(shù)NSLog。

      Cydia Substrate 原名為 Mobile Substrate ,它的主要作用是針對(duì)OC方法、C函數(shù)以及函數(shù)地址進(jìn)行HOOK操作。

      跟method Swizzle類(lèi)似,也是用的OC的動(dòng)態(tài)性,知識(shí)Method Swizzle是用的方法交換,Cydia Substrate 是用的method_getImplementation和 method_setImplementation這兩個(gè)方法,獲取方法實(shí)現(xiàn)和設(shè)置方法實(shí)現(xiàn)。

      Cydia Substrate主要由3部分組成:

      MobileHooker

      它定義一系列的宏和函數(shù),底層調(diào)用objc的runtime和fishhook來(lái)替換系統(tǒng)或者目標(biāo)應(yīng)用的函數(shù)。主要有兩個(gè)函數(shù):MSHookMessageEx 主要作用于Objective-C方法,MSHookFunction 主要作用于C和C++函數(shù);

      MSHookMessageEx函數(shù)的作用對(duì)象是Objective-C函數(shù),其原理是調(diào)用Objective-C中高等級(jí)的運(yùn)行時(shí)函數(shù)API:class_getInstanceMethod、method_setImplementation、method_exchangeImplementations等來(lái)替換原函數(shù)的邏輯,其實(shí)MobileHooker就是對(duì)fishhook和runtime做了封裝,就是和AFNetworking和NSURLSession的關(guān)系是一樣的;

      // MSHookMessageEx void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result) // MSHookFunction void MSHookFunction(voidfunction,void* replacement,void** p_original)

      1

      2

      3

      4

      5

      6

      MobileLoader

      MobileLoader的作用就是去加載第三方dylib,在ios啟動(dòng)的時(shí)候,會(huì)由launchd將MobileLoader載入內(nèi)存,然后MobileLoader會(huì)根據(jù)同名的plist文件指定的作用范圍,有選擇地在不同的進(jìn)程當(dāng)中去通過(guò)dlopen函數(shù)打開(kāi)目錄/Library/MobileSubstrate/DynamicLibraries/下的所有的dylib。

      safe mode

      因?yàn)锳PP程序質(zhì)量參差不齊崩潰再所難免,破解程序本質(zhì)是dylib,寄生在別人進(jìn)程里。 一旦出錯(cuò),就可能導(dǎo)致整個(gè)進(jìn)程崩潰,而一旦崩潰的是SpringBoard等系統(tǒng)進(jìn)程,崩潰后就會(huì)造成iOS癱瘓。所以CydiaSubstrate引入了安全模式,在安全模式下所有基于CydiaSubstratede 的三方dylib都會(huì)被禁用,便于查錯(cuò)與修復(fù)。

      Hook 流程(以O(shè)bjective-C為例)

      在 Objective-C 中,所有的 [receiver message] 都會(huì)轉(zhuǎn)換為 objc_msgSend(receiver, @selector(message))。

      在當(dāng)前 class 的方法緩存里尋找(cache methodLists)

      找到了跳到對(duì)應(yīng)的方法實(shí)現(xiàn),沒(méi)找到繼續(xù)往下執(zhí)行;

      從當(dāng)前 class 的 方法列表里查找(methodLists),找到了添加到緩存列表里,然后跳轉(zhuǎn)到對(duì)應(yīng)的方法實(shí)現(xiàn);沒(méi)找到繼續(xù)往下執(zhí)行;

      從 superClass 的緩存列表和方法列表里查找,直到找到基類(lèi)為止;

      以上步驟還找不到 IMP,則用_objc_msgForward函數(shù)指針代替 IMP ,最后執(zhí)行這個(gè) IMP;

      // objc-runtime-new.mm 文件里與 _objc_msgForward 有關(guān)的三個(gè)函數(shù)使用偽代碼展示,這也是 obj_msgSend 的實(shí)現(xiàn)過(guò)程 id objc_msgSend(id self, SEL op, ...) { if (!self) return nil; IMP imp = class_getMethodImplementation(self->isa, SEL op); // 調(diào)用這個(gè)函數(shù),偽代碼... imp(self, op, ...); } //查找IMP IMP class_getMethodImplementation(Class cls, SEL sel) { if (!cls || !sel) return nil; IMP imp = lookUpImpOrNil(cls, sel); // _objc_msgForward 用于消息轉(zhuǎn)發(fā) if (!imp) return _objc_msgForward; return imp; } IMP lookUpImpOrNil(Class cls, SEL sel) { if (!cls->initialize()) { _class_initialize(cls); } Class curClass = cls; IMP imp = nil; // 先查緩存,緩存沒(méi)有時(shí)重建,仍舊沒(méi)有則向父類(lèi)查詢(xún) do { if (!curClass) break; if (!curClass->cache) fill_cache(cls, curClass); imp = cache_getImp(curClass, sel); if (imp) break; } while (curClass = curClass->superclass); return imp; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      iOS逆向之深入解析Hook的原理方法和安全防護(hù)

      31

      32

      33

      34

      第一個(gè)階段的具體方法是+(BOOL)resolveInstanceMethod:(SEL)sel 和+(BOOL)resolveClassMethod:(SEL)sel,當(dāng)方法是實(shí)例方法時(shí)調(diào)用前者,當(dāng)方法為類(lèi)方法時(shí),調(diào)用后者。這個(gè)方法是為了給類(lèi)利用 class_addMethod 添加方法的機(jī)會(huì);

      第二個(gè)階段是備援接收者階段,對(duì)象的具體方法是-(id)forwardingTargetForSelector:(SEL)aSelector ,此時(shí),運(yùn)行時(shí)詢(xún)問(wèn)能否把消息轉(zhuǎn)給其他接收者處理,也就是此時(shí)系統(tǒng)給了個(gè)將這個(gè) SEL 轉(zhuǎn)給其他對(duì)象的機(jī)會(huì);

      第三個(gè)階段是完整消息轉(zhuǎn)發(fā)階段,對(duì)應(yīng)方法-(void)forwardInvocation:(NSInvocation *)anInvocation,這是消息轉(zhuǎn)發(fā)流程的最后一個(gè)環(huán)節(jié)(hook方案的核心)。

      直接替換原方法的實(shí)現(xiàn)為_(kāi)objc_msgForward。當(dāng)原來(lái)的函數(shù)被調(diào)用時(shí),就不會(huì)在類(lèi)方法,父類(lèi)方法列表里查找實(shí)現(xiàn)了,直接表示找不到,進(jìn)入轉(zhuǎn)發(fā)流程。用_objc_msgForward來(lái)代替原來(lái)的函數(shù),代碼如下:

      class_replaceMethod(class, selector, _objc_msgForward, method_getTypeEncoding(targetMethod));

      1

      替換forwardInvocation:的實(shí)現(xiàn),當(dāng)進(jìn)入轉(zhuǎn)發(fā)流程時(shí),階段一和階段二都不接手,在階段三forwardInvocation:里會(huì)接手;這里會(huì)替換forwardInvocation:的實(shí)現(xiàn),用newForwardInvocation代替,這樣就可以hook,完成自己的邏輯后,還要調(diào)用被hook的函數(shù)原來(lái)的邏輯。

      id newForwardInvocation = ^(id self, NSInvocation *invocation) { // hook時(shí)要添加的代碼 if (originalForwardInvocation == NULL) { [self doesNotRecognizeSelector:invocation.selector]; } else { originalForwardInvocation(self, forwardInvocationSEL, invocation); } }; class_replaceMethod(class, @selector(forwardInvocation:), imp_implementationWithBlock(newForwardInvocation), "v@:@");

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      簡(jiǎn)單防護(hù)

      我們知道Method Swizzle原理是方法交換,那么可以使用fishHook 修改method_exchangeImplementations函數(shù)的指向,這個(gè)修改指向要在我們的方法交換之后進(jìn)行(保證自己能改,別人不能改)。

      我們的方法交換要在別人hook之前執(zhí)行,這個(gè)地方就需要將我們的方法封裝到靜態(tài)庫(kù)中,靜態(tài)庫(kù)中的load方法會(huì)先加載;

      它的原理是修改imp的set和get方法,因此我們也可以通過(guò)fishHook修改method_getImplementation和method_setImplementation方法。

      示例

      + (void)load { // 先交換,防護(hù)之前要將所有的交換都寫(xiě)完 Method oldOne = class_getInstanceMethod(objc_getClass("ViewController"), @selector(btnClickOne:)); Method newOne = class_getInstanceMethod(self, @selector(ClickOneHook:)); method_exchangeImplementations(oldOne, newOne); // 基本防護(hù) Method Swizzle struct rebinding bd ; // 原函數(shù)名(字符串) A函數(shù) bd.name = "method_exchangeImplementations"; // 交換后的函數(shù) B函數(shù) bd.replacement = myExchange; // 暫存原函數(shù)的地址 中間變量temp函數(shù) bd.replaced = (void *)&old_exchage; // 升級(jí)防護(hù),用于防護(hù)logos(cydia substrate) // method_setImplementation struct rebinding bd1 ; bd1.name = "method_getImplementation"; bd1.replacement = myExchange; bd1.replaced = (void *)&getImp; struct rebinding bd2 ; bd2.name = "method_setImplementation"; bd2.replacement = myExchange; bd2.replaced = (void *)&setImp; // fishhook方法交換 struct rebinding rebind[] = {bd,bd1,bd2}; /* arg1:數(shù)組,元素必須是rebinding這個(gè)結(jié)構(gòu)體 arg2:數(shù)組個(gè)數(shù) */ rebind_symbols(rebind, 3); } // 用于存放method_exchangeImplementations涵數(shù) 也就是Temp函數(shù) void (* old_exchage)(Class _Nullable cls, SEL _Nonnull name); // 用于存放method_getImplementation涵數(shù) IMP _Nonnull(*getImp)(Method _Nonnull m) ; // 用于存放method_setImplementation涵數(shù) IMP _Nonnull(*setImp)(Method _Nonnull m, IMP _Nonnull imp) ; // 新的交換函數(shù) B函數(shù) void myExchange(Class _Nullable cls, SEL _Nonnull name){ NSLog(@"檢測(cè)到hook"); exit(1); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      iOS 數(shù)據(jù)結(jié)構(gòu)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Web安全和瀏覽器跨域訪問(wèn)
      下一篇:深度解讀設(shè)備的“萬(wàn)能語(yǔ)言”鴻蒙的分布式軟總線能力
      相關(guān)文章
      亚洲国产精品成人精品无码区| 亚洲a∨国产av综合av下载| 高清在线亚洲精品国产二区| 亚洲另类春色国产精品| 亚洲国产成人久久综合碰碰动漫3d| 亚洲一区二区三区影院| 亚洲AV网站在线观看| 含羞草国产亚洲精品岁国产精品| 亚洲日本乱码在线观看| 亚洲精品国产摄像头| youjizz亚洲| 亚洲AV成人噜噜无码网站| 亚洲欧洲自拍拍偷综合| 亚洲毛片免费观看| 亚洲人成激情在线播放| 精品亚洲国产成人| 亚洲午夜无码毛片av久久京东热 | 亚洲男同gay片| 亚洲情A成黄在线观看动漫软件| 亚洲Av无码一区二区二三区| 亚洲午夜精品一区二区公牛电影院 | 国产亚洲精品第一综合| 国产亚洲蜜芽精品久久| 亚洲国产精品自在拍在线播放 | 日韩精品亚洲专区在线影视| 国产99久久亚洲综合精品| 偷自拍亚洲视频在线观看99| 亚洲免费日韩无码系列| 国产亚洲精品线观看动态图| 亚洲日韩中文无码久久| 亚洲AV无码成人精品区天堂| 亚洲国产精品自在线一区二区 | 国产综合激情在线亚洲第一页| 一区二区三区亚洲视频| 久久久亚洲精品蜜桃臀| 久久久久久a亚洲欧洲aⅴ| 久久亚洲精品中文字幕| 亚洲喷奶水中文字幕电影| 亚洲码欧美码一区二区三区| 高清在线亚洲精品国产二区| jiz zz在亚洲|