вах
April 14

TikTok - cхема на 100 000 000$. Часть 2. Три ебучих капчи.. на запросах.

Введение

В первой части я рассказал о своей истории знакомства с тт, тем как проебал темку с потенциалом в дохуя, а также, тем на что я въебал пол года.

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

Чуть позже, как подкачал скил, капчи всё же раъебал. Потому, хотелось бы ими поделиться.

Да, я натыкался на форуме, что подобное решение продают, но я потратил на тикток слишком много времени и сил, чтобы что-то продавать или допиливать, а потому делюсь тем что есть) Как обычно, я решил сделать чуточку больше чем остальные, больше чем есть в паблике. Похуярили..

Slide Капча

Демо страница: https://sf16-scmcdn-va.ibytedtos.com/goofy/secsdk-captcha/va/2.15.21/index.html

Нашел я эту демо страничку когда-то совсем давно, копаясь в коде запроса капчи тт. Если правильно помню, тогда она (капча) прилетала фреймом с линкой на эту страничку.

Подходы к решению

На zenno форуме когда-то давно уже поднимался вопрос решения капчи слайдера.

Применяемое там решение базировалось на логике: напарсить всё и составить целые картинки, а потом уже искать отличия.

Кстати, несколько позднее я увидел подобную идею на хабре, что было переводом вот этой статьи (спиздинг с зенки?).

Ещё есть варианты переводить в серое, как делал Sadzurami.

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

Мой подход

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

Я взял свой модуль и въебал большие пороговые значения, чтоб получать по сути только белые линии обтекающие пазл на фул картинке.

Первой задачкой стало то, что положение пазла по Y (высоте), которое присылает тт, слишком маленькое.

В итоге оно резало криво.

Решением стало - прописать 2х размер. Почему это сработало, станет очевидно чуть позже.

Второй преградой на пути стало то, что контуры получались слишком тонкие, что в итоге приводило к ошибке. При наличии мусора в контурах или белых объектов часто не мог найти правильное положение. Хотя казалось бы, куда ещё лучше.

В отличие от мелкой картинки банана, тут она имеет размер 552х344 и потому был резон сделать расширение белых областей, подробнее и на умном туть.

Значение подбирать, разумеется, нужно не от пизды.

Я опять использовал image-js. Дока.

В итоге, оно начало стабильно работать, на 10 из 10.

Но веселье на этом не заканчивается. Покопавшись в сурсах капчи, я понял, что они используют не ориг картинку, а уменьшенную (вот так сюрприз). Тоесть если я вот так решу, то эта позиция пазла нахуй не пригодится.

Причем, для пк размеры одни, а для мобилок другие.

Пк
Моб

Поставив брек на модификации атрибута кнопки, который отвечает за перерисовку положения кнопки слайдера..

Я попал сюда, где увидел, что исходная позиция tip_y, которую вертает тикток, увеличена на некоторую константу.

Прокрутив чуть выше, стало очевидно как работает вся эта хуеверть. Оно просто чекает какое у нас устройство (бек это кстати по юа чекает) и в зависимости от этого ставит константу в 1 или в 1.23...

А после сжимает её через css до 276, либо до 340, в зависимости от устройства.

Всё это я применил и в софте.

Ресайз сделал также через image-js. Теперь результат решалки уже можно будет применять на практике.

Третий препон - координаты. Раз я решил делать на запросах, значит нужно и координаты как-то кастовать. Но прежде, стоит разобраться, а чё вообще генерировать.

В случае с пк, данных до ху я.

А с мобилкой, не сказал бы что меньше. Но я решил выбрать мобилку (на деле разницы нет шо выбирать, одинаковая хуйня).

Ну.. пока ты двигал пазл, вот там всё и происходило

Сначала я долго всматривался в координаты, а потом они начали всматриваться в меня. И тогда тикток сказал:

А если серьезно, я поставил бреки, посерчил код и пришел сюда

А потом сюда (на позицию данных перед отправкой).

Вернувшись назад по стеку, я увидел как пополнялись эти массивы.

Ну окэй, мы знаем 2 массива, пазл (drag_track, он же reply) и кнопка слайдера (slide_btn_track, он же m) и можем примерно понять от куда они берутся. Но остается странный массив T. Количество значений в drag_track и reply одинаковое, тк оно по сути описывает одно и то же движение, только с дух разных точек по Y, а вот T..

Причем, заметим что T кратно 5 от количества reply значений всегда.

Прочекав код мы придем вот сюда. Оно тречит позицию не пазла, а "мышки", когда она зажата и сейвит каждую пятую точку.

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

Рисовалка
Данные решения
Скрин

Результаты были не очень читаемые, поэтому мне пришлось применить немного магии рандомного подбора циферков, добавив сдвиги. Точнее, я почекал всякие расстояния, но не прям чтобы сильно уверен, что правильно все понял (но работает же все в итоге). Примечательно, что координаты движения кнопки были прям точные и правильные относительно скрина. Значит, в написании решения от нее и будем отталкиваться.

Чтобы воспроизвести эту хуйню, мне нужно было понять от каких цифр отталкиваться, поэтому я собрал чуть инфы - размеры кнопок и картинок, а также их положение через getBoundingClientRect()

Применительно к тт это выглядело вот так.

Ну и осталась генерация..

В ситуации с бинансом я писал свой говнокод, этот случай конечно не исключение, но часть работы я решил переложить на попсовое решение windmouse. Классека.

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

Благо, у либы есть онлайн визуализатор, благодаря чему можно быстрее понять всю эту хуеверть. По факту, я просто хочу, чтобы из одной точки по координатам XY до другой провели линию. При этом гравитация (плавность) максимальная, отклонения от траектории 1, шаг по времени между точками от 1 до 5 (мс), а в пикселях макс шаг например 4. Таргет зона, это степень отклонения от конечной точки.

Я чуток поигрался с настройками и разобрался как кастовать правильную линию.

И так, я набросал базовую инфу, понял как генерить линии и накидал некий сценарий работы в голове:

  • Берем позицию кнопки от её середины по высоте.
  • От нее ставим позицию до конца по Y + допустимые отклонения и передаем windmouse задачу генерации линии.
  • Имея данные движения, кастуем 3 массива, учитывая специфику доп отклонений каждого. У кнопки это -8 пикселей вверх, у пазла фикса по Y, а X как у кнопки, у курсора добавил некоторое старт отклонения в рамка иконки стрелки у кнопки.

По итогу получился следующий код.

Ииии... он нихуя не работал. Я въебал 6 часов, собирая какую-то хуйню на координатах, до конца вообще не контролируя че происходит и оно блять не заработало.

Вот так сюрприз, с нихуя ничего не работает.

В рисовалке все выглядело как надо, как в решенных. Тоесть я свой генератор тестил на демо картинке и рисовало похоже.

И я уж было собирался идти спать, но подумал порандомить отступы для значения reply. В сравнении с данными от решенных капч, позиции у нее были со сдвигом на размер от окна до кнопки (37.5), тоесть будто движения от края экрана. Но я убрал этот шаг и оно начало нормально работать.

Ну типо 100 из 100 ответ от сервера тт на решение. Решалось по сути мгновенно.

На браузере, ясен хуй, оно тоже пиздато работает. Причем и для моб и для пк режима.

Картинки и тело задачи я дернул через кеш. Сначала вытянул инфу по капче, потом ссылки на картинки, а по ним сами картинки (тоже из кеша).

Не баг, а фича

Не найдя для себя удобным доступы к капче через всякие формы авторизации, я решил потыкать текущую демку.

Я заметил, что если передать в ссылке другой тип капчи, то оно вернет картинки под другую капчу. По сути, ссылку можно свести даже к виду https://verify-sg.byteoversea.com/captcha/get?os_type=2&fp=verify_0&subtype=whirl

А потому, можно попробовать и запрос подменить) Что я собственно и сделал, получив в распоряжение демку на все 3 типа капчи.

Манкипатч запросекаф опять помог мне.

Кстати, при работе с качей на запросах мне нужен был параметр verify_, а это оказалось подобие UUID.

Ещё, было весело играть в отслеживание координат мышки

Whirl Капча

Демо страница: https://www.tiktok.com/login/phone-or-email/email

Не то чтобы данная страница капчи была полезная для меня в тестах, имея описанную ранее фичу, но раз это линка того, где тт использует данную капчу в проде, пусть будет.

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

Подходы к решению

Данная капча похожа на (старую) rotation captcha у funcaptcha.

Есть опенсурс демка и сурсы.

У поворотных капч на гите было решение на основе RotNet.

Только вот данная капча проще чем кажется (это не тот rotation), у неё есть и более интересный подход к решению)

Некоторое время назад на zenno форуме бесплатно выложили решалку этой капчи. Хоть оно и работало, но оказалось с подвохом. В скрипте был стилак)

Все сначала так радовались, пока не поняли подвоха..

Однако, не суть, всё равно оно ведь работало)

И так, оно дергало координаты по некому списку, а потом сравнивало.

Мой подход

До публикации софта со стилаком (каким-то кеком) на форме зенки, я пришел примерно к тем же мыслям и сделал подобное решение. Так как кругляшка у тт 2, а не один, это сильный проеб, благодаря которому сложность всей капчи сводится на нет.

Если разрезать картинку на 2 части, в месте разреза на каждой из картинок будет одинаковый рисунок, с круглым вырезом та же хуйня. Берем внешний контур у мелкой, внутренний у большой, вертим и сравниваем эти 2 круга пока не совпадут.

Подглядел я эту мысль когда-то в статье по взлому KeyCaptcha.

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

Что я пробовал?

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

И так, вертим картинки

Сначала вертел я её сервисами.. как долбаёб.

А потом до меня дошло, что таким макаром я далеко не уеду. И опять пришел к либе image-js, а именно функции rotate.

Я подбирал всякие серые фильтры, экспериментировал с тем как лучше делать: взять мини картинки и растянуть до размера контура кольца или наоборот контур кольца сжать или вообще их оба растянуть или сжать до какой-то иной цифры.

Сжатия и растяжения колец
Чекал влияние контуров на качество решения

Тестировал чб фильтры и их комбинации.

Турнирная таблица
Список фильтров
Серые фильтры
Результаты тестов

Убил недели 2 на всякую хуйню. Зато, код выглядит не сильно по уебански.

Кстати, в один из тестов я даже нашел еще один сбой в матрице (прям как в бинансе с нередач картинкой). Берем контур.

Перегоняем в оттенки серого. И получаем.. изначальную картинку.

Причем если контур из png перевести в jpg, то бага уже не воспроизведется.

Хз почему так выходит.

Остановился я в итоге на фильтре "magenta".

Работа не волк, работа - work, walk - это ходить

Ну и вынес это в отдельный скрипт решалку.

Ну и какбэ, оно решало, да, но не достаточно хорошо. Пробив 20% меня не устраивал.

На деле все решение сводилось вот к чему: вертим картинки и дергаем контур круга, а потом сравниваем через бас совпало или нет.. говно говна, а не решение.

А потом до меня дошло, что линяя не обязательно должна быть круглой. Мы можем перевести контуры в 2 прямые линии и искать позицию уже в них. Тк если делать через поворот круга, происходит пересчет цвета и уебищно все выходит.

Уроборос, который кусает (наверное) свой хвост, отличная визуализация этой мысли. Тоесть ее можно развернуть.

@ZennoTema привел эти мысли в рабочий красивый пример, со своим хитрым алгоритмом поиска краёв.

И оно просто ахуительно работало

Хоть у ZennoTema всё работало заебись, я решил сделать по своему, более топорным методом.

К чему я пришел в итоге?!

Рисуем кружок, как и в случае с tutanota. Только тут задача получить все крайние пиксели кружка.

Чекаем прозрачность и пропускаем пиксели, где пусто.

Но мне не нравилось, что линии получались разной длинны, я был убежден что так быть не должно. Пробуя делать разные алго, в итоге всеравно получалось разное количество пикселей. Сравнивать было неудобно и результат был хуевый. Я чуть даже не дошел до того, чтобы сесть руками позиции пикселей посчитать. Ну типо бля, в одной 169, в другой 276, хуй поймешь как потом от туда вытянуть правильный результат.

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

Центр круг
Кольцо

Однако, при текущем алго возникает проеб.

Получается 361. 0 и 360 градусов совпадают по X и Y. И мы это быстро фиксим.

Сначала я сделал так, поставив шаг от 1 градуса, а потом понял, что лучше наоборот, начинать от 0 до 359.

360 пикселей, 360 градусов.

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

И тут ZennoTema предложил гениальную в своей простоте идею, до которой я сам дойти не смог: просто удваиваем вторую линию, тогда при поиске мы сразу можем найти правильное положение первой во второй.

По итогу получился вот такой простой код. Для кольца мы делаем удвоение линии.

Я въебал кучу времени, чтобы рисовать 360 линий (каждую со сдвигом на 1 пиксель), но в итоге оно у меня работало через хуй, а тут буквально 1 мелочь в пару строк кода и сразу все встало на свои места, стало решать на 100%.

Еще раз, вот это и есть все решение. Да, вот так все просто.

Так как у нас 2 круга, которые крутятся на встречу друг к другу, итоговый угол надо делить на 2 (макс угол для каждой картинки в таком случае 180 градусов).

Ну а теперь перейдем к запросекам.

С точки зрения кода, что слайдер, что это, по сути одна хуйня.

Единственное, меняется тип капчи whirl и положение у reply по Y это 0. Тем не менее, нам надо как-то еще понять, как перевести полученный угол в координаты для слайдера.

Ну окей, ставим брек на rotateZ, а потом чекаем че у нас выше места остановки. А выше формула перевода координат в угол, она нам и нужна: var deg = a.x / (222 * _.n * kt / 100) * 180; Это вроде мусор * kt / 100 там 100 на 100 всегда делится, нахуя оно это делает я так и не понял. А вот _.n коэффициент масштабирования капчи.

Я поставил логпоинт, чтобы почекать данные в процессе решения.

Ну какбэ понятно, берем координаты, делим 222 и умножаем на 180, получаем угол в градусах. А нам нужно наоборот. Кстати, 180 тут тк 1 картинка должна максимально пройти 180 градусов, а картинок у нас 2 движущиеся в противоположных направлениях. Тоесть даже если они уже в правильном положении, если каждая пройдет 180 градусов, они опять встретятся.

Ну и фсе, я просто взял и вывернул формулу, допом обновил startY, тк тут (в куче ответов) она была другая.

В теле поменялись пару мелочей

Ну и оно работает по красоте в итоге. По сути 100 из 100, но часть решений скушал антифрод. Либо проеб на пол пикселя есть.

Пример ситуации с ошибкой. Остальные 2 ошибки такие же. Решено все вроде правильно, но фроду тт чет не понравилось.

Про браузер и смысла нет говорить. Добавилась только формула dist для конвертации угла в координаты кнопки. И тоже работает пиздато. В режиме моб и в режиме пк.

Помимо этого, помнится мне, был вопрос по этой капче применительно к мобилкам.

Мне стало интересно, а можно ли чисто из скрина делать решение. На ранних экспериментах я говнял свой детект краев и думал кропать.

По факту, если юзать метод прохода по кругу, зная размеры кружков, можно все спокойно собрать, причем даже со скрина. Но лучше так не делать.. Лучше дергать ориг картинки.

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

3D Капча

Демо страница: https://ads.tiktok.com/i18n/login/

Ну а теперь перейдем к самому интересному. Именно с этой капчи у меня начались сложности с тиктоком. Все-таки, я ведь именно с ads tiktok работал.

Чисто технически, найти решение данной капчи, да еще и без всяких нейронок (онли на бас), было самой интересной задачкой)

Данное решение (ну не прям точно такое, но суть осталась прежней) я придумал еще тогда, года 4 назад, но не затащил по скилам. На эксперименты с этой хуйней суммарно я потратил где-то недели 2, а может и месяц..

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

Подходы к решению

На форуме зенки была решалка данной капчи. Строилась она на сравнении картинок по phash из другого материала. Челы из авито, кстати, для сравнения картинок в антифроде сетку отдельную обучали.

Вернемся к зенке. Они дергают картинку, режут на мини картинки (фигуры), сравнивают их. Важным шагом тут является вот это:

Nо как они режут на мини картинки

Если я правильно понял, они берут картинку, как-то фильтруют и получают чб маску, вычитают ее и дергают фигуры.

Непосредственно код.

Вся обработка вот этой либой, по аналогии с примером.

Кажется, что фильтруют только фон?!

И сравнивают в итоге через phash. Только вот сравнение по phash тут не является оптимальным подходом, лучше подойдут шаблоны (Template Matching или простыми словами "поиск картинки в картинке"). В чем я убедился на собственных тестах.

Потому не удивительно, что даже на простых примерах оно лажает.

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

С запросеками при решении капчи я чуток намучался, тикток штука крайне специфическая..

Ну и оно работало, я даже по нему софт публиковал на форуме.

Весь смысл капчи тт, на самом деле, сводится к тому, что при входе на сайт дается сгенерированная на фронтенде кука verify_ (как генерится писал чуть ранее), а потом по ней происходит запрос авторизации и капчи. Если капчу на этой куке решили, тт пустит. Поэтому мне на рукапче нужно было передать свои куки и попросить verify_ куку? в которой пройдена капча.

Также я тогда упоминал шифрование логина и пароля. Вдруг, пригодится кому-то.

function encrypt(e) { var t, n = []; if (void 0 === e) return ""; t = function(e) { for (var t, n = e.toString(), o = [], i = 0; i < n.length; i++) 0 <= (t = n.charCodeAt(i)) && t <= 127 ? o.push(t) : 128 <= t && t <= 2047 ? (o.push(192 | 31 & t >> 6), o.push(128 | 63 & t)) : (2048 <= t && t <= 55295 || 57344 <= t && t <= 65535) && (o.push(224 | 15 & t >> 12), o.push(128 | 63 & t >> 6), o.push(128 | 63 & t)); for (var r = 0; r < o.length; r++) o[r] &= 255; return o }(e); for (var o = 0, i = t.length; o < i; ++o) n.push((5 ^ t[o]).toString(16)); return n.join("") }
[[MAIL_HASH]] = encrypt([[MAIL]])
[[PASSWORD_HASH]] = encrypt([[PASSWORD]])
[[TIME]] = Date.now()

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

Но это не мой путь...

Мой подход

Я выбрал для себя выбрал некий вектор, который и хотел добить и почекать что выйдет.

Для начала просто взял картинку, нарезал ее ручками и решил проверить, что имея готовые фигурки я достаточно точно смогу найти правильный ответ. На тот момент я еще не учел важность приведения их к 1 размеру, но и без этого тест оказался удачным. Я заготовил 3 теста: нарезка, с фильтром цвета, с перегоном в серое.

Вырезал я картинки ручками, через фотошоп. В бас создавал картинку - фон 100 на 100 пикселей и добавлял на каждый фигуры в центр. А потом производил сравнение картинок в двойном цикле, как в первой версии скрипта для IconCaptcha.

По результатом сравнения победила нужная пара. Ожидаемо.

Самое забавное, что при цветном тесте победило розовое колесо и розовая буква Y, получается, важно убрать цветовой шум. Поэтому, в ласт тесте показаны серые фигуры. Черипикинг такой черипикинг..

Осталось всего-то понять как вырезать автоматом.. вез всяких питонов, через бас..

По факту ведь нам нужно: перегнать в серый, получить маску, по маске дернуть фигурки. По цветам также есть резон фильтры сделать. Так, ну а тени определенно идут нахуй.

И все бы ничего, если б я не столкнулся вот с этим примером. Оказалось, что в тт не мало (на самом деле мало, нахуя я вообще на это обратил внимание) картинок с перекрытием одноцветных фигур, на решение этого и ушло больше всего времени.

Как оказалось позже, смысла в этом особого и небыло, докинуло всего пару процентов.

Что я пробовал?

Начал я с ресерча подходов к сравнению картинок и поиску похожих. В целом, базированная база.

Так как я хотел решать без нейронок, этот (yolo) подход я проигнорил. Они всетаки для более сложных задач подходят, а эта выглядит посильной и без них.

В целом, накидать контуры, пару фильтров, а потом дергаем то что нашли. Выйдет примерно то шо и у зенки.

Ну какбэ да, опять собель, опять контуры.

Кстати, тени идут нахуй. Как и фон. Чекал туть.

Я пробовал чекать контуры. Но сами по себе контуры решением являться не могут. Наложения картинок, фигуры всетаки 3д и состоят из частей.

Я думал делать цветовую сегментацию. Или как туть.

Только вот у меня не opencv с питоном, а нода и бас.

Тогда я опять вспомнил про image-js, в которой были нужные функции, примерчики, и которая работала в бас 23.2.2 (12 ноде).

Подставив свою картинку я сразу понял, что с этим уже можно будет работать.

За пару часов я накидал простой код выдергивания фигур. И оно прекрасно и абсолютно точно не работало нахуй. Чего-то нехватало.

P.s.: На самом деле, нужно было добавить также сжатие картинок в 1 размер, на скрине просто неудачный пример.

А нехватало разделения объектов. Но я, вместо того чтобы накинуть фильтры по цветам, начал копать совершенно в другую сторону, надеясь заодно порешать вторую проблему - наложение одноцветных.

Я стал копать как можно вообще разделять наложенные объекты. Самое умное к чему я пришел - алгоритм водораздела. На самом деле, я перепробовал дохуища всяких вариантов, но в итоге получалось какое-то говнище и водораздел стал последней надеждой.

Бля, ну ведь с монетками оно работает же.

Вообще, я потом чуть потыкал и дергать без фильтра по цвету, результат хоть не очень, но даже так, оно всеравно работало.

Решило 52 из 100. это без всего. Без цветовой сегментации и без водораздела (разбиения слипшихся одноцветных), чисто минус фон только.

Вернемся к разделению картинок.

Пока все дрочили на чатгпт, я отсматривал хуеву тучу видео от индусов про то, как юзать алгоритм водораздела в опенцв, при том что у меня даже пайтон не установлен.

В image-js был алгоритм fromWaterShed, но он нихуя не работал у меня в бас.

Поэтому мне пришлось ручками его переносить из сурсов.

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

Я решил начать сначала, с подбора алгоритма серого, потом возможно бахну эрозию и собеля или канни, чтоб получить контуры и выкину нахуй ту часть где контуры/

Сложно только, что картинки одного цвета с нечетким контуром

Потом я нашел ещё одно интересное решение. В image-js есть всякие такие проколы: monotoneChainConvexHull, localMaxima

Но в моем случае это наверное не очень подошло бы. Кароче, этот вариант я тоже развивать не стал.

Для решения проблемы наложения картинок у меня было несколько тупых идей:
1) градиентный фильтр
2) херовые точки выпуклых фигур
3) поиск картинки из базы на картинке
4) вычесть контуры
Но остановился я по итогу на контурах.

К чему я пришел в итоге?!

Ранее я писал что получилось делать 52%. Я брал картинку, убирал фон фильтром уровней, переводил в серое и делал маску. Потом, применял маску и дергал по ней те фигуры, которые больше 500. А после, под каждую делал квадратную подложку размером по максимальной стороне и уменьшал до размера 20 на 20. Увеличил их только сейчас для скрина.

Пьем чай и ни каких подвохов)

Далее я пытался разбираться с масками. Заметил, что фильтр шара неплохо режет что-то целое.

Потом, я пытался юзать 2 фильтра, светлый и темный и мерждить маски от них, в надежде получить удачный способ разделения картинок.

Ну и, разумеется, оно работало. Но хуево.

Следующим шагом стала фильтрация по цветам.

Я пытался по аналогии с opencv делать фильтрацию по цветам. Пытался понять что-то на вот этих всяких графках.

Я правда пытался понять как вот эти всякие цвета подбирать https://stackoverflow.com/questions/57469394/opencv-choosing-hsv-thresholds-for-color-filtering

Но в итоге, я просто сам методом научного тыка наугадывал диапазоны под каждый цвет и добил до 78%.

На простых примерах понятно, изи.

Однако, есть и проебы, а они бывают 2х видов:
1) Слипшиеся одноцветные (14)

2) Просто похожесть букв блять разных (8)

Хороший ли это результат, не знаю. Но вряд ли кто то еще проебал бы месяц на такую хуйню.

Поэтому я сел делать дальше, добавив разделение слипшихся одноцветных.

И в итоге добил до 80%

Ну а теперь перейдем к запросекам.

В отличие от остальных, тут все максимально просто. Тупо 2 координаты + параметр T.

Координаты в соответствии с картинкой.

Но есть нюанс, картинку опять ресайзит

Я решил не менять размер картинки сразу, чтобы не сбивать статичные настройки фильтров, но для лога и координат я сделал ресайз.

Значение T у меня было на тестах почему-то одинаковое. Поэтому, его я захардкодил. Помимо формирования JSON все остальное я выкинул.

Ну и в итоге все по красоте ебошило)

В том числе и на эмуляции, в пк и моб режимах

Теперь мы можем ебать все 3 капчи тт)

Но при работе с тт я столкнулся с ещё одной неприятной штукой

Age gate

Блять, это должно было быть легким, но я долго не мог разобраться, пока не подсказал товарищ про одну мелочь.

Казалось бы, окей, берем линию, дергаем текст у selected.

Потом дергаем все тексты и чекаем на какой позиции выбранный и сколько нам шагать до желаемого значения.

Написал отдельный генератор разбиения на свапы с шагом в n.

1) Только вот не все так просто. Вся ебля была вот здесь. Без блока двигать мышь оно начинало играть в angrybirds при шаге выше 1, вместо нормального свапа.

В целом, оно и сейчас иногда багает, но это пофикшено перечеком даты

2) Как не сложно догадаться, блоки идут на самом деле не по порядку. Нулевой индекс у блока с годом, потом у блока с месяцем и уже после идет с днём

Поэтому я сразу сделал генерацию даты в нужном формате и порядке.

3) Блок с днем, центральный блок, тоже оказался с подвохом.

Да, да, опять подвохи

Написано свойство селектед у одного, а по факту там у 24 было. Фиксанул докинув флаг. Перечек тож по итогу спасает.

4) Хорошее решение не всегда хорошо. Когда софт двигал положение пиксель в пиксель на правильную позицию, тт просто не выставлял это число. Тоесть еще один способ палева. У обычных людей так не бывает и должно срабатывать автоматическое докручивание до верной позиции.

Поэтому пришлось добавить небольшое смещение.

Ну а на этом всё, я пиздую пить чай