Commit c03a26b1 authored by wanglei's avatar wanglei

[混淆]提交混淆脚本

parent 28bc2f2e
......@@ -4,6 +4,30 @@ import os
import re
def load_mapping():
"""Load the obfuscation mapping from mapping.json"""
try:
with open("mapping.json", "r", encoding="utf-8") as f:
mapping = json.load(f)
return mapping.get("class", {})
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Warning: Could not load mapping.json - {e}")
return {}
def find_obfuscated_file(directory, original_name, mapping):
"""Find the obfuscated file name in the given directory"""
obfuscated_name = mapping.get(original_name, original_name)
for root, dirs, files in os.walk(directory):
for file in files:
if file == f"{obfuscated_name}.kt" or file == f"{original_name}.kt":
file_path = os.path.join(root, file)
print(f"Found config file: {file_path}")
return file_path
print(f"Could not find {obfuscated_name}.kt or {original_name}.kt in {directory}")
return None
def fetch_app_info(pkg):
"""向指定 URL 发送请求并获取内容"""
base_url = "http://data-api.zhangxinhulian.com/anonymous/getappinfoAndroid"
......@@ -28,7 +52,6 @@ def fetch_app_info(pkg):
"idMaxOpen": "ID_MAX_OPEN",
"idMaxBanner": "ID_MAX_BANNER",
"idMaxReward": "ID_MAX_REWARD",
# "idMaxReward": "ID_ADMOB_APPLICATION"
}
try:
......@@ -37,28 +60,20 @@ def fetch_app_info(pkg):
data = response.json()
if data.get("status") == 200 and data.get("result") and data["result"].get("data"):
app_data = data["result"]["data"]
# 设置 packageName 为用户输入的 pkg
app_data["packageName"] = pkg
# 将 null 转换为 ""
app_data = {key: (value if value is not None else "") for key, value in app_data.items()}
# 打印从服务器获取到的数据字段
print("从服务器获取到的数据字段值:")
for key, value in app_data.items():
print(f"{key}: {value}")
# 替换 key
transformed_data = {key_mapping.get(key, key): value for key, value in app_data.items()}
# 写入 JSON 文件
with open("applicationid.json", "w", encoding="utf-8") as file:
json.dump(transformed_data, file, ensure_ascii=False, indent=4)
with open("applicationid.json", "r", encoding="utf-8") as file:
json_data = json.load(file)
# 打印 applicationid.json 文件中的数据
print("\napplicationid.json 中的数据:")
print(json_data)
print("数据已成功以 JSON 格式写入 applicationid.json 文件。")
......@@ -70,57 +85,40 @@ def fetch_app_info(pkg):
print(f"请求发生错误: {e}")
def find_global_config(directory):
"""遍历目录查找 GlobalConfig.kt 文件"""
for root, dirs, files in os.walk(directory):
if 'GlobalConfig.kt' in files:
file_path = os.path.join(root, 'GlobalConfig.kt')
print(f"找到 GlobalConfig.kt 文件: {file_path}")
return file_path
print("未找到 GlobalConfig.kt 文件")
return None
def update_global_config(file_path, json_data):
"""更新 GlobalConfig.kt 文件中的变量值"""
try:
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
# 获取 json_data 中的 adsApplicationId
ads_application_id = json_data.get("adsApplicationId")
if ads_application_id:
# 使用正则表达式查找并替换 ID_ADMOB_APPLICATION 的值
pattern = r'\binline\s+val\s+ID_ADMOB_APPLICATION\s+get\(\)\s*=\s*.*'
replacement = f'inline val ID_ADMOB_APPLICATION get() = "{ads_application_id}"'
content = re.sub(pattern, replacement, content)
facebook_app_id = json_data.get("facebookAppId")
if facebook_app_id:
# 使用正则表达式查找并替换 ID_ADMOB_APPLICATION 的值
pattern = r'\binline\s+val\s+ID_FACEBOOK\s+get\(\)\s*=\s*.*'
replacement = f'inline val ID_FACEBOOK get() = "{facebook_app_id}"'
content = re.sub(pattern, replacement, content)
# 遍历 JSON 数据中的每个变量名,并在 GlobalConfig.kt 中更新对应的值
for var_name, var_value in json_data.items():
# 替换 const val 的值
pattern_const = rf'\bconst\s+val\s+{re.escape(var_name)}\s*=\s*.*'
replacement_const = f'const val {var_name} = "{var_value}"'
content = re.sub(pattern_const, replacement_const, content)
pattern_inline = rf'\binline\s+val\s+{re.escape(var_name)}\s+get\(\)\s*=\s*.*'
replacement_inline = f'inline val {var_name} get() = "{var_value}"'
content = re.sub(pattern_inline, replacement_inline, content)
# 将修改后的内容写回到 GlobalConfig.kt 文件
with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)
print("\nGlobalConfig.kt 文件已成功更新。")
print("\n配置文件已成功更新。")
except Exception as e:
print(f"更新文件时发生错误: {e}")
def update_google_services(json_data):
"""更新 google-services.json 文件内容"""
try:
......@@ -133,21 +131,17 @@ def update_google_services(json_data):
if google_services_raw:
try:
# 如果是 URL,就去下载内容
if google_services_raw.startswith("https://") or google_services_raw.startswith("http://"):
if google_services_raw.startswith(("https://", "http://")):
print(f"检测到 URL,开始下载: {google_services_raw}")
response = requests.get(google_services_raw, verify=False)
response.raise_for_status()
google_services_raw = response.text
# 反序列化
google_services_data = json.loads(google_services_raw)
# 写入文件
with open(google_services_path, "w", encoding="utf-8") as file:
json.dump(google_services_data, file, ensure_ascii=False, indent=4)
# 打印写入内容
with open(google_services_path, "r", encoding="utf-8") as file:
written_data = file.read()
print("\ngoogle-services.json 文件已更新,写入的内容如下:")
......@@ -183,7 +177,6 @@ def update_google_services(json_data):
def update_build_gradle(json_data):
"""更新 build.gradle 或 build.gradle.kts 文件中的 applicationId 值"""
try:
# 查找 build.gradle.kts 文件
build_gradle_kts_path = os.path.join(os.getcwd(), "build.gradle.kts")
build_gradle_path = os.path.join(os.getcwd(), "build.gradle")
build_file_path = None
......@@ -197,31 +190,26 @@ def update_build_gradle(json_data):
print("未找到 build.gradle 或 build.gradle.kts 文件。")
return
# 从 applicationid.json 中获取 PACKAGE_NAME 的值
package_name = json_data.get("PACKAGE_NAME")
if package_name:
with open(build_file_path, "r", encoding="utf-8") as file:
content = file.read()
# 根据文件名选择不同的正则表达式
if build_file_path.endswith(".kts"):
# 匹配 applicationId 的值,无论其格式如何(字符串或变量引用)
pattern = r'applicationId\s*=\s*[^\s]+'
replacement = f'applicationId = "{package_name}"'
new_content = re.sub(pattern, replacement, content)
else: # build.gradle
pattern = r'applicationId\s*\'[^\']+\'' # 匹配单引号字符串
else:
pattern = r'applicationId\s*\'[^\']+\''
replacement = f'applicationId \'{package_name}\''
new_content = re.sub(pattern, replacement, content)
if new_content == content: # 如果单引号没有匹配到则匹配双引号字符串
if pattern not in content:
pattern = r'applicationId\s*"[^"]+"'
replacement = f'applicationId "{package_name}"'
new_content = re.sub(pattern, replacement, content)
# 写入更新后的内容
new_content = re.sub(pattern, replacement, content)
with open(build_file_path, "w", encoding="utf-8") as file:
file.write(new_content)
# 打印更新后的内容
print(f"\n{os.path.basename(build_file_path)} 文件已更新,更新后的内容如下:")
print(new_content)
else:
......@@ -234,23 +222,19 @@ def update_build_gradle(json_data):
def update_android_manifest(pkg):
'''更新 AndroidManifest.xml 文件中的 Facebook App ID'''
try:
# 查找 AndroidManifest.xml 文件
file_path = os.path.join('.', 'src', 'main', 'AndroidManifest.xml')
if os.path.exists(file_path):
print(f"找到 AndroidManifest.xml 文件: {file_path}")
# 从 applicationid.json 中获取 facebookAppId 的值
facebookAppId = json_data.get("facebookAppId")
if facebookAppId:
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
# 替换 facebookAppId 的值,无论其格式如何(字符串或变量引用)
pattern = r'<meta-data\s*android:name="com\.facebook\.sdk\.ApplicationId"\s*android:value\s*=\s*[^\s]+'
replacement = f'<meta-data android:name="com.facebook.sdk.ApplicationId"\n android:value = "{facebookAppId}"'
new_content = re.sub(pattern, replacement, content)
# 写入更新后的内容
with open(file_path, "w", encoding="utf-8") as file:
file.write(new_content)
......@@ -259,7 +243,6 @@ def update_android_manifest(pkg):
else:
print("applicationid.json 中未找到 facebookAppId 的值。")
# 从 applicationid.json 中获取 adsApplicationId 的值
adsApplicationId = json_data.get("adsApplicationId")
if adsApplicationId:
with open(file_path, "r", encoding="utf-8") as file:
......@@ -269,7 +252,6 @@ def update_android_manifest(pkg):
replacement = f'<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID"\n android:value = "{adsApplicationId}"'
new_content = re.sub(pattern, replacement, content)
# 写入更新后的内容
with open(file_path, "w", encoding="utf-8") as file:
file.write(new_content)
......@@ -278,18 +260,17 @@ def update_android_manifest(pkg):
else:
print("applicationid.json 中未找到 adsApplicationId 的值。")
# 从 applicationid.json 中获取 PACKAGE_NAME 的值
PACKAGE_NAME = json_data.get("PACKAGE_NAME")
if PACKAGE_NAME:
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
# 更宽松的正则表达式模式
pattern = r"""
android:permission="com\.google\.android\.c2dm\.permission\.SEND"\s*>
\s*<intent-filter>\s*
\s*<action\s+android:name="com\.google\.firebase\.MESSAGING_EVENT"\s*/>\s*
\s*<action\s+android:name="com\.google\.android\.c2dm\.intent\.RECEIVE"\s*/>\s*
\s*<category\s+android:name="([^"]+)"\s*/>\s* # 捕获 category 值
\s*<category\s+android:name="([^"]+)"\s*/>\s*
\s*</intent-filter>
"""
replacement = f"""
......@@ -301,47 +282,17 @@ def update_android_manifest(pkg):
</intent-filter>
"""
# 执行替换操作,使用 re.VERBOSE 忽略空白和注释,使用 re.DOTALL 匹配换行
new_content = re.sub(pattern, replacement, content, flags=re.VERBOSE | re.DOTALL)
# 判断是否匹配到并进行了替换
if new_content != content:
print("替换成功,内容已更新。")
# 将修改后的内容写回文件
with open(file_path, 'w', encoding='utf-8') as file:
file.write(new_content)
else:
print("没有找到匹配的内容,文件未更改。")
# pattern = r"""
# android:permission="com.google.android.c2dm.permission.SEND">
# <intent-filter>(.*?)<category android:name="\s*([^"]+)"
# """
#
# replacement = f"""
# android:permission="com.google.android.c2dm.permission.SEND">
# <intent-filter>\1
# <category android:name="{PACKAGE_NAME}"
# """
#
# #pattern = r'android:permission="com.google.android.c2dm.permission.SEND">'
# #r'<intent-filter>'
# #r'<action android:name="com.google.firebase.MESSAGING_EVENT" />'
# #r'<action android:name="com.google.android.c2dm.intent.RECEIVE" />'
#
# #r'<category android:name\s*=\s*[^\s]+'
# #replacement = f' android:permission="com.google.android.c2dm.permission.SEND">'
# #f'<intent-filter>'
# #f'<action android:name="com.google.firebase.MESSAGING_EVENT" />'
# #f'<action android:name="com.google.android.c2dm.intent.RECEIVE" /> android:name = "{PACKAGE_NAME}"'
# new_content = re.sub(pattern, replacement, content)
# 写入更新后的内容
with open(file_path, "w", encoding="utf-8") as file:
file.write(new_content)
print("\nAndroidManifest.xml 文件已更新,c2dm.permission.SEND 更新后的内容如下:")
print(new_content)
print("\nAndroidManifest.xml 文件已更新,c2dm.permission.SEND 更新后的内容如下:")
print(new_content)
else:
print("applicationid.json 中未找到 PACKAGE_NAME 的值。")
......@@ -352,30 +303,26 @@ def update_android_manifest(pkg):
if __name__ == "__main__":
# Load obfuscation mapping
mapping = load_mapping()
pkg_input = input("请输入 pkg 的值:")
if pkg_input.strip():
fetch_app_info(pkg_input.strip())
# 查找 GlobalConfig.kt 文件
# Find the config file (either original or obfuscated name)
java_src_dir = os.path.join(os.getcwd(), "src", "main", "java")
global_config_path = find_global_config(java_src_dir)
config_file_path = find_obfuscated_file(java_src_dir, "GlobalConfig", mapping)
# 读取 applicationid.json 文件并获取数据
if global_config_path and os.path.exists("applicationid.json"):
# Read applicationid.json and update files
if config_file_path and os.path.exists("applicationid.json"):
with open("applicationid.json", "r", encoding="utf-8") as file:
json_data = json.load(file)
# 更新 GlobalConfig.kt 文件
update_global_config(global_config_path, json_data)
# 更新 google-services.json 文件
update_global_config(config_file_path, json_data)
update_google_services(json_data)
# 更新 build.gradle.kts 文件
update_build_gradle(json_data)
# 更新 AndroidManifest.xml
update_android_manifest(json_data["PACKAGE_NAME"])
else:
print("pkg 不能为空!")
print("pkg 不能为空!")
\ No newline at end of file
{
"string_ids": {
"app_name": "honeycombicy",
"facebook_app_id": "cottonicy",
"mb_10": "crimsonicy",
"mb_20": "boondocksicy",
"mb_50": "feedicy",
"mb_100": "journeyicy",
"mb_500": "hypertensionicy",
"involve_ad": "armfulicy",
"consent_required": "openericy",
"which_type_do_you_want_to_clean": "quotaicy",
"consent": "crystallizationicy",
"start": "entertainericy",
"privacy_policy": "erroricy",
"photo": "fogicy",
"audio": "sensationicy",
"document": "greaticy",
"video": "linguisticsicy",
"continue_": "tastefulicy",
"open_settings": "insufficienticy",
"storage_permission_title": "flaccidicy",
"storage_permission_content": "sledicy",
"junk_clean": "sighicy",
"battery_info": "orationicy",
"screenshot_clean": "panthericy",
"large_file_clean": "humaneicy",
"large_file": "artificialicy",
"photo_compression": "headyicy",
"similar_photos": "wovenicy",
"home": "conservationicy",
"settings": "passivelyicy",
"battery_status": "insomniaicy",
"temperature": "turgidicy",
"voltage": "candlestickicy",
"health": "frontiericy",
"good": "outgrowthicy",
"normal": "lesbianicy",
"battery_type": "skillicy",
"battery_capacity": "infatuationicy",
"please_wait": "carryouticy",
"power": "denyicy",
"charging": "inaugurateicy",
"clean_tips": "saboteuricy",
"clean": "applicanticy",
"go_it": "inflateicy",
"empty_folder": "lifelessicy",
"apk_files": "contentmenticy",
"temp_files": "citeicy",
"logs_files": "corrupticy",
"cleaned_up": "forwenticy",
"cleaned_up_content": "bigoticy",
"result_junk_clean": "hunkericy",
"clean_now": "holidayicy",
"all_types": "savagelyicy",
"delete": "weeknighticy",
"other_than": "strikericy",
"image": "misunderstandingicy",
"apk": "archaeologicalicy",
"other_types": "supermarketicy",
"all_time": "floodliticy",
"week_1": "timeicy",
"month_1": "sleeplessicy",
"month_3": "noticeablyicy",
"month_6": "meatyicy",
"year_1": "chunkicy",
"larger_than": "condominiumicy",
"confirm": "bangsicy",
"confirm_content": "turquoiseicy",
"cancel": "pollutedicy",
"delete_title": "grovelicy",
"delete_content": "assassinationicy",
"screenshots_totally": "initialsicy",
"select_all": "puckeredicy",
"auto_select": "hysteriaicy",
"occupies": "lighthouseicy",
"compress": "bloomicy",
"wait_a_moment": "gramicy",
"compress_all": "razoricy",
"best_quality_photo": "retracticy",
"most_space_saved": "swishicy",
"clean_junk": "discernicy",
"already_saved_for_you": "shutdownicy",
"rate_us": "reliablyicy",
"version": "flipicy",
"thank_you_for_using_app": "mantelicy",
"submit": "issueicy",
"guide_tip_1": "snapicy",
"guide_tip_2": "chairwomanicy",
"guide_tip_3": "populateicy",
"next": "foilicy",
"sure": "expulsionicy",
"exit_junk_clean": "physiqueicy",
"exit_junk_clean_content": "irreparableicy",
"exit_battery_info": "premeditatedicy",
"exit_battery_info_content": "swanicy",
"exit_large_file_clean": "austereicy",
"exit_large_file_clean_content": "wineglassicy",
"exit_photo_compression": "moreicy",
"exit_photo_compression_content": "transitoryicy",
"exit_screenshot_cleaner": "knoticy",
"exit_screenshot_cleaner_content": "babbleicy",
"exit_similar_photos": "mammalicy",
"exit_uninstall_app": "paralyzedicy",
"exit_similar_photos_content": "orbitalicy",
"logout_content": "puckericy",
"please_wait_a_moment": "biopsyicy",
"exit": "aroseicy",
"turn_on": "indoorsicy",
"CLEAN": "bridegroomicy",
"uninstall": "bebopicy",
"powered_by_trustlook": "sunbathingicy",
"malware_recommended": "mufficy",
"notification_tips": "yarmulkeicy",
"select_a_language": "creekicy",
"get_started": "uglyicy",
"battery": "Blackicy",
"estimated_battery": "unknownicy",
"electric_current": "boothicy",
"real_time_current": "basesicy",
"average_current": "indemnityicy",
"notify_junk_clean": "cheerfulnessicy",
"notify_battery_info": "whimsicalicy",
"notify_large_file": "childprooficy",
"notify_similar_photos": "acreicy",
"notify_screenshot": "patriotismicy",
"notify_photo_compression": "industrializationicy",
"ads_are_about_to_be_shown_s": "understateicy",
"by_continuing_": "injureicy",
"thank_you_very_much": "hayicy",
"view": "inhumanicy",
"content_not_found": "revelationicy",
"uninstall_app": "befriendicy",
"ok": "crustyicy",
"size": "coastalicy",
"install_time": "integrateicy",
"app_function_experience_tip": "noncommittalicy",
"experience_it_immediately": "ramificationicy",
"screenshot": "filtericy",
"exit_uninstall_app_content": "impostoricy",
"notify_uninstall_app": "overratedicy",
"quick_clean": "stifleicy",
"scan_completed": "improbabilityicy",
"turn_on_notification": "flaredicy",
"redundant_files_found": "canistericy",
"found_f": "parametericy",
"found": "misspellicy",
"don_t_miss_important_tips": "sanctifyicy",
"loading": "sixtyicy",
"file_recovery": "washouticy",
"app_manager": "registericy",
"recovery": "manipulateicy",
"left_with_current_power_consumption": "impulsivelyicy",
"finish": "bumblingicy",
"result_antivirus": "comprehensibleicy",
"result_battery_info": "crosswordicy",
"result_large_file_clean": "splendidlyicy",
"result_photo_compression": "surfingicy",
"result_screenshot_clean": "excludeicy",
"result_similar_photos": "reviveicy",
"recover_tip": "suggesticy",
"photos": "hypocriteicy",
"recover_lost_photos": "killingicy",
"videos": "eradicateicy",
"recover_lost_videos": "jammedicy",
"audios": "auctioneericy",
"documents": "saneicy",
"recover_lost_documents": "supremelyicy",
"scan": "diagnoseicy",
"click_to_view": "literateicy",
"more": "pigicy",
"duplicate_photos": "intuitivelyicy",
"recycle_bin": "articleicy",
"recyclebin_tip": "sofaicy",
"recyclebin": "yippeeicy",
"thank_you_very_much_for_taking_the_time_to_rate_us": "accompanyicy",
"screenshot_cleaner": "italicsicy",
"guide_title_1": "glowinglyicy",
"guide_title_2": "campusicy",
"guide_title_3": "vindicationicy",
"start_to_use": "partiallyicy",
"privacy": "debtoricy",
"agree": "captionicy",
"terms_of_service": "bandannaicy",
"notification_title": "splendoricy",
"notification_content": "windingicy",
"junk_files": "torsoicy",
"memory_used": "endangeredicy",
"storage_used": "trustfulicy",
"make_your_phone_clean": "grasslandicy",
"antivirus": "preventiveicy",
"mobile_antivirus_protection": "inferioricy",
"clear_phone_screenshot": "hotshoticy",
"clear_large_files_on_the_phone": "unearthlyicy",
"clear_similar_pictures_on_the_phone": "aircrafticy",
"image_compression": "newslettericy",
"compress_mobile_phone_images": "libertyicy",
"view_battery_information": "chapelicy",
"show_all_settings": "quivericy",
"malware_scan": "whileicy",
"apps": "ticicy",
"antivirus_scan_error_occurred_please_try_again": "maturityicy",
"exit_malware_clean": "allergicicy",
"exit_malware_clean_content": "disillusionmenticy",
"no_threats_found": "striddenicy",
"kind_tips": "infuriatingicy",
"let_us_know_how_we_re_doing": "smackicy",
"we_feedback_invaluable": "spareicy",
"one_tap_clean": "taperedicy",
"try_it_new": "automobileicy",
"permission_request": "felineicy",
"deny": "hasteicy",
"allow": "mommyicy",
"reject": "hamicy",
"collect_installed_application_information": "kneadicy",
"when_you_use_the_vlrus": "cavorticy",
"using_and_transferring_installed": "stimuliicy",
"virus_scanning_functionality_uses_trustlook_sdk": "girdericy",
"installed_application_information_access_and_sharing_statement": "aquaticicy",
"we_take_the_confidentiality_of_your": "ledicy",
"view_information_collection_instructions": "snagicy",
"notif_antivirus": "clothespinicy",
"lf_you_exit_the_scanning_results_will_be_discarded": "assistanceicy",
"exit_scanning": "comfortingicy",
"issue": "clingicy",
"preparing_advertisement": "clutchesicy"
},
"color_ids": {
"black": "squashicy",
"white": "pancreaticicy",
"transparent": "advisoryicy",
"colorPrimary": "cancelicy",
"colorDisEnable": "motificy",
"color_66000000": "inquiryicy",
"color_1a1a1a": "lipstickicy",
"color_181b1f": "curticy",
"color_666666": "salutationicy",
"color_f7fafa": "cockroachicy",
"color_aeb4bd": "commerceicy",
"color_f0f0f0": "toreicy",
"color_ededed": "tinkericy",
"color_ebebeb": "peticy",
"color_d9d9d9": "slashicy",
"color_9b9595": "crematoriaicy",
"color_999999": "intrigueicy",
"color_fffaf7": "awakeningicy",
"color_fdfff5": "themeicy",
"color_fefaff": "jaguaricy",
"color_fffafa": "centralicy",
"color_f5fff9": "pesticy",
"color_f7feff": "honorableicy",
"color_fff7fe": "tableicy"
},
"dimen_ids": {
"dp_300": "weirdicy",
"dp_150": "rebuildicy",
"dp_40": "southicy",
"dp_20": "establishmenticy",
"dp_50": "anticlimaxicy",
"dp_30": "cordicy",
"dp_80": "entrusticy",
"dp_10": "lengthyicy",
"dp_16": "badicy",
"dp_15": "scannericy",
"dp_2": "anthropologyicy",
"sp_16": "extensiveicy",
"sp_12": "munchiesicy",
"dp_8": "enlightenicy",
"dp_180": "inopportuneicy",
"dp_98": "infractionicy",
"dp_18": "queenicy",
"sp_17": "respectedicy",
"dp_35": "shovelicy",
"dp_5": "audiovisualicy",
"dp_45": "cappuccinoicy",
"sp_18": "mediocreicy",
"dp_4": "destinedicy",
"dp_60": "choppinessicy",
"sp_14": "progressivelyicy",
"dp_12": "sapphireicy",
"dp_14": "taunticy",
"sp_20": "intrusionicy",
"dp_70": "surviveicy",
"dp_38": "pilingicy",
"dp_55": "eschewicy",
"dp_6": "backericy",
"sp_15": "embalmicy",
"dp_306": "neighborhoodicy",
"dp_136": "frequenticy",
"dp_24": "vocationalicy",
"sp_13": "unhookicy",
"dp_26": "realisticallyicy",
"dp_88": "paperboyicy",
"sp_24": "clubhouseicy",
"dp_1": "reflexesicy",
"sp_22": "Pacificicy",
"sp_11": "moderatelyicy",
"dp_112": "cindericy",
"dp_66": "radioactiveicy",
"dp_42": "mileageicy",
"dp_400": "heavenicy",
"sp_19": "tremendousicy",
"dp_28": "convalesceicy",
"dp_54": "credibleicy",
"dp_25": "yearbookicy",
"dp_37": "buzzwordicy",
"dp_220": "roadhouseicy",
"dp_62": "retentionicy",
"dp__30": "pieceworkicy",
"dp_138": "quarantineicy",
"dp_132": "impassiveicy",
"dp_200": "escapeicy",
"dp_238": "uncomfortablyicy"
},
"style_ids": {
"Base.Theme.BaseAppTheme": "breatheicy",
"Theme.AppTheme": "tailsicy",
"splash.theme": "knowinglyicy"
},
"styleable": {
"NativeParentView": "lovericy",
"removeAll_A": "experimenticy",
"TripleSeekBar": "mannishicy",
"default_color_A": "troubleicy",
"selected_color_A": "understaffedicy",
"line_height_A": "parenthesesicy",
"width_A": "reflecticy",
"BaseProgressView": "axisicy",
"progress_max_A": "abroadicy",
"progress_value_A": "sensoryicy",
"progress_size_A": "blendicy",
"progress_color_A": "graduationicy",
"progress_color_background_A": "senilityicy",
"text_size_A": "knowledgeicy",
"text_color_A": "abductionicy",
"text_show_A": "attendicy",
"text_decimal_num_A": "spruceicy",
"light_color_A": "pikeicy",
"light_show_A": "latenticy",
"stroke_color_A": "ruefulicy",
"stroke_width_A": "consolidateicy",
"stroke_show_A": "molluskicy",
"LineBaseProView": "rusticicy",
"radius_A": "toyicy",
"left_top_radius_A": "multimillionaireicy",
"left_bottom_radius_A": "bunsicy",
"right_top_radius_A": "heathenicy",
"right_bottom_radius_A": "widespreadicy",
"progress_radius_A": "waterworksicy",
"LineProView": "immunizationicy",
"LineCentreProView": "toplessicy",
"box_width_A": "parishionericy",
"box_radius_A": "bladeicy",
"LineBottomProView": "wrungicy",
"box_height_A": "lemonadeicy",
"ArcProView": "indignationicy",
"arc_start_angle_A": "calligraphyicy",
"arc_draw_angle_A": "ophthalmologisticy",
"WaterWaveProView": "subordinateicy",
"water_wave_width_A": "panhandlericy",
"water_wave_height_A": "illustratoricy",
"water_wave_speed_A": "syndicationicy"
},
"view_ids": {
"main": "existenceicy",
"flTop": "robberyicy",
"ivBack": "inhabiticy",
"llSort": "detericy",
"llSize": "primlyicy",
"ivSize": "sanatoriumicy",
"llInstallTime": "abominableicy",
"ivInstallTime": "stoicalicy",
"rv": "dropsicy",
"tvOk": "farmicy",
"flAd": "inaugurationicy",
"layoutAnimation": "spaceyicy",
"clTop": "definitelyicy",
"llTitle": "shiticy",
"flBack": "marinateicy",
"nsvContainer": "fecesicy",
"clBattery": "feudalicy",
"ivBattery": "chaleticy",
"tvBattery": "counseloricy",
"tvStandbyHour": "alienateicy",
"tvStandbyMinute": "collaborationicy",
"tvVideoHour": "jockicy",
"tvVideoMinute": "battleicy",
"tvMusicHour": "befiticy",
"tvMusicMinute": "knapsackicy",
"llBatteryStatus": "blithelyicy",
"llBatteryType": "hygieneicy",
"tvTemperature": "collegiateicy",
"tvVoltage": "unzipicy",
"tvPower": "springboardicy",
"clHealth": "sunscreenicy",
"tvHealthContent": "nicheicy",
"tvHealth": "spongeicy",
"clBatteryStatus": "returnicy",
"tvBatteryStatusContent": "chinicy",
"tvBatteryStatus": "fetchingicy",
"clBatteryType": "frigateicy",
"tvBatteryTypeContent": "supervisoryicy",
"tvBatteryType": "infuriateicy",
"clBatteryCapacity": "hastyicy",
"tvBatteryCapacityContent": "checkeredicy",
"tvBatteryCapacity": "birdseedicy",
"tvTitle": "heartacheicy",
"idLottie": "confinedicy",
"tvCleanedUp": "hypnotizeicy",
"tvTip": "legitimacyicy",
"rvResult": "watticy",
"viewpager2": "fiascoicy",
"tv": "imperfectionicy",
"ll": "laxativeicy",
"llPhoto": "vertebraeicy",
"iv1": "dampnessicy",
"llVideo": "nonfaticy",
"iv2": "warpedicy",
"llAudio": "obtuseicy",
"iv3": "bothericy",
"llDocument": "choosyicy",
"iv4": "wepticy",
"flContinue": "sticklericy",
"shimmerLayout": "imperialicy",
"tvBtn": "graphicy",
"viewPager2": "mathicy",
"indicator": "cateringicy",
"expandableFiles": "checkedicy",
"tvClean": "psychosesicy",
"card": "mullicy",
"llNext": "sunlighticy",
"llTab": "jollyicy",
"llType": "fungalicy",
"ivType": "catnapicy",
"tvType": "utopiaicy",
"ivTypeArrow": "mangoicy",
"tvSize": "docileicy",
"ivSizeArrow": "awkwardnessicy",
"llTime": "problematicicy",
"ivTime": "zoomicy",
"tvTime": "evenhandedicy",
"ivTimeArrow": "cathedralicy",
"ivEmpty": "powwowicy",
"rvLargeFile": "particy",
"tvDelete": "selectivelyicy",
"clTab": "bungleicy",
"tvOtherThan": "uselessnessicy",
"rvTab": "recalcitranticy",
"fragment": "degreeicy",
"flBottom": "expoicy",
"tabLayout": "regressicy",
"flBanner": "stabilizeicy",
"rvCompress": "standicy",
"llBottom": "theseicy",
"llSelectAll": "bandicy",
"ivSelectAll": "cookouticy",
"tvCompress": "enhancementicy",
"ivOriginalImage": "fillingicy",
"tvOriginalSize": "circumventionicy",
"ivCompressImage": "specificallyicy",
"tvCompressSize": "artsicy",
"clCompress": "hedonismicy",
"rvPhoto": "collectibleicy",
"llCount": "foreskinicy",
"tvCurrentCount": "hollyicy",
"tvTotalCount": "darknessicy",
"viewTriple": "allegationicy",
"llTriple": "radiologisticy",
"tvCompressAll": "refinanceicy",
"clSize": "admirablyicy",
"tvUnit": "disfigurementicy",
"clSelect": "renownedicy",
"ivSelect": "pictorialicy",
"llDelete": "unavailableicy",
"guideLine": "hackicy",
"ivLogo": "indecisivelyicy",
"tvName": "sillinessicy",
"llConsent": "evacuationicy",
"clBottomStart": "informallyicy",
"tvStart": "forestryicy",
"tvPrivacy": "spewicy",
"tvTerms": "flamboyanceicy",
"clBottomLoading": "envoyicy",
"lottieLoading": "championicy",
"progressBar": "whamicy",
"ivYuan": "unnecessarilyicy",
"tvCountdown": "maulicy",
"ivCancel": "darkicy",
"tvContent": "restrictionicy",
"tvExit": "tarnishicy",
"tvCleanNow": "sapicy",
"fl": "ripeicy",
"tvCancel": "toothbrushicy",
"tvConfirm": "interchangeableicy",
"clExit": "pollicy",
"tvSure": "centenaryicy",
"tvLog": "weightlessicy",
"ivClose": "teetericy",
"tvTurnOn": "publiclyicy",
"ivBg": "gliblyicy",
"tvThank": "tissueicy",
"star1": "concludeicy",
"star2": "amateurishicy",
"star3": "gratuitousicy",
"star4": "pounceicy",
"star5": "inactivityicy",
"tvSubmit": "bloodthirstyicy",
"konfettiView": "cometicy",
"ivPermission": "rerunicy",
"tvOpenSettings": "undersideicy",
"tvPath": "taffyicy",
"tvSkip": "frivolousicy",
"iv": "misticy",
"ivDian": "blobicy",
"lottie": "restrainicy",
"scrollView": "clienticy",
"flClean": "counterfeitericy",
"circleProgress": "parodyicy",
"tvUsed": "bleaknessicy",
"tvTotal": "discreeticy",
"tvSettings": "debticy",
"ivBlade": "overallsicy",
"clSettings": "peeveicy",
"clPrivacyPolicy": "tillicy",
"ivPersona": "captureicy",
"tvPrivacyPolicy": "downgradeicy",
"clRateUs": "airlessicy",
"ivRate": "voyeuricy",
"tvRate": "inwardicy",
"clVersion": "Westernicy",
"ivVersion": "fullicy",
"tvVersion": "crucifixionicy",
"tvToken": "flakicy",
"ivIcon": "heartilyicy",
"tvInfo": "spoolicy",
"tvRealTimeCurrent": "disseminateicy",
"tvAveCurrent": "stuffyicy",
"tvValue": "collectiveicy",
"clVideoImage": "homeownericy",
"ivImage": "tribulationicy",
"ivVideo": "ateicy",
"clAudio": "untilicy",
"ivAudio": "salivateicy",
"tvAudioName": "damningicy",
"tvAudioSize": "armchairicy",
"ivAudioSelect": "hugeicy",
"viewLine": "fraudulentlyicy",
"llContent": "cowgirlicy",
"vDian": "plausibleicy",
"tvTab": "trimmingsicy",
"tvLength": "prideicy",
"clItem": "equitableicy",
"ivIndicator": "discoicy",
"ivRotate": "methadoneicy",
"ivSelector": "hippopotamiicy",
"llPhotoBg": "withholdingicy",
"ivPhoto": "quotationicy",
"clContainer": "hibernateicy",
"viewBg": "pandemoniumicy",
"tvOccupies": "hordeicy",
"clLarge": "denselyicy",
"ivFirstPhoto": "blushicy",
"rvLargePhoto": "urbaneicy",
"nativeAdView": "freezeicy",
"adMedia": "localeicy",
"adHeadline": "operateicy",
"adBody": "grazeicy",
"adAppIcon": "remotelyicy",
"adCallToAction": "clingingicy",
"glLine": "storageicy",
"clAnimation": "relieveicy",
"lottieAnimation": "commandicy",
"tvProgress": "preservationicy",
"llTrustlook": "embodimenticy",
"tvRecommend": "chasteicy",
"tvHint": "rifeicy",
"includeFlAd": "inlandicy",
"iconImageView": "shimmericy",
"textView": "xenophobiaicy",
"titleTextView": "shakilyicy",
"optionsView": "tinnyicy",
"advertiserTextView": "masterpieceicy",
"starRatingView": "sterlingicy",
"bodyTextView": "swollenicy",
"mediaViewContainer": "sinusicy",
"ctaButton": "detracticy",
"tv1": "silhouetteicy",
"tv2": "fundamentalsicy",
"ll1": "hushicy",
"ll2": "diskicy",
"ll3": "sanctuaryicy",
"ll4": "neatnessicy"
},
"layout": {
"activity_app_uninstall": "revalueicy",
"activity_battery_info": "glimmericy",
"activity_clean_result": "literallyicy",
"activity_guide": "stepmothericy",
"activity_guide_clean": "adageicy",
"activity_guide_experience": "mistyicy",
"activity_junk_clean_2": "speculativeicy",
"activity_language": "desegregationicy",
"activity_large_file_clean": "vengefulicy",
"activity_main": "enclosureicy",
"activity_photo_compression": "chordicy",
"activity_photo_compression_detail": "stringenticy",
"activity_screenshot_clean": "weticy",
"activity_setting": "timetableicy",
"activity_similar_photos": "antennaeicy",
"activity_splash": "regreticy",
"dialog_ad_countdown": "jungleicy",
"dialog_app_exit": "writingicy",
"dialog_confirm": "tureenicy",
"dialog_function_back": "cahootsicy",
"dialog_log_content": "highlyicy",
"dialog_notification2": "sunriseicy",
"dialog_rate_1": "specifyicy",
"dialog_storage_2": "infinityicy",
"fragment_clean_native": "comingicy",
"fragment_clean_page": "promontoryicy",
"fragment_guide": "Islamicy",
"fragment_home2": "aisleicy",
"fragment_native_full": "grudgeicy",
"fragment_settings": "shadesicy",
"item_app_uninstall": "lubricateicy",
"item_battery_electric": "Martianicy",
"item_battery_head": "Dutchicy",
"item_battery_info": "revolveicy",
"item_clean_detail": "burrowicy",
"item_clean_result": "meaningicy",
"item_feature_rv": "curableicy",
"item_feature_span1": "jadedicy",
"item_feature_span2": "imbibeicy",
"item_home_tab": "longitudeicy",
"item_junk_clean_child": "oilyicy",
"item_junk_clean_group": "flogicy",
"item_language": "disagreementicy",
"item_large_file_clean": "moronicy",
"item_large_file_clean_tab": "downcasticy",
"item_photo_detail": "walrusicy",
"item_rv": "cabooseicy",
"item_screenshot_clean_child": "unforgettableicy",
"item_screenshot_clean_group": "foundicy",
"item_similar_photos": "Whiteicy",
"item_similar_photos_child": "umbrellaicy",
"layout_admob_native_custom": "savingicy",
"layout_admob_native_custom2": "traumatizeicy",
"layout_admob_native_full": "garbledicy",
"layout_animation": "herdicy",
"layout_animation_2": "contractionicy",
"layout_max_native_custom": "propitiousicy",
"notification_common_large": "woolensicy",
"notification_common_small": "tiebreakericy",
"stay_notification_big": "strategyicy",
"stay_notification_small": "contenticy"
},
"drawable": {
"bg_00e4fd_0066ff": "practitionericy",
"bg_70eb91_4fe5b6": "resentmenticy",
"bg_ad": "knickknackicy",
"bg_btn_4": "forciblyicy",
"bg_btn_50": "definiteicy",
"bg_btn_90": "blemishedicy",
"bg_btn_ad": "harpisticy",
"bg_btn_enable_50": "symbolismicy",
"bg_edf7ff_50": "truncatedicy",
"bg_enable_4": "gmaticy",
"bg_enable_50": "hutchicy",
"bg_enable_no_50": "accountabilityicy",
"bg_f2f4f5_tlr24": "fierceicy",
"bg_f7f8fc_10": "educationicy",
"bg_f8f9fa_20": "mamaicy",
"bg_ff8000_fec300": "semifinalicy",
"bg_ffffff_10": "sportscasticy",
"bg_ffffff_12": "punditicy",
"bg_ffffff_15": "prologueicy",
"bg_ffffff_4": "dutifullyicy",
"bg_ffffff_8": "farewellicy",
"bg_filter_large_size": "salmonicy",
"bg_filter_large_time": "woebegoneicy",
"bg_filter_large_type": "prefericy",
"bg_language_n": "soddenicy",
"bg_language_s": "trackicy",
"bg_oval": "pharaohicy",
"bg_ring_home": "koranicy",
"bg_selector_language": "intimidationicy",
"bg_select_fang": "pivoticy",
"bg_select_yuan": "folkloreicy",
"bg_splash": "roaringicy",
"bg_splash_button": "knighticy",
"bg_stroke_999999_50": "wishicy",
"bg_stroke_aeb4bd_4": "poleicy",
"bg_stroke_d9d9d9_10": "pukeicy",
"icon_notification_svg": "centigradeicy",
"ic_launcher_background": "ultimatelyicy",
"ic_launcher_foreground": "interconnectedicy",
"photo_background": "morallyicy",
"shadow_background": "repentanceicy",
"shadow_background_bottom": "boredicy",
"splash_bp": "paramedicicy",
"tab_home_selector": "trickicy",
"tab_large_file": "likableicy",
"tab_settings_selector": "reliveicy",
"white_background": "overdidicy",
"white_background_24": "servitudeicy",
"white_background_8": "dressmakericy",
"white_background_bottom": "pawnicy",
"white_background_bottom_8": "thesisicy",
"white_background_top": "unmarkedicy",
"white_background_top_8": "layicy",
"ad_full": "genuineicy",
"bg_bg_splash": "suspiciousicy",
"bg_junk_clean": "repatriateicy",
"bg_rate": "sinfulicy",
"bg_select_yuan_n": "possessedicy",
"bg_select_yuan_s": "dogmaicy",
"bg_select_yuan_s_2": "shamicy",
"bg_splash_button_bg": "beautifullyicy",
"dianchi100": "movericy",
"dianchi20": "castrationicy",
"dianchi40": "leotardicy",
"dianchi60": "intangibleicy",
"dianchi80": "areicy",
"dian_1": "presumeicy",
"dian_2": "oathicy",
"dian_3": "mutelyicy",
"icon_ah_battery": "germanicy",
"icon_apk_junk": "parkaicy",
"icon_app_large": "persisticy",
"icon_app_uninstall": "oceanicicy",
"icon_app_uninstall_h": "soiledicy",
"icon_app_uninstall_r": "organicy",
"icon_audio": "secretaryicy",
"icon_audio_junk_nor": "traditionalicy",
"icon_back_w": "inhibitedicy",
"icon_battery_h": "executiveicy",
"icon_battery_info_push": "plaintifficy",
"icon_battery_info_r": "cheeseicy",
"icon_battery_push_s": "herpesicy",
"icon_clean_h": "toothpasteicy",
"icon_clean_push": "vistaicy",
"icon_clean_push_s": "suffericy",
"icon_clean_r": "rightlyicy",
"icon_close": "harmonizeicy",
"icon_close_pop": "doormanicy",
"icon_compression_h": "russianicy",
"icon_compression_push": "gailyicy",
"icon_daiji_battery": "adversityicy",
"icon_document": "windowpaneicy",
"icon_empty": "tutoringicy",
"icon_empty_junk": "chauffeuricy",
"icon_fang_n": "geologicicy",
"icon_fang_s": "whackicy",
"icon_file_push_s": "skinflinticy",
"icon_fork_ad": "togsicy",
"icon_good": "proportionicy",
"icon_image_compression_r": "availicy",
"icon_jiantou": "bodybuildingicy",
"icon_jiantou_down_small": "sportyicy",
"icon_jiantou_up_small": "companionicy",
"icon_large_file_cleaner_push": "blemishicy",
"icon_large_file_clean_r": "phoneticallyicy",
"icon_large_file_h": "districticy",
"icon_li": "superiorityicy",
"icon_lingdang": "detonationicy",
"icon_logs_junk": "bipedicy",
"icon_mah": "nastinessicy",
"icon_mb_file_n": "thisicy",
"icon_mb_file_s": "minstrelicy",
"icon_music_battery": "cloneicy",
"icon_mv": "rebateicy",
"icon_paixu_down": "rhymeicy",
"icon_paixu_normal": "alleyicy",
"icon_paixu_up": "offeringicy",
"icon_photo": "liberalicy",
"icon_privacy": "pompicy",
"icon_rate": "misjudgmenticy",
"icon_return_w": "drudgeryicy",
"icon_right_tool": "anticipationicy",
"icon_saomiao": "fillyicy",
"icon_screenshot_clean_push": "subscriptionicy",
"icon_screenshot_h": "fairyicy",
"icon_screenshot_push_s": "predestinationicy",
"icon_screenshot_r": "superficiallyicy",
"icon_shouqi_clean": "stretchericy",
"icon_similar_h": "talenticy",
"icon_similar_photos_r": "overtureicy",
"icon_similar_pictures_push": "graphiteicy",
"icon_star_normal": "cessationicy",
"icon_star_pressed": "listicy",
"icon_switch_normal": "jokeicy",
"icon_switch_pressed": "halfheartedlyicy",
"icon_temp_junk": "retainicy",
"icon_time_file_n": "scaricy",
"icon_time_file_s": "wandicy",
"icon_type_file_n": "begrudgeicy",
"icon_type_file_s": "sinicy",
"icon_version": "pulpiticy",
"icon_video": "heydayicy",
"icon_video_battery": "proponenticy",
"icon_v_battery": "lessonicy",
"icon_weixuanzhong_photo_off": "usaicy",
"icon_wendu_battery": "cautiousicy",
"icon_wenjianx_large": "conciselyicy",
"icon_xingzuo": "expletiveicy",
"icon_yingyong_large": "reminisceicy",
"icon_yinping_large": "eerilyicy",
"icon_zhankai_clean": "solitaryicy",
"icon_zhuyi": "prickicy",
"img_after_photo": "pharmacisticy",
"img_before_photo": "gruelingicy",
"img_bj_pop": "grievousicy",
"img_emoji": "spoticy",
"img_experience": "additionalicy",
"img_guanggao": "prioritizeicy",
"img_play_file_small": "negroicy",
"img_qidong": "promotionicy",
"img_quanxian_pop": "scamicy",
"img_queshengye": "schoolteachericy",
"img_set": "shyicy",
"img_shuju": "shortsicy",
"jiangtou_3": "preambleicy",
"jiangtou_w": "obeseicy",
"kongzhuangtai_compress": "truckericy",
"lanse_bg": "climateicy",
"tab_home_n": "wafericy",
"tab_home_s": "groupingicy",
"tab_setting_n": "bunkericy",
"tab_setting_s": "simpleicy",
"tanchuang": "mustyicy",
"yindaoye1": "circumciseicy",
"yindaoye2": "forfeiticy",
"yindaoye3": "stalkingicy",
"zhanwei1": "biographicalicy",
"zhuanquan": "opportunisticy"
},
"mipmap": {
"ic_launcher": "peaticy",
"ic_launcher_round": "assignmenticy",
"logo": "sufficientlyicy",
"logo_corners": "ubiquitousicy"
},
"xml": {
"backup_rules": "resuscitationicy",
"data_extraction_rules": "coupleicy",
"file_paths": "puffyicy"
},
"dir": {
"com.simplecleaner.app": "tranquilityicy.epilogueicy",
"com.simplecleaner.app.base": "tranquilityicy.epilogueicy.laundericy.unabatedicy.distincticy",
"com.simplecleaner.app.bean": "tranquilityicy.epilogueicy.laboriouslyicy",
"com.simplecleaner.app.utils": "tranquilityicy.epilogueicy.exhaustingicy.vigorousicy.preposterousicy",
"com.simplecleaner.app.ui.set": "purifyicy.Americaicy",
"com.simplecleaner.app.ui.main": "endiveicy",
"com.simplecleaner.app.ui.clean": "splayicy.disorganizationicy.fruitionicy",
"com.simplecleaner.app.ui.guide": "heredityicy.tobaccoicy",
"com.simplecleaner.app.ui.views": "localicy",
"com.simplecleaner.app.bean.push": "tranquilityicy.epilogueicy.laboriouslyicy.enjoyicy",
"com.simplecleaner.app.ui.dialog": "scenticy.recreationicy.bewilderingicy",
"com.simplecleaner.app.ui.splash": "newticy",
"com.simplecleaner.app.ui.adapter": "woesicy",
"com.simplecleaner.app.ui.similar": "flaticy.scumicy.cuckooicy",
"com.simplecleaner.app.bean.config": "tranquilityicy.epilogueicy.laboriouslyicy.sunicy",
"com.simplecleaner.app.ui.language": "maximicy",
"com.simplecleaner.app.business.ads": "meltdownicy.dimpleicy",
"com.simplecleaner.app.ui.largefile": "ceaselesslyicy",
"com.simplecleaner.app.push.receiver": "octopiicy.depleteicy.lampoonicy",
"com.simplecleaner.app.ui.screenshot": "informativeicy.playfulicy.oneicy",
"com.simplecleaner.app.ui.batteryinfo": "divinelyicy",
"com.simplecleaner.app.ui.cleanresult": "meeknessicy.joyouslyicy",
"com.simplecleaner.app.business.helper": "telegramicy.graceicy",
"com.simplecleaner.app.ui.appuninstall": "attachedicy.smallicy",
"com.simplecleaner.app.business.billing": "hybridicy.provisionsicy",
"com.simplecleaner.app.business.service": "materialisticy.cisternicy",
"com.simplecleaner.app.business.push.fcm": "brideicy.reductionicy",
"com.simplecleaner.app.business.ads.admob": "meltdownicy.dimpleicy.devilicy",
"com.simplecleaner.app.business.push.work": "fillicy.signingicy",
"com.simplecleaner.app.business.push.timer": "faultlessicy.scoreboardicy",
"com.simplecleaner.app.ui.photocompression": "unmovedicy.yondericy.gloomilyicy",
"com.simplecleaner.app.business.ads.applovin": "meltdownicy.dimpleicy.sonicicy.wornicy",
"com.simplecleaner.app.business.push.receiver": "temptingicy.acornicy",
"com.simplecleaner.app.business.push.notification": "legislationicy.softyicy.neglectedicy"
},
"class": {
"AppAdapter": "Honorsicy",
"AppInfoUtils": "Oozeicy",
"AppUninstallActivity": "Beericy",
"AppUninstallViewModel": "Abrasiveicy",
"FCMManager": "Roachicy",
"FcmReceiver": "Fortressicy",
"MessagingService": "Tumultuousicy",
"LargeFileCleanActivity": "Organicicy",
"BatteryInfoActivity": "Prosthesisicy",
"BatteryInfoAdapter": "Unfavorableicy",
"BatteryOtherAdapter": "Remainicy",
"BatteryReceiver": "Blundericy",
"FeatureAdapter": "Confirmicy",
"FeatureItemAdapter": "Dwarficy",
"HomeFragment": "Slowlyicy",
"MainActivity": "Dosageicy",
"MainViewModel": "Alcoholismicy",
"RecoveryFragment": "Capriciouslyicy",
"YuanAdapter2": "Ariesicy",
"TimerManager": "Apticy",
"RepeatingWorker": "Audioicy",
"SimilarPhotosActivity": "Verticalicy",
"SimilarUtils": "Ceramicsicy",
"GuideActivity": "Resurrectionicy",
"GuideCleanActivity": "Fashionablyicy",
"GuideExperienceActivity": "Renditionicy",
"GuideFragment": "Wailicy",
"NativeFullFragment": "Reinicy",
"GoogleSubUtil": "Yiddishicy",
"ScreenshotCleanActivity": "Breedingicy",
"MyNotificationManager": "Puddingicy",
"NotificationBeanUtils": "Studicy",
"NotificationHoverUtils": "Longtimeicy",
"NotificationUiUtil": "Hemophiliacicy",
"BaseProView": "Polygonicy",
"LineBaseProView": "Chessicy",
"LineCentreProView": "Deplorableicy",
"LogDialog": "Fieryicy",
"StayJobService": "Journalisticy",
"StayNotification": "Transpireicy",
"LanguageActivity": "Quellicy",
"LanguageAdapter": "Thinkingicy",
"CleanResultActivity": "Infecticy",
"AdCountDownDialog": "Tentativeicy",
"AdEvent": "Generaicy",
"AdsMgr": "Greekicy",
"AdsShowCallBack": "Appetizingicy",
"AdState": "Nutritiousicy",
"AdsType": "Concurrenceicy",
"AdBannerMgr": "Skateboardicy",
"AdInterMgr": "Scratchyicy",
"AdmobEvent": "Straightenicy",
"AdNativeMgr": "Punishicy",
"AdOpenMgr": "Foamyicy",
"LimitUtils": "Evasiveicy",
"NativeParentView": "Writericy",
"SolarEngineEvent": "Moonbeamicy",
"AdMaxEvent": "Yokeicy",
"MaxInsertMgr": "Coolnessicy",
"MaxNativeMgr": "Worldwideicy",
"MaxOpenMgr": "Bouncyicy",
"SplashActivity": "Illuminationicy",
"SplashViewModel": "Longinglyicy",
"SettingActivity": "Extraordinarilyicy",
"SettingsFragment": "Achyicy",
"AppExitDialog": "Semanticicy",
"ConfirmDialog": "Dispassionatelyicy",
"FunctionBackDialog": "Aphorismicy",
"NotificationTurnOnDialog": "Forswornicy",
"RateDialog": "Lustericy",
"StoragePermissionDialog": "WASPicy",
"CleanNativeFragment": "Permissibleicy",
"CleanPageFragment": "Parqueticy",
"JunkCleanActivity": "Perceptiveicy",
"AESHelper": "Awfulicy",
"EventUtils": "Moroseicy",
"InstallHelper": "Skiericy",
"NewComUtils": "Multipleicy",
"AlarmReceiver": "Suicidalicy",
"ScreenStatusReceiver": "Medallionicy",
"ActivityLauncher": "Powerhouseicy",
"ActivityManagerUtils": "Bulbicy",
"AppPreferences": "Surplusicy",
"BarUtils": "Barbarianicy",
"BatteryUtils": "Spasticicy",
"ClickTimesUtils": "Dangericy",
"ClipboardUtils": "Deviateicy",
"DensityUtils": "Shinnyicy",
"FileUtils": "Finelyicy",
"IntentUtils": "Hydrogenicy",
"JsonUtils": "Facialicy",
"KotlinExt": "Radaricy",
"LogEx": "Syndicatedicy",
"MediaUtils": "Castofficy",
"MineTypeUtils": "Vitalityicy",
"MyAnimationUtils": "Marionetteicy",
"PermissionUtils": "Thornicy",
"SolarEngineUtils": "Romanticizeicy",
"SpannableUtils": "Aheadicy",
"SpStringUtils": "Missicy",
"ToastUtils": "Suddenicy",
"UmpUtils": "Lionicy",
"Utils": "Drapeicy",
"VpnStatusListener": "Ghettoicy",
"WriteLogEx": "Orchidicy",
"XmlEx": "Ignoranceicy",
"AppInfoBean": "Irkicy",
"NotificationInfoBean": "Gulleticy",
"NotificationSendBean": "Horizonicy",
"FeatureBean": "Inalienableicy",
"FileBean": "Fluxicy",
"HomeTabUIBean": "Fauceticy",
"LanguageBean": "Uniformityicy",
"SimilarBean": "Ranicy",
"AdConfigBean": "Blubbericy",
"ConfigBean": "Ophthalmologyicy",
"PopupConfigBean": "Prefixicy",
"VipConfigBean": "Farthesticy",
"BaseActivity": "Inadvisableicy",
"BaseFragment": "Blowicy",
"MyApplication": "Simultaneousicy",
"SpConstObject": "Intoleranticy",
"CleanDetailAdapter": "Degradeicy",
"CompressionUtils": "Blackjackicy",
"PhotoCompressionActivity": "Teaspoonfulicy",
"PhotoCompressionDetailActivity": "Diminishicy",
"TripleSeekBar": "Jokericy",
"AdAdapter": "Sexismicy",
"CommonViewHolder": "Upheavalicy"
}
}
\ No newline at end of file
......@@ -13,6 +13,10 @@ import regex as re2
# import chardet
import string
import random
import nltk
import sys
from nltk.corpus import words
def detect_encoding(file_path):
......@@ -300,9 +304,17 @@ def sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse=True, pa
reverse = sorted(list(mapping.keys()), key=len, reverse=is_reverse)
text_result = text
# 遍历映射规则替换
for name in reverse:
text_result = re2.sub(str(name), mapping[name], text_result)
patterns = sorted(mapping.keys(), key=len, reverse=is_reverse)
for pattern in patterns:
try:
print(f"正在替换 pattern: {pattern}")
text_result = re.sub(pattern, mapping[pattern], text_result)
except Exception as e:
print(f"替换失败: pattern={pattern}, 错误: {e}")
# # 遍历映射规则替换
# for name in reverse:
# text_result = re2.sub(str(name), mapping[name], text_result)
# 方案 3:针对特定 import 的直接替换
text_result = re.sub(
......@@ -400,7 +412,8 @@ def check_class_mapping():
mapping = {}
classes = get_classes()
for i in classes:
if '_D' in i or os.path.basename(i) == "GlobalConfig.kt": # 跳过 GlobalConfig.kt
#or os.path.basename(i) == "GlobalConfig.kt" 去除跳过GlobalConfig
if '_D' in i : # 跳过 GlobalConfig.kt
continue
print(i)
name = os.path.basename(i)
......@@ -510,13 +523,65 @@ def deal_ids_type(ids_type):
sub_map = {}
for i in type_ids_mapping:
if i in type_ids_mapping and type_ids_mapping[i].startswith("android"):
continue
# mapped = type_ids_mapping[i]
#
# sub_map['<' + ids_type + ' name="' + i + '"'] = '<' + ids_type + ' name="' + mapped + '"'
# sub_map['<item name="' + i + '"(.*? type="' + ids_type + '")>'] = '<item name="' + mapped + '"\\g<1>>'
# sub_map[r'(?<=[^\.])R\.' + ids_type + r'\.' + re.escape(i) + r'(?=\W)'] = 'R.' + ids_type + '.' + mapped
# sub_map[r'(?<=>|")@' + ids_type + '/' + re.escape(i) + r'(?=<|")'] = '@' + ids_type + '/' + mapped
# sub_map[r'(?<=[@=:])@' + ids_type + '/' + re.escape(i) + r'(?=[}"\'\s])'] = '@' + ids_type + '/' + mapped
#
# # ✅ DataBinding 表达式中所有 @xxx/yyy(包括拼接字符串等复杂表达式)
# sub_map[r'(?<=@{[^}]*?)@' + ids_type + r'/' + re.escape(i) + r'(?=[^}]*})'] = '@' + ids_type + '/' + mapped
#
# # ✅ <style name="..." parent="xxx"> 资源引用
# sub_map[r'<' + ids_type + r'(.*?) parent="' + re.escape(i) + r'"(.*?)>'] = (
# r'<' + ids_type + r'\g<1> parent="' + mapped + r'"\g<2>>'
# )
sub_map['<' + ids_type + ' name="' + i + '"'] = '<' + ids_type + ' name="' + type_ids_mapping[i] + '"'
sub_map['<item name="' + i + '"(.*? type="' + ids_type + '")>'] = \
'<item name="' + type_ids_mapping[i] + '"\\g<1>>'
sub_map['<item name="' + i + '"(.*? type="' + ids_type + '")>'] = '<item name="' + type_ids_mapping[
i] + '"\\g<1>>'
sub_map['(?<=[^\\.])R\\.' + ids_type + '\\.' + i + '(?=\\W)'] = 'R.' + ids_type + '.' + type_ids_mapping[i]
sub_map['(?<=>|")@' + ids_type + '/' + i + '(?=<|")'] = '@' + ids_type + '/' + type_ids_mapping[i]
sub_map['<' + ids_type + '(.*?) parent="' + i + '"(.*?)>'] = \
'<' + ids_type + '\\g<1> parent="' + type_ids_mapping[i] + '"\\g<2>>'
sub_map[r'(?<=[@=:])@' + ids_type + '/' + i + r'(?=[}"\'\s])'] = '@' + ids_type + '/' + type_ids_mapping[i]
sub_map[r'(?<=@{[^}]*?)@' + ids_type + r'/' + i + r'(?=[^}]*})'] = '@' + ids_type + '/' + type_ids_mapping[
i] # ⬅ 适配 data binding 表达式
sub_map['<' + ids_type + '(.*?) parent="' + i + '"(.*?)>'] = '<' + ids_type + '\\g<1> parent="' + \
type_ids_mapping[i] + '"\\g<2>>'
escaped_i = re.escape(i)
sub_map[rf'(?<![a-zA-Z0-9_/])@{ids_type}/{escaped_i}(?![a-zA-Z0-9_])'] = f'@{ids_type}/{type_ids_mapping[i]}'
# 带包名前缀的资源路径 com.retrytech.ledgeapp.R.color.xxx
# sub_map[rf'(\b[\w\.]+)\.R\.{ids_type}\.{re.escape(i)}\b'] = rf'\1.R.{ids_type}.{type_ids_mapping[i]}'
# sub_map[
# rf'(?<!android\.)(\b[\w\.]+)\.R\.{ids_type}\.{re.escape(i)}\b'] = rf'\1.R.{ids_type}.{type_ids_mapping[i]}'
sub_map[
rf'(?<!\bandroid\.)\b([\w\.]+)\.R\.{ids_type}\.{re.escape(i)}\b'] = rf'\1.R.{ids_type}.{type_ids_mapping[i]}'
# ✅ 推荐的替换逻辑(万能适配 DataBinding 场景)
# sub_map[f'@{ids_type}/{i}'] = f'@{ids_type}/{type_ids_mapping[i]}'
# # ✅ 适配 DataBinding 表达式中包括拼接、三目等形式的字符串资源引用
# sub_map[rf'(?<=@{{[^}}]*?)@{ids_type}/{re.escape(i)}(?=[^}}]*}})'] = f'@{ids_type}/{type_ids_mapping[i]}'
# # DataBinding 表达式中字符串拼接,如:@{@string/subscribe_to+" "+@string/pro}
# sub_map[r'(?<=@{[^}]*?)@' + ids_type + r'/' + re.escape(i) + r'(?=[^}]*})'] = '@' + ids_type + '/' + \
# type_ids_mapping[i]
# sub_map['<' + ids_type + ' name="' + i + '"'] = '<' + ids_type + ' name="' + type_ids_mapping[i] + '"'
# sub_map['<item name="' + i + '"(.*? type="' + ids_type + '")>'] = \
# '<item name="' + type_ids_mapping[i] + '"\\g<1>>'
# sub_map['(?<=[^\\.])R\\.' + ids_type + '\\.' + i + '(?=\\W)'] = 'R.' + ids_type + '.' + type_ids_mapping[i]
# sub_map['(?<=>|")@' + ids_type + '/' + i + '(?=<|")'] = '@' + ids_type + '/' + type_ids_mapping[i]
# sub_map['(?<=[@=:])@' + ids_type + '/' + i + r'(?=[}"\'\s])'] = '@' + ids_type + '/' + type_ids_mapping[i]
# sub_map['<' + ids_type + '(.*?) parent="' + i + '"(.*?)>'] = \
# '<' + ids_type + '\\g<1> parent="' + type_ids_mapping[i] + '"\\g<2>>'
# # 匹配 @color/xxx 出现在 @{} 表达式中,适配 data binding 多种情况
# sub_map[r'(?<=@{[^}]*?)@' + ids_type + r'/' + i + r'(?=[^}]*})'] = '@' + ids_type + '/' + type_ids_mapping[i]
sub_map[
rf'android\.R\.color\.(\w+)'] = lambda m: 'android.R.color.' + type_ids_mapping.get(m.group(1), m.group(1))
sub_map_text(sub_map)
......@@ -675,7 +740,9 @@ def replace_package_in_imports(root_path, old_package, new_package):
patterns = [
(re.compile(rf'import {re.escape(old_package)}(\.databinding\.\w+)'), rf'import {new_package}\1'),
(re.compile(rf'import {re.escape(old_package)}\.R\b'), rf'import {new_package}.R'),
(re.compile(rf'import {re.escape(old_package)}\.BuildConfig'), rf'import {new_package}.BuildConfig')
(re.compile(rf'import {re.escape(old_package)}\.BuildConfig'), rf'import {new_package}.BuildConfig'),
(re.compile(rf'{re.escape(old_package)}\.R\b'), rf'{new_package}.R'),
]
# 遍历目录中的所有文件
......@@ -729,7 +796,6 @@ def replace_package_in_imports(root_path, old_package, new_package):
# return re.findall(class_pattern, text)
def get_method_names(text, filename):
"""
获取 Java 或 Kotlin 文件中的所有方法名
......@@ -749,6 +815,7 @@ def get_method_names(text, filename):
# 匹配所有方法名
return re.findall(method_pattern, text)
def get_variable_names(text, filename):
"""
获取 Java 或 Kotlin 文件中的所有变量名
......@@ -768,6 +835,7 @@ def get_variable_names(text, filename):
# 匹配所有变量名
return re.findall(variable_pattern, text)
def get_file_names_without_extension(root_path):
"""
获取所有 `.kt` 和 `.java` 文件的路径(无扩展名)
......@@ -785,6 +853,7 @@ def get_file_names_without_extension(root_path):
# 存储每个文件名的映射关系
file_to_class_map = {}
def get_constant_names(text, filename):
"""
获取 Java 或 Kotlin 文件中的所有常量名
......@@ -910,9 +979,6 @@ def replace_with_mapped_names(all_files, name_mapping, constant_mapping):
print(f"文件 {file_path} 引用的名称已进行统一混淆处理。")
def deal_code():
print("deal_code start")
# 替换点击事件
......@@ -959,9 +1025,6 @@ def deal_code():
with open(get_path('.\\src\\main\\AndroidManifest.xml'), 'w', encoding='utf-8') as f:
f.write(text)
# 修改依赖
sub_map = {}
for i in mapping:
......@@ -992,7 +1055,8 @@ def deal_code():
classes = get_classes()
print(class_mapping)
for i in classes:
if '_D' in i or os.path.basename(i) == "GlobalConfig.kt": # 跳过 GlobalConfig.kt
#"or os.path.basename(i) == "GlobalConfig.kt" 去除跳过 GlobalConfig.kt
if '_D' in i :
continue
name = os.path.basename(i)
name = name[:name.rfind('.')]
......@@ -1005,6 +1069,12 @@ def deal_code():
# 添加排除前缀 "styleable." 的逻辑
# 原规则匹配整个单词,添加排除前缀 "styleable." 的逻辑,并允许后面有引号的匹配
regex_pattern = r'(?<!")(?<!\bstyleable\.)\b' + i + r'\b'
if 'AppComponent' in class_mapping:
obfuscated_name = class_mapping['AppComponent']
dagger_pattern = rf'(?<!")(?<!\bstyleable\.)\bDaggerAppComponent\b'
sub_map[dagger_pattern] = f'Dagger{obfuscated_name}'
else:
print("⚠️ class_mapping 中没有 AppComponent,跳过 DaggerAppComponent 规则")
# 保持原有规则的匹配,优先处理非引号的情况
sub_map[regex_pattern] = class_mapping[i]
......@@ -1012,7 +1082,6 @@ def deal_code():
sub_map_text(sub_map)
print("类名 over")
# 混淆字典
check_obfuscation_dictionary()
print(root_path)
......@@ -1039,7 +1108,6 @@ def deal_code():
# # 第二步:替换其他文件中的引用,保证同样的混淆名
# replace_with_mapped_names(all_files, name_mapping, constant_mapping)
replace_package_in_imports(root_path, mapping[applicationId], applicationId)
......@@ -1079,8 +1147,45 @@ def deal_res_type(res_type):
sub_map = {}
for i in type_mapping:
sub_map['R\\.' + res_type + '\\.' + i + '(\\W)'] = 'R.' + res_type + '.' + type_mapping[i] + '\\g<1>'
sub_map['(>|")@' + res_type + '/' + i + '(<|")'] = '\\g<1>@' + res_type + '/' + type_mapping[i] + '\\g<2>'
mapped = type_mapping[i]
# 普通 R.xxx.xxx
sub_map[r'R\.' + res_type + r'\.' + re.escape(i) + r'(\W)'] = r'R.' + res_type + '.' + mapped + r'\1'
# # # 包名限定的 com.retrytech.ledgeapp.R.drawable.xxx
# sub_map[r'(\b[\w\.]+)\.R\.' + res_type + r'\.' + re.escape(
# i) + r'(\W)'] = r'\1.R.' + res_type + '.' + mapped + r'\2'
# sub_map[r'(\b[\w\.]+)\.R\.' + res_type + r'\.' + re.escape(
# i) + r'(?=[\s)\];,])'] = r'\1.R.' + res_type + '.' + mapped
# ✅ 推荐统一写法:以单词边界结尾,适配更多结尾符号(避免重复)
sub_map[rf'(\b[\w\.]+)\.R\.{res_type}\.{re.escape(i)}\b'] = rf'\1.R.{res_type}.{mapped}'
# XML 资源:@drawable/xxx
sub_map[r'(>|")@' + res_type + r'/' + re.escape(i) + r'(<|")'] = r'\1@' + res_type + '/' + mapped + r'\2'
# DataBinding 表达式中:@{ condition ? @drawable/xxx :@drawable/yyy }
# # 匹配 ? 后的资源
# sub_map[r'(?<=\? *@' + res_type + r'\/)' + re.escape(i) + r'(?= *:)'] = mapped
# # 匹配 : 后的资源
# sub_map[r'(?<=: *@' + res_type + r'\/)' + re.escape(i) + r'(?= *})'] = mapped
# ? 后的资源
sub_map[r'(?<=\? *@' + res_type + r'/)' + re.escape(i) + r'(?=\b)'] = mapped
# : 后的资源
sub_map[r'(?<=: *@' + res_type + r'/)' + re.escape(i) + r'(?=\b)'] = mapped
# ✅ 通配 DataBinding 内的任意资源引用
sub_map[r'(@\{[^}]*?)@' + res_type + r'/' + re.escape(i) + r'(?=[^}]*})'] = r'\1@' + res_type + '/' + mapped
# 通用 DataBinding 表达式中任意位置(不拆三元)
# sub_map[r'(?<=@{[^}]*?)@' + res_type + r'/' + re.escape(i) + r'(?=[^}]*})'] = '@' + res_type + '/' + mapped
# sub_map['R\\.' + res_type + '\\.' + i + '(\\W)'] = 'R.' + res_type + '.' + type_mapping[i] + '\\g<1>'
# sub_map[
# r'(\b[\w\.]+)\.R\.' + res_type + r'\.' + i + r'(\W)'
# ] = r'\1.R.' + res_type + '.' + type_mapping[i] + r'\2'
#
# sub_map['(>|")@' + res_type + '/' + i + '(<|")'] = '\\g<1>@' + res_type + '/' + type_mapping[i] + '\\g<2>'
# # 适配 DataBinding 表达式中的 @drawable/xxx 写法
# sub_map[r'(?<=@{[^}]*?)@' + res_type + r'/' + i + r'(?=[^}]*})'] = '@' + res_type + '/' + type_mapping[i]
sub_map_text(sub_map)
......@@ -1478,7 +1583,7 @@ def deal_res():
'R.styleable.' + styleable_mapping[styleable_id] + '_' + styleable_mapping[attr + '_A'] + '\\g<1>'
sub_map['app:' + attr + '='] = 'app:' + styleable_mapping[attr + '_A'] + '='
sub_map['\\?attr/' + attr] = '?attr/' + styleable_mapping[attr + '_A'] # 新增的替换规则
sub_map['<item name=\"' + attr +'\"'] = '<item name=\"' + styleable_mapping[attr + '_A'] +'\"' # 新增的替换规则
sub_map['<item name=\"' + attr + '\"'] = '<item name=\"' + styleable_mapping[attr + '_A'] + '\"' # 新增的替换规则
# 判断 attr 是否以 "android:" 开头
if attr.startswith("android:"):
new_attr = "android_" + attr[8:] # 去掉 "android:" 并替换为 "android_"
......@@ -1500,9 +1605,28 @@ def deal_res():
sub_map['(>|")@(\\+)?id/' + i + '(<|")'] = '\\g<1>@\\g<2>id/' + view_ids_mapping[key] + '\\g<3>'
sub_map['R\\.id\\.' + i + '(\\W)'] = 'R.id.' + view_ids_mapping[key] + '\\g<1>'
sub_map['([bB]inding\\??(?:\\.\\w+)?\\??)\\.' + key + '(\\W)'] = '\\g<1>.' + view_ids_mapping[key] + '\\g<2>'
sub_map['([bB]inding\\??(?:\\.\\w+)?\\??)\\.' + key +'\\.'+ key + '(\\W)'] = '\\g<1>.' + view_ids_mapping[key] +'.' +view_ids_mapping[key] +'\\g<2>'
sub_map['([bB]inding\\??(?:\\.\\w+)?\\??)\\.' + key + '\\.' + key + '(\\W)'] = '\\g<1>.' + view_ids_mapping[
key] + '.' + view_ids_mapping[key] + '\\g<2>'
sub_map[r'\(binding as (\w+Binding)\)\.' + key + r'(\W)'] = r'(binding as \1).' + view_ids_mapping[key] + r'\2'
sub_map['(?<=app:constraint_referenced_ids=".*?)' + i + '(?=.*?")'] = view_ids_mapping[key]
# 新增 Kotlin 特有写法适配
sub_map[r'(binding!!(?:\.\w+)*?)\.' + key + r'(\W)'] = r'\1.' + view_ids_mapping[key] + r'\2'
sub_map[r'(binding\?\?(?:\.\w+)*?)\.' + key + r'(\W)'] = r'\1.' + view_ids_mapping[key] + r'\2'
sub_map[r'(binding(?:\.\w+)*?)\.' + key + r'(\W)'] = r'\1.' + view_ids_mapping[key] + r'\2'
sub_map['this\\.' + i + '(\\W)'] = 'this.' + view_ids_mapping[key] + '\\g<1>'
sub_map['this\\.' + i + '(\\.[\\w\\?]+(?:\\([^)]*\\))?)'] = 'this.' + view_ids_mapping[key] + '\\g<1>'
# sub_map['this\\.(\\w+)(\\.[\\w\\?]+(?:\\([^)]*\\))?)'] = 'this.' + view_ids_mapping[key] + '\\g<1>\\g<2>'
sub_map['popupView\\.' + i + '(\\W)'] = 'popupView.' + view_ids_mapping[key] + '\\g<1>'
# sub_map['\\b' + i + '\\.(\\w+)(\\s*=\\s*[^\\s]+)'] = view_ids_mapping[key] + '.\\g<1>\\g<2>'
sub_map['(?<!\\()\\b' + i + '\\.(\\w+)(\\s*=\\s*[^\\s]+)'] = view_ids_mapping[key] + '.\\g<1>\\g<2>'
# sub_map['this\\.' + view_ids_mapping['title']] = 'this.title'
if i == 'imgIcon':
sub_map[r'\.into\(\s*this\.(imgIcon)\s*\)'] = r'.into(this.' + view_ids_mapping[key] + ')'
sub_map_text(sub_map)
# 改 layout 文件名
......@@ -1542,12 +1666,126 @@ def deal_res():
# 改图片内容
deal_image()
# 主执行逻辑
mapping_file = "./mapping.json"
java_path = get_path('.\\src\\main\\java')
mapping_data = load_color_mapping(mapping_file) # 调用正确的函数
# 调试信息:检查 color_ids_mapping 内容
print("Color IDs Mapping:")
for original_color, mapped_color in mapping_data.items():
print(f"{original_color}: {mapped_color}")
# 进行文件处理
process_color_files(java_path, mapping_data)
def process_color_files(src_path, color_ids):
for root, dirs, files in os.walk(src_path):
for file in files:
if file.endswith(".kt") or file.endswith(".java"):
file_path = os.path.join(root, file)
print(f"Processing file: {file_path}")
replace_color_ids_in_file(file_path, color_ids)
def replace_color_ids_in_file(file_path, color_ids_mapping):
print("replace_color_ids_in_file")
print(color_ids_mapping)
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
if "paperedto" in content:
print(f"Found 'paperedto' in: {file_path}")
if "android.R.color.paperedto" in content:
print(f"Found 'android.R.color.paperedto' in: {file_path}")
changed = False
for original_color, mapped_color in color_ids_mapping.items():
print('original_color'+original_color)
print('mapped_color'+mapped_color)
if mapped_color in content:
pattern = r'android.R.color.' + re.escape(mapped_color) + r'(?=[^\w])'
print(pattern)
replacement = 'android.R.color.' + original_color
print(replacement)
if re.search(pattern, content):
print(f"Matched: {mapped_color} → {original_color}")
matches = re.findall(pattern, content)
if matches:
print(f"Matched: {mapped_color} → {original_color} ({len(matches)} times)")
content = re.sub(pattern, replacement, content)
changed = True
if changed:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
def get_path(path):
paths = path.split('\\')
return str(os.path.join(*paths))
def deal_global():
mapping_file_path = 'mapping.json'
src_dir = 'src/main/java'
# 加载映射文件
with open(mapping_file_path, 'r', encoding='utf-8') as f:
mapping_data = json.load(f)
class_mapping = mapping_data.get("class", {})
dir_mapping = mapping_data.get("dir", {})
# 获取混淆后的 GlobalConfig 文件名
obfuscated_name = class_mapping.get("GlobalConfig")
if not obfuscated_name:
print("❌ GlobalConfig not found in class mapping.")
return
obfuscated_filename = obfuscated_name + '.kt'
reversed_dir_mapping = {v: k for k, v in dir_mapping.items()}
found = False
for root, dirs, files in os.walk(src_dir):
if obfuscated_filename in files:
found = True
kt_file_path = os.path.join(root, obfuscated_filename)
with open(kt_file_path, 'r', encoding='utf-8') as f:
content = f.read()
original_content = content
updated = False
# 精确匹配 PACKAGE_NAME 行
match = re.search(r'(const\s+val\s+PACKAGE_NAME\s*=\s*")([^"]+)(")', content)
if match:
current_package = match.group(2)
for obf_pkg, original_pkg in reversed_dir_mapping.items():
if current_package.startswith(obf_pkg):
restored_package = current_package.replace(obf_pkg, original_pkg, 1)
new_line = f'{match.group(1)}{restored_package}{match.group(3)}'
content = content.replace(match.group(0), new_line)
print(f"✅ Updated PACKAGE_NAME in {kt_file_path}: '{current_package}' → '{restored_package}'")
updated = True
break
else:
print(f"❌ PACKAGE_NAME not found in {kt_file_path}")
if updated and content != original_content:
with open(kt_file_path, 'w', encoding='utf-8') as f:
f.write(content)
else:
print(f"ℹ️ No PACKAGE_NAME replacement needed in {kt_file_path}")
break
if not found:
print(f"❌ File {obfuscated_filename} not found under {src_dir}")
def main():
if not os.path.exists(get_path('.\\src\\main\\java\\' + applicationId[:applicationId.find('.')])):
print(get_path('.\\src\\main\\java\\' + applicationId[:applicationId.find('.')]))
......@@ -1558,6 +1796,9 @@ def main():
deal_code()
deal_global()
def load_mapping(file_path):
"""加载 mapping.json 文件并打印内容."""
try:
......@@ -1570,6 +1811,7 @@ def load_mapping(file_path):
print(f"Error loading mapping file: {e}")
return {}
def replace_identifiers_in_file(file_path, mapping, replacements_log):
"""替换单个文件中的标识符,并存储替换的内容到 JSON 日志."""
with open(file_path, 'r', encoding='utf-8') as f:
......@@ -1647,6 +1889,7 @@ def replace_identifiers_in_file(file_path, mapping, replacements_log):
else:
print("No replacements made.")
def process_files_in_directory(directory, mapping, replacements_log):
"""处理目录下的所有文件并打印文件路径."""
for root, _, files in os.walk(directory):
......@@ -1682,14 +1925,105 @@ def solve_runapplyalso():
json.dump(replacements_log, log, ensure_ascii=False, indent=4)
print(f"\nReplacement completed. Log saved to {log_file}.")
def load_color_mapping(file_path):
"""加载 mapping.json 文件并打印内容."""
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
print("Loaded color Mapping:")
print(json.dumps(data, indent=4, ensure_ascii=False)) # 打印映射内容
color_ids = data.get("color_ids", {})
print(f"color_ids extracted: {color_ids}") # 检查 color_ids 是否存在
return color_ids
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading mapping file: {e}")
return {}
# 自动下载 NLTK 的 "words" 数据包(只下载一次)
try:
nltk.data.find("corpora/words")
except LookupError:
print("🔄 正在下载 NLTK 'words' 数据集...")
nltk.download("words")
# 获取当前目录(兼容 PyInstaller 打包)
if getattr(sys, 'frozen', False):
base_dir = os.path.dirname(sys.executable)
else:
base_dir = os.path.abspath(os.path.dirname(__file__))
mapping_path = os.path.join(base_dir, "mapping.json")
word_file_path = os.path.join(base_dir, "word_file.json")
# 是否需要生成 word_file.json
need_generate = True
if os.path.exists(mapping_path):
print("✅ 已存在 mapping.json,跳过生成 word_file.json。")
need_generate = False
else:
print("✅ 不存在 mapping.json,将生成 word_file.json。")
# 删除旧的 word_file.json(若存在)
if os.path.exists(word_file_path):
try:
os.remove(word_file_path)
print("🗑️ 已删除旧的 word_file.json")
except Exception as e:
print(f"❌ 删除旧文件失败:{e}")
sys.exit(1)
# Kotlin + Java 保留关键字(统一为小写)
kotlin_java_keywords = {
kw.lower() for kw in {
'as', 'as?', 'break', 'class', 'continue', 'do', 'else', 'false', 'for',
'fun', 'if', 'in', '!in', 'interface', 'is', '!is', 'null', 'object',
'package', 'return', 'super', 'this', 'throw', 'true', 'try', 'typealias',
'typeof', 'val', 'var', 'when', 'while', 'by', 'catch', 'constructor', 'delegate',
'dynamic', 'field', 'file', 'finally', 'get', 'import', 'init', 'param',
'property', 'receiver', 'set', 'setparam', 'where', 'actual', 'abstract',
'annotation', 'companion', 'const', 'crossinline', 'data', 'enum', 'expect',
'external', 'final', 'infix', 'inline', 'inner', 'internal', 'lateinit',
'noinline', 'open', 'operator', 'out', 'override', 'private', 'protected',
'public', 'reified', 'sealed', 'suspend', 'tailrec', 'vararg', 'assert',
'boolean', 'byte', 'case', 'char', 'default', 'double', 'extends', 'float',
'goto', 'implements', 'instanceof', 'int', 'long', 'native', 'new', 'short',
'static', 'strictfp', 'switch', 'synchronized', 'throws', 'transient', 'void',
'volatile'
}
}
def generate_and_save():
sample_size = 10000
sampled = random.sample(word_list, min(sample_size, len(word_list)))
filtered = [w.lower() for w in sampled if w.lower() not in kotlin_java_keywords]
with open(word_file_path, "w", encoding="utf-8") as f:
json.dump({"word": filtered}, f, ensure_ascii=False, indent=4)
print(f"✅ 成功生成 {len(filtered)} 个小写英文单词!")
print(f"📄 文件保存至:{word_file_path}")
if __name__ == '__main__':
if need_generate:
# 加载 NLTK 单词列表并生成
try:
word_list = list(set(words.words()))
except Exception as e:
print(f"❌ 加载 NLTK 词库失败:{e}")
sys.exit(1)
generate_and_save()
# 继续执行 gradle 文件查找逻辑
if os.path.exists('build.gradle'):
gradle_path = 'build.gradle'
elif os.path.exists('build.gradle.kts'):
gradle_path = 'build.gradle.kts'
else:
exit('找不到 build.gradle 文件')
exit('❌ 找不到 build.gradle 文件')
print(f"✅ 找到构建文件:{gradle_path}")
applicationId = re.search('namespace .*?["\'](.*?)["\']', open(gradle_path, 'r', encoding='utf-8').read())[1]
print(applicationId)
main()
# solve_runapplyalso()
\ No newline at end of file
# solve_runapplyalso()
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment