ЗАДАНИЕ НА РАЗРАБОТКУ МОДУЛЯ ПОДБОРА ПАРОЛЕЙ К OUTLOOK WEB ACCESS (OWA)
Цель модуля - распределенный подбор паролей к OWA
* Пометка (отложить) означает, что этот функционал пока не нужно реализовывать.
ПРИНЦИП РАБОТЫ
Модуль получает с сервера следующую информацию в виде конфигов:
- список логин:пароль для подбора
- список настроек
- список серверов DPOST
Модуль состоит из двух частей:
- кроулер
- сканер
Кроулер генерирует url для проверки.
Сканер их проверяет.
Принцип работы кроулера: случайный обход доменов из топ-50000 списка наподобие Алекса.
Точный источник данных для обхода пока неясен - у Алексы платная подписка. Нужно найти альтернативу.
s3.amazonaws.com/alexa-static/top-1m.csv.zip
Например, https://www.quantcast.com/top-sites/US/3
(отложить) Запасной вариант: работа по жестко заданному списку сайтов, полученному с сервера.
Далее, модуль:
1. берет следующий сайт с выхода кроулера
2. проверяет наличие пути /owa
3. проверяет наличие пути mail.domain.com/owa
4. проверяет наличие пути webmail.domain.com/owa
5. если owa не найден ни по одному пути, goto 1
7. берет следующую пару логин:пароль из словаря
8. отправляет HTTP-запрос для логина в owa.
9. при неудаче логина, goto 7
10. при успехе, добавляем найденную комбинацию в список найденных логинов, в виде url|логин|пароль
РЕАЛИЗАЦИЯ
0. Название проекта - owa.
При реализации, следует сделать следующее (описание алгоритма существенно упрощено):
1. брут-форс должен производиться в несколько потоков.
Выбор конкретной схемы многопоточности за разработчиком.
Можно предложить следующий вариант:
* кроулер работает в один поток, все найденные url складывает в очередь (защищенную мютексом).
Потоки сканирования (число ограничено) берут несколько url для сканирования из очереди (это вариация пула потоков).
Каждый поток сканирования работает по Н случайно выбранным сайтам из списка.
При неудаче логина берется следующий сайт, а текущий ставится в конец очереди.
То есть, брут производится циклически по Н сайтам, чтобы не давать пик нагрузки на один и тот же сайт.
Если для сайта был найден пароль, он убирается из очереди.
- число потоков задается константой компиляции и настройкой из конфига
- модуль минимизирует число вызовов connect() для открытия TCP-соединений. Между итерациями, соединение следует держать
открытым до тех пор, пока сервер его не закроет. В этом случае, соединение следует переоткрыть.
Если попытка переоткрытия соединения не удалась дважды подряд, прекращаются попытки соединиться с данным сайтом на полчаса
(константа задается во время компиляции).
2. нужно предусмотреть задержку в секундах между итерациями подбора (также константа компиляции и настройка из конфига)
3. нужно предусмотреть настройку User-Agent. Он должен конфигурироваться как константа компиляции,
и как настройка модуля.
4. нужно предусмотреть, что сайт может реагировать на куки. К примеру, отказаться работать, если не получит куки,
отданные на изначальный GET / HTTP/1.1
5. Модуль отправляет список найденных паролей раз в Н минут (задается константой компиляции и настройкой из конфига),
при условии что с предыдущей отправки были найдены новые пароли.
Логика отправки и протокол описаны в документе "ТЗ граб паролей DPOST.txt"
6. (отложить) если брут не дал результатов, следует начать проверку по словарю.
URL словарей для скачивания берется из конфига "список настроек".
7. Модуль оформляется в соответствии с правилами разработки модулей (см. modules_HOWTO.txt)
8. Модуль отправляет следующие события с тегом owa:
- "Version build %DATE% %TIME%" (один раз при старте)
- "OWA passwords sent to DPOST server" при успешной отправке собранных паролей
- "OWA passwords send failure: servers unavailable" при отсутствии доступных серверов DPOST
- "No OWA passwords in range; trying dictionaries", если закончена отработка по всему списку, ничего не найдено, и начата отработка по словарям
- "No OWA passwords; give up", есди закончена отработка по словарям, и ничего не найдено.
В таком случае, модуль должен выдать событие WantRelease (см "module_HOWTO") для выгрузки из памяти
9. В данном модуле можно ограниченно использовать C++ STL (std::string, контейнеры).
Запрещено использовать std::mutex и примитивы синхронизации - для этого можно использовать только
примитивы синхронизации WinAPI (CRITICAL_SECTION итд).
10. Строки обфусцировать библиотекой Andrivet (приложена, см.макрос _STR())
11. Системные вызовы обфусцировать библиотекой GetApi.h. Быть внимательным, обфускация сисвызовов может давать падения.
12. Модуль должен иметь две версии - x32- и x64-разрядную.
13. В боевой сборке должны быть обфусцированы по максимуму строки, отключен всяческий отладочный вывод.
14. Модуль должен иметь отладочную версию. Отладочный вывод должен выводиться в c:/temp/owa.log (путь к логу настраивается в макросе).
15. В проекте должен быть файл настроек config.h (название неважно, важна суть - здесь все глобальные настройки - пути, макросы-переключатели условной компиляции итд).
16. Модуль должен работать на всех современных версиях Windows.
Минимальная поддерживаемая версия Windows - Windows XP (если невозможно - Windows Vista).
17. Проект должен быть оформлен для сборки в Microsoft Visual Studio не ниже 2015.
18. Проект Visual Studio должен быть настроен следующим образом:
* Для ВСЕХ профилей сборки:
- выходной каталог: $(SolutionDir)Bin\$(PlatformTarget)\$(Configuration)\
- Промежуточный каталог: $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
- Многопроцессорная компиляция: да
* Профиль Release:
- Формат отладочной информации (С/С++ создание кода): нет
- Создавать отладочную информацию (компоновщик/отладка): нет
КОНФИГИ
Имя конфига - это аргумент Ctl функции Control, содержимое конфига - это аргумент CtlArg (см. modules_HOWTO.txt)
Весь текст в конфигах регистрозависимый; теги и служебные значения должны быть в нижнем регистре.
Конфиги должны быть в любой однобайтной кодировке (предпочтительно ASCII).
XML-комментарии запрещены.
* settings
Конфиг представляет из себя простой xml в следующем формате:
задержка между итерациями подбора, в миллисекундах
число потоков подбора
число url, проверяемых одним потоком (циклически)
user agent
(отложить)URL дополнительного словаря 1
(отложить)URL дополнительного словаря 2
(отложить)URL дополнительного словаря 3
...
URL дополнительного словаря N
Все параметры из этого конфига опциональные. Если параметр не указан, используется константа времени компиляции.
* dpost
Конфиг представляет из себя простой xml в следующем формате:
http://11.22.33.44:8082
127.0.0.1:8083
Префикс http/https к обработчику опционален. Если он указан, следует работать по указанному протоколу.
Если он не указан:
- если значение порта чётное, то работа идёт без шифрования (HTTP), если порт нечётный, то работа идёт поверх SSL/TLS (HTTPS).
Конфиг содержит список серверов, на которые следует отправлять результаты по протоколу DPOST.
Формат отправки: простой текст; разделитель строк - \r\n, разделитель полей - символ '|' (вертикальная черта).
Формат записи:
url|user|password\r\n
* pw
Список пар "имя пользователя" "пароль".
Текст в упаковке gzip.
формат строки username|password\r\n
(отложить) * sites
Конфиг представляет из себя простой текстовый список, разделитель строк - символы \r\n
Каждая строка - одно доменное имя. Может как содержать префикс протокола http(s)://, так и не содержать.
В этом случае, при брут-форсе следует пробовать оба префикса.
(отложить) * dict
Конфиг представляет из себя простой текстовый список, разделитель строк - символы \r\n
Каждая строка - пара логин|пароль. Разделитель полей - символ '|' (вертикальная черта).
(отложить) * ignore
Конфиг представляет из себя простой текстовый список, разделитель строк - символы \r\n
Каждая строка - URL.
Сюда будут включены адреса топ-сайтов вроде gmail.
Адреса из этого списка следует игнорировать при переборе. Имеется в виду адрес текущего сканируемого домена,
а не доменная часть текущего перебираемого email-адреса.
ВТОРАЯ ВЕРСИЯ
Основные изменения второй версии:
- новый режим проверки
- работа с командным сервером
РЕЖИМ ПРОВЕРКИ
В этом режиме модуль не ищет новые пароли, а проверяет имеющуюся базу на актуальность.
Соответственно, в этом режиме:
- сканер работает не по списку Alexa, а берет на вход очередной email из словаря email:password
- алгоритм поиска URL OWA сохраняется (угадываем url'ы вида webmail.domain.com/owa)
- по одному домену (точнее, по угаданному URL OWA этого домена) мы проверяем одну конкретную пару email:password
- добавляется настройка mode=check|brute, где check - режим проверки, brute - режим поиска и брутфорса (логика первой версии).
По поводу конфигов и словарей см.дальше.
КОМАНДНЫЙ СЕРВЕР И КОНФИГИ
Ранее мы получали все исходные данные в виде конфигов от бекенда ботов.
Это довольно неудобно по разным причинам - ограничения бекенда на размеры конфигов,
ограничения на управление конфигами оператором, отсутствие общего статуса сети,
отсутствие специализированного хранилища для результатов.
Вместо этого будет использоваться командный сервер, у которого мы просим настройки и входные списки,
и которому отдаем добычу.
В связи с этим, упраздняются все конфиги из первой версии.
Появляется новый конфиг srv, содержащий список адресов управляющего сервера,
разделенных \r\n или \n, в формате адрес:порт.
Если порт четный, работа идет по HTTP, если нечетный - HTTPS.
Если указан префикс протокола (http/https), префикс имеет приоритет над указанным портом.
Модуль работает с тем управляющим сервером, до которого удалось достучаться первым, по каждому запросу.
Получить режим работы можно HTTP-запросом на сервер
GET ///owa/mode HTTP/1.1
Значения group и clientid - это поля struct ParentInfo
CHAR ParentID[256];
CHAR ParentGroup[64];
(см. module_HOWTO)
В теле HTTP-ответа модуль ожидает строку brute или check.
Любое другое значение некорректно - в таком случае модуль делает повторные запросы
каждые 5 минут; до получения корректного ответа работа модуля не начинается.
Сканер получает список доменов для проверки HTTP-запросом на сервер
Число потоков сканирования:
GET ///owa/th HTTP/1.1
В ответ - неотрицательное число.
Если atoi(ответ) == 0, то число потоков по умолчанию = std::thread_concurrency() - 1.
GET ///owa/domains HTTP/1.1
Формат ответа:
адрес1[\r]\n
домен2[\r]\n
...
(одна или множество записей)
При завершении перебора по выданному списку мы даем знать об этом серверу:
GET ///owa/over HTTP/1.1
Ответ сервера - такой же, как на запрос /domains - новый список доменов для работы.
При неожиданном ответе (пустой список, код ошибки итд) модуль переходит на холостой ход (сканирование остановлено)
и делает тот же самый запрос раз в 10 минут (время - в константу).
Словарь для перебора получаем HTTP-запросом к управляющему серверу:
GET ///owa/dict HTTP/1.1
В ответ нам приходит словарь либо как text/plain, либо application/gzip (смотрим на заголовок ответа Content-Type)
Если упаковка в gzip, то после распаковки мы ожидаем такой же формат словаря, как для простого текста.
Формат:
email:password[\r]\n
Отправка делается по протоколу DPOST (см. "ТЗ граб паролей DPOST" для описания протокола) запросом
POST ///owa/81 HTTP/1.1
Собранные данные отправляются в контейнере multipart/form-data с полями source и data.
Значение поля source - "OWA Passwords"
Значение поля data: простой текст, разделитель строк \r\n
Формат записи:
owa|url||\r\n
...
(одна или множество записей)
Частоту отправки намайненных данных можно получить с управляющего сервера HTTP-запросом
GET ///owa/freq HTTP/1.1
В теле ответа мы ожидаем число - это число секунд, не чаще которого следует отправлять данные.
Если это 0 - отправка сразу по готовности нового результата.
Если это положительное число - мы накапливаем записи в буфере и отправляем раз в X секунд,
очищая буфер при успешной отправке.
При завершении перебора по выданному списку мы даем знать об этом серверу:
GET ///owa/over HTTP/1.1
Ответ сервера - такой же, как на запрос /domains - новый список доменов для работы.
При неожиданном ответе (пустой список, код ошибки итд) модуль переходит на холостой ход (сканирование остановлено)
и делает тот же самый запрос раз в 10 минут (время - в константу).