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.
271 lines
12 KiB
271 lines
12 KiB
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
|
|
СПАМ-БОТ
|
|
|
|
ЦЕЛЬ
|
|
Разработать спам-бота, используещего ресурсы компьютера-хоста для рассылки спама.
|
|
|
|
РЕЖИМЫ РАБОТЫ
|
|
Есть два основных режима:
|
|
- сбор контактов: только собираем адреса и контакты из локальных почтовых ящиков и отправляем на сервер
|
|
- сбор и рассылка: то же + спамим.
|
|
|
|
Исходные данные для работы бота - это
|
|
- текст письма
|
|
- вложения
|
|
- список адресов для рассылки
|
|
- векторы отправки (списки SMTP-серверов, локальный почтовый клиент)
|
|
|
|
Первые два пункта (письмо и вложения) бот получает с сервера.
|
|
Список рассылки и векторы отправки могут быть как внутренние, так и внешние:
|
|
- внутренние - это полученные с локальных ресурсов компьютера
|
|
- внешние - задаваемые с сервера.
|
|
|
|
Дополнительные режимы:
|
|
- работа по локально добытому списку рассылки, или по полученному с сервера;
|
|
- отправка через локальные почтовые клиенты, или через указанные сервером SMTP-сервера.
|
|
|
|
РАНДОМИЗАЦИЯ ПИСЕМ
|
|
Бот должен поддерживать рандомизацию писем и вложений, путем использования макросов в теле письма и именах вложений.
|
|
Макросы представляют из себя:
|
|
- словари (выбор случайного слова из словаря);
|
|
- генерация случайного числа;
|
|
- генерация случайной строки.
|
|
|
|
(Мысли вслух) есть два пути:
|
|
- рандомизация на сервере: плюсы в упрощении клиента, минусы в увеличении нагрузки на сервер
|
|
- рандомизация на клиенте: все наоборот.
|
|
|
|
ТРЕБОВАНИЯ
|
|
- связь с командным сервером для получения письма, вложений, списка адресов на рассылку и списка SMTP-серверов
|
|
- оформление в виде статически скомпонованного .exe
|
|
- соответствование требованиям в "оформление кода и сборок" по защите от анализа и детектов
|
|
- программа не должна делать попытки получить собственный путь
|
|
- программа не должна перезапускать себя
|
|
- программа должна работать с любыми правами - в том числе с правами СИСТЕМЫ!
|
|
- программа должна работать в любой сессии - как интерактивной (>0), так и системной (сессия 0)
|
|
Проверять psexec -d -s program.exe
|
|
- реализация обмена по HTTP - по умолчанию WinInet/WinHTTP. Однако нужно сделать простые обертки для HTTP-запросов,
|
|
чтобы легко и просто заменить реализацию
|
|
|
|
ЭТАПЫ РАЗРАБОТКИ
|
|
1. только сбор адресов с Microsoft Outlook
|
|
2. рассылка по собранным на этапе 1 адресам через Microsoft Outlook
|
|
3. получение адресов для рассылки с сервера, рассылка через Microsoft Outlook
|
|
4. вдобавок, рассылка по списку полученных с сервера SMTP-серверов
|
|
5. сбор с веб-почты GMail
|
|
6. рассылка через веб-почту GMail
|
|
7, 8 + Yahoo Mail
|
|
|
|
|
|
ПРОТОКОЛ
|
|
Протокол - обычный HTTPS.
|
|
HTTP-сервер ОБЯЗАН предоставлять заголовок Content-Length для каждого ответа.
|
|
Тела запросов и ответов должны быть зашифрованы простым XOR, используя URI как гамму (ключ шифрования).
|
|
То есть, для тела запроса GET /1/2/sv ключом шифрования будет строка /1/2/sv
|
|
|
|
-Зачеркнуто-
|
|
Связь с командным сервером происходит через домены .bazar (или другой домен Emercoin DNS).
|
|
Доменов может быть несколько; для первоначального соединения с сервером домены перебираются случайным образом
|
|
до первого успешного ответа. Программист должен исходить из того, что все домены ведут на один и тот же сервер.
|
|
|
|
После резолва IP-адреса из домена Emercoin, следует сделать пробу ДВУХ адресов:
|
|
- непосредственно полученный из DNS-ответа
|
|
- преобразовать IP-адрес путем операции XOR 254 для каждого октета. Например,
|
|
124.245.101.251 (получен из DNS-ответа) -> 130.11.155.5
|
|
|
|
Т.к. DNS-информация доступна каждому, таким образом защищаемся от абюзов по взятым из DNS-записи адресам.
|
|
|
|
Код скрипта ipxor.ps1 на PowerShell:
|
|
$ip = read-host -prompt "Enter IP";
|
|
write-host $ip;
|
|
$newip = '';
|
|
($ip.split('.') | foreach {
|
|
$octet = [byte] ( $_)
|
|
$octet = $octet -bxor 254;
|
|
$newip = -join($newip,'.',$octet);
|
|
}
|
|
)
|
|
write-host $newip;
|
|
-Конец зачеркнутого-
|
|
|
|
Связь с командным сервером происходит через жестко зашитый список IP-адресов.
|
|
Перебором выбирается первый адрес, отвечающий на порт 443 по протоколу HTTPS.
|
|
Дальнейшая работа происходит с ним.
|
|
|
|
При установлении соединения, в случае таймаута или обрыва соединения, следует повторить попытку один раз.
|
|
Далее следует перейти к перебору адресов до первого успешного ответа.
|
|
|
|
-Зачеркнуто-
|
|
При отстуке, следует иметь в виду, что обусловленная шифрованием XOR двойственность адресов может привести
|
|
случайным совпадениям: вам может ответить сервер, который ни сном ни духом.
|
|
-Конец зачеркнутого-
|
|
|
|
|
|
URI запроса имеет вид
|
|
|
|
/id_mailout/id_bot/request
|
|
|
|
где
|
|
- id_mailout - идентификатор рассылки - uint64_t
|
|
- id_bot - идентификатор бота - строка; по умолчанию это GUID в формате CBD27893-F9EB-465C-AAF6-D620ED24C8C9,
|
|
но также это может быть произвольная строка с допустимыми символами a-zA-Z0-9_-.
|
|
|
|
Оба параметра могут быть переданы боту извне, через аргументы командной строки либо переменные окружения.
|
|
По умолчанию формат ответа - простой текст с разделителем строк [\r]\n
|
|
|
|
По умолчанию, любые коды ответа кроме HTTP 200 или HTTP 102 является ошибкой (в том числе коды 204, 30*).
|
|
HTTP-код 102 "Processing" означает, что сервер не может дать ответ прямо сейчас, и следует повторить запрос через некоторое время.
|
|
В этом случае бот должен делать циклический опрос с интервалом 30 секунд, до получения не-102 кода.
|
|
В случае кода ошибки (не 200 и не 102) бот должен повторить попытку пять раз с интервалом в 5 секунд, до первого успеха.
|
|
При отсутствии успеха бот фиксирует ошибку и завершает работу.
|
|
При невозможности отпарсить и интерпретировать существенные поля из ответа сервера, бот фиксирует ошибку и завершает работу.
|
|
|
|
1. Дай параметры: интервал между письмами, тип списка рассылки, тип отправки, число вложений, контрольный ящик
|
|
GET /<idm>/<idb>/st
|
|
|
|
Ответ:
|
|
<interval>[\r]\n // число секунд между отправкой двух последовательных писем. 0 означает нету интервала. По умолчанию 0.
|
|
<mailout_type>[\r]\n // битовая маска: 1 - все адреса с локального десктоп-клиента;
|
|
// 2 - все адреса с локальных учеток веб-почты;
|
|
// 4 - получить список рассылки с сервера;
|
|
// остальные значения (биты) - ошибка
|
|
<send_type>[\r]\n // битовая маска: 1 - отправка через десктопный локальный почтовый клиент;
|
|
// 2 - отправка через локальные учетки веб-почты;
|
|
// 4 - отправка через полученный с сервера список SMTP-серверов
|
|
// не выставлен ни один бит - только сбор контактов
|
|
// остальные значения (биты) - ошибка
|
|
<attach_num>[\r]\n // число вложений для письма: от 0 до 10 (другие значения - ошибка)
|
|
<rcpt_every>[\r]\n // одно письмо на указанное число получателей; дополнительные получатели указываются в Bcc:
|
|
<random_every>[\r]\n // рандомизировать каждое Н-е письмо
|
|
<control_mailbox>[\r]\n // контрольный почтовый ящик
|
|
<validate_emails>[\r]\n // нужно ли валидировать email-адреса после сбора: 0 - нет, 1 - да
|
|
|
|
2. дай тему
|
|
GET /<idm>/<idb>/sb/<number>
|
|
|
|
В ответ - тема письма, по одной на строку (можно получить сразу множество тем).
|
|
<number> - запрашиваемое число тем.
|
|
В этом запросе и в запросе №3, параметр <number> используется для минимизации числа запросов к серверу.
|
|
Чтобы, к примеру, получить 1000 писем за один раз.
|
|
|
|
3. дай письмо
|
|
GET /<idm>/<idb>/m/<number>
|
|
|
|
<number> - запрашиваемое число писем.
|
|
В ответ - текст письма в том виде, как оно должно быть отправлено.
|
|
Здесь возможно уточнение - т.к. письмо может быть в multipart-контейнере.
|
|
Если все почтовые клиенты позволяют задать письмо в сыром виде (со всеми разделителями контейнеров итд),
|
|
то в ответ на этот запрос мы получаем полностью сверстанное сырое тело.
|
|
В противном случае, нужны подзапросы для получения всех частей multipart-письма.
|
|
|
|
4. дай вложение №
|
|
GET /<idm>/<idb>/a/<№>
|
|
|
|
Здесь № - номер вложения от 1 до 10.
|
|
Ответ должен содержать заголовок Content-Disposition, однозначно определяющий имя и MIME-тип вложения.
|
|
Отсутствие этого заголовка является ошибкой.
|
|
Содержимое ответа интерпретируется по HTTP-заголовкам ответа (контейнер, заголовки сжатия итд).
|
|
|
|
5. дай список рассылки
|
|
GET /<idm>/<idb>/l
|
|
|
|
В ответе содержится простое перечисление email-адресов, на которые следует отправить письмо.
|
|
Один адрес на строку.
|
|
|
|
6. дай сервера отправки
|
|
GET /<idm>/<idb>/sv
|
|
|
|
В ответе содержится простое перечисление SMTP-серверов, через которые следует отправить письмо, по одному на строку.
|
|
Формат строки:
|
|
[<proto>:]<IP-address>:<port>:<user>:<password>[:field=value[:field=value...]]
|
|
Содержимое поля proto указывает на необходимость работы поверх SSL-канала.
|
|
Уточнить.
|
|
|
|
Параметры field=value предназначены для отправки дополнительных полей, например, DNS-записей, RSA-ключей, селекторов итд.
|
|
Число и назначение полей интерпретируется конкретной реализацией сервера и бота.
|
|
|
|
|
|
7. возьми контакты
|
|
POST /<idm>/<idb>/c
|
|
|
|
Содержимое тела запроса - простой текст (БЕЗ КОНТЕЙНЕРА multipart или form-urlencoded!)
|
|
по одной записи контакта на строку, в кодировке UTF-8.
|
|
Запись контакта имеет следующий формат:
|
|
field=value;field=value;...;field=value\r\n
|
|
Все значения value в кодировке urlencoded.
|
|
Для field поддерживаются следующие значения:
|
|
|
|
email
|
|
firstname
|
|
midname
|
|
lastname
|
|
country
|
|
state
|
|
city
|
|
zip
|
|
street
|
|
phone
|
|
url
|
|
|
|
Любые неизвестные значения подлежат сохранению сервером в БД! Для этого должен быть предусмотрен механизм,
|
|
позволяющий сохранить расширенные поля контакта.
|
|
При этом нужно исключить отказы в обслуживании за счет отправки гиганстких запросов.
|
|
|
|
Если объем отправки превышает порог (задается константой компиляции), бот обязан раздробить отправку
|
|
на соответствующее число запросов. По умолчанию предел запроса - 2М.
|
|
|
|
8. возьми информацию
|
|
POST /<idm>/<idb>/info
|
|
|
|
Содержимое тела запроса - простой текст (БЕЗ КОНТЕЙНЕРА multipart или form-urlencoded!)
|
|
следующего вида:
|
|
|
|
os: <название и версия ОС>
|
|
arch: <архитектура машины x86/x64>
|
|
hostname: <имя компьютера>
|
|
username: <имя пользователя>
|
|
domain: <домен или рабочая группа>
|
|
tz: <временнАя зона>
|
|
locale: <локаль>
|
|
ip: <внешний IP-адрес>
|
|
client: <название и версия локального почтового клиента, если найден. Таких строк может быть много>
|
|
webmail: <URL и учетка почтового клиента, если найден. Таких строк может быть много>
|
|
me: <email и контакты локальной почтовой учетной записи. Таких строк может быть много>
|
|
|
|
Бот может отправлять больше информации в формате поле:значение - этот запрос может подлежать расширению.
|
|
Реализация сервера должна учитывать это и быть готовой сохранить неизвестные данные.
|
|
|
|
9. возьми статистику
|
|
|
|
POST /<idm>/<idb>/info
|
|
|
|
Содержимое тела запроса - простой текст (БЕЗ КОНТЕЙНЕРА multipart или form-urlencoded!)
|
|
следующего вида:
|
|
|
|
sent: <всего писем отправлено, штук>
|
|
addresses: <всего адресатов>
|
|
|
|
Таких запросов бот может отправить множество в течение одной сессии работы, для отражения прогресса рассылки.
|
|
Сервер ориентируется на последний полученный от бота запрос.
|
|
|
|
|
|
АЛГОРИТМ РАБОТЫ
|
|
|
|
Принципы установки связи с сервером отражены в разделе ПРОТОКОЛ.
|
|
|
|
После старта бот должен:
|
|
1. установить связь с сервером - найти живой домен, дать запрос GET / HTTP/1.1 и убедиться в том,
|
|
что код ответа 200.
|
|
2. собрать информацию о системе и отправить ее на сервер. По ответу сервера убедиться,
|
|
что это "наш" сервер, иначе завершить работу.
|
|
3. запросить с сервера режимы работы
|
|
4. если указано в режимах, собрать адреса с локальных почтовых клиентов, провалидировать их и отправить на сервер.
|
|
5. если указано в режимах, произвести рассылку писем.
|
|
5.1. при рассылке, отражать прогресс путем периодической отправки статистики (раз в 1000 адресов или 1 минуту, что наступит раньше)
|
|
6. самоудалиться с диска (если указано в опциях сборки).
|
|
|
|
ДОПОЛНИТЕЛЬНО
|
|
Имеется готовый исходный код для:
|
|
- сбора адресов и отправки писем через Microsoft Outlook
|
|
- сбора адресов и отправки писем через Gmail и Yahoo! Mail
|
|
|