diff --git a/README.md b/README.md index 90d9c1c..7e15699 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,8 @@ git add * # Добавляем написанный код в комит git commit -m 'Написал код' # Комитим в локальную ветку git push origin my_dns # Пушим свою ветку в репозиторий # Теперь в интерфейсе https://gitea.serafimdev.com/serafim/dos создаём пул реквест и пишем мне в тг -``` \ No newline at end of file +``` + +Для компиляции: +g++ DosAtk.cpp -lcurl +Если ошибка отсутствия заголовочного файла "curl.h", то нужно установить: sudo apt-get install libcurl4-openssl-dev \ No newline at end of file diff --git a/src/DosAtk.cpp b/src/DosAtk.cpp index 725ef8f..e4ea23f 100644 --- a/src/DosAtk.cpp +++ b/src/DosAtk.cpp @@ -10,36 +10,42 @@ #include #include -// ====== DCL ====== // +std::string attack_type; // Тип атаки: scan или syn +std::string domain; // Доменное Имя +std::string ip; // Ip жертвы +std::string port; // Порт +std::string log_file; // Путь к директории для логов +std::string telegram_id; // Telegram ID для уведомлений +std::string telegram_token; // Токен бота +int n_ok_requests; // Количество успешных запросов +int n_fail_requests; // Количество не успешных запросов +std::chrono::system_clock::time_point start_timestamp; // Начальное время работы +std::string log_msg; // Сообщение, которое будет записано в лог-файл +std::string fin_msg; // Сообщение, которое будет выведено в консоль пользователю +std::string msg; // Сообщение, которое будет отправлено в телеграм -std::string attack_type; -std::string domain; -std::string ip; -std::string port; -std::string log_file; -std::string telegram_id; -std::string telegram_token; -int n_ok_requests; -int n_fail_requests; -std::chrono::system_clock::time_point start_timestamp; -std::string log_msg; -std::string fin_msg; -std::string msg; +// ====== end of DCL ====== // +// Данная процедура записывает в глобальные переменные параметры +// (attack_type, domain, ip, port, log_file, telegram_id, telegram_token) проводимой атаки, поступившие при вызове программы +// На вход получает int argc, char **argv, возвращает код выполнения +// Коды возврата: +// 2 - Атака флуд, все нужные опции есть +// 1 - Атака порт скан, все нужные опции есть +// 0 - нужна помощь +// -1 - пользователь не ввел тип атаки или ввел неверный тип атаки +// -10 - Пользователь выбрал тип атаки порт сканнинг, но не ввел нужные параметры +// -20 - Пользователь выбрал тип атаки флуд, но не ввел нужные параметры +// -101 - неизвестная опция или потерян аргумент, следует предложить вызвать флаг помощи +// -600 - пользователь ввел токен, но не id или наоборот int my_check_params(int argc, char **argv) { - std::string debug_msg; - debug_msg = ""; - for (int i = 0; i < argc; i++) { - debug_msg += argv[i]; - debug_msg += " "; - } - printf("begin my_check_params (argc: %i, argv: %s)\n", argc, debug_msg.c_str()); - int status; int opt; - const char* short_options = "a:d:i:p:l:t:b:h"; - const struct option long_options[] = { + const char* short_options; + short_options = "a:d:i:p:l:t:b:h"; + const struct option long_options[] = + { {"attack", required_argument, NULL, 'a'}, {"domain", required_argument, NULL, 'd'}, {"ip", required_argument, NULL, 'i'}, @@ -51,6 +57,14 @@ int my_check_params(int argc, char **argv) {NULL, 0, NULL, 0} }; + std::string debug_msg; + debug_msg = ""; + for (int i = 0; i < argc; i++) { + debug_msg += argv[i]; + debug_msg += " "; + } + printf("begin my_check_params (argc: %i, argv: %s)\n", argc, debug_msg.c_str()); + while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'a': @@ -109,6 +123,8 @@ int my_check_params(int argc, char **argv) return status; } +// Данная функция вызывается в случае ошибки на каком-то этапе и на основании поступившего кода, +// формирует сообщение с описанием произошедшей ошибки void my_diag(int status) { printf("begin my_diag (status: %i)\n", status); @@ -145,18 +161,115 @@ void my_diag(int status) printf("end my_diag\n"); } -void my_msg() -{ - printf("begin my_msg()\n"); - printf("%s\n", msg.c_str()); - printf("end my_msg"); +// Функция для экранирования спецсимволов в JSON +std::string escape_json(const std::string& s) { + std::string result; + for (char c : s) { + switch (c) { + case '"': result += "\\\""; break; + case '\\': result += "\\\\"; break; + case '\b': result += "\\b"; break; + case '\f': result += "\\f"; break; + case '\n': result += "\\n"; break; + case '\r': result += "\\r"; break; + case '\t': result += "\\t"; break; + default: result += c; break; + } + } + return result; } +// Проверка, является ли строка числом (включая отрицательные) +bool is_numeric(const std::string& s) { + size_t start; + if (s.empty()) return false; + + start = 0; + if (s[0] == '-') { + if (s.size() == 1) return false; + start = 1; + } + + for (size_t i = start; i < s.size(); ++i) { + if (!isdigit(s[i])) return false; + } + return true; +} + +int my_msg() { + CURL* curl; + std::string escaped_msg; + std::cout << msg << std::endl; + std::string chat_id_field; + std::string json_data; + struct curl_slist* headers; + headers = nullptr; + long http_code; + CURLcode res; + + if (telegram_token.empty() || telegram_id.empty()) { + return 0; // Интеграция не настроена + } + + curl = curl_easy_init(); + if (!curl) return 6; // Ошибка инициализации CURL + + // Экранируем сообщение + escaped_msg = escape_json(msg); + + // Формируем поле chat_id + if (is_numeric(telegram_id)) { + chat_id_field = "\"chat_id\": " + telegram_id; + } else { + chat_id_field = "\"chat_id\": \"" + telegram_id + "\""; + } + + // Формируем JSON + json_data = "{" + chat_id_field + ", \"text\": \"" + escaped_msg + "\"}"; + // Настраиваем заголовоки + headers = curl_slist_append(headers, "Content-Type: application/json"); + + // Настраиваем параметры CURL + curl_easy_setopt(curl, CURLOPT_URL, ("https://api.telegram.org/bot" + telegram_token + "/sendMessage").c_str()); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/7.68.0"); + + // Игнорируем вывод ответа + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void*, size_t size, size_t nmemb, void*) -> size_t { + return size * nmemb; + }); + + // Выполняем запрос + res = curl_easy_perform(curl); + + http_code = 0; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + + // Освобождаем ресурсы + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + if (res != CURLE_OK) return 5; + + switch (http_code) { + case 200: return 0; + case 401: return 1; + case 400: return 2; + case 404: return 3; + default: + if (http_code >= 500) return 4; + return 4; + } +} +// Данная функция записывает в файл лога сообщение int my_log() { return 0; } +// Данная функция завершает программу и рассчитывает итоговое время выполнения программы void my_fin() { auto end_timestamp = std::chrono::system_clock::now(); @@ -189,21 +302,25 @@ void my_fin() std::exit(0); } +// Данная процедура сопостовляет доменное имя с IP int my_dns() { return 0; } +// Данная процедура выполняет TCP SYN Flood атаку int my_tcp_syn() { return 2; } +// Данная процедура выполняет UDP Flood (port scanning) атаку int my_udp() { return 2; } +// Тело программы int main(int argc, char **argv) { int check_params_status; @@ -217,9 +334,11 @@ int main(int argc, char **argv) n_fail_requests = 0; start_timestamp = std::chrono::system_clock::now(); - time_t now_time_t = std::chrono::system_clock::to_time_t(start_timestamp); + time_t now_time_t; + now_time_t = std::chrono::system_clock::to_time_t(start_timestamp); - std::chrono::milliseconds ms = std::chrono::duration_cast(start_timestamp.time_since_epoch()) % 1000; + std::chrono::milliseconds ms; + ms = std::chrono::duration_cast(start_timestamp.time_since_epoch()) % 1000; printf("Starting DosAtk at %04d-%02d-%02d %02d:%02d:%02d.%03ld\n", std::localtime(&now_time_t)->tm_year + 1900, diff --git a/src/a.out b/src/a.out new file mode 100755 index 0000000..4f5b579 Binary files /dev/null and b/src/a.out differ