javascript

Обманываем систему мониторинга Discord-серверов: self-bot + LLM против капчи

  • пятница, 6 марта 2026 г. в 00:00:06
https://habr.com/ru/articles/1006630/

Сейчас в Discord до сих пор популярны мониторинги серверов, где можно продвигать свой сервер либо заплатив, либо каждые n часов бамкать его через бота. Крупные сервера часто дают людям, повышающим рейтинг сервера, приятные бонусы, чтобы не опускать сервер в рейтингах. Однако, можем ли мы обмануть систему?

На одном из серверов было 4 бота: SD.C Monitoring, Server Monitoring, DSMonitoring и DISBOARD. Последние два достаточно прямолинейные боты: у каждого есть команда, которую нужно вызвать через n часов или позже, чтобы поднять сервер в мониторинге. Однако первые два имеют заметную проблему: капча.

Если SD.C Monitoring ещё имеет понятную капчу и её решение вводится фактически в ту же команду только с аргументами, то капчу от Server Monitoring я и сам не всегда могу разгадать. Более того, её решение нужно вводить в модальное окно (не такое старое нововведение Discord, но у ботов его вижу редко).

Как вообще представиться в Discord человеком?

Во времена библиотеки discord.js версии 11 API для пользователя и для бота фактически не различались, как и одна из первых версий 12 той же библиотеки. Однако в ней же, но чуть позже, ввели ограничение - нельзя использовать токены от аккаунтов Discord. Фактически это называется self-bot, на то время достаточно частое явление.

Эти методы устарели с выходом API v13, в которой добавили интерактивное взаимодействие с ботами (в том числе модальные окна). Однако когда-то была создана библиотека discord.js-selfbot-v13, которая ныне депрекейтнута, но подходит под наши цели и содержит необходимый функционал и относительно подробную документацию. Все основные функции по получению фотографии и отправке ответа удалось в последствии реализовать через эту библиотеку, не прибегая к вызовам API напрямую, как это было в черновом варианте кода.

Главная задача - разгадать капчи

Стандартные методы решения через OCR, заточенные на решение похожих капч, не сработали: распознавание крайне низкое и не подходило готовое решение. А чтобы обучить модель OCR, нужно хотя бы 500+ фотографий. У меня же на руках было около 40 примеров, собранных участниками сервера, и те были не прямо таки идеальными. Человеческий фактор берёт своё - некоторые изображения были .jpg или .tff формата, хотя оригинал был .png.

Альтернативно я заметил, что большие LLM запросто решают такие капчи. Grok, DeepSeek или GPT идеально видели все эти капчи, а значит, их младшие братья должны быть способные на схожее. Gemma-3-12b от Google имело нейрозрение, и при тестах через LM Studio результаты оказались положительными. LLM видела капчу достаточно точно, и распознавание было что-то около 60%, но это очень неточные цифры, ведь выборки у меня как таковой нет.

Однако, экспериментируя с промптами, нашёл закономерность, влияющую на точность распознавания. Поиск в интернете привёл меня к тому, что нужно в промпте к фотографии прямо таки чётко указывать, что у 9 есть маленький хвостик снизу, а у 0 нет отростков и т.д. Но по факту самым эффективным промптом оказалось "Смотри внимательнее, это капча". Я не сильно разбираюсь в LLM, но если кто-то знает, почему такой абстрактный промпт может эффективно действовать на распознавание - с удовольствием бы прочёл в комментариях.

Чтобы ещё больше поднять точность, я добавил дополнительные фильтры для капчи. Сначала обычным JS-кодом через canvas капча прогонялась через несколько фильтров (контраст, яркость, инверсия, шумоподавление и тому подобное), а потом совсем маленькая LLM (Скорее даже OCR) решала, какой из этих фильтров дал самый читаемый результат. Эта связка тоже заметно улучшила распознавание: LLM уже не приходилось работать с "сырой" картинкой.

Железо и тайминги

Gemma-3-12b способна работать на процессоре, но очень медленно, а боты имеют ограничение на разгадывание капчи в 15 секунд. Благо, у меня была старая видеокарта GTX 1070 на 8 ГБ ОЗУ, и часть модели удалось загрузить в неё, что очень сильно ускорило распознавание и время ответа. В среднем около 8-10 секунд, что укладывалось в необходимый участок времени.

Что дальше

В дальнейшем планирую заменить LLM на OCR, т.к. текущий бот пассивно выписывает все решённые и нерешённые капчи в чат, собирая датасет для обучения. Обученную OCR и датасет я планирую выложить на GitHub/GitLab.

Если у кого-то есть идеи, как ускорить сбор датасета или улучшить промпт ещё сильнее - пишите в комментариях. Буду рад обсудить!