Tutanota и капча с часами
Цель жизни - въебать тутаноту (или хотябы тикток).
В очередной раз, все началось с вопросика в чате
Я в ответ в чатике написал небольшой обзор подходов, как ее можно было бы решать. И сразу написал в лс автору вопроса и.. игнор, час, два. Кто вообще спит в 5 утра? Хотя на след день мне уже ответили.
А я вообще-то потыкать ее хотел. Нахуя тогда было спрашивать..(
- Как узнать время по часам https://ru.wikihow.com/%D1%83%D0%B7%D0%BD%D0%B0%D1%82%D1%8C-%D0%B2%D1%80%D0%B5%D0%BC%D1%8F-%D0%BF%D0%BE-%D1%87%D0%B0%D1%81%D0%B0%D0%BC
- Аналоговые часы на JS https://gohtml.ru/js/82-canvas-s-nulya-analogovyie-chasyi-na-js
- Часы отрисованные canvas https://ru.stackoverflow.com/questions/859941/%D0%A7%D0%B0%D1%81%D1%8B-%D0%BE%D1%82%D1%80%D0%B8%D1%81%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-canvas
Тогда я подумал: В пизду, сам блять найду эту капчу и выебу ее нахуй
И где же я ее нашел? в Яндексе, а в Гугле блять нихуя! Хотя, странно что оно гит коммит проиндексировало.
https://github.com/tutao/tutanota/commit/23017c06e4291acf9cd9265749ec055cc4ac78bb.patch
https://github.com/tutao/tutanota/commit/23017c06e4291acf9cd9265749ec055cc4ac78bb
https://github.com/tutao/tutanota/blob/f52ac6e09af03925863d76410fd0862b147c58f4/src/subscription/Captcha.ts
https://github.com/tutao/tutanota/blob/c3637bf6487431c7383b49da033e894adc19bd06/test/tests/subscription/SignupFormTest.ts
Еще было обсуждение на форуме зенки. Я мельком почекал, но чужие решения мне не сильно инетересны
Нашел про капчу часы в блоге протона, но примера не нашел там https://proton.me/blog/captchas
Похуярили
Даже зная что искать, капчу получить мне удалось не сразу, пришлось по перебирать прокси.
Сразу бросается в глаза то, что часы разных размеров и расположены в разных частях картинки. Тогда над для начала кропнуть их.
Проходимся по всей картинке, ищем границы чекая черные пиксели.
Кропаем картинку по полученным координатам. Пока всё довольно просто.
Акей, теперь мысля следующая, нам надо как-то рисовать круги зная радиус. Я решил поискать другой варик, не тот что скинул в ориг ответе, чуток погуглил и нашел ответ на хабре https://qna.habr.com/q/623933
И в итоге накидал следующий код, чтобы рисовать кружок.
Я перегнал градусы в другую систему координат, чтоб можно было считать позицию X и Y.
Прошелся по всему кругу, увеличивая позицию на шаг. Тк шаг мелкий, а пиксель большой, сейвил позицию ласт пикселя, чтобы 2 раза его не считать потом. Дополнительно +радиус к позиции, тк в радианах оно считает типо от центра, а у нас 0 это лево верх.
Докинем лог и получим чет типо этого, если чекать и менять цвет пикселя. Тогда остается сделать так, чтобы проходило по кругу в некотором диапозоне и как-то понимать где какая стрелка.
Если мы будем двигаться из центра наружу, то нам получается нужно найти сначала центр, выкинуть центральный круг и двигаться от его позиции, потом найти первый пиксель и засейвить его положение в градусах, чтобы следить отдельно тк мы не знаем какая именно это стрелка. Потом ждать на каком из диапазонов, первом или большом, кончается черные пиксели, что в итоге и станет ответом на вопрос какая первая была стрелка. Если обе были на 1 позиции, то во втором диапазоне изначально не будет черных пикселей.
Я не очень умный, поэтому подумал сделать все наоборот, искать первую - большую, а потом мелкую, двигаясь из наружи к центру.
А еще, вдруг картинка повернута, как например тут или хуже, значит над в любом случае будет искать где начало.
На самом деле, в любом случае нужно искать границы для стрелок, чтобы учесть ситуацию, где обе стрелки в 1 положении, иначе оно будет ебошить либо в 0, либо на край капчи и проще сразу это учесть)
И так уж совпало, что начало - цифра 1, всегда прорисована твердо и четко, поэтому я захардкодил ее поиск. Делим на 8 частей и в 4 ищем длинную прямую палку.
Двигаемся сверху вниз (y), справа налево (x), чтоб быстрее добраться и прийти от зеленой точки к синей. Ищем черный пиксель. К синей (левому краю), тк в ситуации с зеленой стрелкой (12-60 минут), у нас самой нижней точкой может оказаться стрелка, а нужно получить нижнюю точку единички, потому ищем макс нижнюю левую.
Она будет нашим отступом от края по всей длине окружности.
В итоге получим вот такую границу.
Теперь надо найти границы центрального кружка, чтобы установить нижнюю границу для диапазона поиска. Я просто двигался в 4 стороны по 1 пикселю, пока не встретил не черный на как минимум 2х позициях.
В итоге я все накидал, но столкнулся вот с такой хуйней. Я не оч умный, хоть и видел всякое дерьмо, но даже я ахуел. Хотя казалось бы, база.. (зеленым выделил диапазон, который скипается при проверке).
Речь про лог. Если чекнуть внимательно, видно как на переменную в итоге влиял реверс. Массив перемешивается в процессе работы, блен, это ж типо другая функция.. хуле оно так делает. Зелененький диапазон распидорасило, неприятненько.
Вот более простой пример, чтобы было понятно о чем речь.
Все дело в старом советском .. Копировани объектов и ссылки и нет, const тут не поможет. Вот еще пример.
Ебучий, сука, JS, блять, ебучее программирование.
Да, это говнокод.. Но суть не поменялась, через searchPos мы перебираем круги и чекаем ответ и сервим черные пиксели, при том передавая диапазон если нашли первую стрелку. А через getPos просто рисуем кружок и собираем черные пиксели, исключая диапазон, если он передан.
Также важно не забыть, что у нас на часах 0 там где 12, а у тригонометрического круга там где 3 и при том, на нем отсчет против часовой, поэтому надо докинуть 90 градусов и потом пересчитать их. Всё довольно логично.
Функцию определения координат предложила чат гпт.
Ошибку я случайно заметил на тестах, тупо вхуячив ее код.. ненадо так делать.
8:60, очевидно, не пройдет валидацию
Я ее трохи поправил, чтоб округляло времени до 5 минут - нашего шага в капче.
И для часов пофиксил округление, чтоб не было как на центральном примере (9:00).
Однако, я не мог остановиться просто на одной капче и решил сделать регер.
Реверс!?
Ну я и сел тыкать че же там после капчи.
А после капчи какой-то пиздец. Более того, еще и минуту ожидания зачем-то (pow).
Ладно, поехали разбираться с проблемами по мере поступления.
Другое дело) Тогда можно будет тупо фул код подрезать..
Трохи поресерчим, что тут происходит
Ясна понятна, криптография ебучая значит
Хмммм.. https://www.npmjs.com/package/@tutao/tutanota-crypto?activeTab=explore
Штош, раз просто так взять и поставить либы нельзя, летс гоу хэнд джоб
Ну а потом я тупо взял и перенес каждый файл, добавил все нужные импорты и фсе. Всего-то 2 дня ушло.. (если правильно помню)
Как он работает? Ну.. он работает.. да.
По сути я тупо подтянул весь код который был нужен из всех файлов и чуть поправил. Наверное можно было проще, спиздить из воркера, но я не догадался.. или не получилось, не помню уже.
Ещё, вот эт хуйню вынес в отдельный блок, она по сути и майнила минуту у меня ключи с браузера. https://www.npmjs.com/package/jsbn-rsa
По порту файлов в ноде баса я спросил у Ghost, и он поделился багой - утечкой памяти и ее решением.
Тоесть нужно сейвить в глобалку, чтобы постоянно не дергать файлы.
А я прост в объект все сейвил и фсе. Кароч, наверное так не надо делать.
Тесты
Тутанота сосатб. Капча решается.
Код работает. Я вообще в ахуе, что оно без всяких тестов завелось. Столько кода и сразу все работает. Вот что значит копипейст)