亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS通過shell腳本批量修改屬性

2019-10-21 18:41:36
字體:
來源:轉載
供稿:網友

背景

公司需要做一系列的殼版本,殼版本如果內容雷同提交到App Store會有被拒絕的風險,除了我在上一篇文章中說道的在殼版本中注入混淆的代碼,防止被蘋果檢測到內容太過雷同而導致審核被拒絕。還有另一種可行的方法是批量修改源文件中的類名、屬性、方法名稱等會在二進制文件中留下符號標記的信息,繞過蘋果的機器審核。
這篇文章介紹的是如何使用腳本批量修改屬性名稱,后續還有系列的包括使用腳本批量修改類名稱、方法名稱等信息的文章。

結果

下面是執行腳本替換了屬性的結果圖,腳本把所有需要替換的屬性添加了abc后綴,當然依然是可以正常編譯運行的

源碼:https://gitee.com/dhar/YTTInjectedContentKit

iOS,shell,修改屬性

分析

原理分析

objc代碼中的類名、屬性、方法、源文件路徑等信息最終會被打包到二進制文件中,保存在二進制文件中的.sym符號表段中,可以使用objdump -t命令查看二進制符號信息,以下的命令把objdump -t的結果寫入到文件InjectedContentKit_Example_Symbols中去。

objdump -t InjectedContentKit_Example > InjectedContentKit_Example_Symbols

文件的內容會很大,所以選擇了幾個代表性的內容說明:

0000000100026350 l d __TEXT,__text	__text# 這里保存的是類源文件的路徑符號信息0000000000000000 l d *UND*	/Users/aron/PuTaoWorkSpace/project/sscatch/DevPods/InjectedContentKit/InjectedContentKit/Classes/Composer/PubSearchDataComposer.h# 這里保存的是屬性對應的var信息0000000000000000 l d *UND*	_OBJC_IVAR_$_TextCardItem._title0000000000000000 l d *UND*	_OBJC_IVAR_$_TextCardItem._showReact0000000000000000 l d *UND*	_OBJC_IVAR_$_TextCardItem._topChart0000000000000000 l d *UND*	_OBJC_IVAR_$_TextCardItem._reaction# 這里保存的是屬性信息對應的getter方法信息00000001000264a0 l  F __TEXT,__text	-[TextCardItem title]00000001000264c0 l  F __TEXT,__text	-[TextCardItem showReact]00000001000264f0 l  F __TEXT,__text	-[TextCardItem topChart]0000000100026510 l  F __TEXT,__text	-[TextCardItem setTopChart:]# 這里保存的是屬性信息對應的setter方法信息00000001000028a0 l  F __TEXT,__text	-[SSCatchInviteScheduler setOrganizer:]00000001000028e0 l  F __TEXT,__text	-[SSCatchInviteScheduler setInputCardBack:]0000000100002920 l  F __TEXT,__text	-[SSCatchInviteScheduler setInputTextBack:]# 這里保存的是類文件的文件名信息0000000000000000 l d *UND*	PubSearchDataComposer.m000000005a937587 l d __TEXT,__stub_helper	__stub_helper00000001000251c0 l d __TEXT,__text	__text

從上面可以看出,二進制中保留了很多信息和源代碼有很大關系,我們做個簡單的猜測蘋果后臺機器審查二進制的時候會通過二進制中的符號進行對比,如果兩個二進制(一個主版本、一個殼版本)代碼中的符號重合度超過某個閾值,就會判定這是發布殼版本的行為,而這是蘋果說不允許的,所以可行的方法是修改源文件中的這些信息來繞過蘋果的審查機制。

另外猜測蘋果應該是不會根據代碼中的流程控制來判斷的,因為二進制中的控制流程已經是機器碼了,反編譯出來也就是匯編代碼,只要稍微做點改動二進制(.text段)就會變化很大。所以從這個方面來判斷就難度很大了。

步驟分析

主要有以下幾個步驟

  1. 尋找到需要替換的源文件中的所有的屬性,處理之后保存在配置文件中
  2. 用戶自定義一個黑名單配置文件
  3. 某部分需要隔離的代碼中的屬性生成黑名單配置文件
  4. 把需要替換的源文件中的所有匹配的屬性做批量的替換

這里說明下為什么第一步需要保存在配置文件中,因為第三步的操作有部分和第一步是相同的,所有這部分單獨出來一個模塊共用,都是輸入一個文件夾,最終保存在指定的文件中,后面的代碼中可以看到這部分。

實現

單步實現

1、尋找到需要替換的源文件中的所有的屬性,處理之后保存在配置文件中

這一步的功能是客戶端輸入一個需要處理的源碼文件夾,遞歸遍歷該源碼文件夾獲取所有源碼文件(.h .m 文件)。使用正則匹配找到屬性名稱,暫時保存到數組中,最后經過黑名單過濾、去重過濾、其他過濾條件過濾,最終把待處理的屬性保存到客戶端輸入的輸出文件中。

可以分解為一下幾個小步驟

  • 遞歸遍歷文件夾獲取源碼文件
  • 正則匹配源碼文件的屬性
  • 過濾屬性(可選)
  • 保存屬性到文件

這部分功能的源碼如下:

文件名: GetAndStoreProperties.sh

該腳本在多個地方都有用到,所以作為一個單獨的模塊,定義了一些參數,以適應不同的應用場景。在下面可以看到使用該腳本的地方。

#!/bin/bash######################### 腳本功能:從指定目錄獲取和保存屬性到指定的文件# 輸入參數 -i 輸入的文件夾# 輸入參數 -o 保存的文件# 輸入參數 -f 使用黑名單和自定義過濾條件的參數# 輸入參數 -c 自定義的黑名單文件############################### 參數定義param_input_dir=""param_output_file=""param_custom_filter_file=""param_should_use_filter=0####### 參數解析while getopts :i:o:c:f optdo	case "$opt" in		i) param_input_dir=$OPTARG			echo "Found the -i option, with parameter value $OPTARG"			;;		o) param_output_file=$OPTARG			echo "Found the -o option, with parameter value $OPTARG"			;;		c) param_custom_filter_file=$OPTARG			echo "Found the -c option, with parameter value $OPTARG"			;;		f) echo "Found the -f option" 			param_should_use_filter=1			;;		*) echo "Unknown option: $opt";;	esacdone####### 配置# 屬性黑名單配置文件blacklist_cfg_file="$(pwd)/DefaultBlackListPropertiesConfig.cfg"####### 數據定義# 定義保存源文件的數組declare -a implement_source_file_arrayimplement_source_file_count=0# 定義保存屬性的數組declare -a tmp_props_arrayprops_count=0# mark: p384# 遞歸函數讀取目錄下的所有.m文件function read_source_file_recursively {	echo "read_implement_file_recursively"	if [[ -d $1 ]]; then		for item in $(ls $1); do			itemPath="$1/${item}"			if [[ -d $itemPath ]]; then				# 目錄				echo "處理目錄 ${itemPath}"				read_source_file_recursively $itemPath				echo "處理目錄結束====="			else 				# 文件				echo "處理文件 ${itemPath}"				if [[ $(expr "$item" : '.*/.m') -gt 0 ]] || [[ $(expr "$item" : '.*/.h') -gt 0 ]]; then					echo ">>>>>>>>>>>>mmmmmmm"					implement_source_file_array[$implement_source_file_count]=${itemPath}					implement_source_file_count=$[ implement_source_file_count + 1 ];				fi				echo ""			fi		done	else		echo "err:不是一個目錄"	fi}# 讀取源碼中的屬性,保存到數組中# 參數一: 源碼文件路徑function get_properties_from_source_file {	local class_file=$1;	echo "class_file=${class_file}"	properties=$(grep "@property.*" ${class_file})	IFS_OLD=$IFS	IFS=$'/n'	for prop_line in $properties; do		echo ">>>>>${prop_line}"		asterisk_seperator_pattern="/*"		if [[ ${prop_line} =~ ${asterisk_seperator_pattern} ]]; then			# 從左向右截取最后一個string后的字符串			prop_name=${prop_line##*${asterisk_seperator_pattern}}			# 從左向右截取第一個string后的字符串			seal_pattern=";*"			seal_pattern_replacement=""			prop_name=${prop_name//${seal_pattern}/${seal_pattern_replacement}}			subsring_pattern="[ |;]"			replacement=""			prop_name=${prop_name//${subsring_pattern}/${replacement}}			if [[ ${param_should_use_filter} -gt 0 ]]; then				grep_result=$(grep ${prop_name} ${blacklist_cfg_file})				echo "grep_result = >>${grep_result}<<"				custom_grep_result=""				if [[ -n ${param_custom_filter_file} ]]; then					custom_grep_result=$(grep ${prop_name} ${param_custom_filter_file})				fi				if [[ -n ${grep_result} ]] || [[ -n ${custom_grep_result} ]]; then					echo "--${prop_name}--存在配置文件中"				else					echo "--${prop_name}--XXX不存在配置文件中"					tmp_props_array[$props_count]=$prop_name					props_count=$[ props_count + 1 ]					echo ">>>>>>>result_prop_name=${prop_name}"				fi			else				tmp_props_array[$props_count]=$prop_name				props_count=$[ props_count + 1 ]			fi					fi	done	IFS=$IFS_OLD}# 獲取目錄下的所有源文件,讀取其中的屬性function get_properties_from_source_dir {	local l_classed_folder=$1	echo "獲取需要處理的源文件... ${l_classed_folder}"	# 讀取需要處理目標文件	read_source_file_recursively ${l_classed_folder}	echo "讀取源文件中的屬性..."	for(( i=0;i<${#implement_source_file_array[@]};i++)) 	do 		class_file=${implement_source_file_array[i]}; 		echo "處理源文件:${class_file}"		get_properties_from_source_file ${class_file}	done;}# 把獲取到的屬性過濾之后寫入文件中# 過濾步驟包含去重、去掉簡單詞匯、去掉長度少于多少的詞匯# 如果在執行的過程中遇到特殊情況,添加到黑名單配置(DefaultBlackListPropertiesConfig.cfg文件中添加配置)function post_get_properties_handle {	local prop_config_file=$1	# 寫入文件中	echo "# Properties Configs" > ${prop_config_file}	for key in $(echo ${!tmp_props_array[*]})	do	 # echo "$key : ${tmp_props_array[$key]}"	 echo ${tmp_props_array[$key]} >> ${prop_config_file}	done	# 去重	cfg_back_file="${prop_config_file}.bak"	mv ${prop_config_file} ${cfg_back_file}	sort ${cfg_back_file} | uniq > ${prop_config_file}		# 過濾	if [[ ${param_should_use_filter} -gt 0 ]]; then		mv ${prop_config_file} ${cfg_back_file}		echo "# Properties Configs Filtered" > ${prop_config_file}		IFS_OLD=$IFS		IFS=$'/n'		# 上一行的內容		lastLine="";		for line in $(cat ${cfg_back_file} | sed 's/^[ /t]*//g')		do			if [[ ${#line} -le 6 ]] || [[ $(expr "$line" : '^#.*') -gt 0 ]]; then				# 長度小于等于6或者注釋內容的行不處理				echo "less then 6 char line or comment line"			else				if [[ -n ${lastLine} ]]; then					# 上一行是非空白行					# 比較上一行內容是否是當前行的一部分,不是添加上一行					if [[ ${line} =~ ${lastLine} ]]; then						echo "${line} 和 ${lastLine} 有交集"					else						echo ${lastLine} >> ${prop_config_file}					fi				fi				# 更新上一行				lastLine=${line}			fi			done		IFS=${IFS_OLD}	fi	# 刪除臨時文件	rm -f ${cfg_back_file}}get_properties_from_source_dir ${param_input_dir}post_get_properties_handle ${param_output_file}

使用以上腳本生成的配置文件 PropertiesConfigs.cfg 部分如下:

# Properties Configs FilteredUserRestrictionLabelaboutusButtonactivitySamplersaddAddressPressaddressSamplersaddressTextBoxappealPressappliedGroupedSamplersappliedSamplersapplyPressasyncArrayasyncListSampleraudioPlayer

2. 用戶自定義一個黑名單配置文件

在實踐的過程中,替換屬性的符號有時候會把系統類的屬性替換了,比如

  • 把 AppDelegate 中的 window 屬性替換了,導致了編譯鏈接沒錯,但是界面出不來了,因為初始的window對象找不到了
  • 把 UIButton 中的 titleLabel 屬性替換了,直接導致了編譯出錯

對于這類問題,需要在黑名單中配置一些默認的過濾屬性,對于黑名單中的這些屬性不處理即可,在我的業務場景下,黑名單文件的配置如下:

文件名:DefaultBlackListPropertiesConfig.cfg

# BlackListPropertiesConfig.cfg# 屬性黑名單配置,在此配置文件中的屬性不需要替換名稱windownametitletitleLabellayoutappealSamplers

在 GetAndStoreProperties.sh 腳本使用到的代碼片段如下,其實就是使用了 grep 命來查找,判斷時候有找到,如果有就不處理,具體的可以看上面提供的完整的 GetAndStoreProperties.sh 腳本代碼

if [[ ${param_should_use_filter} -gt 0 ]]; then	grep_result=$(grep ${prop_name} ${blacklist_cfg_file})	echo "grep_result = >>${grep_result}<<"	custom_grep_result=""	if [[ -n ${param_custom_filter_file} ]]; then		custom_grep_result=$(grep ${prop_name} ${param_custom_filter_file})	fi	if [[ -n ${grep_result} ]] || [[ -n ${custom_grep_result} ]]; then		echo "--${prop_name}--存在配置文件中"	else		echo "--${prop_name}--XXX不存在配置文件中"		tmp_props_array[$props_count]=$prop_name		props_count=$[ props_count + 1 ]		echo ">>>>>>>result_prop_name=${prop_name}"	fielse	tmp_props_array[$props_count]=$prop_name	props_count=$[ props_count + 1 ]fi	

3. 某部分需要隔離的代碼中的屬性生成黑名單配置文件

這部分的功能其實就是調用 GetAndStoreProperties.sh 這個腳本,最終把文件輸出的文件以追加的方式寫入到用戶自定義的黑名單屬性文件中。

#...# 黑名單類目錄declare -a custom_blacklist_search_dirscustom_blacklist_search_dirs=("/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/SSCatchAPI" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Categories" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Components" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/External" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/HandyTools" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Macros" )# ...# 屬性黑名單配置文件custom_blacklist_cfg_file="$(pwd)/CustomBlackListPropertiesConfig.cfg"# ...# 獲取自定義的黑名單屬性并保存到文件中echo "" > ${custom_blacklist_cfg_file}for (( i = 0; i < ${#custom_blacklist_search_dirs[@]}; i++ )); do	custom_blacklist_search_dir=${custom_blacklist_search_dirs[${i}]}	./GetAndStoreProperties.sh /		-i ${custom_blacklist_search_dir}/		-o ${custom_blacklist_cfg_tmp_file}	cat ${custom_blacklist_cfg_tmp_file} >> ${custom_blacklist_cfg_file}done#...

最終生成的用戶自定義的黑名單文件部分如下

文件:CustomBlackListPropertiesConfig.cfg

# Properties ConfigsDBFilePathValidityStringaccessQueueageattributedNameStringavatarURLStringavatarUrlStringbackColorStringbodySchedulerbodyViewcatchDateStringcellHeightchannelKeycityNameconditionString# ....

4. 把需要替換的源文件中的所有匹配的屬性做批量的替換

這一步在前面三部的基礎上,查找并替換源碼目錄中在 PropertiesConfigs.cfg 配置文件中出現的屬性和屬性的引用,查找使用grep命令、替換使用了sed命令。腳本代碼如下

#!/bin/bash# 屬性重命名腳本####### 配置# classes類目錄classes_dir="$(pwd)/../InjectedContentKitx"# 黑名單類目錄declare -a custom_blacklist_search_dirscustom_blacklist_search_dirs=("/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/SSCatchAPI" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Categories" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Components" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/External" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/HandyTools" 	"/Users/aron/PuTaoWorkSpace/project/sscatch/sscatch/Classes/Macros" )# 配置文件cfg_file="$(pwd)/PropertiesConfigs.cfg"# 屬性黑名單配置文件blacklist_cfg_file="$(pwd)/DefaultBlackListPropertiesConfig.cfg"# 屬性黑名單配置文件custom_blacklist_cfg_file="$(pwd)/CustomBlackListPropertiesConfig.cfg"custom_blacklist_cfg_tmp_file="$(pwd)/TmpCustomBlackListPropertiesConfig.cfg"# 屬性前綴,屬性前綴需要特殊處理class_prefix=""# 屬性后綴class_suffix="abc"# 檢測文件是否存在,不存在則創建checkOrCreateFile() {	file=$1	if [[ -f $file ]]; then		echo "檢測到配置文件存在 $file"	else		echo "創建配置文件 $file"		touch $file	fi}# 配置文件檢查checkOrCreateFile $cfg_file# 循環檢測輸入的文件夾function checkInputDestDir {	echo -n "請輸入需處理源碼目錄: "	read path	if [[ -d $path ]]; then		classes_dir=$path	else		echo -n "輸入的目錄無效,"		checkInputDestDir	fi}# 需處理源碼目錄檢查if [[ -d $classes_dir ]]; then	echo "需處理源碼目錄存在 $classes_dir"else	echo "請確認需處理源碼目錄是否存在 $classes_dir"	checkInputDestDirfi####### 數據定義# 定義屬性保存數組declare -a rename_properties_config_content_arraycfg_line_count=0# 讀取屬性配置文件function read_rename_properties_configs {	IFS_OLD=$IFS	IFS=$'/n'	# 刪除文件行首的空白字符 http://www.49028c.com/article/57972.htm	for line in $(cat $cfg_file | sed 's/^[ /t]*//g')	do		is_comment=$(expr "$line" : '^#.*')		echo "line=${line} is_common=${is_comment}"		if [[ ${#line} -eq 0 ]] || [[ $(expr "$line" : '^#.*') -gt 0 ]]; then			echo "blank line or comment line"		else			rename_properties_config_content_array[$cfg_line_count]=$line			cfg_line_count=$[ $cfg_line_count + 1 ]			# echo "line>>>>${line}"		fi		done	IFS=${IFS_OLD}}function print_array {	# 獲取數組	local newarray	newarray=($(echo "$@"))	for (( i = 0; i < ${#newarray[@]}; i++ )); do		item=${newarray[$i]}		echo "array item >>> ${item}"	done}# 重命名所有的屬性function rename_properties {	# 讀取屬性配置文件	read_rename_properties_configs	# print_array ${rename_properties_config_content_array[*]}	# 執行替換操作	for (( i = 0; i < ${#rename_properties_config_content_array[@]}; i++ )); do		original_prop_name=${rename_properties_config_content_array[i]};		result_prop_name="${class_prefix}${original_prop_name}${class_suffix}"		sed -i '{			s/'"${original_prop_name}"'/'"${result_prop_name}"'/g		}' `grep ${original_prop_name} -rl ${classes_dir}`		echo "正在處理屬性 ${original_prop_name}....."	done}checkOrCreateFile ${custom_blacklist_cfg_tmp_file}# 獲取自定義的黑名單屬性并保存到文件中echo "" > ${custom_blacklist_cfg_file}for (( i = 0; i < ${#custom_blacklist_search_dirs[@]}; i++ )); do	custom_blacklist_search_dir=${custom_blacklist_search_dirs[${i}]}	./GetAndStoreProperties.sh /		-i ${custom_blacklist_search_dir}/		-o ${custom_blacklist_cfg_tmp_file}	cat ${custom_blacklist_cfg_tmp_file} >> ${custom_blacklist_cfg_file}done# 獲取和保存屬性到熟悉配置文件./GetAndStoreProperties.sh /	-i ${classes_dir}/	-o ${cfg_file}/	-f /	-c ${custom_blacklist_cfg_file}# 執行屬性重命名rename_propertiesecho "done."

總結

以上就是基于shell腳本,以殼版本為場景,把屬性的批量替換做了一個半自動化的實現步驟,如果不妥之處,還請不吝賜教。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
海角国产乱辈乱精品视频| 亚洲一区二区久久久久久久| 国内精品一区二区三区| 日韩大片免费观看视频播放| 91手机视频在线观看| 欧美日韩在线影院| 亚洲www永久成人夜色| 国产区精品视频| 国产日韩精品视频| 亚洲最大福利视频| 性视频1819p久久| 国产精品大陆在线观看| 久久亚洲国产精品成人av秋霞| 欧美日韩国产色视频| 国产精品女视频| 国产精品一二区| 国产精品人成电影在线观看| 久久久免费精品视频| 欧美亚洲国产成人精品| 国产中文字幕日韩| 国产精品日韩在线观看| 国产精品久久久久久久久久久久久久| 久久久久免费精品国产| 在线视频欧美性高潮| 精品国产依人香蕉在线精品| 亚洲影视九九影院在线观看| 97超级碰在线看视频免费在线看| 色哟哟网站入口亚洲精品| 日本91av在线播放| 亚洲人成网站在线播| 成人免费看黄网站| 亚洲欧美自拍一区| 69国产精品成人在线播放| 国产精品美女无圣光视频| 日韩电影免费观看在线观看| 欧美乱大交做爰xxxⅹ性3| 在线视频欧美日韩| 久久69精品久久久久久国产越南| 国产亚洲欧美日韩美女| 色综合老司机第九色激情| 亚洲男人天堂手机在线| 国产精品吹潮在线观看| 欧美日韩免费在线| 欧美与黑人午夜性猛交久久久| 国产欧美日韩视频| 欧美午夜精品伦理| 欧美大尺度电影在线观看| 亚洲精品电影网| 久久久久久亚洲精品| 亚洲色图第一页| 91精品久久久久久久久久久| 亚洲国模精品私拍| www国产91| 51视频国产精品一区二区| 一本色道久久综合狠狠躁篇的优点| 色偷偷9999www| 97精品伊人久久久大香线蕉| 美女黄色丝袜一区| 日韩欧美精品网站| 欧美激情一二区| 久久精品99久久久香蕉| 欧美片一区二区三区| 色婷婷综合久久久久| 亚洲区免费影片| 亚洲视频日韩精品| 中文字幕亚洲字幕| 亚洲最大福利网站| 91黑丝在线观看| 久久久久久有精品国产| 国产精品av网站| 日韩一级裸体免费视频| 国产精品久久久久久婷婷天堂| 日本久久久久久久| 午夜精品99久久免费| 日韩精品在线免费| 成人午夜两性视频| 日韩av一区在线| 亚洲a成v人在线观看| 久青草国产97香蕉在线视频| 岛国av一区二区| 欧美色另类天堂2015| 亚洲视频在线看| 国产精品视频永久免费播放| 国产视频精品久久久| 亚洲精品国产品国语在线| 亚洲欧美一区二区精品久久久| 亚洲va欧美va国产综合久久| 久久久久久91香蕉国产| 韩国v欧美v日本v亚洲| 欧美日韩福利电影| 欧洲成人在线视频| 在线性视频日韩欧美| 久色乳综合思思在线视频| 91成人在线观看国产| 欧美性生交xxxxx久久久| 欧美视频中文在线看| 欧美日韩一区二区三区在线免费观看| 97国产精品视频人人做人人爱| 亚洲免费一级电影| 欧美日韩亚洲一区二区| 91牛牛免费视频| 美女视频久久黄| 欧美色图在线视频| 日韩免费在线播放| 欧美成人精品三级在线观看| 青青精品视频播放| 欧美床上激情在线观看| 欧美亚洲另类激情另类| 欧美激情精品久久久久久蜜臀| 91久久国产精品91久久性色| 日韩精品久久久久| 欧美最猛性xxxxx(亚洲精品)| 国产激情视频一区| 欧美成人免费观看| 久久亚洲综合国产精品99麻豆精品福利| 亚洲午夜久久久影院| 欧美日韩国产在线| 亚洲免费福利视频| 日本老师69xxx| 精品人伦一区二区三区蜜桃免费| 欧美一级成年大片在线观看| 亚洲二区中文字幕| 午夜精品久久久久久久99热浪潮| 亚洲精品在线91| 日本中文字幕不卡免费| 久久精品国产69国产精品亚洲| 国产97色在线| 精品国产欧美成人夜夜嗨| 992tv成人免费视频| 欧美日韩国产一中文字不卡| 欧美激情乱人伦| 国产精品一区二区久久久久| 91精品国产综合久久久久久蜜臀| 欧美成人免费视频| 亚洲电影免费在线观看| 91精品久久久久久综合乱菊| 超碰91人人草人人干| 一区二区三区国产在线观看| 欧美一二三视频| 国产精品aaaa| 亚洲美女免费精品视频在线观看| 在线视频欧美日韩| 美女黄色丝袜一区| 成人黄色av免费在线观看| 亚洲色图激情小说| 日韩高清电影免费观看完整| 亚洲美女性视频| 欧美在线视频网| 日韩在线观看成人| 久久综合伊人77777| 国产成人精品在线视频| 欧美性受xxxx黑人猛交| 日韩极品精品视频免费观看| 成人欧美一区二区三区在线| 久久久久久久亚洲精品| 日韩中文字幕国产精品| 成人免费xxxxx在线观看| 国产日韩欧美在线视频观看| 久久精品2019中文字幕| 久久精品福利视频| 欧美日韩国产精品一区二区不卡中文| 欧美日韩中文在线观看| 午夜伦理精品一区| 91高潮精品免费porn|