forked from serafim/dos
1
0
Fork 0
dos/src/DosAtk.cpp

448 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <stdlib.h>
#include <string>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <getopt.h>
#include <cctype>
#include <curl/curl.h>
#include <iostream>
#include <string>
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<std::chrono::milliseconds>(end_timestamp.time_since_epoch()) % 1000;
auto duration = end_timestamp - start_timestamp;
auto hours = std::chrono::duration_cast<std::chrono::hours>(duration);
auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration % std::chrono::hours(1));
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration % std::chrono::minutes(1));
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration % std::chrono::seconds(1));
std::cout << "Worked for ";
if (duration < std::chrono::minutes(2)) {
double total_seconds = std::chrono::duration<double>(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<std::chrono::milliseconds>(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;
}