#include #include #include #include #include #include #include #include #include #include #include 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; // Сообщение, которое будет отправлено в телеграм // ====== 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) { int status; int opt; 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'}, {"port", required_argument, NULL, 'p'}, {"log", required_argument, NULL, 'l'}, {"telegram", required_argument, NULL, 't'}, {"token", required_argument, NULL, 'b'}, {"help", no_argument, NULL, 'h'}, {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': attack_type = optarg; break; case 'd': domain = optarg; break; case 'i': ip = optarg; break; case 'p': port = optarg; break; case 'l': log_file = optarg; break; case 't': telegram_id = optarg; break; case 'b': telegram_token = optarg; break; case 'h': status = 0; break; case '?': status = -101; break; } } if (status != 0 && status != -101) { if (attack_type != "flood" && attack_type != "scan") { status = -1; } else if (attack_type == "scan" && domain.empty() && ip.empty()) { status = -10; } else if (attack_type == "flood" && domain.empty() && ip.empty()) { status = -20; } else if ((!telegram_id.empty() && telegram_token.empty()) || (telegram_id.empty() && !telegram_token.empty())) { status = -600; } else if (attack_type == "scan") { status = 1; } else if (attack_type == "flood") { status = 2; } } printf("end my_check_params status: %i\n", status); return status; } // Данная функция вызывается в случае ошибки на каком-то этапе и на основании поступившего кода, // формирует сообщение с описанием произошедшей ошибки void my_diag(int status) { printf("begin my_diag (status: %i)\n", status); switch (status) { case 0: printf("Usage: ./DosAtk [options]\n" "Required:\n" " -a, --attack TYPE Type of attack (scan|flood)\n" " -d, --domain DOMAIN Target domain\n" " -i, --ip IP Target IP\n" " -p, --port PORT Port. Required only for flood type!\n" "Optional:\n" " -l, --log FILE Log file\n" " -t, --telegram ID Telegram ID\n" " -b, --token TOKEN Telegram bot token\n"); break; case -1: printf("Error: Invalid attack type!\n--help for more info\n"); break; case -10: printf("Error: Missing required parameters for port scanning!\n--help for more info\n"); break; case -20: printf("Error: Missing required parameters for tcp syn dos attack!\n--help for more info\n"); break; case -101: printf("Error: Unknown option!\n.--help for info\n"); break; case -600: printf("Error: To use telegram integration both telegram_id and telegram_token have to be provided!\n.--help for info\n"); break; } printf("end my_diag\n"); } // Функция для экранирования спецсимволов в 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(); auto end_time_t = std::chrono::system_clock::to_time_t(end_timestamp); auto end_ms = std::chrono::duration_cast(end_timestamp.time_since_epoch()) % 1000; auto duration = end_timestamp - start_timestamp; auto hours = std::chrono::duration_cast(duration); auto minutes = std::chrono::duration_cast(duration % std::chrono::hours(1)); auto seconds = std::chrono::duration_cast(duration % std::chrono::minutes(1)); auto milliseconds = std::chrono::duration_cast(duration % std::chrono::seconds(1)); std::cout << "Worked for "; if (duration < std::chrono::minutes(2)) { double total_seconds = std::chrono::duration(duration).count(); std::cout << std::fixed << std::setprecision(3) << total_seconds << " seconds"; } else { if (hours.count() > 0) std::cout << hours.count() << "h "; if (minutes.count() > 0) std::cout << minutes.count() << "m "; std::cout << seconds.count() << "s " << milliseconds.count() << "ms"; } std::cout << std::endl; std::cout << "Sent " << (n_ok_requests + n_fail_requests) << " requests (" << n_ok_requests << " ok, " << n_fail_requests << " failed)" << std::endl; std::cout << "DosAtk stopped at " << std::put_time(std::localtime(&end_time_t), "%Y-%m-%d %H:%M:%S") << "." << std::setfill('0') << std::setw(3) << end_ms.count() << std::endl; 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; int log_status; int dns_status; int udp_status; int tcp_syn_status; // ====== Тело программы ====== // n_ok_requests = 0; n_fail_requests = 0; start_timestamp = std::chrono::system_clock::now(); time_t now_time_t; now_time_t = std::chrono::system_clock::to_time_t(start_timestamp); 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, std::localtime(&now_time_t)->tm_mon + 1, std::localtime(&now_time_t)->tm_mday, std::localtime(&now_time_t)->tm_hour, std::localtime(&now_time_t)->tm_min, std::localtime(&now_time_t)->tm_sec, ms.count()); check_params_status = my_check_params(argc, argv); switch (check_params_status) { case 1: dns_status = my_dns(); if (dns_status == 0) { while (udp_status = my_udp()) { if (udp_status == 2) { break; } else if (udp_status < 0) { my_diag(udp_status); log_status = my_log(); if (log_status == 1) { my_msg(); } } } log_status = my_log(); my_msg(); my_fin(); } else if (dns_status == 1) { my_diag(check_params_status); log_status = my_log(); if (log_status == 0){ my_fin(); } else if (log_status == 1) { my_msg(); my_fin(); } } break; case 2: dns_status = my_dns(); if (dns_status == 0) { while (tcp_syn_status = my_tcp_syn()) { if (tcp_syn_status == 2) { break; } else if (tcp_syn_status < 0) { my_diag(tcp_syn_status); log_status = my_log(); if (log_status == 1) { my_msg(); } } } log_status = my_log(); my_msg(); my_fin(); } else if (dns_status == 1) { my_diag(check_params_status); log_status = my_log(); if (log_status == 0) { my_fin(); } else if (log_status == 1) { my_msg(); my_fin(); } } break; default: my_diag(check_params_status); log_status = my_log(); if (log_status == 0) { my_fin(); } else if (log_status == 1) { my_msg(); my_fin(); } break; } return 0; }