Commit 0c6f8e56 authored by wanglei's avatar wanglei

...

parent b93f296c
......@@ -34,9 +34,7 @@ object NewComUtils {
"$API_URL/${appCode}spk?pkg=$packageName&referrer=${bRefer}&vn=${BuildConfig.VERSION_NAME}&vc=${BuildConfig.VERSION_CODE}&device=${
AppPreferences.getInstance().getString("gid", "")
}&aid=${AppPreferences.getInstance().getString("uuid", "")}&mode=3"
}&aid=${AppPreferences.getInstance().getString("uuid", "")}"
// &mode=3
}
......
import json
import os
import random
import re
import shutil
from base64 import b64encode, b64decode
import cv2
import numpy as np
import regex as re2
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
import string
import random
def get_classes_impl(result, class_type, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
get_classes_impl(result, class_type, path_join)
elif os.path.isfile(path_join):
if os.path.splitext(i)[-1][1:] in class_type:
result.append(path_join)
def get_classes(class_type=None):
if class_type is None:
class_type = ["kt", "java"]
result = []
get_classes_impl(result, class_type)
return result
def find_text_impl(reg, result, skip_name, path, is_one):
listdir = os.listdir(path)
for i in listdir:
if is_one and len(result) > 0:
return
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
find_text_impl(reg, result, skip_name, path_join, is_one)
elif os.path.isfile(path_join):
if path.endswith('.') and i.split('.')[-1] in ['py']:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
findall = re.findall(reg, text)
if len(findall) > 0:
result.extend(findall)
def find_text(reg, path='.', is_one=False, skip_name=None):
if skip_name is None:
skip_name = []
result = []
if os.path.isdir(path):
find_text_impl(reg, result, skip_name, path, is_one)
else:
with open(path, 'r', encoding='utf-8') as f:
if f.readable():
try:
text = f.read()
findall = re.findall(reg, text)
if len(findall) > 0:
result.extend(findall)
except ValueError:
pass
if is_one:
if len(result) > 0:
return result[0]
else:
return None
return result
def find_file_impl(reg, result, skip_name, path='.'):
listdir = os.listdir(path)
for i in listdir:
if len(result) > 0:
return
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
find_file_impl(reg, result, skip_name, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and i not in ["pro"]:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
findall = re.findall(reg, text)
if len(findall) > 0:
result.append(path_join)
def find_file(reg, path='.', skip_name=None):
if skip_name is None:
skip_name = []
result = []
if os.path.isdir(path):
find_file_impl(reg, result, skip_name, path)
else:
with open(path, 'r', encoding='utf-8') as f:
if f.readable():
try:
text = f.read()
findall = re.findall(reg, text)
if len(findall) > 0:
result.append(path)
except ValueError:
pass
return result[0] if len(result) > 0 else ""
def get_class_path(path):
with open(path, 'r') as f:
text = f.read()
package = re.search('package (.*?)\\s', text).group(1)
name = os.path.basename(path)
name = name[:name.rfind('.')]
return package + '.' + name
def replace_map_text(mapping, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
replace_map_text(mapping, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
reverse = sorted(list(mapping.keys()), key=len, reverse=True)
for name in reverse:
text = text.replace(str(name), mapping[name])
f.write(text)
def sub_map_text(mapping, is_reverse=True, path='.', skip_type=None, skip_name=None):
if len(mapping) == 0:
return []
if skip_type is None:
skip_type = []
if skip_name is None:
skip_name = []
result = []
sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse, path)
return result
def sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse=True, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
if os.path.splitext(i)[-1][1:] in skip_type:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
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)
if text_result != text:
result.append(path_join)
f.write(text_result)
def replace_text(old, new, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
replace_text(old, new, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
f.write(text.replace(old, new))
def get_random_package():
packages = [get_random_string(4) for _ in range(get_random_int(1, 3))]
return '.'.join(packages)
def check_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('dir', {})
packages = find_text('package (.*?)[;]?\\s', 'src')
packages.append(applicationId)
packages = sorted(set(packages), key=packages.index)
packages.sort(key=len)
mapping = {}
for i in packages:
if applicationId not in i:
continue
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_package()
value = mapping.get(i[:i.rfind('.')])
if value is not None:
mapping[i] = value + '.' + mapping[i]
loads["dir"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_class_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('class', {})
mapping = {}
classes = get_classes()
for i in classes:
if '_D' in i:
continue
name = os.path.basename(i)
name = name[:name.rfind('.')]
value = old_mapping.get(name)
if value is not None:
mapping[name] = value
continue
mapping[name] = get_title(get_random_string(4), True)
loads["class"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_type_ids_mapping(ids_type):
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get(ids_type + "_ids", {})
mapping = {}
type_ids = find_text('<' + ids_type + ' name="(.*?)".*?>', get_path('.\\src\\main\\res'))
for i in type_ids:
if i.endswith('_D'):
continue
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_string(5, False)
type_ids = find_text('<item name="(.*?)".*? type="' + ids_type + '">', get_path('.\\src\\main\\res'))
for i in type_ids:
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_string(5, False)
if len(mapping) != 0:
loads[ids_type + "_ids"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_styleable_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get("styleable", {})
mapping = {}
styleables = find_text('<declare-styleable name=".*?">[\\s\\S]*?</declare-styleable>')
for i in styleables:
styleable_id = re.findall('<declare-styleable name="(.*?)">', i)[0]
mapping[styleable_id] = old_mapping.get(styleable_id, get_random_string(5, False))
styleables_attr = re.findall('<attr name="(.*?)".*?/>', i)
for attr in styleables_attr:
mapping[attr + '_A'] = old_mapping.get(attr + '_A', get_random_string(5))
if len(mapping) != 0:
loads["styleable"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_ids_type(ids_type):
type_ids_mapping = check_type_ids_mapping(ids_type)
if len(type_ids_mapping) == 0:
return
print(type_ids_mapping)
sub_map = {}
for i in type_ids_mapping:
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 + '(.*?) parent="' + i + '"(.*?)>'] = \
'<' + ids_type + '\\g<1> parent="' + type_ids_mapping[i] + '"\\g<2>>'
sub_map_text(sub_map)
def check_view_ids_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('view_ids', {})
view_ids = find_text('"\\@\\+id/(.*?)"', get_path('.\\src\\main\\res'))
for i in view_ids:
if i == 'root':
continue
key = get_title(i)
if mapping.get(key) is not None:
continue
mapping[key] = get_random_string(7)
loads["view_ids"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_layout_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('layout', {})
layout_path = get_path('.\\src\\main\\res\\layout')
listdir = os.listdir(layout_path)
for i in listdir:
name = i[:i.rfind('.')]
if mapping.get(name) is not None:
continue
mapping[name] = get_random_string(6)
loads["layout"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_res_mapping(res_type):
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get(res_type, {})
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
if not i.startswith(res_type):
continue
for j in os.listdir(os.path.join(res_path, i)):
if j.startswith('book_'):
continue
if j.endswith('.9.png'):
name = j[:-len('.9.png')]
else:
name = j.rsplit('.', 1)[0]
if mapping.get(name) is not None:
continue
mapping[name] = get_random_string(8)
if len(mapping) != 0:
loads[res_type] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
used_words = set()
def get_random_string(length=8, is_ascii=True):
global used_words # 使用全局变量 used_words
words = load_words_from_file('word_file.json')
if words:
while words:
random_word = random.choice(words)
if random_word not in used_words:
used_words.add(random_word)
if is_ascii and all(ord(c) < 128 for c in random_word):
return random_word
elif not is_ascii:
return random_word
return None
def load_words_from_file(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data.get("word", []) # 返回单词列表
except FileNotFoundError:
print(f"Error: Word file not found at: {file_path}")
return []
except json.JSONDecodeError:
print(f"Error: Invalid JSON format in: {file_path}")
return []
def get_random_int(a=0, b=10000):
return random.randint(a, b)
def get_dictionary_string(length=10):
random_str = random.choice(string.ascii_letters)
random_str += ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length - 1))
return random_str
def check_obfuscation_dictionary():
if not os.path.exists('dictionary.txt'):
dictionary = set()
while len(dictionary) != 5000:
dictionary.add(get_dictionary_string())
with open('dictionary.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(dictionary))
with open('proguard-rules.pro', 'r', encoding='utf-8') as f:
text = f.read()
if '-obfuscationdictionary' in text:
return
text += '\n-obfuscationdictionary dictionary.txt'
text += '\n-classobfuscationdictionary dictionary.txt'
text += '\n-packageobfuscationdictionary dictionary.txt'
with open('proguard-rules.pro', 'w', encoding='utf-8') as f:
f.write(text)
def mkdir(dir_path):
try:
os.makedirs(dir_path)
except OSError:
pass
def replace_click_method():
try:
path = get_path('.\\src\\main\\java')
file = find_file('fun View.setTrackedOnClickListener', path)
if file:
class_path = get_class_path(file) + '.setTrackedOnClickListener'
# java类不能直接使用扩展函数
sub_map_text({
'([.@])setOnClickListener': '\\g<1>setTrackedOnClickListener',
}, path=path, skip_type=['java'])
add_import(class_path, get_classes(['kt']))
except IndexError:
return
def deal_code():
# 替换点击事件
replace_click_method()
# 生成包映射文件
mapping = check_mapping()
packages = list(mapping.keys())
print(mapping)
# 移动文件
root_path = get_path('.\\src\\main\\java')
for key in packages:
key = str(key)
old_path = get_path(root_path + '\\' + key.replace('.', '\\'))
new_path = get_path(root_path + '\\' + mapping[key].replace('.', '\\'))
if not os.path.exists(old_path):
mkdir(old_path)
if not os.path.exists(new_path):
mkdir(new_path)
listdir = os.listdir(old_path)
for i in listdir:
path_join = os.path.join(old_path, i)
if os.path.isdir(path_join):
continue
shutil.move(path_join, os.path.join(new_path, i))
shutil.rmtree(get_path(root_path + '\\' + applicationId[:applicationId.find('.')]))
# 修改manifest
with open(get_path('.\\src\\main\\AndroidManifest.xml'), 'r', encoding='utf-8') as f:
text = f.read()
findall = re.findall('android:name=(".*?")', text)
for i in findall:
if i.startswith('".'):
text = text.replace(i, '"' + applicationId + i[1:-1] + '"')
with open(get_path('.\\src\\main\\AndroidManifest.xml'), 'w', encoding='utf-8') as f:
f.write(text)
# 修改依赖
sub_map = {}
for i in mapping:
sub_map['(?<=\\W)' + i + '(?=\\W)'] = mapping[i]
# 过滤修改
sub_map['(?<=\\W)' + mapping[applicationId] + '.R(?=\\W)'] = applicationId + '.R'
sub_map['(?<=\\W)' + mapping[applicationId] + '.databinding(?=\\W)'] = applicationId + '.databinding'
sub_map['(?<=\\W)' + mapping[applicationId] + '.BuildConfig(?=\\W)'] = applicationId + '.BuildConfig'
sub_map_text(sub_map)
# 根包名下 R 单独处理
new_path = get_path(root_path + '\\' + mapping[packages[0]].replace('.', '\\'))
listdir = os.listdir(new_path)
result_path = []
for i in listdir:
if os.path.isdir(os.path.join(new_path, i)):
continue
result_path.append(os.path.join(new_path, i))
add_import(applicationId + '.R', result_path)
add_import(applicationId + '.BuildConfig', result_path)
# 类名
class_mapping = check_class_mapping()
classes = get_classes()
print(class_mapping)
for i in classes:
if '_D' in i:
continue
name = os.path.basename(i)
name = name[:name.rfind('.')]
shutil.move(i, i.replace(name, class_mapping[name]))
sub_map = {}
for i in class_mapping:
sub_map['(?<=\\W)' + i + '(?=\\W)'] = class_mapping[i]
sub_map_text(sub_map)
# 混淆字典
check_obfuscation_dictionary()
def deal_res_type(res_type):
type_mapping = check_res_mapping(res_type)
if len(type_mapping) == 0:
return
print(type_mapping)
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
if not i.startswith(res_type):
continue
path_join = os.path.join(res_path, i)
for j in os.listdir(path_join):
if j.startswith('book_'):
continue
if j.endswith('.9.png'):
name = j[:-len('.9.png')]
else:
name = j.rsplit('.', 1)[0]
path = os.path.join(path_join, j)
if '.DS_Store' not in path:
shutil.move(path, path.replace(name, type_mapping[name]))
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>'
sub_map_text(sub_map)
def add_image_noise(path):
try:
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
if path.endswith('.9.png'):
return
# 添加随机噪声
noise = np.random.randint(0, 2, image.shape, np.uint8)
image = cv2.add(image, noise)
new_path = path.rsplit('.', 1)[0] + '.webp'
cv2.imwrite(new_path, image, [cv2.IMWRITE_WEBP_QUALITY, 75])
if new_path != path:
os.remove(path)
except AttributeError:
return
def deal_image():
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
path_join = os.path.join(res_path, i)
if os.path.isdir(path_join):
for j in os.listdir(path_join):
add_image_noise(os.path.join(path_join, j))
def get_title(string, is_all_upper=False):
splits = string.split('_')
s = ''
for i in range(len(splits)):
if i == 0 and not is_all_upper:
s = splits[i]
elif len(splits[i]) > 0:
s += splits[i][0].upper() + splits[i][1:]
return s
def add_import(path, listfile):
for i in listfile:
with open(i, 'r', encoding='utf-8') as f:
text = f.read()
if len(re.findall('import ' + path, text)) != 0:
continue
if i.endswith('kt'):
text = re.sub('(package \\S+?\\s+?)(?=\\S)', '\\g<1>import ' + path + '\n', text, flags=re.S)
elif i.endswith('java'):
text = re.sub('(package \\S+?\\s+?)(?=\\S)', '\\g<1>import ' + path + ';\n', text, flags=re.S)
with open(i, 'w', encoding='utf-8') as f:
f.write(text)
def check_class_string_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('class_string', {})
classes = get_classes(['kt'])
for path in classes:
if os.path.basename(path).startswith('AESHelper'):
continue
with open(path, 'r', encoding='utf-8') as f:
text = f.read()
text = re.sub('@SuppressLint.*?\n', '\n', text)
text = re.sub('//[^"]*?(("[^"]*?){2})*?\n', '\n', text)
text = re.sub(' +\n', '\n', text)
text = re.sub('=\\s+', '= ', text)
text = re.sub(':\\s+', ': ', text)
text = re.sub(',\\s+', ', ', text)
text = re.sub('\n{2,}', '\n\n', text)
result_text = text
strings = re.findall('".*?[^\\\\]"', re.sub(r'@[^)]*', lambda x: x.group().replace('"', "'"), result_text))
last_string = ''
for string in strings:
if len(string) <= 4 or string.isspace() or \
string[1:-1] in ['\\\\n', '\\\\r', '\\\\\'', '\\\\\\"', '\\\\?', '&amp;', 'UTF-8']:
continue
if string in last_string:
continue
start = text.find(string)
if start == -1:
continue
index = start + 1
sign_stack = ['"']
while len(sign_stack) != 0:
if text[index] == '\\':
index += 1
elif text[index] == '"' and sign_stack[-1] == '"':
sign_stack.pop()
elif text[index] == '"':
sign_stack.append('"')
elif text[index] == '}' and sign_stack[-1] == '${':
sign_stack.pop()
elif text[index - 1:index + 1] == '${':
sign_stack.append('${')
index += 1
string = text[start:index]
last_string = string
params = []
result = string
if '$' in string:
count = 0
last = -1
res = []
for i in range(len(string)):
if last == -1 and string[i] == '$':
if count == 0:
last = i
elif last != -1:
if string[i] == '{':
count += 1
elif string[i] == '}':
count -= 1
if count == 0:
res.append((last, i + 1))
last = -1
elif count == 0:
last = -1
for i in re.findall('\\$\\w*', string):
if i == '$':
continue
find = string.find(i)
res.append((find, find + len(i)))
res = sorted(res, key=lambda l: l[0])
last_res = None
for i in res:
if last_res is not None and i[0] < last_res[1]:
continue
params.append(string[i[0]:i[1]])
last_res = i
for i in params:
result = result.replace(i, "[str]")
result = result[1:-1].replace('%', '%%').replace('\\\\', '\\').replace('[str]', '%s')
if mapping.get(result) is not None:
continue
mapping[result] = get_random_string(5, False) + '_D'
loads['class_string'] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_class_string():
# 获取映射
string_mapping = check_class_string_mapping()
print(string_mapping)
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'r', encoding='utf-8') as f:
text = f.read()
rfind = text.rfind('\n')
text_result = text[:rfind]
for i in string_mapping:
string = i
string = string.replace('&', '&amp;')
string = string.replace('?', '\\?')
string = string.replace('\'', '\\\'')
text_result += '\n <string name="' + string_mapping[i] + '" translatable="false">' + string + '</string>'
text_result += text[rfind:]
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'w', encoding='utf-8') as f:
f.write(text_result)
# 搜索 Int.string() 路径
file_path = find_file('fun Int.string', get_path('.\\src\\main\\java'))
class_path = get_class_path(file_path) + '.string' if file_path else ""
classes = get_classes(['kt'])
for path in classes:
# 跳过 AESHelper 类中的字符串,避免嵌套
if os.path.basename(path).startswith('AESHelper'):
continue
with open(path, 'r', encoding='utf-8') as f:
text = f.read()
text = re.sub('@SuppressLint.*?\n', '\n', text)
text = re.sub('//[^"]*?(("[^"]*?){2})*?\n', '\n', text)
text = re.sub(' +\n', '\n', text)
text = re.sub('=\\s+', '= ', text)
text = re.sub(':\\s+', ': ', text)
text = re.sub(',\\s+', ', ', text)
text = re.sub('\n{2,}', '\n\n', text)
result_text = text
strings = re.findall('".*?[^\\\\]"', re.sub(r'@[^)]*', lambda x: x.group().replace('"', "'"), result_text))
last_string = ''
for string in strings:
if len(string) <= 4 or string.isspace() or \
string[1:-1] in ['\\\\n', '\\\\r', '\\\\\'', '\\\\\\"', '\\\\?', '&amp;', 'UTF-8']:
continue
if string in last_string:
continue
start = text.find(string)
if start == -1:
continue
index = start + 1
sign_stack = ['"']
while len(sign_stack) != 0:
if text[index] == '\\':
index += 1
elif text[index] == '"' and sign_stack[-1] == '"':
sign_stack.pop()
elif text[index] == '"':
sign_stack.append('"')
elif text[index] == '}' and sign_stack[-1] == '${':
sign_stack.pop()
elif text[index - 1:index + 1] == '${':
sign_stack.append('${')
index += 1
# 得到完整字符串
string = text[start:index]
last_string = string
# 参数
params = []
result = string
# 处理字符串拼接
if '$' in string:
count = 0
last = -1
res = []
for i in range(len(string)):
if last == -1 and string[i] == '$':
if count == 0:
last = i
elif last != -1:
if string[i] == '{':
count += 1
elif string[i] == '}':
count -= 1
if count == 0:
res.append((last, i + 1))
last = -1
elif count == 0:
last = -1
for i in re.findall('\\$\\w*', string):
if i == '$':
continue
find = string.find(i)
res.append((find, find + len(i)))
res = sorted(res, key=lambda l: l[0])
last_res = None
for i in res:
if last_res is not None and i[0] < last_res[1]:
continue
params.append(string[i[0]:i[1]])
last_res = i
for i in params:
result = result.replace(i, "[str]")
for i in range(len(params)):
if params[i][1] == '{':
params[i] = params[i][2:-1]
else:
params[i] = params[i][1:]
# 每个参数加上 toString
params[i] = '(' + params[i] + ').toString()'
# 拼接部分替换为 %s
result = result[1:-1].replace('%', '%%').replace('\\\\', '\\').replace('[str]', '%s')
# 添加 Int.string() 方法引用
if class_path:
if len(re.findall('import ' + class_path, text)) == 0:
result_text = re.sub('(package \\S+?\\s+?)(?=\\S)',
'\\g<1>import ' + class_path + '\n', result_text, flags=re.S)
# 添加资源 R 引用
if len(re.findall('import ' + applicationId + '.R', text)) == 0:
result_text = re.sub('(package \\S+?\\s+?)(?=\\S)',
'\\g<1>import ' + applicationId + '.R' + '\n', result_text, flags=re.S)
# 去除 const
result_text = re.sub('const (val.*?R\\.string\\.\\S+?\\.string\\(\\))', '\\g<1>', result_text)
with open(path, 'w', encoding='utf-8') as f:
f.write(result_text)
def check_xml_string_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('xml_string', {})
strings = find_text('android:text="(?<!@string/)([^@"]+?)"', get_path('.\\src\\main\\res\\layout'),
skip_name=['notify', 'notity'])
mapping = {}
for i in strings:
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
# 添加 '_D' 结尾,资源混淆时过滤不用再次改名
mapping[i] = get_random_string(5, False) + '_D'
loads['xml_string'] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_xml_string():
# 获取映射
string_mapping = check_xml_string_mapping()
print(string_mapping)
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'r', encoding='utf-8') as f:
text = f.read()
rfind = text.rfind('\n')
text_result = text[:rfind]
for i in string_mapping:
string = i
string = string.replace('&', '&amp;')
string = string.replace('?', '\\?')
string = string.replace('\'', '\\\'')
text_result += '\n <string name="' + string_mapping[i] + '" translatable="false">' + string + '</string>'
text_result += text[rfind:]
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'w', encoding='utf-8') as f:
f.write(text_result)
sub_map = {}
for i in string_mapping:
sub_map['(?<=android:text=")' + re.escape(i) + '(?=")'] = '@string/' + re.escape(string_mapping[i])
# 替换时跳过通知布局
sub_map_text(sub_map, path=get_path('.\\src\\main\\res\\layout'), skip_name=['notify', 'notity'])
def deal_code_string():
# 处理布局文件中的明文字符串
deal_xml_string()
# 处理代码文件中的明文字符串
deal_class_string()
def deal_res():
# 改 string id
deal_ids_type('string')
# 改 color id
deal_ids_type('color')
# 改 dimen id
deal_ids_type('dimen')
# 改 style id
deal_ids_type('style')
# 改 declare-styleable
styleable_mapping = check_styleable_mapping()
print(styleable_mapping)
sub_map = {}
styleables = find_text('<declare-styleable name=".*?">[\\s\\S]*?</declare-styleable>')
for i in styleables:
result = i
styleable_id = re.findall('<declare-styleable name="(.*?)">', i)[0]
result = result.replace('<declare-styleable name="' + styleable_id + '">',
'<declare-styleable name="' + styleable_mapping[styleable_id] + '">')
sub_map['R\\.styleable\\.' + styleable_id + '(\\W)'] = \
'R.styleable.' + styleable_mapping[styleable_id] + '\\g<1>'
styleables_attr = re.findall('<attr name="(.*?)".*?/>', i)
for attr in styleables_attr:
result = result.replace('<attr name="' + attr + '"', '<attr name="' + styleable_mapping[attr + '_A'] + '"')
sub_map['R\\.styleable\\.' + styleable_id + '_' + attr + '(\\W)'] = \
'R.styleable.' + styleable_mapping[styleable_id] + '_' + styleable_mapping[attr + '_A'] + '\\g<1>'
sub_map['app:' + attr + '='] = 'app:' + styleable_mapping[attr + '_A'] + '='
sub_map[re.escape(i)] = result
sub_map_text(sub_map)
# 改 view id
view_ids = find_text('"\\@\\+id/(.*?)"', get_path('.\\src\\main\\res'))
view_ids_mapping = check_view_ids_mapping()
print(view_ids_mapping)
sub_map = {}
for i in view_ids:
if i == 'root':
continue
key = get_title(i)
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['(?<=app:constraint_referenced_ids=".*?)' + i + '(?=.*?")'] = view_ids_mapping[key]
sub_map_text(sub_map)
# 改 layout 文件名
layout_mapping = check_layout_mapping()
print(layout_mapping)
layout_path = get_path('.\\src\\main\\res\\layout')
listdir = os.listdir(layout_path)
for i in listdir:
name = i[:i.rfind('.')]
if layout_mapping.get(name) is None:
continue
path_join = os.path.join(layout_path, i)
shutil.move(path_join, path_join.replace(name, layout_mapping[name]))
sub_map = {}
for i in layout_mapping:
sub_map['R\\.layout\\.' + i + '(\\W)'] = 'R.layout.' + layout_mapping[i] + '\\g<1>'
# ViewBinding 同步修改
sub_map[get_title(i, True) + 'Binding'] = get_title(layout_mapping[i], True) + 'Binding'
sub_map['(>|")@layout/' + i + '(<|")'] = '\\g<1>@layout/' + layout_mapping[i] + '\\g<2>'
sub_map_text(sub_map)
# 改 drawable 文件名
deal_res_type('drawable')
# 改 mipmap 文件名
deal_res_type('mipmap')
# 改 raw 文件名
deal_res_type('raw')
# 改 raw 文件名
deal_res_type('xml')
# 改图片内容
deal_image()
def get_path(path):
paths = path.split('\\')
return str(os.path.join(*paths))
def main():
if not os.path.exists(get_path('.\\src\\main\\java\\' + applicationId[:applicationId.find('.')])):
return
# 资源混淆
deal_res()
deal_code()
if __name__ == '__main__':
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 文件')
applicationId = re.search('applicationId .*?["\'](.*?)["\']', open(gradle_path, 'r', encoding='utf-8').read())[1]
main()
{
"word": [
"zero",
"midnight",
"yard",
"volume",
"boat",
"belly",
"demand",
"intelligence",
"literacy",
"voice",
"miserable",
"free",
"growth",
"residence",
"apathy",
"majority",
"fast",
"outline",
"degree",
"emphasis",
"positive",
"achieve",
"achievement",
"agreement",
"history",
"account",
"recognize",
"accumulation",
"experience",
"charge",
"star",
"hurt",
"black",
"admit",
"concede",
"admission",
"thanks",
"receipt",
"friend",
"get",
"bitter",
"delay",
"stimulation",
"exchange",
"deal",
"favour",
"performance",
"production",
"jest",
"play",
"activity",
"solo",
"player",
"cast",
"real",
"advertising",
"version",
"dependence",
"addition",
"speech",
"facility",
"stick",
"formal",
"orthodox",
"glue",
"plaster",
"tape",
"poison",
"council",
"division",
"executive",
"confession",
"include",
"warning",
"teenager",
"acceptance",
"woman",
"man",
"notice",
"progress",
"lead",
"opponent",
"hardship",
"adviser",
"revolutionary",
"function",
"affair",
"attachment",
"association",
"statement",
"open",
"tissue",
"collection",
"hostility",
"fan",
"shake",
"excitement",
"consensus",
"peasant",
"help",
"support",
"object",
"wind",
"broadcast",
"cabin",
"pilot",
"wing",
"plane",
"alarm",
"beer",
"alcohol",
"consciousness",
"excuse",
"extraterrestrial",
"foreigner",
"similar",
"commitment",
"bond",
"comprehensive",
"allocation",
"compromise",
"lonely",
"distance",
"directory",
"index",
"change",
"height",
"aluminium",
"graduate",
"romantic",
"atmosphere",
"dream",
"ambition",
"shell",
"pardon",
"quantity",
"figure",
"supply",
"speed",
"entertainment",
"game",
"funny",
"parallel",
"ancestor",
"fox",
"animal",
"ankle",
"birthday",
"note",
"program",
"bother",
"response",
"expect",
"expectation",
"restless",
"anxiety",
"share",
"factor",
"flat",
"stroke",
"clothes",
"attract",
"sympathetic",
"appeal",
"seem",
"debut",
"look",
"texture",
"convenience",
"engineer",
"rub",
"paint",
"general",
"date",
"assessment",
"estimate",
"arrest",
"permission",
"spider",
"random",
"wall",
"archive",
"arch",
"fire",
"room",
"argument",
"line",
"desert",
"rise",
"weapon",
"sleeve",
"tank",
"smell",
"garlic",
"tease",
"move",
"provoke",
"moving",
"pack",
"row",
"timetable",
"bow",
"gallery",
"reservoir",
"craftsman",
"painter",
"art",
"silver",
"beg",
"invite",
"view",
"attack",
"battery",
"assembly",
"claim",
"selection",
"astonishing",
"far",
"forward",
"runner",
"sport",
"front",
"nuclear",
"tin",
"monstrous",
"strike",
"effort",
"serve",
"care",
"costume",
"culture",
"lawyer",
"draw",
"cute",
"attraction",
"property",
"gold",
"auction",
"sound",
"sign",
"aunt",
"writer",
"command",
"regulation",
"government",
"car",
"bus",
"robot",
"transmission",
"motorist",
"fall",
"supplementary",
"common",
"conscious",
"axis",
"baby",
"carriage",
"nursery",
"heel",
"withdrawal",
"suitcase",
"sphere",
"vote",
"trivial",
"patch",
"band",
"slam",
"deposit",
"failure",
"feast",
"banish",
"tycoon",
"drum",
"fence",
"bar",
"trade",
"basis",
"baseball",
"wrong",
"rational",
"democratic",
"cellar",
"essential",
"infrastructure",
"introduction",
"cell",
"principle",
"foundation",
"club",
"bathtub",
"bathroom",
"wash",
"battlefield",
"resist",
"represent",
"oppose",
"suit",
"know",
"trail",
"ride",
"depend",
"dare",
"differ",
"match",
"like",
"dominate",
"love",
"owe",
"mind",
"run",
"belong",
"beat",
"host",
"win",
"lack",
"worry",
"drop",
"bill",
"kidney",
"carry",
"testify",
"hold",
"stand",
"posture",
"presence",
"rhythm",
"scramble",
"grace",
"salon",
"wave",
"increase",
"conceive",
"deteriorate",
"sheet",
"friendly",
"start",
"source",
"captivate",
"low",
"absent",
"present",
"critical",
"opposed",
"hot",
"outer",
"salvation",
"late",
"swallow",
"think",
"roar",
"noble",
"left",
"bad",
"flex",
"turn",
"curve",
"flexible",
"good",
"advantage",
"hook",
"leave",
"mourning",
"shoulder",
"siege",
"engagement",
"improve",
"coffee",
"wine",
"drink",
"prejudice",
"bike",
"offer",
"large",
"contract",
"duck",
"turkey",
"call",
"delivery",
"pill",
"morsel",
"chip",
"snack",
"sting",
"burn",
"sword",
"space",
"cover",
"blast",
"combine",
"approval",
"pest",
"flash",
"obstacle",
"brick",
"forget",
"slab",
"vein",
"mosquito",
"inflate",
"punch",
"depressed",
"blue",
"flush",
"heart",
"muscle",
"scale",
"mass",
"constituency",
"lake",
"appendix",
"flesh",
"guard",
"kettle",
"steam",
"cheek",
"bomb",
"sandwich",
"rib",
"tooth",
"dividend",
"horn",
"album",
"notebook",
"prosper",
"stall",
"loot",
"dull",
"adopt",
"breast",
"cap",
"base",
"avenue",
"end",
"border",
"reward",
"cow",
"stadium",
"ring",
"electronics",
"courage",
"toast",
"bread",
"width",
"shatter",
"smash",
"cereal",
"discovery",
"hiccup",
"rest",
"corruption",
"workshop",
"bulletin",
"summary",
"glimpse",
"light",
"brilliance",
"lip",
"prosecute",
"bring",
"generate",
"introduce",
"create",
"organize",
"publish",
"disclose",
"update",
"take",
"glass",
"spectrum",
"reception",
"leaflet",
"fragment",
"brother",
"eyebrow",
"review",
"cruel",
"champagne",
"garage",
"center",
"architecture",
"displace",
"roll",
"cluster",
"nerve",
"cottage",
"nonsense",
"load",
"rabbit",
"pop",
"split",
"operation",
"office",
"counter",
"agency",
"burst",
"fuss",
"buttocks",
"cigarette",
"traffic",
"carbon",
"taxi",
"conspiracy",
"corpse",
"disaster",
"multiply",
"month",
"week",
"request",
"cancel",
"predict",
"card",
"career",
"calm",
"crusade",
"candidate",
"frank",
"wolf",
"sail",
"canvas",
"ceiling",
"able",
"content",
"memory",
"capital",
"execution",
"impulse",
"legend",
"prisoner",
"treat",
"consideration",
"shark",
"wrist",
"sketch",
"waterfall",
"precedent",
"advance",
"register",
"barrel",
"coffin",
"hurl",
"catalogue",
"capture",
"bracket",
"nap",
"ranch",
"white",
"cause",
"nature",
"kill",
"offend",
"pour",
"pit",
"crash",
"fame",
"planet",
"orbit",
"paper",
"penny",
"core",
"headquarters",
"wheat",
"hemisphere",
"ceremony",
"parade",
"funeral",
"license",
"neck",
"straw",
"necklace",
"throne",
"president",
"champion",
"title",
"reform",
"convert",
"freeze",
"role",
"feature",
"provincial",
"hostile",
"systematic",
"poor",
"loud",
"plot",
"chase",
"talkative",
"check",
"cheque",
"urge",
"compound",
"element",
"reaction",
"chemistry",
"king",
"chest",
"main",
"head",
"adoption",
"chorus",
"chop",
"helicopter",
"watch",
"lump",
"church",
"slide",
"film",
"round",
"condition",
"reference",
"quote",
"orange",
"block",
"mayor",
"tribe",
"applaud",
"bang",
"confrontation",
"mud",
"pottery",
"soap",
"clarify",
"acquit",
"cut",
"crack",
"mercy",
"fist",
"bishop",
"clerk",
"smart",
"tick",
"snap",
"customer",
"climb",
"climate",
"cutting",
"time",
"close",
"contact",
"cupboard",
"dress",
"overall",
"belt",
"fool",
"seize",
"train",
"coalition",
"harsh",
"coat",
"code",
"contemporary",
"generation",
"cafe",
"proof",
"knowledge",
"belief",
"judgment",
"laser",
"curl",
"snub",
"fish",
"cold",
"cooperate",
"give",
"tent",
"raise",
"wardrobe",
"settlement",
"rainbow",
"mosaic",
"chord",
"land",
"confront",
"enter",
"appear",
"discover",
"bait",
"comfort",
"comfortable",
"leader",
"memorial",
"recommend",
"transaction",
"business",
"commerce",
"market",
"committee",
"board",
"sense",
"park",
"infect",
"write",
"network",
"compact",
"company",
"pity",
"remunerate",
"competence",
"plaintiff",
"finish",
"perfect",
"complication",
"complex",
"follow",
"module",
"behave",
"constitution",
"understand",
"squeeze",
"accountant",
"calculation",
"hardware",
"menu",
"mouse",
"computing",
"software",
"computer",
"hide",
"design",
"imagine",
"notion",
"concept",
"embryo",
"practical",
"applied",
"sacred",
"personal",
"domestic",
"definition",
"last",
"harmony",
"coincide",
"terms",
"freedom",
"danger",
"improvement",
"behavior",
"experiment",
"director",
"south",
"federation",
"trust",
"constellation",
"impound",
"battle",
"fit",
"adjust",
"standard",
"normal",
"compliance",
"praise",
"representative",
"link",
"related",
"node",
"draft",
"sanctuary",
"agree",
"product",
"effect",
"doubt",
"courtesy",
"thoughtful",
"tight",
"structure",
"use",
"infection",
"bin",
"cassette",
"full",
"pollution",
"competition",
"satisfaction",
"race",
"circumstance",
"Europe",
"pupil",
"deny",
"contradiction",
"joystick",
"recovery",
"rule",
"transition",
"convince",
"vehicle",
"sentence",
"fabricate",
"biscuit",
"herb",
"oil",
"pan",
"pot",
"cage",
"partnership",
"cooperative",
"policeman",
"hospitality",
"cord",
"right",
"discipline",
"decorative",
"makeup",
"price",
"clique",
"cotton",
"sofa",
"matter",
"mole",
"offset",
"poll",
"coup",
"voucher",
"brave",
"seminar",
"credit",
"course",
"curriculum",
"direction",
"warrant",
"polite",
"court",
"designer",
"bloody",
"jealous",
"colleague",
"cattle",
"gap",
"wisecrack",
"cunning",
"craft",
"crackpot",
"crevice",
"rotten",
"appetite",
"creep",
"fold",
"creation",
"artist",
"thinker",
"literature",
"credibility",
"creed",
"sailor",
"prosecution",
"record",
"criticism",
"crosswalk",
"bend",
"collapse",
"squash",
"gravel",
"copper",
"snuggle",
"clue",
"cucumber",
"ethnic",
"mug",
"cabinet",
"cup",
"remedy",
"suppress",
"heal",
"lock",
"money",
"damn",
"swear",
"pillow",
"convention",
"tradition",
"reduce",
"amputate",
"crop",
"carve",
"skin",
"fork",
"sale",
"pat",
"sunrise",
"dairy",
"total",
"ballet",
"navy",
"dark",
"favourite",
"style",
"file",
"track",
"dawn",
"anniversary",
"holiday",
"fog",
"shock",
"body",
"hand",
"lot",
"franchise",
"shortage",
"consider",
"expose",
"behead",
"death",
"betray",
"decade",
"resolution",
"classify",
"refuse",
"recession",
"descent",
"decay",
"medal",
"reduction",
"order",
"devote",
"profound",
"well",
"carrot",
"coma",
"nonremittal",
"fault",
"lemon",
"payment",
"temperature",
"quality",
"god",
"extension",
"censorship",
"debate",
"lace",
"tasty",
"pleasure",
"please",
"pleasant",
"preach",
"rescue",
"challenge",
"limit",
"demonstration",
"destruction",
"thick",
"density",
"reliable",
"describe",
"subject",
"exile",
"bank",
"depression",
"rob",
"commission",
"lineage",
"origin",
"integration",
"merit",
"motif",
"plan",
"functional",
"architect",
"want",
"despair",
"sweet",
"fate",
"point",
"confine",
"custody",
"discourage",
"weigh",
"decisive",
"hate",
"explode",
"explosion",
"modernize",
"abnormal",
"instrument",
"filter",
"crown",
"dialogue",
"negotiation",
"journal",
"drown",
"diet",
"disagree",
"mess",
"difficulty",
"excavation",
"industry",
"proportion",
"decrease",
"diplomatic",
"management",
"manager",
"soil",
"disability",
"denial",
"unpleasant",
"separation",
"disk",
"dump",
"study",
"negative",
"stop",
"disco",
"offense",
"find",
"incongruous",
"digital",
"consultation",
"treatment",
"contempt",
"spirit",
"mask",
"pie",
"dish",
"disorder",
"chart",
"quarrel",
"difference",
"neglect",
"dismiss",
"joint",
"undress",
"interrupt",
"disturbance",
"disagreement",
"thesis",
"deter",
"mile",
"aloof",
"trait",
"characteristic",
"spread",
"circulate",
"quarter",
"upset",
"trench",
"butterfly",
"variety",
"deviation",
"even",
"harm",
"work",
"doctor",
"philosophy",
"charter",
"pound",
"dollar",
"goat",
"dog",
"chicken",
"cultivate",
"control",
"contribution",
"gate",
"bell",
"threshold",
"dorm",
"drug",
"image",
"ruin",
"drain",
"opera",
"drama",
"theater",
"curtain",
"pull",
"tap",
"tie",
"diagram",
"fear",
"awful",
"sip",
"dribble",
"drive",
"quit",
"heroin",
"user",
"rehearsal",
"east",
"north",
"west",
"ditch",
"repeat",
"length",
"twilight",
"responsibility",
"obligation",
"house",
"home",
"dynamic",
"past",
"mail",
"world",
"pole",
"relief",
"relaxation",
"accessible",
"tender",
"distinct",
"handy",
"restaurant",
"aid",
"economist",
"boom",
"economics",
"economy",
"value",
"margin",
"bean",
"onion",
"corn",
"building",
"school",
"influence",
"effective",
"egg",
"self",
"ego",
"hip",
"elbow",
"old",
"choose",
"voter",
"current",
"electron",
"hill",
"lift",
"elite",
"banana",
"articulate",
"flag",
"eagle",
"utter",
"glow",
"sentiment",
"pain",
"stress",
"conglomerate",
"empirical",
"authorise",
"blank",
"clear",
"brain",
"witch",
"surround",
"frame",
"meeting",
"favorable",
"invasion",
"restrain",
"settle",
"output",
"acute",
"conclusion",
"terminal",
"survival",
"opposition",
"fuel",
"wrap",
"wrestle",
"mastermind",
"technology",
"concentration",
"enjoy",
"indulge",
"expansion",
"soldier",
"registration",
"plead",
"penetrate",
"tempt",
"temptation",
"solid",
"burial",
"entry",
"access",
"ticket",
"twist",
"environment",
"era",
"balance",
"breakdown",
"just",
"ambiguous",
"ambiguity",
"delete",
"error",
"intensify",
"adventure",
"flight",
"leak",
"perfume",
"habit",
"institution",
"admiration",
"respect",
"evening",
"incident",
"trouble",
"eternal",
"estate",
"grounds",
"contrary",
"test",
"screen",
"inspector",
"mine",
"exclude",
"fat",
"sell",
"redeem",
"correspond",
"correspondence",
"proclaim",
"exclusive",
"monopoly",
"justify",
"example",
"illustrate",
"practice",
"dominant",
"exercise",
"press",
"show",
"display",
"museum",
"emergency",
"elaborate",
"area",
"anticipation",
"prospect",
"eject",
"spend",
"feel",
"authority",
"expertise",
"reason",
"explain",
"remark",
"graphic",
"exhibition",
"complain",
"explicit",
"apology",
"highway",
"delicate",
"reach",
"society",
"surface",
"outside",
"blackmail",
"deport",
"galaxy",
"glasses",
"lid",
"silk",
"material",
"manufacture",
"side",
"grimace",
"aspect",
"beard",
"fax",
"parameter",
"observation",
"attention",
"fairy",
"miss",
"overlook",
"lose",
"weakness",
"absence",
"sunshine",
"forge",
"illusion",
"distort",
"acquaintance",
"kinship",
"crystal",
"agriculture",
"model",
"trick",
"secure",
"screw",
"knot",
"cream",
"tired",
"blame",
"prefer",
"progressive",
"cower",
"concern",
"bold",
"viable",
"banquet",
"agent",
"toll",
"desire",
"unrest",
"confidence",
"proud",
"cat",
"criminal",
"hen",
"girl",
"bitch",
"queen",
"mother",
"iron",
"ferry",
"conception",
"celebration",
"story",
"fibre",
"character",
"novel",
"fight",
"stuff",
"fill",
"occupy",
"movie",
"producer",
"fund",
"treasurer",
"convict",
"clay",
"powder",
"sand",
"thumb",
"fastidious",
"particular",
"goal",
"fireplace",
"shoot",
"rifle",
"firefighter",
"strong",
"cousin",
"initial",
"beginning",
"initiative",
"freshman",
"financial",
"salmon",
"aquarium",
"fisherman",
"healthy",
"equip",
"convulsion",
"scene",
"cook",
"fee",
"interest",
"tile",
"meat",
"steward",
"toss",
"deck",
"level",
"stun",
"floor",
"vegetation",
"plant",
"dough",
"spill",
"lily",
"variation",
"chimney",
"soar",
"concentrate",
"family",
"folk",
"conventional",
"second",
"cheese",
"grain",
"salad",
"cheat",
"reckless",
"football",
"trace",
"marathon",
"step",
"boot",
"offensive",
"raid",
"patience",
"power",
"camp",
"impact",
"force",
"exotic",
"chief",
"deer",
"prevent",
"branch",
"spin",
"shape",
"ball",
"format",
"abandon",
"strength",
"castle",
"accident",
"coal",
"spring",
"wheel",
"skeleton",
"rack",
"hotdog",
"fraud",
"monster",
"relieve",
"straight",
"safe",
"clean",
"dry",
"pure",
"weight",
"exempt",
"release",
"liberty",
"halt",
"frequency",
"original",
"clash",
"refrigerator",
"ally",
"warm",
"terrify",
"medieval",
"facade",
"ice",
"cherry",
"apple",
"defeat",
"foot",
"smoke",
"official",
"mushroom",
"mold",
"desk",
"seat",
"lamp",
"rage",
"joke",
"choke",
"profit",
"make",
"gallon",
"risk",
"net",
"score",
"top",
"gas",
"meet",
"homosexual",
"regard",
"gear",
"jelly",
"diamond",
"jewel",
"gem",
"sex",
"category",
"health",
"productive",
"mutation",
"genetic",
"exploration",
"zone",
"circle",
"escape",
"cope",
"age",
"abolish",
"eliminate",
"master",
"arise",
"outfit",
"ghostwriter",
"charity",
"talented",
"daughter",
"bless",
"define",
"perform",
"pay",
"distribute",
"thank",
"spare",
"resignation",
"secretion",
"marble",
"glance",
"shine",
"gloom",
"glare",
"frown",
"sticky",
"sink",
"retire",
"happen",
"accompany",
"pass",
"fail",
"goalkeeper",
"departure",
"golf",
"peanut",
"charm",
"bloodshed",
"overeat",
"extort",
"ministry",
"minister",
"gradient",
"mark",
"drift",
"rice",
"grandfather",
"grandmother",
"grip",
"hay",
"scrape",
"tip",
"gravity",
"cemetery",
"major",
"high",
"produce",
"green",
"welcome",
"grudge",
"mill",
"traction",
"army",
"background",
"cooperation",
"flock",
"herd",
"organisation",
"fleet",
"troop",
"adult",
"development",
"ensure",
"defend",
"hypothesis",
"direct",
"guide",
"guideline",
"guilt",
"innocent",
"taste",
"water",
"inhabitant",
"haircut",
"hall",
"hammer",
"basket",
"manual",
"cart",
"umbrella",
"glove",
"hang",
"yearn",
"coincidence",
"difficult",
"cash",
"wood",
"nut",
"damage",
"collar",
"harvest",
"harass",
"rush",
"have",
"wear",
"dine",
"afford",
"brown",
"sour",
"steep",
"smooth",
"sharp",
"sensitive",
"complete",
"square",
"deep",
"weak",
"infinite",
"mature",
"meadow",
"veil",
"governor",
"helmet",
"clearance",
"therapist",
"pile",
"listen",
"rumor",
"grief",
"heat",
"responsible",
"service",
"portion",
"dome",
"moment",
"future",
"reluctance",
"retreat",
"fever",
"highlight",
"extreme",
"handicap",
"interference",
"employ",
"slap",
"pawn",
"pig",
"keep",
"resort",
"tube",
"bubble",
"excavate",
"habitat",
"housewife",
"honor",
"addicted",
"tire",
"basketball",
"platform",
"ward",
"inn",
"enemy",
"firm",
"hut",
"hour",
"husband",
"color",
"embrace",
"giant",
"act",
"face",
"arm",
"humanity",
"comedy",
"hunting",
"safari",
"hunter",
"suffer",
"injury",
"suffering",
"cross",
"theory",
"preoccupation",
"identity",
"identification",
"dialect",
"lighter",
"sick",
"unlawful",
"notorious",
"fantasy",
"projection",
"picture",
"copy",
"huge",
"exemption",
"affect",
"spoil",
"fair",
"jungle",
"pressure",
"flawed",
"temporary",
"tool",
"brush",
"issue",
"jail",
"unlikely",
"momentum",
"tense",
"regular",
"unanimous",
"accurate",
"central",
"inch",
"passive",
"still",
"dead",
"helpless",
"tendency",
"whole",
"conflict",
"incapable",
"contain",
"few",
"insurance",
"bay",
"separate",
"needle",
"need",
"person",
"morale",
"single",
"lazy",
"incentive",
"splurge",
"cheap",
"implicit",
"childish",
"virus",
"hell",
"hospital",
"determine",
"flu",
"information",
"recording",
"rare",
"violation",
"consumption",
"monk",
"instinct",
"heir",
"first",
"shot",
"pioneer",
"inquiry",
"ask",
"question",
"dedicate",
"bee",
"indoor",
"insistence",
"fresh",
"establish",
"episode",
"exception",
"college",
"teach",
"lecture",
"education",
"teacher",
"means",
"deficiency",
"abuse",
"coverage",
"policy",
"premium",
"guerrilla",
"rebel",
"rebellion",
"unity",
"news",
"mean",
"purpose",
"intervention",
"inside",
"middle",
"medium",
"translate",
"read",
"spokesperson",
"crossing",
"period",
"bowel",
"fascinate",
"suspicion",
"feeling",
"flood",
"innovation",
"stock",
"reverse",
"speculate",
"detective",
"investment",
"guest",
"physical",
"anger",
"publication",
"exit",
"loop",
"twitch",
"appointment",
"athlete",
"reporter",
"voyage",
"joy",
"litigation",
"parachute",
"judicial",
"law",
"judge",
"justice",
"deprive",
"discreet",
"piano",
"child",
"calorie",
"favor",
"lion",
"affinity",
"oven",
"knee",
"stab",
"horse",
"sweater",
"experienced",
"laboratory",
"union",
"maze",
"ignorance",
"ignorant",
"shallow",
"bald",
"soft",
"bare",
"girlfriend",
"secular",
"island",
"site",
"ground",
"landowner",
"name",
"lick",
"theft",
"cathedral",
"tiger",
"great",
"river",
"crowd",
"stage",
"range",
"pumpkin",
"whip",
"endure",
"permanent",
"tension",
"fashion",
"crime",
"grass",
"save",
"store",
"leadership",
"blade",
"leaf",
"thin",
"jump",
"academy",
"resign",
"farewell",
"depart",
"talk",
"leftovers",
"action",
"trustee",
"liability",
"opinion",
"jurisdiction",
"trial",
"verdict",
"key",
"legislation",
"legislature",
"continuation",
"wound",
"minor",
"disappoint",
"disappointment",
"deadly",
"letter",
"hover",
"dictionary",
"licence",
"lie",
"biography",
"revoke",
"beam",
"bulb",
"pastel",
"ignite",
"blonde",
"equal",
"restrict",
"diameter",
"column",
"language",
"context",
"connection",
"soup",
"eavesdrop",
"torch",
"essay",
"fiction",
"small",
"alive",
"accept",
"enthusiasm",
"resident",
"social",
"lend",
"engine",
"housing",
"attic",
"log",
"implication",
"linger",
"strip",
"ridge",
"shaft",
"bench",
"monkey",
"admire",
"relax",
"misplace",
"sacrifice",
"drawing",
"speaker",
"chin",
"minimum",
"fortune",
"chance",
"trunk",
"timber",
"lunch",
"thrust",
"grand",
"intermediate",
"machinery",
"spell",
"enlarge",
"dimension",
"maid",
"post",
"brand",
"reproduce",
"deliver",
"impress",
"guess",
"activate",
"bark",
"enhance",
"weave",
"amuse",
"obscure",
"touch",
"revise",
"develop",
"knit",
"reconcile",
"decide",
"widen",
"presentation",
"father",
"spite",
"cancer",
"mistreat",
"finance",
"exploit",
"falsify",
"laborer",
"construct",
"demonstrate",
"march",
"seal",
"wild",
"seller",
"distributor",
"proposal",
"wedding",
"marriage",
"wife",
"marsh",
"wonder",
"communist",
"grind",
"rally",
"glacier",
"domination",
"chew",
"concrete",
"plastic",
"mathematics",
"equation",
"grow",
"maximum",
"buffet",
"way",
"qualify",
"measure",
"beef",
"pump",
"dressing",
"clinic",
"medicine",
"specimen",
"symptom",
"see",
"conference",
"qualified",
"theme",
"tune",
"partner",
"citizen",
"memorandum",
"learn",
"crew",
"threat",
"attitude",
"outlook",
"refer",
"merchant",
"freighter",
"cruelty",
"deserve",
"fun",
"hypnothize",
"steel",
"wire",
"metal",
"subway",
"city",
"microphone",
"bomber",
"campaign",
"occupation",
"factory",
"minute",
"aware",
"miner",
"mislead",
"distortion",
"mixture",
"cake",
"air",
"solution",
"confusion",
"groan",
"pattern",
"mild",
"routine",
"empire",
"abbey",
"grant",
"coin",
"allowance",
"debt",
"virtue",
"ethics",
"integrity",
"morning",
"breakfast",
"gesture",
"movement",
"motivation",
"motorcycle",
"truck",
"slogan",
"mountain",
"volcano",
"of",
"at",
"if",
"no",
"my",
"me",
"to",
"be",
"so",
"we",
"he",
"by",
"on",
"up",
"am",
"us",
"stir",
"dance",
"skate",
"glide",
"swipe",
"bounce",
"swing",
"migration",
"circulation",
"cinema",
"mobile",
"multimedia",
"mutter",
"contraction",
"composer",
"piece",
"orchestra",
"concert",
"dragon",
"sodium",
"appoint",
"nomination",
"tell",
"channel",
"lane",
"narrow",
"congress",
"hair",
"tongue",
"sickness",
"marine",
"approach",
"tidy",
"requirement",
"thirsty",
"negligence",
"ignore",
"bargain",
"neighbour",
"cool",
"nervous",
"latest",
"report",
"headline",
"night",
"agile",
"retired",
"lost",
"duke",
"owl",
"bat",
"extinct",
"article",
"civilian",
"objective",
"average",
"census",
"relative",
"indirect",
"ordinary",
"genuine",
"unfortunate",
"tough",
"slow",
"modest",
"integrated",
"inappropriate",
"other",
"loose",
"raw",
"hard",
"mention",
"warn",
"reputation",
"harmful",
"reactor",
"chain",
"count",
"number",
"foster",
"food",
"approve",
"oak",
"fixture",
"protest",
"dirty",
"stubborn",
"reserve",
"borrow",
"available",
"profession",
"seasonal",
"sea",
"visual",
"eye",
"primary",
"heavy",
"superior",
"neutral",
"oral",
"diplomat",
"twin",
"senior",
"nose",
"bear",
"leg",
"page",
"critic",
"survivor",
"trainer",
"linear",
"half",
"tray",
"window",
"hole",
"surgeon",
"automatic",
"aviation",
"driver",
"contrast",
"choice",
"mouth",
"satellite",
"agenda",
"liver",
"donor",
"orgy",
"decoration",
"kit",
"expenditure",
"printer",
"scandal",
"overwhelm",
"manage",
"exaggerate",
"revolution",
"obese",
"due",
"possession",
"rate",
"elephant",
"treaty",
"bucket",
"shame",
"palm",
"tract",
"chaos",
"gasp",
"trouser",
"heaven",
"ideal",
"paralyzed",
"uncle",
"parking",
"word",
"drawer",
"member",
"root",
"colon",
"thigh",
"jaw",
"unfair",
"bride",
"detail",
"elapse",
"perforate",
"faint",
"skip",
"reject",
"exceed",
"aisle",
"hallway",
"passage",
"passion",
"graze",
"pasture",
"patent",
"route",
"terrace",
"nationalist",
"nationalism",
"syndrome",
"hesitate",
"pause",
"wage",
"pension",
"royalty",
"rent",
"peace",
"fur",
"punish",
"retiree",
"population",
"hear",
"observer",
"percent",
"insight",
"absolute",
"benefit",
"performer",
"century",
"magazine",
"cycle",
"die",
"allow",
"vertical",
"persist",
"remain",
"porter",
"rider",
"conductor",
"vegetarian",
"virgin",
"slave",
"patient",
"witness",
"consumer",
"worker",
"hero",
"radical",
"personality",
"pin",
"manner",
"staff",
"sweat",
"basic",
"operational",
"dramatic",
"throat",
"telephone",
"photograph",
"camera",
"wording",
"evolution",
"assault",
"fitness",
"size",
"shelter",
"physics",
"broken",
"prescription",
"collect",
"pluck",
"photography",
"print",
"chalk",
"bed",
"field",
"mechanism",
"stereotype",
"tablet",
"dismissal",
"organ",
"urine",
"slant",
"arena",
"bury",
"insert",
"mosque",
"sow",
"address",
"put",
"arrangement",
"position",
"braid",
"layout",
"biology",
"flower",
"houseplant",
"fossil",
"weed",
"sculpture",
"panel",
"pen",
"fragrant",
"attractive",
"abundant",
"shower",
"feather",
"looting",
"dive",
"asset",
"poetry",
"concession",
"location",
"extent",
"corner",
"arrow",
"officer",
"party",
"ideology",
"colony",
"pyramid",
"bacon",
"dose",
"part",
"portrait",
"easy",
"orientation",
"charismatic",
"beautiful",
"rich",
"acquisition",
"possibility",
"station",
"stamp",
"tail",
"possible",
"potential",
"pocket",
"swarm",
"flour",
"hierarchy",
"blow",
"application",
"realism",
"sermon",
"priority",
"exact",
"definite",
"precision",
"precede",
"predator",
"horoscope",
"preference",
"racism",
"chauvinist",
"assumption",
"absorption",
"training",
"bake",
"ready",
"prevalence",
"gift",
"conservation",
"jam",
"administration",
"presidency",
"push",
"lobby",
"coerce",
"glory",
"prestige",
"assume",
"imposter",
"mainstream",
"quotation",
"discount",
"chimpanzee",
"crude",
"form",
"prison",
"hostage",
"coach",
"privacy",
"award",
"likely",
"investigation",
"process",
"gradual",
"perception",
"announcement",
"manufacturer",
"professor",
"uniform",
"professional",
"chair",
"technique",
"gain",
"offspring",
"forecast",
"forbid",
"ban",
"missile",
"prediction",
"sustain",
"pledge",
"marketing",
"remind",
"launch",
"pitch",
"advocate",
"quota",
"advice",
"suggest",
"owner",
"protection",
"demonstrator",
"pride",
"entertain",
"feed",
"state",
"soul",
"analysis",
"analyst",
"psychology",
"sensation",
"forum",
"publicity",
"riot",
"edition",
"promotion",
"publisher",
"pool",
"drag",
"extract",
"penalty",
"student",
"buy",
"hobby",
"button",
"advertise",
"lay",
"instal",
"install",
"execute",
"nominate",
"earthquake",
"dilemma",
"prey",
"satisfied",
"pursuit",
"problem",
"quiet",
"silence",
"fraction",
"radio",
"radiation",
"railcar",
"railroad",
"storm",
"rain",
"breed",
"build",
"noise",
"knock",
"rape",
"ecstasy",
"rank",
"preparation",
"reality",
"back",
"beneficiary",
"mutual",
"appreciate",
"realize",
"tolerate",
"referral",
"compensation",
"document",
"matrix",
"correction",
"recover",
"loss",
"red",
"redundancy",
"polish",
"sugar",
"elegant",
"mirror",
"reflection",
"asylum",
"garbage",
"popular",
"continental",
"national",
"presidential",
"constitutional",
"imperial",
"cultural",
"economic",
"magnetic",
"moral",
"environmental",
"ratio",
"relation",
"relevance",
"faith",
"comment",
"commemorate",
"retain",
"shave",
"relinquish",
"restoration",
"lease",
"tenant",
"fix",
"meal",
"refund",
"repetition",
"regret",
"substitute",
"reproduction",
"answer",
"storage",
"recycle",
"reptile",
"horror",
"researcher",
"qualification",
"palace",
"community",
"ash",
"immune",
"conservative",
"tolerant",
"pneumonia",
"lung",
"feedback",
"kneel",
"brake",
"constraint",
"result",
"revival",
"revive",
"retailer",
"outlet",
"revenge",
"withdraw",
"remember",
"echo",
"opposite",
"reader",
"reinforce",
"wealth",
"jockey",
"entitlement",
"copyright",
"option",
"fruit",
"rear",
"inflation",
"venture",
"ritual",
"gown",
"rock",
"kitchen",
"suite",
"rotation",
"path",
"road",
"carpet",
"rugby",
"finished",
"flow",
"country",
"countryside",
"undermine",
"salesperson",
"greeting",
"irony",
"moon",
"stroll",
"flavor",
"pray",
"dictate",
"expression",
"strikebreaker",
"frighten",
"spray",
"landscape",
"scheme",
"system",
"scholar",
"session",
"classroom",
"forestry",
"science",
"despise",
"scratch",
"conscience",
"bronze",
"gossip",
"harbor",
"seek",
"coast",
"endorse",
"mystery",
"secretary",
"patrol",
"security",
"visible",
"seed",
"recruit",
"quest",
"transparent",
"gene",
"section",
"bite",
"elect",
"pick",
"assertive",
"vain",
"paradox",
"willpower",
"spontaneous",
"arrogant",
"dignity",
"autonomy",
"export",
"greet",
"perceive",
"humor",
"ear",
"reasonable",
"sensitivity",
"detector",
"discriminate",
"distant",
"barrier",
"scenario",
"sequence",
"series",
"snake",
"waiter",
"established",
"arrange",
"apparatus",
"strict",
"stitch",
"faithful",
"shadow",
"nuance",
"feign",
"embarrassment",
"disgrace",
"cylinder",
"edge",
"bundle",
"bleed",
"protect",
"budge",
"reflect",
"horseshoe",
"beach",
"jacket",
"shorts",
"deficit",
"abridge",
"injection",
"strap",
"brag",
"prove",
"shrink",
"bush",
"shiver",
"mix",
"ostracize",
"closed",
"temple",
"profile",
"digress",
"pavement",
"symbol",
"meaning",
"important",
"lover",
"velvet",
"flatware",
"plain",
"stool",
"simplicity",
"honest",
"unit",
"sin",
"sister",
"nun",
"sit",
"locate",
"ample",
"magnitude",
"survey",
"slip",
"skilled",
"scan",
"freckle",
"peel",
"omission",
"captain",
"horizon",
"angle",
"killer",
"murder",
"bedroom",
"steak",
"stumble",
"gaffe",
"slippery",
"dip",
"slump",
"slime",
"snail",
"bullet",
"sleep",
"particle",
"berry",
"pony",
"limited",
"packet",
"sample",
"scrap",
"slot",
"compartment",
"village",
"minority",
"fine",
"petty",
"dash",
"smile",
"spot",
"trap",
"snatch",
"kidnap",
"snow",
"serious",
"gregarious",
"ant",
"welfare",
"socialist",
"civilization",
"pudding",
"worm",
"casualty",
"suspect",
"communication",
"wreck",
"prince",
"resource",
"monarch",
"bridge",
"formation",
"shout",
"snarl",
"whisper",
"privilege",
"audience",
"hypothesize",
"accent",
"trance",
"spit",
"sector",
"pepper",
"shed",
"angel",
"divorce",
"divide",
"referee",
"stain",
"expand",
"scatter",
"encourage",
"team",
"waste",
"crouch",
"jet",
"crutch",
"staircase",
"stake",
"haunt",
"stem",
"stable",
"norm",
"sun",
"begin",
"situation",
"safety",
"relationship",
"reliance",
"isolation",
"say",
"declaration",
"formula",
"rung",
"wait",
"lodge",
"constant",
"plagiarize",
"ladder",
"stay",
"pierce",
"muggy",
"miscarriage",
"shareholder",
"sock",
"plug",
"shop",
"straighten",
"strategic",
"wander",
"banner",
"trolley",
"struggle",
"stretch",
"hit",
"kick",
"stunning",
"guitar",
"ribbon",
"conviction",
"emotion",
"vigorous",
"cable",
"tower",
"nest",
"auditor",
"trip",
"fashionable",
"chapter",
"paragraph",
"soak",
"replace",
"suburb",
"brainstorm",
"inspiration",
"evoke",
"indication",
"proper",
"sulphur",
"budget",
"sum",
"overview",
"summer",
"summit",
"superintendent",
"miracle",
"dinner",
"bag",
"prayer",
"cater",
"inspire",
"provide",
"provision",
"shelf",
"pier",
"inhibition",
"overcharge",
"certain",
"excess",
"deputy",
"replacement",
"defendant",
"chocolate",
"swell",
"door",
"shift",
"swop",
"understanding",
"interactive",
"calendar",
"research",
"salt",
"table",
"undertake",
"tactic",
"breathe",
"insist",
"inject",
"eat",
"absorb",
"insure",
"participate",
"musical",
"conversation",
"discuss",
"tree",
"suntan",
"candle",
"duty",
"assignment",
"job",
"bland",
"tax",
"species",
"instruction",
"tear",
"rhetoric",
"television",
"mood",
"disposition",
"pace",
"loan",
"trend",
"strain",
"finger",
"abortion",
"district",
"panic",
"examination",
"will",
"tribute",
"recommendation",
"leash",
"text",
"grateful",
"tragedy",
"theorist",
"slice",
"mist",
"nail",
"layer",
"thread",
"dilute",
"combination",
"thought",
"spine",
"idea",
"brink",
"flourish",
"fling",
"confuse",
"bolt",
"relate",
"bind",
"lean",
"occasion",
"youth",
"reign",
"season",
"clock",
"shy",
"can",
"topple",
"tiptoe",
"frog",
"labour",
"item",
"liberal",
"grave",
"tone",
"knife",
"drill",
"dentist",
"roof",
"place",
"tumble",
"agony",
"torture",
"add",
"tournament",
"doll",
"dealer",
"myth",
"tread",
"transfer",
"transform",
"freight",
"fare",
"transport",
"rubbish",
"fly",
"swim",
"visit",
"rehabilitation",
"jury",
"triangle",
"victory",
"prize",
"gutter",
"truth",
"loyalty",
"vat",
"pipe",
"stomach",
"tumour",
"rotate",
"ivory",
"dozen",
"year",
"day",
"pair",
"couple",
"tropical",
"incredible",
"uncertainty",
"reveal",
"vague",
"spy",
"cave",
"underline",
"bottom",
"minimize",
"project",
"unlike",
"unique",
"surprise",
"discrimination",
"thaw",
"continuous",
"lesson",
"ton",
"consolidate",
"global",
"different",
"volunteer",
"artificial",
"live",
"dangerous",
"invisible",
"blind",
"rough",
"crisis",
"frozen",
"premature",
"strange",
"illness",
"unaware",
"folklore",
"promote",
"hilarious",
"nightmare",
"urgency",
"sweep",
"walk",
"mechanical",
"useful",
"sigh",
"threaten",
"vacuum",
"valley",
"evaluate",
"worth",
"disappear",
"variable",
"variant",
"broccoli",
"vegetable",
"van",
"rocket",
"embark",
"promise",
"poem",
"peak",
"bottle",
"veteran",
"neighborhood",
"winner",
"video",
"compete",
"wake",
"energy",
"active",
"ghost",
"sight",
"tourist",
"appearance",
"colorful",
"vision",
"singer",
"soprano",
"intention",
"book",
"election",
"ballot",
"exposure",
"bet",
"waist",
"queue",
"lounge",
"hike",
"stride",
"pedestrian",
"cane",
"deprivation",
"war",
"bird",
"guarantee",
"laundry",
"basin",
"password",
"fountain",
"stream",
"vessel",
"acid",
"fluctuation",
"method",
"lifestyle",
"gun",
"cry",
"valid",
"familiar",
"wagon",
"sniff",
"linen",
"extend",
"pigeon",
"wilderness",
"winter",
"hope",
"retirement",
"fade",
"express",
"feminine",
"feminist",
"forest",
"courtship",
"sheep",
"term",
"formulate",
"solve",
"employee",
"studio",
"decline",
"respectable",
"acceptable",
"misery",
"compose",
"wriggle",
"script",
"message",
"offender",
"sausage",
"photocopy",
"annual",
"scream",
"amber",
"calf",
"kid",
"boy",
"lamb",
"junior",
"young",
"breeze",
"earthflax",
"earthwax",
"earwax",
"eaux",
"econobox",
"efflux",
"embox",
"enfix",
"epicalyx",
"equinox",
"ex",
"executrix",
"quaint",
"tomorrow",
"nearest",
"cookies",
"born",
"stepped",
"fallen",
"together",
"threw",
"stove",
"such",
"yellow",
"nation",
"yesterday",
"whistle",
"longer",
"cloth",
"primitive",
"instead",
"feet",
"entire",
"setting",
"gave",
"layers",
"hardly",
"stone",
"teeth",
"driving",
"hidden",
"being",
"atom",
"rope",
"universe",
"birds",
"greatly",
"studying",
"slope",
"that",
"needs",
"wise",
"fully",
"apartment",
"getting",
"earlier",
"sold",
"what",
"lady",
"children",
"shorter",
"specific",
"until",
"interior",
"box",
"weather",
"travel",
"famous",
"stairs",
"cent",
"headed",
"income",
"afraid",
"forty",
"fact",
"nothing",
"announced",
"every",
"eventually",
"none",
"fairly",
"explanation",
"gone",
"shirt",
"military",
"biggest",
"hat",
"southern",
"there",
"parts",
"natural",
"feathers",
"though",
"sides",
"grew",
"completely",
"farther",
"rubber",
"anything",
"happy",
"local",
"eleven",
"worse",
"whale",
"would",
"blew",
"than",
"him",
"silly",
"tea",
"goose",
"out",
"something",
"dried",
"tobacco",
"hunt",
"from",
"plural",
"laid",
"everybody",
"observe",
"perhaps",
"partly",
"simplest",
"acres",
"chosen",
"hearing",
"might",
"nearly",
"chose",
"became",
"never",
"were",
"about",
"consonant",
"various",
"whom",
"scientific",
"author",
"alike",
"stiff",
"foreign",
"golden",
"shown",
"sets",
"hung",
"within",
"bone",
"should",
"happened",
"silent",
"whenever",
"frequently",
"has",
"exclaimed",
"swam",
"dirt",
"maybe",
"planned",
"tonight",
"too",
"earth",
"nobody",
"gulf",
"ants",
"furniture",
"somebody",
"graph",
"gently",
"depth",
"toy",
"per",
"any",
"bowl",
"here",
"drew",
"kids",
"further",
"earn",
"necessary",
"after",
"easily",
"floating",
"farm",
"excellent",
"deeply",
"into",
"yourself",
"correct",
"fought",
"importance",
"nuts",
"troops",
"eaten",
"massage",
"noon",
"whispered",
"bigger",
"highest",
"yes",
"porch",
"evidence",
"aside",
"noted",
"opportunity",
"kept",
"under",
"require",
"actual",
"ship",
"halfway",
"given",
"quietly",
"behind",
"empty",
"ten",
"flame",
"clothing",
"did",
"seven",
"adjective",
"grabbed",
"upper",
"alone",
"felt",
"suddenly",
"saddle",
"two",
"zipper",
"merely",
"signal",
"our",
"task",
"ran",
"event",
"believed",
"through",
"properly",
"ago",
"doing",
"skill",
"cost",
"made",
"caught",
"possibly",
"themselves",
"shinning",
"label",
"dust",
"mental",
"forgotten",
"began",
"sudden",
"tall",
"carefully",
"upward",
"independent",
"along",
"mysterious",
"gather",
"better",
"journey",
"son",
"both",
"oxygen",
"sent",
"anybody",
"beauty",
"failed",
"police",
"song",
"zulu",
"slight",
"over",
"cannot",
"could",
"flies",
"enough",
"everywhere",
"but",
"wore",
"connected",
"continued",
"must",
"mission",
"magnet",
"rhyme",
"rising",
"impossible",
"who",
"aloud",
"birth",
"thing",
"speak",
"men",
"exciting",
"tide",
"lying",
"same",
"slightly",
"everything",
"leaving",
"pond",
"modern",
"early",
"nor",
"particularly",
"anywhere",
"buried",
"drawn",
"sad",
"western",
"ate",
"town",
"nodded",
"neighbor",
"milk",
"shells",
"helpful",
"previous",
"motion",
"stood",
"fastened",
"search",
"extra",
"spent",
"above",
"brought",
"invented",
"donkey",
"stuck",
"instance",
"quickly",
"happily",
"magic",
"handle",
"married",
"gentle",
"remove",
"discussion",
"fort",
"toward",
"newspaper",
"swept",
"beyond",
"mice",
"obtain",
"more",
"pine",
"one",
"zebra",
"which",
"plus",
"torn",
"particles",
"perfectly",
"become",
"whatever",
"wrapped",
"exactly",
"bound",
"circus",
"angry",
"eight",
"clearly",
"fed",
"chamber",
"running",
"bright",
"compare",
"came",
"wish",
"secret",
"whose",
"pale",
"now",
"supper",
"forth",
"stared",
"music",
"equally",
"faster",
"fourth",
"among",
"her",
"herself",
"already",
"attached",
"each",
"claws",
"greater",
"nearby",
"itself",
"noun",
"riding",
"canal",
"living",
"led",
"pink",
"best",
"according",
"unknown",
"occur",
"ruler",
"laugh",
"typical",
"today",
"studied",
"said",
"liquid",
"darkness",
"brass",
"swimming",
"later",
"gradually",
"not",
"equipment",
"valuable",
"probably",
"life",
"continent",
"type",
"someone",
"myself",
"shaking",
"plates",
"steady",
"thus",
"phrase",
"around",
"blanket",
"vessels",
"vast",
"also",
"changing",
"lower",
"may",
"met",
"twenty",
"another",
"glad",
"rapidly",
"heard",
"dot",
"gray",
"curious",
"wet",
"verb",
"busy",
"successful",
"third",
"found",
"minerals",
"them",
"aboard",
"all",
"thy",
"wool",
"entirely",
"again",
"labor",
"substance",
"rod",
"rays",
"fell",
"amount",
"knew",
"leather",
"recall",
"chemical",
"ahead",
"mostly",
"onto",
"organization",
"introduced",
"customs",
"those",
"refused",
"actually",
"correctly",
"because",
"pet",
"fighting",
"declared",
"motor",
"greatest",
"least",
"success",
"hello",
"barn",
"these",
"buffalo",
"alphabet",
"zoo",
"join",
"very",
"butter",
"fifteen",
"since",
"breath",
"driven",
"putting",
"principal",
"alchemy",
"anarchy",
"anechoic",
"antenna",
"aurora",
"azure",
"balsam",
"bazaar",
"beloved",
"bliss",
"bravado",
"brimstone",
"cadence",
"cathode",
"caviar",
"chivalry",
"chutzpah",
"cobalt",
"cobbler",
"cobblestone",
"cognac",
"cynosure",
"daffodil",
"dandelion",
"decibel",
"dewdrop",
"diligence",
"edict",
"epicurean",
"equinox",
"ethereal",
"exodus",
"fjord",
"flair",
"flamboyant",
"flora",
"fluorescent",
"fractal",
"gossamer",
"guild",
"halcyon",
"hegemony",
"hemoglobin",
"hibernate",
"idiosyncrasy",
"igneous",
"incognito",
"infrastructure",
"jovial",
"jubilee",
"kinetic",
"kiosk",
"lagoon",
"lava",
"libertarian",
"lilac",
"lilt",
"maverick",
"medley",
"mesmerize",
"metropolis",
"miasma",
"mnemonic",
"mystic",
"nemeses",
"neutron",
"nirvana",
"noxious",
"oasis",
"omnipotent",
"opal",
"optimism",
"papyrus",
"paradox",
"phantom",
"phosphorescent",
"plutonium",
"poltroon",
"prism",
"quasar",
"quintessence",
"quixotic",
"rhapsody",
"serendipity",
"solstice",
"sonorous",
"spectrum",
"tachyon",
"terracotta",
"threnody",
"transcend",
"turquoise",
"ubiquitous",
"unicorn",
"vacuum",
"vortex",
"vivid",
"willow",
"wisdom",
"xenon",
"yin",
"yoga",
"zeitgeist",
"zephyr"
]
}
\ No newline at end of file
import json
import os
import random
import re
import shutil
from base64 import b64encode, b64decode
import cv2
import numpy as np
import regex as re2
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
import string
import random
def get_classes_impl(result, class_type, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
get_classes_impl(result, class_type, path_join)
elif os.path.isfile(path_join):
if os.path.splitext(i)[-1][1:] in class_type:
result.append(path_join)
def get_classes(class_type=None):
if class_type is None:
class_type = ["kt", "java"]
result = []
get_classes_impl(result, class_type)
return result
def find_text_impl(reg, result, skip_name, path, is_one):
listdir = os.listdir(path)
for i in listdir:
if is_one and len(result) > 0:
return
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
find_text_impl(reg, result, skip_name, path_join, is_one)
elif os.path.isfile(path_join):
if path.endswith('.') and i.split('.')[-1] in ['py']:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
findall = re.findall(reg, text)
if len(findall) > 0:
result.extend(findall)
def find_text(reg, path='.', is_one=False, skip_name=None):
if skip_name is None:
skip_name = []
result = []
if os.path.isdir(path):
find_text_impl(reg, result, skip_name, path, is_one)
else:
with open(path, 'r', encoding='utf-8') as f:
if f.readable():
try:
text = f.read()
findall = re.findall(reg, text)
if len(findall) > 0:
result.extend(findall)
except ValueError:
pass
if is_one:
if len(result) > 0:
return result[0]
else:
return None
return result
def find_file_impl(reg, result, skip_name, path='.'):
listdir = os.listdir(path)
for i in listdir:
if len(result) > 0:
return
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
find_file_impl(reg, result, skip_name, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and i not in ["pro"]:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
findall = re.findall(reg, text)
if len(findall) > 0:
result.append(path_join)
def find_file(reg, path='.', skip_name=None):
if skip_name is None:
skip_name = []
result = []
if os.path.isdir(path):
find_file_impl(reg, result, skip_name, path)
else:
with open(path, 'r', encoding='utf-8') as f:
if f.readable():
try:
text = f.read()
findall = re.findall(reg, text)
if len(findall) > 0:
result.append(path)
except ValueError:
pass
return result[0] if len(result) > 0 else ""
def get_class_path(path):
with open(path, 'r') as f:
text = f.read()
package = re.search('package (.*?)\\s', text).group(1)
name = os.path.basename(path)
name = name[:name.rfind('.')]
return package + '.' + name
def replace_map_text(mapping, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
replace_map_text(mapping, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
reverse = sorted(list(mapping.keys()), key=len, reverse=True)
for name in reverse:
text = text.replace(str(name), mapping[name])
f.write(text)
def sub_map_text(mapping, is_reverse=True, path='.', skip_type=None, skip_name=None):
if len(mapping) == 0:
return []
if skip_type is None:
skip_type = []
if skip_name is None:
skip_name = []
result = []
sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse, path)
return result
def sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse=True, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
sub_map_text_impl(mapping, result, skip_type, skip_name, is_reverse, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
if os.path.splitext(i)[-1][1:] in skip_type:
continue
is_skip = False
for j in skip_name:
if j in i:
is_skip = True
break
if is_skip:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
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)
if text_result != text:
result.append(path_join)
f.write(text_result)
def replace_text(old, new, path='.'):
listdir = os.listdir(path)
for i in listdir:
path_join = os.path.join(path, i)
if os.path.isdir(path_join):
if path.endswith('.') and i in ["build", "debug", "release"]:
continue
if path.endswith('src') and i in ["androidTest", "test"]:
continue
replace_text(old, new, path_join)
elif os.path.isfile(path_join):
if path.endswith('.') and os.path.splitext(i)[-1][1:] not in ["pro"]:
continue
with open(path_join, 'r', encoding='utf-8') as f:
if not f.readable():
continue
try:
text = f.read()
except ValueError:
continue
with open(path_join, 'w', encoding='utf-8') as f:
f.write(text.replace(old, new))
def get_random_package():
packages = [get_random_string(4) for _ in range(get_random_int(1, 3))]
return '.'.join(packages)
def check_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('dir', {})
packages = find_text('package (.*?)[;]?\\s', 'src')
packages.append(applicationId)
packages = sorted(set(packages), key=packages.index)
packages.sort(key=len)
mapping = {}
for i in packages:
if applicationId not in i:
continue
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_package()
value = mapping.get(i[:i.rfind('.')])
if value is not None:
mapping[i] = value + '.' + mapping[i]
loads["dir"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_class_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('class', {})
mapping = {}
classes = get_classes()
for i in classes:
if '_D' in i:
continue
name = os.path.basename(i)
name = name[:name.rfind('.')]
value = old_mapping.get(name)
if value is not None:
mapping[name] = value
continue
mapping[name] = get_title(get_random_string(4), True)
loads["class"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_type_ids_mapping(ids_type):
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get(ids_type + "_ids", {})
mapping = {}
type_ids = find_text('<' + ids_type + ' name="(.*?)".*?>', get_path('.\\src\\main\\res'))
for i in type_ids:
if i.endswith('_D'):
continue
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_string(5, False)
type_ids = find_text('<item name="(.*?)".*? type="' + ids_type + '">', get_path('.\\src\\main\\res'))
for i in type_ids:
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
mapping[i] = get_random_string(5, False)
if len(mapping) != 0:
loads[ids_type + "_ids"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_styleable_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get("styleable", {})
mapping = {}
styleables = find_text('<declare-styleable name=".*?">[\\s\\S]*?</declare-styleable>')
for i in styleables:
styleable_id = re.findall('<declare-styleable name="(.*?)">', i)[0]
mapping[styleable_id] = old_mapping.get(styleable_id, get_random_string(5, False))
styleables_attr = re.findall('<attr name="(.*?)".*?/>', i)
for attr in styleables_attr:
mapping[attr + '_A'] = old_mapping.get(attr + '_A', get_random_string(5))
if len(mapping) != 0:
loads["styleable"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_ids_type(ids_type):
type_ids_mapping = check_type_ids_mapping(ids_type)
if len(type_ids_mapping) == 0:
return
print(type_ids_mapping)
sub_map = {}
for i in type_ids_mapping:
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 + '(.*?) parent="' + i + '"(.*?)>'] = \
'<' + ids_type + '\\g<1> parent="' + type_ids_mapping[i] + '"\\g<2>>'
sub_map_text(sub_map)
def check_view_ids_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('view_ids', {})
view_ids = find_text('"\\@\\+id/(.*?)"', get_path('.\\src\\main\\res'))
for i in view_ids:
if i == 'root':
continue
key = get_title(i)
if mapping.get(key) is not None:
continue
mapping[key] = get_random_string(7)
loads["view_ids"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_layout_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('layout', {})
layout_path = get_path('.\\src\\main\\res\\layout')
listdir = os.listdir(layout_path)
for i in listdir:
name = i[:i.rfind('.')]
if mapping.get(name) is not None:
continue
mapping[name] = get_random_string(6)
loads["layout"] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def check_res_mapping(res_type):
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get(res_type, {})
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
if not i.startswith(res_type):
continue
for j in os.listdir(os.path.join(res_path, i)):
if j.startswith('book_'):
continue
if j.endswith('.9.png'):
name = j[:-len('.9.png')]
else:
name = j.rsplit('.', 1)[0]
if mapping.get(name) is not None:
continue
mapping[name] = get_random_string(8)
if len(mapping) != 0:
loads[res_type] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
used_words = set()
def get_random_string(length=8, is_ascii=True):
global used_words # 使用全局变量 used_words
words = load_words_from_file('word_file.json')
if words:
while words:
random_word = random.choice(words)
if random_word not in used_words:
used_words.add(random_word)
if is_ascii and all(ord(c) < 128 for c in random_word):
return random_word
elif not is_ascii:
return random_word
return None
def load_words_from_file(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data.get("word", []) # 返回单词列表
except FileNotFoundError:
print(f"Error: Word file not found at: {file_path}")
return []
except json.JSONDecodeError:
print(f"Error: Invalid JSON format in: {file_path}")
return []
def get_random_int(a=0, b=10000):
return random.randint(a, b)
def get_dictionary_string(length=10):
random_str = random.choice(string.ascii_letters)
random_str += ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length - 1))
return random_str
def check_obfuscation_dictionary():
if not os.path.exists('dictionary.txt'):
dictionary = set()
while len(dictionary) != 5000:
dictionary.add(get_dictionary_string())
with open('dictionary.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(dictionary))
with open('proguard-rules.pro', 'r', encoding='utf-8') as f:
text = f.read()
if '-obfuscationdictionary' in text:
return
text += '\n-obfuscationdictionary dictionary.txt'
text += '\n-classobfuscationdictionary dictionary.txt'
text += '\n-packageobfuscationdictionary dictionary.txt'
with open('proguard-rules.pro', 'w', encoding='utf-8') as f:
f.write(text)
def mkdir(dir_path):
try:
os.makedirs(dir_path)
except OSError:
pass
def replace_click_method():
try:
path = get_path('.\\src\\main\\java')
file = find_file('fun View.setTrackedOnClickListener', path)
if file:
class_path = get_class_path(file) + '.setTrackedOnClickListener'
# java类不能直接使用扩展函数
sub_map_text({
'([.@])setOnClickListener': '\\g<1>setTrackedOnClickListener',
}, path=path, skip_type=['java'])
add_import(class_path, get_classes(['kt']))
except IndexError:
return
def deal_code():
# 替换点击事件
replace_click_method()
# 生成包映射文件
mapping = check_mapping()
packages = list(mapping.keys())
print(mapping)
# 移动文件
root_path = get_path('.\\src\\main\\java')
for key in packages:
key = str(key)
old_path = get_path(root_path + '\\' + key.replace('.', '\\'))
new_path = get_path(root_path + '\\' + mapping[key].replace('.', '\\'))
if not os.path.exists(old_path):
mkdir(old_path)
if not os.path.exists(new_path):
mkdir(new_path)
listdir = os.listdir(old_path)
for i in listdir:
path_join = os.path.join(old_path, i)
if os.path.isdir(path_join):
continue
shutil.move(path_join, os.path.join(new_path, i))
shutil.rmtree(get_path(root_path + '\\' + applicationId[:applicationId.find('.')]))
# 修改manifest
with open(get_path('.\\src\\main\\AndroidManifest.xml'), 'r', encoding='utf-8') as f:
text = f.read()
findall = re.findall('android:name=(".*?")', text)
for i in findall:
if i.startswith('".'):
text = text.replace(i, '"' + applicationId + i[1:-1] + '"')
with open(get_path('.\\src\\main\\AndroidManifest.xml'), 'w', encoding='utf-8') as f:
f.write(text)
# 修改依赖
sub_map = {}
for i in mapping:
sub_map['(?<=\\W)' + i + '(?=\\W)'] = mapping[i]
# 过滤修改
sub_map['(?<=\\W)' + mapping[applicationId] + '.R(?=\\W)'] = applicationId + '.R'
sub_map['(?<=\\W)' + mapping[applicationId] + '.databinding(?=\\W)'] = applicationId + '.databinding'
sub_map['(?<=\\W)' + mapping[applicationId] + '.BuildConfig(?=\\W)'] = applicationId + '.BuildConfig'
sub_map_text(sub_map)
# 根包名下 R 单独处理
new_path = get_path(root_path + '\\' + mapping[packages[0]].replace('.', '\\'))
listdir = os.listdir(new_path)
result_path = []
for i in listdir:
if os.path.isdir(os.path.join(new_path, i)):
continue
result_path.append(os.path.join(new_path, i))
add_import(applicationId + '.R', result_path)
add_import(applicationId + '.BuildConfig', result_path)
# 类名
class_mapping = check_class_mapping()
classes = get_classes()
print(class_mapping)
for i in classes:
if '_D' in i:
continue
name = os.path.basename(i)
name = name[:name.rfind('.')]
shutil.move(i, i.replace(name, class_mapping[name]))
sub_map = {}
for i in class_mapping:
sub_map['(?<=\\W)' + i + '(?=\\W)'] = class_mapping[i]
sub_map_text(sub_map)
# 混淆字典
check_obfuscation_dictionary()
def deal_res_type(res_type):
type_mapping = check_res_mapping(res_type)
if len(type_mapping) == 0:
return
print(type_mapping)
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
if not i.startswith(res_type):
continue
path_join = os.path.join(res_path, i)
for j in os.listdir(path_join):
if j.startswith('book_'):
continue
if j.endswith('.9.png'):
name = j[:-len('.9.png')]
else:
name = j.rsplit('.', 1)[0]
path = os.path.join(path_join, j)
if '.DS_Store' not in path:
shutil.move(path, path.replace(name, type_mapping[name]))
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>'
sub_map_text(sub_map)
def add_image_noise(path):
try:
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
if path.endswith('.9.png'):
return
# 添加随机噪声
noise = np.random.randint(0, 2, image.shape, np.uint8)
image = cv2.add(image, noise)
new_path = path.rsplit('.', 1)[0] + '.webp'
cv2.imwrite(new_path, image, [cv2.IMWRITE_WEBP_QUALITY, 75])
if new_path != path:
os.remove(path)
except AttributeError:
return
def deal_image():
res_path = get_path('.\\src\\main\\res')
listdir = os.listdir(res_path)
for i in listdir:
path_join = os.path.join(res_path, i)
if os.path.isdir(path_join):
for j in os.listdir(path_join):
add_image_noise(os.path.join(path_join, j))
def get_title(string, is_all_upper=False):
splits = string.split('_')
s = ''
for i in range(len(splits)):
if i == 0 and not is_all_upper:
s = splits[i]
elif len(splits[i]) > 0:
s += splits[i][0].upper() + splits[i][1:]
return s
def add_import(path, listfile):
for i in listfile:
with open(i, 'r', encoding='utf-8') as f:
text = f.read()
if len(re.findall('import ' + path, text)) != 0:
continue
if i.endswith('kt'):
text = re.sub('(package \\S+?\\s+?)(?=\\S)', '\\g<1>import ' + path + '\n', text, flags=re.S)
elif i.endswith('java'):
text = re.sub('(package \\S+?\\s+?)(?=\\S)', '\\g<1>import ' + path + ';\n', text, flags=re.S)
with open(i, 'w', encoding='utf-8') as f:
f.write(text)
def check_class_string_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
mapping = loads.get('class_string', {})
classes = get_classes(['kt'])
for path in classes:
if os.path.basename(path).startswith('AESHelper'):
continue
with open(path, 'r', encoding='utf-8') as f:
text = f.read()
text = re.sub('@SuppressLint.*?\n', '\n', text)
text = re.sub('//[^"]*?(("[^"]*?){2})*?\n', '\n', text)
text = re.sub(' +\n', '\n', text)
text = re.sub('=\\s+', '= ', text)
text = re.sub(':\\s+', ': ', text)
text = re.sub(',\\s+', ', ', text)
text = re.sub('\n{2,}', '\n\n', text)
result_text = text
strings = re.findall('".*?[^\\\\]"', re.sub(r'@[^)]*', lambda x: x.group().replace('"', "'"), result_text))
last_string = ''
for string in strings:
if len(string) <= 4 or string.isspace() or \
string[1:-1] in ['\\\\n', '\\\\r', '\\\\\'', '\\\\\\"', '\\\\?', '&amp;', 'UTF-8']:
continue
if string in last_string:
continue
start = text.find(string)
if start == -1:
continue
index = start + 1
sign_stack = ['"']
while len(sign_stack) != 0:
if text[index] == '\\':
index += 1
elif text[index] == '"' and sign_stack[-1] == '"':
sign_stack.pop()
elif text[index] == '"':
sign_stack.append('"')
elif text[index] == '}' and sign_stack[-1] == '${':
sign_stack.pop()
elif text[index - 1:index + 1] == '${':
sign_stack.append('${')
index += 1
string = text[start:index]
last_string = string
params = []
result = string
if '$' in string:
count = 0
last = -1
res = []
for i in range(len(string)):
if last == -1 and string[i] == '$':
if count == 0:
last = i
elif last != -1:
if string[i] == '{':
count += 1
elif string[i] == '}':
count -= 1
if count == 0:
res.append((last, i + 1))
last = -1
elif count == 0:
last = -1
for i in re.findall('\\$\\w*', string):
if i == '$':
continue
find = string.find(i)
res.append((find, find + len(i)))
res = sorted(res, key=lambda l: l[0])
last_res = None
for i in res:
if last_res is not None and i[0] < last_res[1]:
continue
params.append(string[i[0]:i[1]])
last_res = i
for i in params:
result = result.replace(i, "[str]")
result = result[1:-1].replace('%', '%%').replace('\\\\', '\\').replace('[str]', '%s')
if mapping.get(result) is not None:
continue
mapping[result] = get_random_string(5, False) + '_D'
loads['class_string'] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_class_string():
# 获取映射
string_mapping = check_class_string_mapping()
print(string_mapping)
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'r', encoding='utf-8') as f:
text = f.read()
rfind = text.rfind('\n')
text_result = text[:rfind]
for i in string_mapping:
string = i
string = string.replace('&', '&amp;')
string = string.replace('?', '\\?')
string = string.replace('\'', '\\\'')
text_result += '\n <string name="' + string_mapping[i] + '" translatable="false">' + string + '</string>'
text_result += text[rfind:]
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'w', encoding='utf-8') as f:
f.write(text_result)
# 搜索 Int.string() 路径
file_path = find_file('fun Int.string', get_path('.\\src\\main\\java'))
class_path = get_class_path(file_path) + '.string' if file_path else ""
classes = get_classes(['kt'])
for path in classes:
# 跳过 AESHelper 类中的字符串,避免嵌套
if os.path.basename(path).startswith('AESHelper'):
continue
with open(path, 'r', encoding='utf-8') as f:
text = f.read()
text = re.sub('@SuppressLint.*?\n', '\n', text)
text = re.sub('//[^"]*?(("[^"]*?){2})*?\n', '\n', text)
text = re.sub(' +\n', '\n', text)
text = re.sub('=\\s+', '= ', text)
text = re.sub(':\\s+', ': ', text)
text = re.sub(',\\s+', ', ', text)
text = re.sub('\n{2,}', '\n\n', text)
result_text = text
strings = re.findall('".*?[^\\\\]"', re.sub(r'@[^)]*', lambda x: x.group().replace('"', "'"), result_text))
last_string = ''
for string in strings:
if len(string) <= 4 or string.isspace() or \
string[1:-1] in ['\\\\n', '\\\\r', '\\\\\'', '\\\\\\"', '\\\\?', '&amp;', 'UTF-8']:
continue
if string in last_string:
continue
start = text.find(string)
if start == -1:
continue
index = start + 1
sign_stack = ['"']
while len(sign_stack) != 0:
if text[index] == '\\':
index += 1
elif text[index] == '"' and sign_stack[-1] == '"':
sign_stack.pop()
elif text[index] == '"':
sign_stack.append('"')
elif text[index] == '}' and sign_stack[-1] == '${':
sign_stack.pop()
elif text[index - 1:index + 1] == '${':
sign_stack.append('${')
index += 1
# 得到完整字符串
string = text[start:index]
last_string = string
# 参数
params = []
result = string
# 处理字符串拼接
if '$' in string:
count = 0
last = -1
res = []
for i in range(len(string)):
if last == -1 and string[i] == '$':
if count == 0:
last = i
elif last != -1:
if string[i] == '{':
count += 1
elif string[i] == '}':
count -= 1
if count == 0:
res.append((last, i + 1))
last = -1
elif count == 0:
last = -1
for i in re.findall('\\$\\w*', string):
if i == '$':
continue
find = string.find(i)
res.append((find, find + len(i)))
res = sorted(res, key=lambda l: l[0])
last_res = None
for i in res:
if last_res is not None and i[0] < last_res[1]:
continue
params.append(string[i[0]:i[1]])
last_res = i
for i in params:
result = result.replace(i, "[str]")
for i in range(len(params)):
if params[i][1] == '{':
params[i] = params[i][2:-1]
else:
params[i] = params[i][1:]
# 每个参数加上 toString
params[i] = '(' + params[i] + ').toString()'
# 拼接部分替换为 %s
result = result[1:-1].replace('%', '%%').replace('\\\\', '\\').replace('[str]', '%s')
# 添加 Int.string() 方法引用
if class_path:
if len(re.findall('import ' + class_path, text)) == 0:
result_text = re.sub('(package \\S+?\\s+?)(?=\\S)',
'\\g<1>import ' + class_path + '\n', result_text, flags=re.S)
# 添加资源 R 引用
if len(re.findall('import ' + applicationId + '.R', text)) == 0:
result_text = re.sub('(package \\S+?\\s+?)(?=\\S)',
'\\g<1>import ' + applicationId + '.R' + '\n', result_text, flags=re.S)
# 去除 const
result_text = re.sub('const (val.*?R\\.string\\.\\S+?\\.string\\(\\))', '\\g<1>', result_text)
with open(path, 'w', encoding='utf-8') as f:
f.write(result_text)
def check_xml_string_mapping():
try:
loads = json.load(open('mapping.json', 'r', encoding='utf-8'))
except (ValueError, IOError):
loads = {}
old_mapping = loads.get('xml_string', {})
strings = find_text('android:text="(?<!@string/)([^@"]+?)"', get_path('.\\src\\main\\res\\layout'),
skip_name=['notify', 'notity'])
mapping = {}
for i in strings:
value = old_mapping.get(i)
if value is not None:
mapping[i] = value
continue
# 添加 '_D' 结尾,资源混淆时过滤不用再次改名
mapping[i] = get_random_string(5, False) + '_D'
loads['xml_string'] = mapping
json.dump(loads, open('mapping.json', 'w', encoding='utf-8'), indent=4)
return mapping
def deal_xml_string():
# 获取映射
string_mapping = check_xml_string_mapping()
print(string_mapping)
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'r', encoding='utf-8') as f:
text = f.read()
rfind = text.rfind('\n')
text_result = text[:rfind]
for i in string_mapping:
string = i
string = string.replace('&', '&amp;')
string = string.replace('?', '\\?')
string = string.replace('\'', '\\\'')
text_result += '\n <string name="' + string_mapping[i] + '" translatable="false">' + string + '</string>'
text_result += text[rfind:]
with open(get_path('.\\src\\main\\res\\values\\strings.xml'), 'w', encoding='utf-8') as f:
f.write(text_result)
sub_map = {}
for i in string_mapping:
sub_map['(?<=android:text=")' + re.escape(i) + '(?=")'] = '@string/' + re.escape(string_mapping[i])
# 替换时跳过通知布局
sub_map_text(sub_map, path=get_path('.\\src\\main\\res\\layout'), skip_name=['notify', 'notity'])
def deal_code_string():
# 处理布局文件中的明文字符串
deal_xml_string()
# 处理代码文件中的明文字符串
deal_class_string()
def deal_res():
# 改 string id
deal_ids_type('string')
# 改 color id
deal_ids_type('color')
# 改 dimen id
deal_ids_type('dimen')
# 改 style id
deal_ids_type('style')
# 改 declare-styleable
styleable_mapping = check_styleable_mapping()
print(styleable_mapping)
sub_map = {}
styleables = find_text('<declare-styleable name=".*?">[\\s\\S]*?</declare-styleable>')
for i in styleables:
result = i
styleable_id = re.findall('<declare-styleable name="(.*?)">', i)[0]
result = result.replace('<declare-styleable name="' + styleable_id + '">',
'<declare-styleable name="' + styleable_mapping[styleable_id] + '">')
sub_map['R\\.styleable\\.' + styleable_id + '(\\W)'] = \
'R.styleable.' + styleable_mapping[styleable_id] + '\\g<1>'
styleables_attr = re.findall('<attr name="(.*?)".*?/>', i)
for attr in styleables_attr:
result = result.replace('<attr name="' + attr + '"', '<attr name="' + styleable_mapping[attr + '_A'] + '"')
sub_map['R\\.styleable\\.' + styleable_id + '_' + attr + '(\\W)'] = \
'R.styleable.' + styleable_mapping[styleable_id] + '_' + styleable_mapping[attr + '_A'] + '\\g<1>'
sub_map['app:' + attr + '='] = 'app:' + styleable_mapping[attr + '_A'] + '='
sub_map[re.escape(i)] = result
sub_map_text(sub_map)
# 改 view id
view_ids = find_text('"\\@\\+id/(.*?)"', get_path('.\\src\\main\\res'))
view_ids_mapping = check_view_ids_mapping()
print(view_ids_mapping)
sub_map = {}
for i in view_ids:
if i == 'root':
continue
key = get_title(i)
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['(?<=app:constraint_referenced_ids=".*?)' + i + '(?=.*?")'] = view_ids_mapping[key]
sub_map_text(sub_map)
# 改 layout 文件名
layout_mapping = check_layout_mapping()
print(layout_mapping)
layout_path = get_path('.\\src\\main\\res\\layout')
listdir = os.listdir(layout_path)
for i in listdir:
name = i[:i.rfind('.')]
if layout_mapping.get(name) is None:
continue
path_join = os.path.join(layout_path, i)
shutil.move(path_join, path_join.replace(name, layout_mapping[name]))
sub_map = {}
for i in layout_mapping:
sub_map['R\\.layout\\.' + i + '(\\W)'] = 'R.layout.' + layout_mapping[i] + '\\g<1>'
# ViewBinding 同步修改
sub_map[get_title(i, True) + 'Binding'] = get_title(layout_mapping[i], True) + 'Binding'
sub_map['(>|")@layout/' + i + '(<|")'] = '\\g<1>@layout/' + layout_mapping[i] + '\\g<2>'
sub_map_text(sub_map)
# 改 drawable 文件名
deal_res_type('drawable')
# 改 mipmap 文件名
deal_res_type('mipmap')
# 改 raw 文件名
deal_res_type('raw')
# 改 raw 文件名
deal_res_type('xml')
# 改图片内容
deal_image()
def get_path(path):
paths = path.split('\\')
return str(os.path.join(*paths))
def main():
if not os.path.exists(get_path('.\\src\\main\\java\\' + applicationId[:applicationId.find('.')])):
return
# 资源混淆
deal_res()
deal_code()
if __name__ == '__main__':
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 文件')
applicationId = re.search('applicationId .*?["\'](.*?)["\']', open(gradle_path, 'r', encoding='utf-8').read())[1]
main()
{
"word": [
"zero",
"midnight",
"yard",
"volume",
"boat",
"belly",
"demand",
"intelligence",
"literacy",
"voice",
"miserable",
"free",
"growth",
"residence",
"apathy",
"majority",
"fast",
"outline",
"degree",
"emphasis",
"positive",
"achieve",
"achievement",
"agreement",
"history",
"account",
"recognize",
"accumulation",
"experience",
"charge",
"star",
"hurt",
"black",
"admit",
"concede",
"admission",
"thanks",
"receipt",
"friend",
"get",
"bitter",
"delay",
"stimulation",
"exchange",
"deal",
"favour",
"performance",
"production",
"jest",
"play",
"activity",
"solo",
"player",
"cast",
"real",
"advertising",
"version",
"dependence",
"addition",
"speech",
"facility",
"stick",
"formal",
"orthodox",
"glue",
"plaster",
"tape",
"poison",
"council",
"division",
"executive",
"confession",
"include",
"warning",
"teenager",
"acceptance",
"woman",
"man",
"notice",
"progress",
"lead",
"opponent",
"hardship",
"adviser",
"revolutionary",
"function",
"affair",
"attachment",
"association",
"statement",
"open",
"tissue",
"collection",
"hostility",
"fan",
"shake",
"excitement",
"consensus",
"peasant",
"help",
"support",
"object",
"wind",
"broadcast",
"cabin",
"pilot",
"wing",
"plane",
"alarm",
"beer",
"alcohol",
"consciousness",
"excuse",
"extraterrestrial",
"foreigner",
"similar",
"commitment",
"bond",
"comprehensive",
"allocation",
"compromise",
"lonely",
"distance",
"directory",
"index",
"change",
"height",
"aluminium",
"graduate",
"romantic",
"atmosphere",
"dream",
"ambition",
"shell",
"pardon",
"quantity",
"figure",
"supply",
"speed",
"entertainment",
"game",
"funny",
"parallel",
"ancestor",
"fox",
"animal",
"ankle",
"birthday",
"note",
"program",
"bother",
"response",
"expect",
"expectation",
"restless",
"anxiety",
"share",
"factor",
"flat",
"stroke",
"clothes",
"attract",
"sympathetic",
"appeal",
"seem",
"debut",
"look",
"texture",
"convenience",
"engineer",
"rub",
"paint",
"general",
"date",
"assessment",
"estimate",
"arrest",
"permission",
"spider",
"random",
"wall",
"archive",
"arch",
"fire",
"room",
"argument",
"line",
"desert",
"rise",
"weapon",
"sleeve",
"tank",
"smell",
"garlic",
"tease",
"move",
"provoke",
"moving",
"pack",
"row",
"timetable",
"bow",
"gallery",
"reservoir",
"craftsman",
"painter",
"art",
"silver",
"beg",
"invite",
"view",
"attack",
"battery",
"assembly",
"claim",
"selection",
"astonishing",
"far",
"forward",
"runner",
"sport",
"front",
"nuclear",
"tin",
"monstrous",
"strike",
"effort",
"serve",
"care",
"costume",
"culture",
"lawyer",
"draw",
"cute",
"attraction",
"property",
"gold",
"auction",
"sound",
"sign",
"aunt",
"writer",
"command",
"regulation",
"government",
"car",
"bus",
"robot",
"transmission",
"motorist",
"fall",
"supplementary",
"common",
"conscious",
"axis",
"baby",
"carriage",
"nursery",
"heel",
"withdrawal",
"suitcase",
"sphere",
"vote",
"trivial",
"patch",
"band",
"slam",
"deposit",
"failure",
"feast",
"banish",
"tycoon",
"drum",
"fence",
"bar",
"trade",
"basis",
"baseball",
"wrong",
"rational",
"democratic",
"cellar",
"essential",
"infrastructure",
"introduction",
"cell",
"principle",
"foundation",
"club",
"bathtub",
"bathroom",
"wash",
"battlefield",
"resist",
"represent",
"oppose",
"suit",
"know",
"trail",
"ride",
"depend",
"dare",
"differ",
"match",
"like",
"dominate",
"love",
"owe",
"mind",
"run",
"belong",
"beat",
"host",
"win",
"lack",
"worry",
"drop",
"bill",
"kidney",
"carry",
"testify",
"hold",
"stand",
"posture",
"presence",
"rhythm",
"scramble",
"grace",
"salon",
"wave",
"increase",
"conceive",
"deteriorate",
"sheet",
"friendly",
"start",
"source",
"captivate",
"low",
"absent",
"present",
"critical",
"opposed",
"hot",
"outer",
"salvation",
"late",
"swallow",
"think",
"roar",
"noble",
"left",
"bad",
"flex",
"turn",
"curve",
"flexible",
"good",
"advantage",
"hook",
"leave",
"mourning",
"shoulder",
"siege",
"engagement",
"improve",
"coffee",
"wine",
"drink",
"prejudice",
"bike",
"offer",
"large",
"contract",
"duck",
"turkey",
"call",
"delivery",
"pill",
"morsel",
"chip",
"snack",
"sting",
"burn",
"sword",
"space",
"cover",
"blast",
"combine",
"approval",
"pest",
"flash",
"obstacle",
"brick",
"forget",
"slab",
"vein",
"mosquito",
"inflate",
"punch",
"depressed",
"blue",
"flush",
"heart",
"muscle",
"scale",
"mass",
"constituency",
"lake",
"appendix",
"flesh",
"guard",
"kettle",
"steam",
"cheek",
"bomb",
"sandwich",
"rib",
"tooth",
"dividend",
"horn",
"album",
"notebook",
"prosper",
"stall",
"loot",
"dull",
"adopt",
"breast",
"cap",
"base",
"avenue",
"end",
"border",
"reward",
"cow",
"stadium",
"ring",
"electronics",
"courage",
"toast",
"bread",
"width",
"shatter",
"smash",
"cereal",
"discovery",
"hiccup",
"rest",
"corruption",
"workshop",
"bulletin",
"summary",
"glimpse",
"light",
"brilliance",
"lip",
"prosecute",
"bring",
"generate",
"introduce",
"create",
"organize",
"publish",
"disclose",
"update",
"take",
"glass",
"spectrum",
"reception",
"leaflet",
"fragment",
"brother",
"eyebrow",
"review",
"cruel",
"champagne",
"garage",
"center",
"architecture",
"displace",
"roll",
"cluster",
"nerve",
"cottage",
"nonsense",
"load",
"rabbit",
"pop",
"split",
"operation",
"office",
"counter",
"agency",
"burst",
"fuss",
"buttocks",
"cigarette",
"traffic",
"carbon",
"taxi",
"conspiracy",
"corpse",
"disaster",
"multiply",
"month",
"week",
"request",
"cancel",
"predict",
"card",
"career",
"calm",
"crusade",
"candidate",
"frank",
"wolf",
"sail",
"canvas",
"ceiling",
"able",
"content",
"memory",
"capital",
"execution",
"impulse",
"legend",
"prisoner",
"treat",
"consideration",
"shark",
"wrist",
"sketch",
"waterfall",
"precedent",
"advance",
"register",
"barrel",
"coffin",
"hurl",
"catalogue",
"capture",
"bracket",
"nap",
"ranch",
"white",
"cause",
"nature",
"kill",
"offend",
"pour",
"pit",
"crash",
"fame",
"planet",
"orbit",
"paper",
"penny",
"core",
"headquarters",
"wheat",
"hemisphere",
"ceremony",
"parade",
"funeral",
"license",
"neck",
"straw",
"necklace",
"throne",
"president",
"champion",
"title",
"reform",
"convert",
"freeze",
"role",
"feature",
"provincial",
"hostile",
"systematic",
"poor",
"loud",
"plot",
"chase",
"talkative",
"check",
"cheque",
"urge",
"compound",
"element",
"reaction",
"chemistry",
"king",
"chest",
"main",
"head",
"adoption",
"chorus",
"chop",
"helicopter",
"watch",
"lump",
"church",
"slide",
"film",
"round",
"condition",
"reference",
"quote",
"orange",
"block",
"mayor",
"tribe",
"applaud",
"bang",
"confrontation",
"mud",
"pottery",
"soap",
"clarify",
"acquit",
"cut",
"crack",
"mercy",
"fist",
"bishop",
"clerk",
"smart",
"tick",
"snap",
"customer",
"climb",
"climate",
"cutting",
"time",
"close",
"contact",
"cupboard",
"dress",
"overall",
"belt",
"fool",
"seize",
"train",
"coalition",
"harsh",
"coat",
"code",
"contemporary",
"generation",
"cafe",
"proof",
"knowledge",
"belief",
"judgment",
"laser",
"curl",
"snub",
"fish",
"cold",
"cooperate",
"give",
"tent",
"raise",
"wardrobe",
"settlement",
"rainbow",
"mosaic",
"chord",
"land",
"confront",
"enter",
"appear",
"discover",
"bait",
"comfort",
"comfortable",
"leader",
"memorial",
"recommend",
"transaction",
"business",
"commerce",
"market",
"committee",
"board",
"sense",
"park",
"infect",
"write",
"network",
"compact",
"company",
"pity",
"remunerate",
"competence",
"plaintiff",
"finish",
"perfect",
"complication",
"complex",
"follow",
"module",
"behave",
"constitution",
"understand",
"squeeze",
"accountant",
"calculation",
"hardware",
"menu",
"mouse",
"computing",
"software",
"computer",
"hide",
"design",
"imagine",
"notion",
"concept",
"embryo",
"practical",
"applied",
"sacred",
"personal",
"domestic",
"definition",
"last",
"harmony",
"coincide",
"terms",
"freedom",
"danger",
"improvement",
"behavior",
"experiment",
"director",
"south",
"federation",
"trust",
"constellation",
"impound",
"battle",
"fit",
"adjust",
"standard",
"normal",
"compliance",
"praise",
"representative",
"link",
"related",
"node",
"draft",
"sanctuary",
"agree",
"product",
"effect",
"doubt",
"courtesy",
"thoughtful",
"tight",
"structure",
"use",
"infection",
"bin",
"cassette",
"full",
"pollution",
"competition",
"satisfaction",
"race",
"circumstance",
"Europe",
"pupil",
"deny",
"contradiction",
"joystick",
"recovery",
"rule",
"transition",
"convince",
"vehicle",
"sentence",
"fabricate",
"biscuit",
"herb",
"oil",
"pan",
"pot",
"cage",
"partnership",
"cooperative",
"policeman",
"hospitality",
"cord",
"right",
"discipline",
"decorative",
"makeup",
"price",
"clique",
"cotton",
"sofa",
"matter",
"mole",
"offset",
"poll",
"coup",
"voucher",
"brave",
"seminar",
"credit",
"course",
"curriculum",
"direction",
"warrant",
"polite",
"court",
"designer",
"bloody",
"jealous",
"colleague",
"cattle",
"gap",
"wisecrack",
"cunning",
"craft",
"crackpot",
"crevice",
"rotten",
"appetite",
"creep",
"fold",
"creation",
"artist",
"thinker",
"literature",
"credibility",
"creed",
"sailor",
"prosecution",
"record",
"criticism",
"crosswalk",
"bend",
"collapse",
"squash",
"gravel",
"copper",
"snuggle",
"clue",
"cucumber",
"ethnic",
"mug",
"cabinet",
"cup",
"remedy",
"suppress",
"heal",
"lock",
"money",
"damn",
"swear",
"pillow",
"convention",
"tradition",
"reduce",
"amputate",
"crop",
"carve",
"skin",
"fork",
"sale",
"pat",
"sunrise",
"dairy",
"total",
"ballet",
"navy",
"dark",
"favourite",
"style",
"file",
"track",
"dawn",
"anniversary",
"holiday",
"fog",
"shock",
"body",
"hand",
"lot",
"franchise",
"shortage",
"consider",
"expose",
"behead",
"death",
"betray",
"decade",
"resolution",
"classify",
"refuse",
"recession",
"descent",
"decay",
"medal",
"reduction",
"order",
"devote",
"profound",
"well",
"carrot",
"coma",
"nonremittal",
"fault",
"lemon",
"payment",
"temperature",
"quality",
"god",
"extension",
"censorship",
"debate",
"lace",
"tasty",
"pleasure",
"please",
"pleasant",
"preach",
"rescue",
"challenge",
"limit",
"demonstration",
"destruction",
"thick",
"density",
"reliable",
"describe",
"subject",
"exile",
"bank",
"depression",
"rob",
"commission",
"lineage",
"origin",
"integration",
"merit",
"motif",
"plan",
"functional",
"architect",
"want",
"despair",
"sweet",
"fate",
"point",
"confine",
"custody",
"discourage",
"weigh",
"decisive",
"hate",
"explode",
"explosion",
"modernize",
"abnormal",
"instrument",
"filter",
"crown",
"dialogue",
"negotiation",
"journal",
"drown",
"diet",
"disagree",
"mess",
"difficulty",
"excavation",
"industry",
"proportion",
"decrease",
"diplomatic",
"management",
"manager",
"soil",
"disability",
"denial",
"unpleasant",
"separation",
"disk",
"dump",
"study",
"negative",
"stop",
"disco",
"offense",
"find",
"incongruous",
"digital",
"consultation",
"treatment",
"contempt",
"spirit",
"mask",
"pie",
"dish",
"disorder",
"chart",
"quarrel",
"difference",
"neglect",
"dismiss",
"joint",
"undress",
"interrupt",
"disturbance",
"disagreement",
"thesis",
"deter",
"mile",
"aloof",
"trait",
"characteristic",
"spread",
"circulate",
"quarter",
"upset",
"trench",
"butterfly",
"variety",
"deviation",
"even",
"harm",
"work",
"doctor",
"philosophy",
"charter",
"pound",
"dollar",
"goat",
"dog",
"chicken",
"cultivate",
"control",
"contribution",
"gate",
"bell",
"threshold",
"dorm",
"drug",
"image",
"ruin",
"drain",
"opera",
"drama",
"theater",
"curtain",
"pull",
"tap",
"tie",
"diagram",
"fear",
"awful",
"sip",
"dribble",
"drive",
"quit",
"heroin",
"user",
"rehearsal",
"east",
"north",
"west",
"ditch",
"repeat",
"length",
"twilight",
"responsibility",
"obligation",
"house",
"home",
"dynamic",
"past",
"mail",
"world",
"pole",
"relief",
"relaxation",
"accessible",
"tender",
"distinct",
"handy",
"restaurant",
"aid",
"economist",
"boom",
"economics",
"economy",
"value",
"margin",
"bean",
"onion",
"corn",
"building",
"school",
"influence",
"effective",
"egg",
"self",
"ego",
"hip",
"elbow",
"old",
"choose",
"voter",
"current",
"electron",
"hill",
"lift",
"elite",
"banana",
"articulate",
"flag",
"eagle",
"utter",
"glow",
"sentiment",
"pain",
"stress",
"conglomerate",
"empirical",
"authorise",
"blank",
"clear",
"brain",
"witch",
"surround",
"frame",
"meeting",
"favorable",
"invasion",
"restrain",
"settle",
"output",
"acute",
"conclusion",
"terminal",
"survival",
"opposition",
"fuel",
"wrap",
"wrestle",
"mastermind",
"technology",
"concentration",
"enjoy",
"indulge",
"expansion",
"soldier",
"registration",
"plead",
"penetrate",
"tempt",
"temptation",
"solid",
"burial",
"entry",
"access",
"ticket",
"twist",
"environment",
"era",
"balance",
"breakdown",
"just",
"ambiguous",
"ambiguity",
"delete",
"error",
"intensify",
"adventure",
"flight",
"leak",
"perfume",
"habit",
"institution",
"admiration",
"respect",
"evening",
"incident",
"trouble",
"eternal",
"estate",
"grounds",
"contrary",
"test",
"screen",
"inspector",
"mine",
"exclude",
"fat",
"sell",
"redeem",
"correspond",
"correspondence",
"proclaim",
"exclusive",
"monopoly",
"justify",
"example",
"illustrate",
"practice",
"dominant",
"exercise",
"press",
"show",
"display",
"museum",
"emergency",
"elaborate",
"area",
"anticipation",
"prospect",
"eject",
"spend",
"feel",
"authority",
"expertise",
"reason",
"explain",
"remark",
"graphic",
"exhibition",
"complain",
"explicit",
"apology",
"highway",
"delicate",
"reach",
"society",
"surface",
"outside",
"blackmail",
"deport",
"galaxy",
"glasses",
"lid",
"silk",
"material",
"manufacture",
"side",
"grimace",
"aspect",
"beard",
"fax",
"parameter",
"observation",
"attention",
"fairy",
"miss",
"overlook",
"lose",
"weakness",
"absence",
"sunshine",
"forge",
"illusion",
"distort",
"acquaintance",
"kinship",
"crystal",
"agriculture",
"model",
"trick",
"secure",
"screw",
"knot",
"cream",
"tired",
"blame",
"prefer",
"progressive",
"cower",
"concern",
"bold",
"viable",
"banquet",
"agent",
"toll",
"desire",
"unrest",
"confidence",
"proud",
"cat",
"criminal",
"hen",
"girl",
"bitch",
"queen",
"mother",
"iron",
"ferry",
"conception",
"celebration",
"story",
"fibre",
"character",
"novel",
"fight",
"stuff",
"fill",
"occupy",
"movie",
"producer",
"fund",
"treasurer",
"convict",
"clay",
"powder",
"sand",
"thumb",
"fastidious",
"particular",
"goal",
"fireplace",
"shoot",
"rifle",
"firefighter",
"strong",
"cousin",
"initial",
"beginning",
"initiative",
"freshman",
"financial",
"salmon",
"aquarium",
"fisherman",
"healthy",
"equip",
"convulsion",
"scene",
"cook",
"fee",
"interest",
"tile",
"meat",
"steward",
"toss",
"deck",
"level",
"stun",
"floor",
"vegetation",
"plant",
"dough",
"spill",
"lily",
"variation",
"chimney",
"soar",
"concentrate",
"family",
"folk",
"conventional",
"second",
"cheese",
"grain",
"salad",
"cheat",
"reckless",
"football",
"trace",
"marathon",
"step",
"boot",
"offensive",
"raid",
"patience",
"power",
"camp",
"impact",
"force",
"exotic",
"chief",
"deer",
"prevent",
"branch",
"spin",
"shape",
"ball",
"format",
"abandon",
"strength",
"castle",
"accident",
"coal",
"spring",
"wheel",
"skeleton",
"rack",
"hotdog",
"fraud",
"monster",
"relieve",
"straight",
"safe",
"clean",
"dry",
"pure",
"weight",
"exempt",
"release",
"liberty",
"halt",
"frequency",
"original",
"clash",
"refrigerator",
"ally",
"warm",
"terrify",
"medieval",
"facade",
"ice",
"cherry",
"apple",
"defeat",
"foot",
"smoke",
"official",
"mushroom",
"mold",
"desk",
"seat",
"lamp",
"rage",
"joke",
"choke",
"profit",
"make",
"gallon",
"risk",
"net",
"score",
"top",
"gas",
"meet",
"homosexual",
"regard",
"gear",
"jelly",
"diamond",
"jewel",
"gem",
"sex",
"category",
"health",
"productive",
"mutation",
"genetic",
"exploration",
"zone",
"circle",
"escape",
"cope",
"age",
"abolish",
"eliminate",
"master",
"arise",
"outfit",
"ghostwriter",
"charity",
"talented",
"daughter",
"bless",
"define",
"perform",
"pay",
"distribute",
"thank",
"spare",
"resignation",
"secretion",
"marble",
"glance",
"shine",
"gloom",
"glare",
"frown",
"sticky",
"sink",
"retire",
"happen",
"accompany",
"pass",
"fail",
"goalkeeper",
"departure",
"golf",
"peanut",
"charm",
"bloodshed",
"overeat",
"extort",
"ministry",
"minister",
"gradient",
"mark",
"drift",
"rice",
"grandfather",
"grandmother",
"grip",
"hay",
"scrape",
"tip",
"gravity",
"cemetery",
"major",
"high",
"produce",
"green",
"welcome",
"grudge",
"mill",
"traction",
"army",
"background",
"cooperation",
"flock",
"herd",
"organisation",
"fleet",
"troop",
"adult",
"development",
"ensure",
"defend",
"hypothesis",
"direct",
"guide",
"guideline",
"guilt",
"innocent",
"taste",
"water",
"inhabitant",
"haircut",
"hall",
"hammer",
"basket",
"manual",
"cart",
"umbrella",
"glove",
"hang",
"yearn",
"coincidence",
"difficult",
"cash",
"wood",
"nut",
"damage",
"collar",
"harvest",
"harass",
"rush",
"have",
"wear",
"dine",
"afford",
"brown",
"sour",
"steep",
"smooth",
"sharp",
"sensitive",
"complete",
"square",
"deep",
"weak",
"infinite",
"mature",
"meadow",
"veil",
"governor",
"helmet",
"clearance",
"therapist",
"pile",
"listen",
"rumor",
"grief",
"heat",
"responsible",
"service",
"portion",
"dome",
"moment",
"future",
"reluctance",
"retreat",
"fever",
"highlight",
"extreme",
"handicap",
"interference",
"employ",
"slap",
"pawn",
"pig",
"keep",
"resort",
"tube",
"bubble",
"excavate",
"habitat",
"housewife",
"honor",
"addicted",
"tire",
"basketball",
"platform",
"ward",
"inn",
"enemy",
"firm",
"hut",
"hour",
"husband",
"color",
"embrace",
"giant",
"act",
"face",
"arm",
"humanity",
"comedy",
"hunting",
"safari",
"hunter",
"suffer",
"injury",
"suffering",
"cross",
"theory",
"preoccupation",
"identity",
"identification",
"dialect",
"lighter",
"sick",
"unlawful",
"notorious",
"fantasy",
"projection",
"picture",
"copy",
"huge",
"exemption",
"affect",
"spoil",
"fair",
"jungle",
"pressure",
"flawed",
"temporary",
"tool",
"brush",
"issue",
"jail",
"unlikely",
"momentum",
"tense",
"regular",
"unanimous",
"accurate",
"central",
"inch",
"passive",
"still",
"dead",
"helpless",
"tendency",
"whole",
"conflict",
"incapable",
"contain",
"few",
"insurance",
"bay",
"separate",
"needle",
"need",
"person",
"morale",
"single",
"lazy",
"incentive",
"splurge",
"cheap",
"implicit",
"childish",
"virus",
"hell",
"hospital",
"determine",
"flu",
"information",
"recording",
"rare",
"violation",
"consumption",
"monk",
"instinct",
"heir",
"first",
"shot",
"pioneer",
"inquiry",
"ask",
"question",
"dedicate",
"bee",
"indoor",
"insistence",
"fresh",
"establish",
"episode",
"exception",
"college",
"teach",
"lecture",
"education",
"teacher",
"means",
"deficiency",
"abuse",
"coverage",
"policy",
"premium",
"guerrilla",
"rebel",
"rebellion",
"unity",
"news",
"mean",
"purpose",
"intervention",
"inside",
"middle",
"medium",
"translate",
"read",
"spokesperson",
"crossing",
"period",
"bowel",
"fascinate",
"suspicion",
"feeling",
"flood",
"innovation",
"stock",
"reverse",
"speculate",
"detective",
"investment",
"guest",
"physical",
"anger",
"publication",
"exit",
"loop",
"twitch",
"appointment",
"athlete",
"reporter",
"voyage",
"joy",
"litigation",
"parachute",
"judicial",
"law",
"judge",
"justice",
"deprive",
"discreet",
"piano",
"child",
"calorie",
"favor",
"lion",
"affinity",
"oven",
"knee",
"stab",
"horse",
"sweater",
"experienced",
"laboratory",
"union",
"maze",
"ignorance",
"ignorant",
"shallow",
"bald",
"soft",
"bare",
"girlfriend",
"secular",
"island",
"site",
"ground",
"landowner",
"name",
"lick",
"theft",
"cathedral",
"tiger",
"great",
"river",
"crowd",
"stage",
"range",
"pumpkin",
"whip",
"endure",
"permanent",
"tension",
"fashion",
"crime",
"grass",
"save",
"store",
"leadership",
"blade",
"leaf",
"thin",
"jump",
"academy",
"resign",
"farewell",
"depart",
"talk",
"leftovers",
"action",
"trustee",
"liability",
"opinion",
"jurisdiction",
"trial",
"verdict",
"key",
"legislation",
"legislature",
"continuation",
"wound",
"minor",
"disappoint",
"disappointment",
"deadly",
"letter",
"hover",
"dictionary",
"licence",
"lie",
"biography",
"revoke",
"beam",
"bulb",
"pastel",
"ignite",
"blonde",
"equal",
"restrict",
"diameter",
"column",
"language",
"context",
"connection",
"soup",
"eavesdrop",
"torch",
"essay",
"fiction",
"small",
"alive",
"accept",
"enthusiasm",
"resident",
"social",
"lend",
"engine",
"housing",
"attic",
"log",
"implication",
"linger",
"strip",
"ridge",
"shaft",
"bench",
"monkey",
"admire",
"relax",
"misplace",
"sacrifice",
"drawing",
"speaker",
"chin",
"minimum",
"fortune",
"chance",
"trunk",
"timber",
"lunch",
"thrust",
"grand",
"intermediate",
"machinery",
"spell",
"enlarge",
"dimension",
"maid",
"post",
"brand",
"reproduce",
"deliver",
"impress",
"guess",
"activate",
"bark",
"enhance",
"weave",
"amuse",
"obscure",
"touch",
"revise",
"develop",
"knit",
"reconcile",
"decide",
"widen",
"presentation",
"father",
"spite",
"cancer",
"mistreat",
"finance",
"exploit",
"falsify",
"laborer",
"construct",
"demonstrate",
"march",
"seal",
"wild",
"seller",
"distributor",
"proposal",
"wedding",
"marriage",
"wife",
"marsh",
"wonder",
"communist",
"grind",
"rally",
"glacier",
"domination",
"chew",
"concrete",
"plastic",
"mathematics",
"equation",
"grow",
"maximum",
"buffet",
"way",
"qualify",
"measure",
"beef",
"pump",
"dressing",
"clinic",
"medicine",
"specimen",
"symptom",
"see",
"conference",
"qualified",
"theme",
"tune",
"partner",
"citizen",
"memorandum",
"learn",
"crew",
"threat",
"attitude",
"outlook",
"refer",
"merchant",
"freighter",
"cruelty",
"deserve",
"fun",
"hypnothize",
"steel",
"wire",
"metal",
"subway",
"city",
"microphone",
"bomber",
"campaign",
"occupation",
"factory",
"minute",
"aware",
"miner",
"mislead",
"distortion",
"mixture",
"cake",
"air",
"solution",
"confusion",
"groan",
"pattern",
"mild",
"routine",
"empire",
"abbey",
"grant",
"coin",
"allowance",
"debt",
"virtue",
"ethics",
"integrity",
"morning",
"breakfast",
"gesture",
"movement",
"motivation",
"motorcycle",
"truck",
"slogan",
"mountain",
"volcano",
"of",
"at",
"if",
"no",
"my",
"me",
"to",
"be",
"so",
"we",
"he",
"by",
"on",
"up",
"am",
"us",
"stir",
"dance",
"skate",
"glide",
"swipe",
"bounce",
"swing",
"migration",
"circulation",
"cinema",
"mobile",
"multimedia",
"mutter",
"contraction",
"composer",
"piece",
"orchestra",
"concert",
"dragon",
"sodium",
"appoint",
"nomination",
"tell",
"channel",
"lane",
"narrow",
"congress",
"hair",
"tongue",
"sickness",
"marine",
"approach",
"tidy",
"requirement",
"thirsty",
"negligence",
"ignore",
"bargain",
"neighbour",
"cool",
"nervous",
"latest",
"report",
"headline",
"night",
"agile",
"retired",
"lost",
"duke",
"owl",
"bat",
"extinct",
"article",
"civilian",
"objective",
"average",
"census",
"relative",
"indirect",
"ordinary",
"genuine",
"unfortunate",
"tough",
"slow",
"modest",
"integrated",
"inappropriate",
"other",
"loose",
"raw",
"hard",
"mention",
"warn",
"reputation",
"harmful",
"reactor",
"chain",
"count",
"number",
"foster",
"food",
"approve",
"oak",
"fixture",
"protest",
"dirty",
"stubborn",
"reserve",
"borrow",
"available",
"profession",
"seasonal",
"sea",
"visual",
"eye",
"primary",
"heavy",
"superior",
"neutral",
"oral",
"diplomat",
"twin",
"senior",
"nose",
"bear",
"leg",
"page",
"critic",
"survivor",
"trainer",
"linear",
"half",
"tray",
"window",
"hole",
"surgeon",
"automatic",
"aviation",
"driver",
"contrast",
"choice",
"mouth",
"satellite",
"agenda",
"liver",
"donor",
"orgy",
"decoration",
"kit",
"expenditure",
"printer",
"scandal",
"overwhelm",
"manage",
"exaggerate",
"revolution",
"obese",
"due",
"possession",
"rate",
"elephant",
"treaty",
"bucket",
"shame",
"palm",
"tract",
"chaos",
"gasp",
"trouser",
"heaven",
"ideal",
"paralyzed",
"uncle",
"parking",
"word",
"drawer",
"member",
"root",
"colon",
"thigh",
"jaw",
"unfair",
"bride",
"detail",
"elapse",
"perforate",
"faint",
"skip",
"reject",
"exceed",
"aisle",
"hallway",
"passage",
"passion",
"graze",
"pasture",
"patent",
"route",
"terrace",
"nationalist",
"nationalism",
"syndrome",
"hesitate",
"pause",
"wage",
"pension",
"royalty",
"rent",
"peace",
"fur",
"punish",
"retiree",
"population",
"hear",
"observer",
"percent",
"insight",
"absolute",
"benefit",
"performer",
"century",
"magazine",
"cycle",
"die",
"allow",
"vertical",
"persist",
"remain",
"porter",
"rider",
"conductor",
"vegetarian",
"virgin",
"slave",
"patient",
"witness",
"consumer",
"worker",
"hero",
"radical",
"personality",
"pin",
"manner",
"staff",
"sweat",
"basic",
"operational",
"dramatic",
"throat",
"telephone",
"photograph",
"camera",
"wording",
"evolution",
"assault",
"fitness",
"size",
"shelter",
"physics",
"broken",
"prescription",
"collect",
"pluck",
"photography",
"print",
"chalk",
"bed",
"field",
"mechanism",
"stereotype",
"tablet",
"dismissal",
"organ",
"urine",
"slant",
"arena",
"bury",
"insert",
"mosque",
"sow",
"address",
"put",
"arrangement",
"position",
"braid",
"layout",
"biology",
"flower",
"houseplant",
"fossil",
"weed",
"sculpture",
"panel",
"pen",
"fragrant",
"attractive",
"abundant",
"shower",
"feather",
"looting",
"dive",
"asset",
"poetry",
"concession",
"location",
"extent",
"corner",
"arrow",
"officer",
"party",
"ideology",
"colony",
"pyramid",
"bacon",
"dose",
"part",
"portrait",
"easy",
"orientation",
"charismatic",
"beautiful",
"rich",
"acquisition",
"possibility",
"station",
"stamp",
"tail",
"possible",
"potential",
"pocket",
"swarm",
"flour",
"hierarchy",
"blow",
"application",
"realism",
"sermon",
"priority",
"exact",
"definite",
"precision",
"precede",
"predator",
"horoscope",
"preference",
"racism",
"chauvinist",
"assumption",
"absorption",
"training",
"bake",
"ready",
"prevalence",
"gift",
"conservation",
"jam",
"administration",
"presidency",
"push",
"lobby",
"coerce",
"glory",
"prestige",
"assume",
"imposter",
"mainstream",
"quotation",
"discount",
"chimpanzee",
"crude",
"form",
"prison",
"hostage",
"coach",
"privacy",
"award",
"likely",
"investigation",
"process",
"gradual",
"perception",
"announcement",
"manufacturer",
"professor",
"uniform",
"professional",
"chair",
"technique",
"gain",
"offspring",
"forecast",
"forbid",
"ban",
"missile",
"prediction",
"sustain",
"pledge",
"marketing",
"remind",
"launch",
"pitch",
"advocate",
"quota",
"advice",
"suggest",
"owner",
"protection",
"demonstrator",
"pride",
"entertain",
"feed",
"state",
"soul",
"analysis",
"analyst",
"psychology",
"sensation",
"forum",
"publicity",
"riot",
"edition",
"promotion",
"publisher",
"pool",
"drag",
"extract",
"penalty",
"student",
"buy",
"hobby",
"button",
"advertise",
"lay",
"instal",
"install",
"execute",
"nominate",
"earthquake",
"dilemma",
"prey",
"satisfied",
"pursuit",
"problem",
"quiet",
"silence",
"fraction",
"radio",
"radiation",
"railcar",
"railroad",
"storm",
"rain",
"breed",
"build",
"noise",
"knock",
"rape",
"ecstasy",
"rank",
"preparation",
"reality",
"back",
"beneficiary",
"mutual",
"appreciate",
"realize",
"tolerate",
"referral",
"compensation",
"document",
"matrix",
"correction",
"recover",
"loss",
"red",
"redundancy",
"polish",
"sugar",
"elegant",
"mirror",
"reflection",
"asylum",
"garbage",
"popular",
"continental",
"national",
"presidential",
"constitutional",
"imperial",
"cultural",
"economic",
"magnetic",
"moral",
"environmental",
"ratio",
"relation",
"relevance",
"faith",
"comment",
"commemorate",
"retain",
"shave",
"relinquish",
"restoration",
"lease",
"tenant",
"fix",
"meal",
"refund",
"repetition",
"regret",
"substitute",
"reproduction",
"answer",
"storage",
"recycle",
"reptile",
"horror",
"researcher",
"qualification",
"palace",
"community",
"ash",
"immune",
"conservative",
"tolerant",
"pneumonia",
"lung",
"feedback",
"kneel",
"brake",
"constraint",
"result",
"revival",
"revive",
"retailer",
"outlet",
"revenge",
"withdraw",
"remember",
"echo",
"opposite",
"reader",
"reinforce",
"wealth",
"jockey",
"entitlement",
"copyright",
"option",
"fruit",
"rear",
"inflation",
"venture",
"ritual",
"gown",
"rock",
"kitchen",
"suite",
"rotation",
"path",
"road",
"carpet",
"rugby",
"finished",
"flow",
"country",
"countryside",
"undermine",
"salesperson",
"greeting",
"irony",
"moon",
"stroll",
"flavor",
"pray",
"dictate",
"expression",
"strikebreaker",
"frighten",
"spray",
"landscape",
"scheme",
"system",
"scholar",
"session",
"classroom",
"forestry",
"science",
"despise",
"scratch",
"conscience",
"bronze",
"gossip",
"harbor",
"seek",
"coast",
"endorse",
"mystery",
"secretary",
"patrol",
"security",
"visible",
"seed",
"recruit",
"quest",
"transparent",
"gene",
"section",
"bite",
"elect",
"pick",
"assertive",
"vain",
"paradox",
"willpower",
"spontaneous",
"arrogant",
"dignity",
"autonomy",
"export",
"greet",
"perceive",
"humor",
"ear",
"reasonable",
"sensitivity",
"detector",
"discriminate",
"distant",
"barrier",
"scenario",
"sequence",
"series",
"snake",
"waiter",
"established",
"arrange",
"apparatus",
"strict",
"stitch",
"faithful",
"shadow",
"nuance",
"feign",
"embarrassment",
"disgrace",
"cylinder",
"edge",
"bundle",
"bleed",
"protect",
"budge",
"reflect",
"horseshoe",
"beach",
"jacket",
"shorts",
"deficit",
"abridge",
"injection",
"strap",
"brag",
"prove",
"shrink",
"bush",
"shiver",
"mix",
"ostracize",
"closed",
"temple",
"profile",
"digress",
"pavement",
"symbol",
"meaning",
"important",
"lover",
"velvet",
"flatware",
"plain",
"stool",
"simplicity",
"honest",
"unit",
"sin",
"sister",
"nun",
"sit",
"locate",
"ample",
"magnitude",
"survey",
"slip",
"skilled",
"scan",
"freckle",
"peel",
"omission",
"captain",
"horizon",
"angle",
"killer",
"murder",
"bedroom",
"steak",
"stumble",
"gaffe",
"slippery",
"dip",
"slump",
"slime",
"snail",
"bullet",
"sleep",
"particle",
"berry",
"pony",
"limited",
"packet",
"sample",
"scrap",
"slot",
"compartment",
"village",
"minority",
"fine",
"petty",
"dash",
"smile",
"spot",
"trap",
"snatch",
"kidnap",
"snow",
"serious",
"gregarious",
"ant",
"welfare",
"socialist",
"civilization",
"pudding",
"worm",
"casualty",
"suspect",
"communication",
"wreck",
"prince",
"resource",
"monarch",
"bridge",
"formation",
"shout",
"snarl",
"whisper",
"privilege",
"audience",
"hypothesize",
"accent",
"trance",
"spit",
"sector",
"pepper",
"shed",
"angel",
"divorce",
"divide",
"referee",
"stain",
"expand",
"scatter",
"encourage",
"team",
"waste",
"crouch",
"jet",
"crutch",
"staircase",
"stake",
"haunt",
"stem",
"stable",
"norm",
"sun",
"begin",
"situation",
"safety",
"relationship",
"reliance",
"isolation",
"say",
"declaration",
"formula",
"rung",
"wait",
"lodge",
"constant",
"plagiarize",
"ladder",
"stay",
"pierce",
"muggy",
"miscarriage",
"shareholder",
"sock",
"plug",
"shop",
"straighten",
"strategic",
"wander",
"banner",
"trolley",
"struggle",
"stretch",
"hit",
"kick",
"stunning",
"guitar",
"ribbon",
"conviction",
"emotion",
"vigorous",
"cable",
"tower",
"nest",
"auditor",
"trip",
"fashionable",
"chapter",
"paragraph",
"soak",
"replace",
"suburb",
"brainstorm",
"inspiration",
"evoke",
"indication",
"proper",
"sulphur",
"budget",
"sum",
"overview",
"summer",
"summit",
"superintendent",
"miracle",
"dinner",
"bag",
"prayer",
"cater",
"inspire",
"provide",
"provision",
"shelf",
"pier",
"inhibition",
"overcharge",
"certain",
"excess",
"deputy",
"replacement",
"defendant",
"chocolate",
"swell",
"door",
"shift",
"swop",
"understanding",
"interactive",
"calendar",
"research",
"salt",
"table",
"undertake",
"tactic",
"breathe",
"insist",
"inject",
"eat",
"absorb",
"insure",
"participate",
"musical",
"conversation",
"discuss",
"tree",
"suntan",
"candle",
"duty",
"assignment",
"job",
"bland",
"tax",
"species",
"instruction",
"tear",
"rhetoric",
"television",
"mood",
"disposition",
"pace",
"loan",
"trend",
"strain",
"finger",
"abortion",
"district",
"panic",
"examination",
"will",
"tribute",
"recommendation",
"leash",
"text",
"grateful",
"tragedy",
"theorist",
"slice",
"mist",
"nail",
"layer",
"thread",
"dilute",
"combination",
"thought",
"spine",
"idea",
"brink",
"flourish",
"fling",
"confuse",
"bolt",
"relate",
"bind",
"lean",
"occasion",
"youth",
"reign",
"season",
"clock",
"shy",
"can",
"topple",
"tiptoe",
"frog",
"labour",
"item",
"liberal",
"grave",
"tone",
"knife",
"drill",
"dentist",
"roof",
"place",
"tumble",
"agony",
"torture",
"add",
"tournament",
"doll",
"dealer",
"myth",
"tread",
"transfer",
"transform",
"freight",
"fare",
"transport",
"rubbish",
"fly",
"swim",
"visit",
"rehabilitation",
"jury",
"triangle",
"victory",
"prize",
"gutter",
"truth",
"loyalty",
"vat",
"pipe",
"stomach",
"tumour",
"rotate",
"ivory",
"dozen",
"year",
"day",
"pair",
"couple",
"tropical",
"incredible",
"uncertainty",
"reveal",
"vague",
"spy",
"cave",
"underline",
"bottom",
"minimize",
"project",
"unlike",
"unique",
"surprise",
"discrimination",
"thaw",
"continuous",
"lesson",
"ton",
"consolidate",
"global",
"different",
"volunteer",
"artificial",
"live",
"dangerous",
"invisible",
"blind",
"rough",
"crisis",
"frozen",
"premature",
"strange",
"illness",
"unaware",
"folklore",
"promote",
"hilarious",
"nightmare",
"urgency",
"sweep",
"walk",
"mechanical",
"useful",
"sigh",
"threaten",
"vacuum",
"valley",
"evaluate",
"worth",
"disappear",
"variable",
"variant",
"broccoli",
"vegetable",
"van",
"rocket",
"embark",
"promise",
"poem",
"peak",
"bottle",
"veteran",
"neighborhood",
"winner",
"video",
"compete",
"wake",
"energy",
"active",
"ghost",
"sight",
"tourist",
"appearance",
"colorful",
"vision",
"singer",
"soprano",
"intention",
"book",
"election",
"ballot",
"exposure",
"bet",
"waist",
"queue",
"lounge",
"hike",
"stride",
"pedestrian",
"cane",
"deprivation",
"war",
"bird",
"guarantee",
"laundry",
"basin",
"password",
"fountain",
"stream",
"vessel",
"acid",
"fluctuation",
"method",
"lifestyle",
"gun",
"cry",
"valid",
"familiar",
"wagon",
"sniff",
"linen",
"extend",
"pigeon",
"wilderness",
"winter",
"hope",
"retirement",
"fade",
"express",
"feminine",
"feminist",
"forest",
"courtship",
"sheep",
"term",
"formulate",
"solve",
"employee",
"studio",
"decline",
"respectable",
"acceptable",
"misery",
"compose",
"wriggle",
"script",
"message",
"offender",
"sausage",
"photocopy",
"annual",
"scream",
"amber",
"calf",
"kid",
"boy",
"lamb",
"junior",
"young",
"breeze",
"earthflax",
"earthwax",
"earwax",
"eaux",
"econobox",
"efflux",
"embox",
"enfix",
"epicalyx",
"equinox",
"ex",
"executrix",
"quaint",
"tomorrow",
"nearest",
"cookies",
"born",
"stepped",
"fallen",
"together",
"threw",
"stove",
"such",
"yellow",
"nation",
"yesterday",
"whistle",
"longer",
"cloth",
"primitive",
"instead",
"feet",
"entire",
"setting",
"gave",
"layers",
"hardly",
"stone",
"teeth",
"driving",
"hidden",
"being",
"atom",
"rope",
"universe",
"birds",
"greatly",
"studying",
"slope",
"that",
"needs",
"wise",
"fully",
"apartment",
"getting",
"earlier",
"sold",
"what",
"lady",
"children",
"shorter",
"specific",
"until",
"interior",
"box",
"weather",
"travel",
"famous",
"stairs",
"cent",
"headed",
"income",
"afraid",
"forty",
"fact",
"nothing",
"announced",
"every",
"eventually",
"none",
"fairly",
"explanation",
"gone",
"shirt",
"military",
"biggest",
"hat",
"southern",
"there",
"parts",
"natural",
"feathers",
"though",
"sides",
"grew",
"completely",
"farther",
"rubber",
"anything",
"happy",
"local",
"eleven",
"worse",
"whale",
"would",
"blew",
"than",
"him",
"silly",
"tea",
"goose",
"out",
"something",
"dried",
"tobacco",
"hunt",
"from",
"plural",
"laid",
"everybody",
"observe",
"perhaps",
"partly",
"simplest",
"acres",
"chosen",
"hearing",
"might",
"nearly",
"chose",
"became",
"never",
"were",
"about",
"consonant",
"various",
"whom",
"scientific",
"author",
"alike",
"stiff",
"foreign",
"golden",
"shown",
"sets",
"hung",
"within",
"bone",
"should",
"happened",
"silent",
"whenever",
"frequently",
"has",
"exclaimed",
"swam",
"dirt",
"maybe",
"planned",
"tonight",
"too",
"earth",
"nobody",
"gulf",
"ants",
"furniture",
"somebody",
"graph",
"gently",
"depth",
"toy",
"per",
"any",
"bowl",
"here",
"drew",
"kids",
"further",
"earn",
"necessary",
"after",
"easily",
"floating",
"farm",
"excellent",
"deeply",
"into",
"yourself",
"correct",
"fought",
"importance",
"nuts",
"troops",
"eaten",
"massage",
"noon",
"whispered",
"bigger",
"highest",
"yes",
"porch",
"evidence",
"aside",
"noted",
"opportunity",
"kept",
"under",
"require",
"actual",
"ship",
"halfway",
"given",
"quietly",
"behind",
"empty",
"ten",
"flame",
"clothing",
"did",
"seven",
"adjective",
"grabbed",
"upper",
"alone",
"felt",
"suddenly",
"saddle",
"two",
"zipper",
"merely",
"signal",
"our",
"task",
"ran",
"event",
"believed",
"through",
"properly",
"ago",
"doing",
"skill",
"cost",
"made",
"caught",
"possibly",
"themselves",
"shinning",
"label",
"dust",
"mental",
"forgotten",
"began",
"sudden",
"tall",
"carefully",
"upward",
"independent",
"along",
"mysterious",
"gather",
"better",
"journey",
"son",
"both",
"oxygen",
"sent",
"anybody",
"beauty",
"failed",
"police",
"song",
"zulu",
"slight",
"over",
"cannot",
"could",
"flies",
"enough",
"everywhere",
"but",
"wore",
"connected",
"continued",
"must",
"mission",
"magnet",
"rhyme",
"rising",
"impossible",
"who",
"aloud",
"birth",
"thing",
"speak",
"men",
"exciting",
"tide",
"lying",
"same",
"slightly",
"everything",
"leaving",
"pond",
"modern",
"early",
"nor",
"particularly",
"anywhere",
"buried",
"drawn",
"sad",
"western",
"ate",
"town",
"nodded",
"neighbor",
"milk",
"shells",
"helpful",
"previous",
"motion",
"stood",
"fastened",
"search",
"extra",
"spent",
"above",
"brought",
"invented",
"donkey",
"stuck",
"instance",
"quickly",
"happily",
"magic",
"handle",
"married",
"gentle",
"remove",
"discussion",
"fort",
"toward",
"newspaper",
"swept",
"beyond",
"mice",
"obtain",
"more",
"pine",
"one",
"zebra",
"which",
"plus",
"torn",
"particles",
"perfectly",
"become",
"whatever",
"wrapped",
"exactly",
"bound",
"circus",
"angry",
"eight",
"clearly",
"fed",
"chamber",
"running",
"bright",
"compare",
"came",
"wish",
"secret",
"whose",
"pale",
"now",
"supper",
"forth",
"stared",
"music",
"equally",
"faster",
"fourth",
"among",
"her",
"herself",
"already",
"attached",
"each",
"claws",
"greater",
"nearby",
"itself",
"noun",
"riding",
"canal",
"living",
"led",
"pink",
"best",
"according",
"unknown",
"occur",
"ruler",
"laugh",
"typical",
"today",
"studied",
"said",
"liquid",
"darkness",
"brass",
"swimming",
"later",
"gradually",
"not",
"equipment",
"valuable",
"probably",
"life",
"continent",
"type",
"someone",
"myself",
"shaking",
"plates",
"steady",
"thus",
"phrase",
"around",
"blanket",
"vessels",
"vast",
"also",
"changing",
"lower",
"may",
"met",
"twenty",
"another",
"glad",
"rapidly",
"heard",
"dot",
"gray",
"curious",
"wet",
"verb",
"busy",
"successful",
"third",
"found",
"minerals",
"them",
"aboard",
"all",
"thy",
"wool",
"entirely",
"again",
"labor",
"substance",
"rod",
"rays",
"fell",
"amount",
"knew",
"leather",
"recall",
"chemical",
"ahead",
"mostly",
"onto",
"organization",
"introduced",
"customs",
"those",
"refused",
"actually",
"correctly",
"because",
"pet",
"fighting",
"declared",
"motor",
"greatest",
"least",
"success",
"hello",
"barn",
"these",
"buffalo",
"alphabet",
"zoo",
"join",
"very",
"butter",
"fifteen",
"since",
"breath",
"driven",
"putting",
"principal",
"alchemy",
"anarchy",
"anechoic",
"antenna",
"aurora",
"azure",
"balsam",
"bazaar",
"beloved",
"bliss",
"bravado",
"brimstone",
"cadence",
"cathode",
"caviar",
"chivalry",
"chutzpah",
"cobalt",
"cobbler",
"cobblestone",
"cognac",
"cynosure",
"daffodil",
"dandelion",
"decibel",
"dewdrop",
"diligence",
"edict",
"epicurean",
"equinox",
"ethereal",
"exodus",
"fjord",
"flair",
"flamboyant",
"flora",
"fluorescent",
"fractal",
"gossamer",
"guild",
"halcyon",
"hegemony",
"hemoglobin",
"hibernate",
"idiosyncrasy",
"igneous",
"incognito",
"infrastructure",
"jovial",
"jubilee",
"kinetic",
"kiosk",
"lagoon",
"lava",
"libertarian",
"lilac",
"lilt",
"maverick",
"medley",
"mesmerize",
"metropolis",
"miasma",
"mnemonic",
"mystic",
"nemeses",
"neutron",
"nirvana",
"noxious",
"oasis",
"omnipotent",
"opal",
"optimism",
"papyrus",
"paradox",
"phantom",
"phosphorescent",
"plutonium",
"poltroon",
"prism",
"quasar",
"quintessence",
"quixotic",
"rhapsody",
"serendipity",
"solstice",
"sonorous",
"spectrum",
"tachyon",
"terracotta",
"threnody",
"transcend",
"turquoise",
"ubiquitous",
"unicorn",
"vacuum",
"vortex",
"vivid",
"willow",
"wisdom",
"xenon",
"yin",
"yoga",
"zeitgeist",
"zephyr"
]
}
\ No newline at end of file
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