From bca003780712e598774b70035f94cfc3bc2d7bf4 Mon Sep 17 00:00:00 2001 From: dr-wh0 <79003667309@yandex.ru> Date: Fri, 9 May 2025 15:45:22 +0300 Subject: [PATCH] =?UTF-8?q?bugfix:=20=D0=A0=D0=B5=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D1=8B=20?= =?UTF-8?q?=D1=81=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=D0=BC,=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=BB=D0=BE=D0=B3=D0=B0=20=D0=B8=20=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Решает issue #26 2. Обновлённый формат логов: ``` drwho@ubuntu:~/PycharmProjects/dos$ cat /var/log/DosAtk [2025-05-08 23:42:50.704] Starting DosAtk | Type: TCP SYN flood | Sent 1000 requests | Stopping DosAtk [2025-05-08 23:42:50.723] [2025-05-08 23:43:07.943] Starting DosAtk | Type: UDP port scan | Sent 1000 requests | Stopping DosAtk [2025-05-08 23:43:07.957] [2025-05-08 23:43:21.388] Starting DosAtk | Type: TCP SYN flood | Sent 1000 requests | Stopping DosAtk [2025-05-08 23:43:21.407] [2025-05-08 23:43:35.619] Starting DosAtk | Type: UDP port scan | Sent 1000 requests | Stopping DosAtk [2025-05-08 23:43:35.637] [2025-05-08 23:54:52.170] Starting DosAtk | Stopping DosAtk [2025-05-08 23:54:52.170] [2025-05-08 23:55:45.017] Starting DosAtk | Type: TCP SYN flood | Sent 1000 requests | Stopping DosAtk [2025-05-08 23:55:45.037] ``` ![image](/attachments/04c4de29-6903-440b-9926-710489deb5dd) 3. Использование scan-атаки: ``` drwho@ubuntu:~/PycharmProjects/dos$ sudo ./DosAtk -a scan -i 127.0.0.1 start my_check_params Starting DosAtk at 2025-05-09 00:12:38.324 end my_check_params start my_dns end my_dns start my_udp end my_udp start my_log end my_log start my_fin Worked for 0.015 seconds Sent 1000 requests (1000 ok, 0 failed) DosAtk stopped at 2025-05-09 00:12:38.339 end my_fin ``` ![image](/attachments/5ba46d05-00b5-4691-8a61-6d58f7a7824b) 4. Использование flood-атаки: ``` drwho@ubuntu:~/PycharmProjects/dos$ sudo ./DosAtk -a flood -i 127.0.0.1 -p 800 start my_check_params Starting DosAtk at 2025-05-08 23:56:31.850 end my_check_params start my_dns end my_dns start my_tcp_syn end my_tcp_syn start my_log end my_log start my_fin Worked for 0.019 seconds Sent 1000 requests (1000 ok, 0 failed) DosAtk stopped at 2025-05-08 23:56:31.869 end my_fin ``` ![image](/attachments/584eb9d3-88d3-4741-8dc2-a7579e79f536) 5. Небольшой рефакторинг кода, обновление в соответствии с актуальной блок-схемой Reviewed-on: https://gitea.serafimdev.com/serafim/dos/pulls/28 Reviewed-by: serafim Co-authored-by: dr-wh0 <79003667309@yandex.ru> Co-committed-by: dr-wh0 <79003667309@yandex.ru> --- build.py | 3 +- src/DosAtk.cpp | 151 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 43 deletions(-) diff --git a/build.py b/build.py index 909fa40..c11014c 100755 --- a/build.py +++ b/build.py @@ -17,4 +17,5 @@ if subprocess.call(["g++", "src/DosAtk.cpp", "-o", "DosAtk", "-lcurl", "-lssl", sys.exit(1) # Запуск с аргументами -os.execvp("./DosAtk", ["./DosAtk"] + sys.argv[1:]) \ No newline at end of file +if len(sys.argv[1:]) > 0: + os.execvp("./DosAtk", ["./DosAtk"] + sys.argv[1:]) \ No newline at end of file diff --git a/src/DosAtk.cpp b/src/DosAtk.cpp index 78f2793..801bb75 100644 --- a/src/DosAtk.cpp +++ b/src/DosAtk.cpp @@ -103,7 +103,7 @@ int my_check_params() long_options[8] = {NULL, 0, NULL, 0}; i = 0; - printf("begin my_check_params\n"); // debug + printf("start my_check_params\n"); // debug now_time_t = std::time(nullptr); // Выводим информацию о времени запуска программы @@ -118,7 +118,7 @@ int my_check_params() char buffer[100]; snprintf(buffer, sizeof(buffer), - "Starting DosAtk at %04d-%02d-%02d %02d:%02d:%02d.%03ld", + "[%04d-%02d-%02d %02d:%02d:%02d.%03ld] Starting DosAtk", std::localtime(&now_time_t)->tm_year + 1900, // Год (с 1900) std::localtime(&now_time_t)->tm_mon + 1, // Месяц (0-11) std::localtime(&now_time_t)->tm_mday, // День месяца @@ -183,11 +183,13 @@ int my_check_params() return -600; // Неполные данные для Telegram } else if (attack_type == "scan") { // Если все проверки пройдены и тип атаки - сканирование + log_msg += " | Type: UDP port scan"; printf("end my_check_params\n"); // debug return 1; // Валидные параметры для сканирования } else if (attack_type == "flood") { // Если все проверки пройдены и тип атаки - флуд + log_msg += " | Type: TCP SYN flood"; printf("end my_check_params\n"); // debug return 2; // Валидные параметры для флуда } @@ -198,6 +200,10 @@ int my_check_params() } int my_udp() { + if ((n_ok_requests + n_fail_requests) == 0) { + printf("start my_udp\n"); // debug + } + int sockfd; int port_idx; int curr_port; @@ -248,6 +254,7 @@ int my_udp() { // Преобразование IP if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { n_fail_requests++; + log_msg += " | Failed to parse IP for udp flood"; status = -501; // Код ошибки: неверный IP if (sockfd != -1) close(sockfd); } @@ -256,6 +263,7 @@ int my_udp() { sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd < 0) { n_fail_requests++; + log_msg += " | Failed to open socket for udp flood"; status = -502; // Ошибка создания сокета if (sockfd != -1) close(sockfd); } @@ -265,6 +273,7 @@ int my_udp() { (struct sockaddr*)&target_addr, sizeof(target_addr)); if (send_result < 0) { n_fail_requests++; + log_msg += " | Failed to send udp flood request"; status = -503; // Ошибка отправки } else { n_ok_requests++; @@ -273,7 +282,10 @@ int my_udp() { // Проверка общего числа запросов if (n_ok_requests + n_fail_requests >= 1000) { + printf("end my_udp\n"); // debug + log_msg += " | Sent 1000 requests"; status = 2; // Условие завершения + return status; } // Переход к следующему порту @@ -285,7 +297,7 @@ void my_diag() { // Данная функция вызывается в случае ошибки на каком-то этапе и на основании поступившего кода, // формирует сообщение с описанием произошедшей ошибки - printf("begin my_diag, status: %i\n", status); // debug + printf("start my_diag, status: %i\n", status); // debug switch (status) // Выбор сообщения в зависимости от кода ошибки { @@ -303,18 +315,23 @@ void my_diag() break; case -1: // Некорректный тип атаки printf("Error: Invalid attack type!\n--help for more info\n"); + log_msg += " | Error: Invalid attack type"; break; case -10: // Отсутствуют обязательные параметры для сканирования портов printf("Error: Missing required parameters for port scanning!\n--help for more info\n"); + log_msg += " | Error: Missing required parameters for port scanning"; break; case -20: // Отсутствуют обязательные параметры для SYN flood атаки printf("Error: Missing required parameters for tcp syn dos attack!\n--help for more info\n"); + log_msg += " | Error: Missing required parameters for tcp syn dos attack"; break; case -101: // Встречена неизвестная опция командной строки printf("Error: Unknown option!\n--help for info\n"); + log_msg += " | Error: Unknown option"; break; case -600: // Неполные данные для Telegram-уведомлений printf("Error: To use telegram integration both telegram_id and telegram_token have to be provided!\n.--help for info\n"); + log_msg += " | Error: To use telegram integration both telegram_id and telegram_token have to be provided"; break; } @@ -387,7 +404,7 @@ bool is_numeric(const std::string& s) int my_msg() { - printf("begin my_msg\n"); // debug + printf("start my_msg\n"); // debug // Объявление struct curl_slist* headers; // Заголовки HTTP-запроса @@ -410,6 +427,7 @@ int my_msg() // Проверка наличия обязательных параметров Telegram if (telegram_token.empty() || telegram_id.empty()) { + printf("end my_msg\n"); // debug return 0; // Интеграция с Telegram не настроена (отсутствует токен или ID) } @@ -446,6 +464,7 @@ int my_msg() // Обработка ошибок CURL if (res != CURLE_OK) { + log_msg += " | Failed to send telegram msg - CURL error"; status = 5; // Ошибка выполнения запроса } @@ -455,12 +474,16 @@ int my_msg() case 200: status = 0; // Успешный запрос case 401: + log_msg += " | Failed to send telegram msg - authorization token error"; status = 1; // Ошибка авторизации (неверный токен) case 400: + log_msg += " | Failed to send telegram msg - wrong request"; status = 2; // Неверный запрос case 404: + log_msg += " | Failed to send telegram msg - resource not found"; status = 3; // Ресурс не найден - case 500: + case 500: + log_msg += " | Failed to send telegram msg - server error"; status = 4; // Ошибка сервера } @@ -503,7 +526,8 @@ int my_log() // === Основная логика === // Если путь к лог-файлу не указан if(log_file.empty()) { - return 0; + printf("end my_log\n"); // debug + return 1; } // Открытие файла в режиме добавления @@ -511,13 +535,14 @@ int my_log() // Проверка успешности открытия файла if(!log_stream.is_open()) { + printf("end my_log\n"); // debug return 1; } // Запись сообщения в лог - log_stream << "[" << std::put_time(&now_tm, "%Y-%m-%d %H:%M:%S") - << "." << std::setfill('0') << std::setw(3) << ms.count() << "] " - << log_msg << std::endl; + log_stream << log_msg << " | Stopping DosAtk [" << std::put_time(&now_tm, "%Y-%m-%d %H:%M:%S") + << "." << std::setfill('0') << std::setw(3) << ms.count() << "]" + << std::endl; // Проверка размер файла и выполняем ротацию if(stat_result == 0 && file_stat.st_size > max_log_size) { @@ -525,12 +550,14 @@ int my_log() // Переименование файла if(rename(log_file.c_str(), rotated_log_name.c_str()) != 0) { + printf("end my_log\n"); // debug return 1; } // Открытие нового лог-файла log_stream.open(log_file, std::ios::app); if(!log_stream.is_open()) { + printf("end my_log\n"); // debug return 1; } } @@ -546,12 +573,17 @@ void my_fin() // Данная процедура завершает программу и рассчитывает итоговое время выполнения программы // Объявления - time_t end_time_t; // Время завершения выполненя программы - std::chrono::milliseconds duration; // Длительность выполнения программы - std::chrono::hours hours; // Компонента часов времени завершения - std::chrono::minutes minutes; // Компонента минут времени завершения - std::chrono::seconds seconds; // Компонента секунд времени завершения - std::chrono::milliseconds milliseconds; // Компонента миллисекунд времени завершения + time_t end_time_t; // Время завершения выполнения программы + std::chrono::milliseconds duration; // Длительность выполнения программы + std::chrono::hours hours; // Компонента часов времени завершения + std::chrono::minutes minutes; // Компонента минут времени завершения + std::chrono::seconds seconds; // Компонента секунд времени завершения + std::chrono::milliseconds milliseconds; // Компонента миллисекунд времени завершения + std::chrono::system_clock::time_point now; // Текущее время + std::time_t now_time_t; // Время в time_t + std::tm now_tm; // Время в tm структуре + char time_buf[20]; // Буфер для времени + std::chrono::milliseconds ms; // Миллисекунды double total_seconds; // Иницаализация @@ -561,8 +593,15 @@ void my_fin() minutes = std::chrono::duration_cast(duration % std::chrono::hours(1)); // Разбиваем продолжительность на компоненты seconds = std::chrono::duration_cast(duration % std::chrono::minutes(1)); // Разбиваем продолжительность на компоненты milliseconds = std::chrono::duration_cast(duration % std::chrono::seconds(1)); // Разбиваем продолжительность на компоненты + now = std::chrono::system_clock::now(); + now_time_t = std::chrono::system_clock::to_time_t(now); + localtime_r(&now_time_t, &now_tm); + memset(time_buf, 0, sizeof(time_buf)); + strftime(time_buf, sizeof(time_buf), "%Y%m%d_%H%M%S", &now_tm); + ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; - printf("begin my_diag\n"); // debug + printf("start my_fin\n"); // debug std::cout << "Worked for "; // Выводим информацию о времени работы // Для коротких периодов (<2 минут) выводим в секундах с дробной частью @@ -578,9 +617,9 @@ void my_fin() { std::cout << hours.count() << "h "; // Выводим часы } - if (minutes.count() > 0) // Если программа работала хотя бы одину минуту + if (minutes.count() > 0) // Если программа работала хотя бы одну минуту { - std::cout << minutes.count() << "m "; // Вывовим минуты + std::cout << minutes.count() << "m "; // Выводим минуты } std::cout << seconds.count() << "s " << milliseconds.count() << "ms"; // Выводим секунды и миллисекунды } @@ -591,11 +630,12 @@ void my_fin() << 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) << milliseconds.count() << std::endl; + std::cout << "DosAtk stopped at " << std::put_time(&now_tm, "%Y-%m-%d %H:%M:%S") + << "." << std::setfill('0') << std::setw(3) << ms.count() << std::endl; log_msg = ""; + printf("end my_fin\n"); // debug // Завершаем программу с кодом состояния std::exit(status); } @@ -609,7 +649,9 @@ int my_tcp_syn() { * -201 - ошибка создания raw-сокета * -202 - ошибка отправки SYN-пакета */ - printf("start my_tcp_syn\n"); // debug + if ((n_ok_requests + n_fail_requests) == 0) { + printf("start my_tcp_syn\n"); // debug + } // === Объявление локальных переменных === int sock; // Основной raw-сокет для отправки пакетов @@ -656,6 +698,8 @@ int my_tcp_syn() { // === Основная логика процедуры === // 1. Создание raw-сокета if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { + n_fail_requests++; + log_msg += " | Failed to create tcp syn raw-socket"; return -201; } @@ -667,6 +711,8 @@ int my_tcp_syn() { target_addr.sin_family = AF_INET; if (inet_pton(AF_INET, ip.c_str(), &target_addr.sin_addr) <= 0) { close(sock); + n_fail_requests++; + log_msg += " | Failed to send tcp syn packet"; return -202; } @@ -725,23 +771,23 @@ int my_tcp_syn() { if (sendto(sock, packet, sizeof(packet), 0, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) { n_fail_requests++; + close(sock); printf("end my_tcp_syn\n"); // debug - log_msg = "Failed to send tcp syn msg"; + log_msg += " | Failed to send tcp syn packet"; return -202; } else { n_ok_requests++; } // 9. Проверка завершения - if ((n_ok_requests + n_fail_requests) >= 10000) { - log_msg = "Sent 10000 requests, stopping attack"; + if ((n_ok_requests + n_fail_requests) >= 1000) { + log_msg += " | Sent 1000 requests"; printf("end my_tcp_syn\n"); // debug + close(sock); return 2; } close(sock); - printf("end my_tcp_syn\n"); // debug - log_msg = "Sent tcp syn msg"; return 0; } @@ -870,11 +916,6 @@ int main(int arg_ctr, char **arg_ptr) status = 0; status = my_check_params(); // Проверяем параметры командной строки - - if (my_log()) // Если записать лог не удалось - { - my_msg(); // Отправляем сообщение - } switch (status) // Обрабатываем результат проверки параметров { @@ -893,16 +934,29 @@ int main(int arg_ctr, char **arg_ptr) { my_diag(); // Выводим диагностику status = my_log(); // Пытаемся записать в лог - if (status == 1) // Если записать лог не удалось + if (status == 0) // Если лог получилось записать { - my_msg(); // Отправляем сообщение + my_fin(); // Просто завершаем программу } + else if (status == 1) // Если лог не удалось записать + { + my_msg(); // Отправляем финальное сообщение + my_fin(); // Завершаем программу + } + break; } } // Завершающие действия после атаки - my_log(); // Логируем завершение - my_msg(); // Отправляем финальное сообщение - my_fin(); // Корректно завершаем программу + status = my_log(); // Логируем завершение + if (status == 0) // Если лог получилось записать + { + my_fin(); // Просто завершаем программу + } + else if (status == 1) // Если лог не удалось записать + { + my_msg(); // Отправляем финальное сообщение + my_fin(); // Корректно завершаем программу + } } else if (status == 1) // Ошибка DNS-разрешения { @@ -926,7 +980,7 @@ int main(int arg_ctr, char **arg_ptr) if (status == 0) // Если DNS разрешен успешно { - // Запускаем цикл UDP-атаки + // Запускаем цикл TCP-атаки while (true) { status = my_tcp_syn(); @@ -938,16 +992,29 @@ int main(int arg_ctr, char **arg_ptr) { my_diag(); // Выводим диагностику status = my_log(); // Пытаемся записать в лог - if (status == 1) // Если записать лог не удалось + if (status == 0) // Если лог получилось записать { - my_msg(); // Отправляем сообщение + my_fin(); // Просто завершаем программу } + else if (status == 1) // Если лог не удалось записать + { + my_msg(); // Отправляем финальное сообщение + my_fin(); // Завершаем программу + } + break; } } // Завершающие действия после атаки - my_log(); // Логируем завершение - my_msg(); // Отправляем финальное сообщение - my_fin(); // Корректно завершаем программу + status = my_log(); // Логируем завершение + if (status == 0) // Если лог получилось записать + { + my_fin(); // Просто завершаем программу + } + else if (status == 1) // Если лог не удалось записать + { + my_msg(); // Отправляем финальное сообщение + my_fin(); // Корректно завершаем программу + } } else if (status == 1) // Ошибка DNS-разрешения {