/* * hydra (c) 2001-2023 by van Hauser / THC * https://github.com/vanhauser-thc/thc-hydra * * Parallized network login hacker. * Please don't use in military or secret service organizations, or for illegal * purposes. This is a wish and is non-binding. * If you ignore this be sure you are not a good person though. * * License: GNU AFFERO GENERAL PUBLIC LICENSE v3.0, see LICENSE file */ #include "hydra.h" #include "bfg.h" #include #ifdef LIBNCURSES #include #include #endif void usage_oracle(const char *service); void usage_oracle_listener(const char *service); void usage_cvs(const char *service); void usage_xmpp(const char *service); void usage_pop3(const char *service); void usage_rdp(const char *service); void usage_s7_300(const char *service); void usage_nntp(const char *service); void usage_imap(const char *service); void usage_smtp_enum(const char *service); void usage_smtp(const char *service); void usage_svn(const char *service); void usage_ncp(const char *service); void usage_firebird(const char *service); void usage_mysql(const char *service); void usage_mongodb(const char *service); void usage_irc(const char *service); void usage_postgres(const char *service); void usage_telnet(const char *service); void usage_sapr3(const char *service); void usage_sshkey(const char *service); void usage_cisco_enable(const char *service); void usage_cisco(const char *service); void usage_ldap(const char *service); void usage_smb(const char *service); void usage_http_form(const char *service); void usage_http_proxy(const char *service); void usage_http_proxy_urlenum(const char *service); void usage_snmp(const char *service); void usage_http(const char *service); void usage_smb2(const char *service); extern void service_asterisk(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_telnet(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ftp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ftps(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_pop3(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_vmauthd(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_imap(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ldap2(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ldap3(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ldap3_cram_md5(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_ldap3_digest_md5(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_adam6500(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_cisco(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_cisco_enable(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_vnc(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_socks5(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_rexec(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_rlogin(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_rsh(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_nntp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_head(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_get(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_post(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_get_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_icq(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_pcnfs(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_mssql(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_cobaltstrike(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_cvs(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_snmp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_smtp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_smtp_enum(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_teamspeak(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_pcanywhere(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_proxy(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_xmpp(char *target, char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_irc(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_redis(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_http_proxy_urlenum(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_s7_300(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_rtsp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_rpcap(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); // ADD NEW SERVICES HERE #if defined(LIBSMBCLIENT) extern int32_t service_smb2_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_smb2(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef HAVE_MATH_H extern void service_mysql(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_mysql_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBPOSTGRES extern void service_postgres(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_postgres_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBOPENSSL extern void service_smb(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_smb_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_oracle_listener(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_oracle_listener_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_oracle_sid(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_oracle_sid_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_sip(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_sip_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBFREERDP extern void service_rdp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rdp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBSAPR3 extern void service_sapr3(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_sapr3_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBFIREBIRD extern void service_firebird(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_firebird_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBAFP extern void service_afp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_afp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBNCP extern void service_ncp(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_ncp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBSSH extern void service_ssh(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_ssh_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern void service_sshkey(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_sshkey_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBSVN extern void service_svn(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_svn_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBORACLE extern void service_oracle(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_oracle_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef HAVE_GCRYPT extern void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_radmin2_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBMCACHED extern void service_mcached(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_mcached_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif #ifdef LIBMONGODB extern void service_mongodb(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_mongodb_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); #endif extern int32_t service_adam6500_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_cisco_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_cisco_enable_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_cvs_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_smtp_enum_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_http_form_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_ftp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_http_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_icq_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_imap_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_irc_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_ldap_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_mssql_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_cobaltstrike_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_nntp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_pcanywhere_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_pcnfs_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_pop3_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_http_proxy_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_asterisk_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_redis_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rexec_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rlogin_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rsh_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_smtp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_snmp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_socks5_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_teamspeak_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_telnet_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_http_proxy_urlenum_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_vmauthd_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_vnc_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_xmpp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_s7_300_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rtsp_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); extern int32_t service_rpcap_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); // ADD NEW SERVICES HERE char *SERVICES = "adam6500 asterisk afp cisco cisco-enable cobaltstrike cvs firebird ftp[s] " "http[s]-{head|get|post} http[s]-{get|post}-form http-proxy " "http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] " "memcached mongodb mssql mysql ncp nntp oracle oracle-listener oracle-sid " "pcanywhere pcnfs pop3[s] postgres radmin2 rdp redis rexec rlogin rpcap " "rsh rtsp s7-300 sapr3 sip smb smb2 smtp[s] smtp-enum snmp socks5 ssh " "sshkey svn teamspeak telnet[s] vmauthd vnc xmpp"; #define MAXBUF 520 #define MAXLINESIZE ((MAXBUF / 2) - 4) #define MAXTASKS 64 #define MAXSERVERS 16 #define MAXFAIL 3 #define MAXENDWAIT 20 #define WAITTIME 32 #define TASKS 16 #define SKIPLOGIN 256 #define USLEEP_LOOP 10 #define MAX_LINES 50000000 // 50 millions, do not put more than 65millions #define MAX_BYTES 500000000 // 500 millions, do not put more than 650millions #define RESTOREFILE "./hydra.restore" #define PROGRAM "Hydra" #define VERSION "v9.6dev" #define AUTHOR "van Hauser/THC" #define EMAIL "" #define AUTHOR2 "David Maciejak" #define EMAIL2 "" #define RESOURCE "https://github.com/vanhauser-thc/thc-hydra" extern char *hydra_strcasestr(const char *haystack, const char *needle); extern void hydra_tobase64(unsigned char *buf, int32_t buflen, int32_t bufsize); extern char *hydra_string_replace(const char *string, const char *substr, const char *replacement); extern char *hydra_address2string(char *address); extern char *hydra_address2string_beautiful(char *address); extern uint32_t colored_output; extern char quiet; extern int32_t do_retry; extern int32_t old_ssl; void hydra_kill_head(int32_t head_no, int32_t killit, int32_t fail); // some enum definitions typedef enum { HEAD_DISABLED = -1, HEAD_UNUSED = 0, HEAD_ACTIVE = 1 } head_state_t; typedef enum { TARGET_ACTIVE = 0, TARGET_FINISHED = 1, TARGET_ERROR = 2, TARGET_UNRESOLVED = 3 } target_state_t; // some structure definitions typedef struct { pid_t pid; int32_t sp[2]; int32_t target_no; char *current_login_ptr; char *current_pass_ptr; char reverse[256]; head_state_t active; int32_t redo; time_t last_seen; } hydra_head; typedef struct { char *target; char *miscptr; char ip[36]; char *login_ptr; char *pass_ptr; uint64_t login_no; uint64_t pass_no; uint64_t sent; int32_t pass_state; int32_t use_count; target_state_t done; int32_t fail_count; int32_t redo_state; int32_t redo; int32_t ok; int32_t failed; int32_t skipcnt; int32_t port; char *redo_login[MAXTASKS * 2 + 2]; char *redo_pass[MAXTASKS * 2 + 2]; char *skiplogin[SKIPLOGIN]; // char *bfg_ptr[MAXTASKS]; } hydra_target; typedef struct { int32_t active; // active tasks of hydra_options.max_use int32_t targets; int32_t finished; int32_t exit; uint64_t todo_all; uint64_t todo; uint64_t sent; uint64_t found; uint64_t countlogin; uint64_t countpass; size_t sizelogin; size_t sizepass; FILE *ofp; } hydra_brain; typedef struct { char *name; int32_t port; int32_t port_ssl; } hydra_portlist; // external vars extern char *HYDRA_EXIT; #if !defined(ANDROID) && !defined(__BIONIC__) extern int32_t errno; #endif extern int32_t debug; extern int32_t verbose; extern int32_t waittime; extern int32_t port; extern int32_t found; extern int32_t use_proxy; extern int32_t proxy_count; extern int32_t selected_proxy; extern int32_t proxy_string_port[MAX_PROXY_COUNT]; extern char proxy_string_ip[MAX_PROXY_COUNT][36]; extern char proxy_string_type[MAX_PROXY_COUNT][10]; extern char *proxy_authentication[MAX_PROXY_COUNT]; extern char *cmdlinetarget; extern char *fe80; // required global vars char *prg; size_t size_of_data = -1; hydra_head **hydra_heads = NULL; hydra_target **hydra_targets = NULL; hydra_option hydra_options; hydra_brain hydra_brains; char *sck = NULL; int32_t prefer_ipv6 = 0, conwait = 0, loop_cnt = 0, fck = 0, options = 0, killed = 0; int32_t child_head_no = -1, child_socket; int32_t total_redo_count = 0; // requred for distributed attack capability uint32_t num_segments = 0; uint32_t my_segment = 0; char junk_file[50]; // moved for restore feature int32_t process_restore = 0, dont_unlink; char *login_ptr = NULL, *pass_ptr = "", *csv_ptr = NULL, *servers_ptr = NULL; size_t countservers = 1, sizeservers = 0; char empty_login[2] = "", unsupported[500] = ""; // required to save stack memory char snpbuf[MAXBUF]; int32_t snpdone, snp_is_redo, snpbuflen, snpi, snpj, snpdont; #include "performance.h" typedef void (*service_t)(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); typedef int32_t (*service_init_t)(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname); typedef void (*service_usage_t)(const char *service); #define SERVICE2(name, func) \ { name, service_##func##_init, service_##func, NULL } #define SERVICE(name) \ { #name, service_##name##_init, service_##name, NULL } #define SERVICE3(name, func) \ { name, service_##func##_init, service_##func, usage_##func } static const struct { const char *name; service_init_t init; service_t exec; service_usage_t usage; } services[] = {SERVICE(adam6500), #ifdef LIBAFP SERVICE(afp), #endif SERVICE(asterisk), SERVICE3("cisco", cisco), SERVICE3("cisco-enable", cisco_enable), SERVICE3("cvs", cvs), #ifdef LIBFIREBIRD SERVICE3("firebird", firebird), #endif SERVICE(ftp), {"ftps", service_ftp_init, service_ftps, NULL}, {"http-get", service_http_init, service_http_get, usage_http}, {"http-get-form", service_http_form_init, service_http_get_form, usage_http_form}, {"http-head", service_http_init, service_http_head, NULL}, {"http-form", service_http_form_init, NULL, usage_http_form}, {"http-post", service_http_init, service_http_post, usage_http}, {"http-post-form", service_http_form_init, service_http_post_form, usage_http_form}, SERVICE3("http-proxy", http_proxy), SERVICE3("http-proxy-urlenum", http_proxy_urlenum), SERVICE(icq), SERVICE3("imap", imap), SERVICE3("irc", irc), {"ldap", service_ldap_init, service_ldap2, usage_ldap}, {"ldap2", service_ldap_init, service_ldap2, usage_ldap}, {"ldap3", service_ldap_init, service_ldap3, usage_ldap}, {"ldap3-crammd5", service_ldap_init, service_ldap3_cram_md5, usage_ldap}, {"ldap3-digestmd5", service_ldap_init, service_ldap3_digest_md5, usage_ldap}, #ifdef LIBMCACHED {"memcached", service_mcached_init, service_mcached, NULL}, #endif SERVICE(mssql), SERVICE(cobaltstrike), #ifdef LIBMONGODB SERVICE3("mongodb", mongodb), #endif #ifdef HAVE_MATH_H SERVICE3("mysql", mysql), #endif #ifdef LIBNCP SERVICE3("ncp", ncp), #endif SERVICE3("nntp", nntp), #ifdef LIBORACLE SERVICE3("oracle", oracle), #endif #ifdef LIBOPENSSL SERVICE3("oracle-listener", oracle_listener), SERVICE2("oracle-sid", oracle_sid), #endif SERVICE(pcanywhere), SERVICE(pcnfs), SERVICE3("pop3", pop3), #ifdef LIBPOSTGRES SERVICE3("postgres", postgres), #endif SERVICE(redis), SERVICE(rexec), #ifdef LIBFREERDP SERVICE3("rdp", rdp), #endif SERVICE(rlogin), SERVICE(rsh), SERVICE(rtsp), SERVICE(rpcap), SERVICE3("s7-300", s7_300), #ifdef LIBSAPR3 SERVICE3("sarp3", sapr3), #endif #ifdef LIBOPENSSL SERVICE(sip), SERVICE3("smbnt", smb), SERVICE3("smb", smb), #endif #if defined(LIBSMBCLIENT) SERVICE3("smb2", smb2), #endif SERVICE3("smtp", smtp), SERVICE3("smtp-enum", smtp_enum), SERVICE3("snmp", snmp), SERVICE(socks5), #ifdef LIBSSH {"ssh", NULL, service_ssh, NULL}, SERVICE3("sshkey", sshkey), #endif #ifdef LIBSVN SERVICE3("svn", svn), #endif SERVICE(teamspeak), SERVICE3("telnet", telnet), SERVICE(vmauthd), SERVICE(vnc), #ifdef HAVE_GCRYPT SERVICE(radmin2), #endif {"xmpp", service_xmpp_init, NULL, usage_xmpp}}; #define PRINT_NORMAL(ext, text, ...) printf(text, ##__VA_ARGS__) #define PRINT_EXTEND(ext, text, ...) \ do { \ if (ext) \ printf(text, ##__VA_ARGS__); \ } while (0) int32_t /*inline*/ check_flag(int32_t value, int32_t flag) { // inline does not compile with debug return (value & flag) == flag; } void help(int32_t ext) { PRINT_NORMAL(ext, "Syntax: hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | " "[-C FILE]] [-e nsr]" " [-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-W " "TIME] [-f] [-s PORT]" #ifdef HAVE_MATH_H " [-x MIN:MAX:CHARSET]" #endif " [-c TIME] [-ISOuvVd46] [-m MODULE_OPT] " //"[server service [OPT]]|" "[service://server[:PORT][/OPT]]\n"); PRINT_NORMAL(ext, "\nOptions:\n"); PRINT_EXTEND(ext, " -R restore a previous aborted/crashed session\n" " -I ignore an existing restore file (don't wait 10 seconds)\n" #ifdef LIBOPENSSL " -S perform an SSL connect\n" #endif " -s PORT if the service is on a different default port, define it " "here\n"); PRINT_NORMAL(ext, " -l LOGIN or -L FILE login with LOGIN name, or load " "several logins from FILE\n" " -p PASS or -P FILE try password PASS, or load several " "passwords from FILE\n"); PRINT_EXTEND(ext, #ifdef HAVE_MATH_H " -x MIN:MAX:CHARSET password bruteforce generation, type " "\"-x -h\" to get help\n" " -y disable use of symbols in bruteforce, see above\n" " -r use a non-random shuffling method for option -x\n" #endif " -e nsr try \"n\" null password, \"s\" login as pass " "and/or \"r\" reversed login\n" " -u loop around users, not passwords (effective! " "implied with -x)\n"); PRINT_NORMAL(ext, " -C FILE colon separated \"login:pass\" format, " "instead of -L/-P options\n" " -M FILE list of servers to attack, one entry per " "line, ':' to specify port\n"); PRINT_NORMAL(ext, " -D XofY Divide wordlist into Y segments and use the " "Xth segment.\n"); PRINT_EXTEND(ext, " -o FILE write found login/password pairs to FILE instead of stdout\n" " -b FORMAT specify the format for the -o FILE: text(default), json, " "jsonv1\n" " -f / -F exit when a login/pass pair is found (-M: -f per host, -F " "global)\n"); PRINT_NORMAL(ext, " -t TASKS run TASKS number of connects in parallel per " "target (default: %d)\n", TASKS); PRINT_EXTEND(ext, " -T TASKS run TASKS connects in parallel overall (for -M, default: " "%d)\n" " -w / -W TIME wait time for a response (%d) / between connects per " "thread (%d)\n" #ifdef MSG_PEEK " -c TIME wait time per login attempt over all threads (enforces -t " "1)\n" #endif " -4 / -6 use IPv4 (default) / IPv6 addresses (put always in [] also " "in -M)\n" " -v / -V / -d verbose mode / show login+pass for each attempt / debug " "mode \n" " -O use old SSL v2 and v3\n" " -K do not redo failed attempts (good for -M mass scanning)\n" " -q do not print messages about connection errors\n", MAXTASKS, WAITTIME, conwait); PRINT_NORMAL(ext, " -U service module usage details\n" " -m OPT options specific for a module, see -U output for " "information\n" " -h more command line options (COMPLETE HELP)\n" " server the target: DNS, IP or 192.168.0.0/24 (this OR the -M " "option)\n" " service the service to crack (see below for supported protocols)\n" " OPT some service modules support additional input (-U for " "module help)\n"); PRINT_NORMAL(ext, "\nSupported services: %s\n" "\n%s is a tool to guess/crack valid login/password pairs.\n" "Licensed under AGPL v3.0. The newest version is always available at;\n%s\n" "Please don't use in military or secret service organizations, or for illegal\n" "purposes. (This is a wish and non-binding - most such people do not care about\n" "laws and ethics anyway - and tell themselves they are one of the good ones.)\n", SERVICES, PROGRAM, RESOURCE); if (ext && strlen(unsupported) > 0) { if (unsupported[strlen(unsupported) - 1] == ' ') unsupported[strlen(unsupported) - 1] = 0; printf("These services were not compiled in: %s.\n", unsupported); } PRINT_EXTEND(ext, "\nUse HYDRA_PROXY_HTTP or HYDRA_PROXY environment variables for a proxy " "setup.\n" "E.g. %% export HYDRA_PROXY=socks5://l:p@127.0.0.1:9150 (or: socks4:// " "connect://)\n" " %% export HYDRA_PROXY=connect_and_socks_proxylist.txt (up to 64 " "entries)\n" " %% export HYDRA_PROXY_HTTP=http://login:pass@proxy:8080\n" " %% export HYDRA_PROXY_HTTP=proxylist.txt (up to 64 entries)\n"); PRINT_NORMAL(ext, "\nExample%s:%s hydra -l user -P passlist.txt ftp://192.168.0.1\n", ext == 0 ? "" : "s", ext == 0 ? "" : "\n"); PRINT_EXTEND(ext, " hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN\n" " hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5\n" " hydra -l admin -p password ftp://[192.168.0.0/24]/\n" " hydra -L logins.txt -P pws.txt -M targets.txt ssh\n"); exit(-1); } void help_bfg() { printf("Hydra bruteforce password generation option usage:\n\n" " -x MIN:MAX:CHARSET\n\n" " MIN is the minimum number of characters in the password\n" " MAX is the maximum number of characters in the password\n" " CHARSET is a specification of the characters to use in the " "generation\n" " valid CHARSET values are: 'a' for lowercase letters,\n" " 'A' for uppercase letters, '1' for numbers, and for all " "others,\n" " just add their real representation.\n" " -y disable the use of the above letters as placeholders\n" "Examples:\n" " -x 3:5:a generate passwords from length 3 to 5 with all " "lowercase letters\n" " -x 5:8:A1 generate passwords from length 5 to 8 with uppercase " "and numbers\n" " -x 1:3:/ generate passwords from length 1 to 3 containing only " "slashes\n" " -x 5:5:/%%,.- generate passwords with length 5 which consists " "only of /%%,.-\n" " -x 3:5:aA1 -y generate passwords from length 3 to 5 with a, A and " "1 only\n" "\nThe bruteforce mode was made by Jan Dlabal, " "http://houbysoft.com/bfg/\n"); exit(-1); } void module_usage() { int32_t i; printf("\nHelp for module " "%s:\n================================================================" "============\n", hydra_options.service); if (strncmp(hydra_options.service, "https-", 6) == 0) memmove(hydra_options.service + 4, hydra_options.service + 5, strlen(hydra_options.service) - 4); for (i = 0; i < sizeof(services) / sizeof(services[0]); i++) { if (strcmp(hydra_options.service, services[i].name) == 0) { if (services[i].usage) { services[i].usage(hydra_options.service); exit(0); } } } printf("The Module %s does not need or support optional parameters\n", hydra_options.service); exit(0); } #define STR_NULL(s) ((s) == NULL ? "(null)" : (s)) void hydra_debug(int32_t force, char *string) { int32_t active = 0, inactive = 0, i; if (!debug && !force) return; printf("[DEBUG] Code: %s Time: %" hPRIu64 "\n", string, (uint64_t)time(NULL)); printf("[DEBUG] Options: mode %d ssl %d restore %d showAttempt %d tasks " "%d max_use %d tnp %d tpsal %d tprl %d exit_found %d miscptr %s " "service %s\n", hydra_options.mode, hydra_options.ssl, hydra_options.restore, hydra_options.showAttempt, hydra_options.tasks, hydra_options.max_use, hydra_options.try_null_password, hydra_options.try_password_same_as_login, hydra_options.try_password_reverse_login, hydra_options.exit_found, STR_NULL(hydra_options.miscptr), hydra_options.service); printf("[DEBUG] Brains: active %d targets %d finished %d todo_all %" hPRIu64 " todo %" hPRIu64 " sent %" hPRIu64 " found %" hPRIu64 " countlogin %" hPRIu64 " sizelogin %" hPRIu64 " countpass %" hPRIu64 " sizepass %" hPRIu64 "\n", hydra_brains.active, hydra_brains.targets, hydra_brains.finished, hydra_brains.todo_all + total_redo_count, hydra_brains.todo, hydra_brains.sent, hydra_brains.found, (uint64_t)hydra_brains.countlogin, (uint64_t)hydra_brains.sizelogin, (uint64_t)hydra_brains.countpass, (uint64_t)hydra_brains.sizepass); for (i = 0; i < hydra_brains.targets; i++) { hydra_target *target = hydra_targets[i]; printf("[DEBUG] Target %d - target %s ip %s login_no %" hPRIu64 " pass_no %" hPRIu64 " sent %" hPRIu64 " pass_state %d redo_state %d (%d redos) use_count %d failed %d " " done %d fail_count %d login_ptr %s pass_ptr %s\n", i, STR_NULL(target->target), hydra_address2string_beautiful(target->ip), target->login_no, target->pass_no, target->sent, target->pass_state, target->redo_state, target->redo, target->use_count, target->failed, target->done, target->fail_count, STR_NULL(target->login_ptr), STR_NULL(target->pass_ptr)); } if (hydra_heads == NULL) return; for (i = 0; i < hydra_options.max_use; i++) { if (hydra_heads[i]->active >= HEAD_UNUSED) { printf("[DEBUG] Task %d - pid %d active %d redo %d current_login_ptr " "%s current_pass_ptr %s\n", i, (int32_t)hydra_heads[i]->pid, hydra_heads[i]->active, hydra_heads[i]->redo, STR_NULL(hydra_heads[i]->current_login_ptr), STR_NULL(hydra_heads[i]->current_pass_ptr)); if (hydra_heads[i]->active == HEAD_UNUSED) inactive++; else active++; } } printf("[DEBUG] Tasks %d inactive %d active\n", inactive, active); } void bail(char *text) { fprintf(stderr, "[ERROR] %s\n", text); exit(-1); } void hydra_restore_write(int32_t print_msg) { FILE *f; hydra_brain brain; char mynull[4] = {0, 0, 0, 0}, buf[4]; int32_t i = 0, j = 0; hydra_head hh; if (process_restore != 1) return; for (i = 0; i < hydra_brains.targets; i++) if (hydra_targets[j]->done != TARGET_FINISHED && hydra_targets[j]->done != TARGET_UNRESOLVED) j++; if (j == 0) { process_restore = 0; return; } if ((f = fopen(RESTOREFILE, "w")) == NULL) { fprintf(stderr, "[ERROR] Can not create restore file (%s) - ", RESTOREFILE); perror(""); process_restore = 0; return; } else if (debug) printf("[DEBUG] Writing restore file... "); fprintf(f, "%s\n", PROGRAM); buf[0] = VERSION[1]; buf[1] = VERSION[3]; buf[2] = sizeof(int32_t) % 256; buf[3] = sizeof(hydra_target *) % 256; fwrite(buf, 1, 4, f); memcpy(&brain, &hydra_brains, sizeof(hydra_brain)); brain.targets = i; brain.ofp = NULL; brain.finished = brain.active = 0; fck = fwrite(&bf_options, sizeof(bf_options), 1, f); if (bf_options.crs != NULL) fck = fwrite(bf_options.crs, BF_CHARSMAX, 1, f); else fck = fwrite(mynull, sizeof(mynull), 1, f); fck = fwrite(&brain, sizeof(hydra_brain), 1, f); fck = fwrite(&hydra_options, sizeof(hydra_option), 1, f); fprintf(f, "%s\n", hydra_options.server == NULL ? "" : hydra_options.server); if (hydra_options.outfile_ptr == NULL) fprintf(f, "\n"); else fprintf(f, "%s\n", hydra_options.outfile_ptr); fprintf(f, "%s\n%s\n", hydra_options.miscptr == NULL ? "" : hydra_options.miscptr, hydra_options.service); fck = fwrite(login_ptr, hydra_brains.sizelogin + hydra_brains.countlogin + 8, 1, f); if (hydra_options.colonfile == NULL || hydra_options.colonfile == empty_login) fck = fwrite(pass_ptr, hydra_brains.sizepass + hydra_brains.countpass + 8, 1, f); for (j = 0; j < hydra_brains.targets; j++) if (hydra_targets[j]->done != TARGET_FINISHED) { fck = fwrite(hydra_targets[j], sizeof(hydra_target), 1, f); fprintf(f, "%s\n%d\n%d\n", hydra_targets[j]->target == NULL ? "" : hydra_targets[j]->target, (int32_t)(hydra_targets[j]->login_ptr - login_ptr), (int32_t)(hydra_targets[j]->pass_ptr - pass_ptr)); fprintf(f, "%s\n%s\n", hydra_targets[j]->login_ptr, hydra_targets[j]->pass_ptr); if (hydra_targets[j]->redo) for (i = 0; i < hydra_targets[j]->redo; i++) fprintf(f, "%s\n%s\n", hydra_targets[j]->redo_login[i], hydra_targets[j]->redo_pass[i]); if (hydra_targets[j]->skipcnt) for (i = 0; i < hydra_targets[j]->skipcnt; i++) fprintf(f, "%s\n", hydra_targets[j]->skiplogin[i]); } for (j = 0; j < hydra_options.max_use; j++) { memcpy((char *)&hh, hydra_heads[j], sizeof(hydra_head)); if (j == 0 && debug) { printf("[DEBUG] sizeof hydra_head: %lu\n", sizeof(hydra_head)); printf("[DEBUG] memcmp: %d\n", memcmp(hydra_heads[j], &hh, sizeof(hydra_head))); } hh.active = 0; // re-enable disabled heads if ((hh.current_login_ptr != NULL && hh.current_login_ptr != empty_login) || (hh.current_pass_ptr != NULL && hh.current_pass_ptr != empty_login)) { hh.redo = 1; if (print_msg && debug) printf("[DEBUG] we will redo the following combination: target %s " "child %d login \"%s\" pass \"%s\"\n", hydra_targets[hh.target_no]->target, j, hh.current_login_ptr, hh.current_pass_ptr); } fck = fwrite((char *)&hh, sizeof(hydra_head), 1, f); if (hh.redo /* && (hydra_options.bfg == 0 || (hh.current_pass_ptr == hydra_targets[hh.target_no]->bfg_ptr[j] && isprint((char) hh.current_pass_ptr[0]))) */) fprintf(f, "%s\n%s\n", hh.current_login_ptr == NULL ? "" : hh.current_login_ptr, hh.current_pass_ptr == NULL ? "" : hh.current_pass_ptr); else fprintf(f, "\n\n"); } fprintf(f, "%s\n", PROGRAM); fclose(f); if (debug) printf("[DEBUG] done writing session file\n"); if (print_msg) printf("The session file ./hydra.restore was written. Type \"hydra -R\" to " "resume session.\n"); hydra_debug(0, "hydra_restore_write()"); } void hydra_restore_read() { FILE *f; char mynull[4], buf[4]; int32_t i, j, orig_debug = debug; char out[1024]; printf("[INFORMATION] reading restore file %s\n", RESTOREFILE); if ((f = fopen(RESTOREFILE, "r")) == NULL) { fprintf(stderr, "[ERROR] restore file (%s) not found - ", RESTOREFILE); perror(""); exit(-1); } sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (strcmp(out, PROGRAM) != 0) { fprintf(stderr, "[ERROR] invalid restore file (begin)\n"); exit(-1); } if ((fck = (int32_t)fread(buf, 1, 4, f)) != 4) { fprintf(stderr, "[ERROR] invalid restore file (platform)\n"); exit(-1); } if (buf[0] == 0 || buf[1] == 0) { fprintf(stderr, "[ERROR] restore file is prior hydra version v8.5!\n"); exit(-1); } if (buf[0] != VERSION[1] || buf[1] != VERSION[3]) fprintf(stderr, "[WARNING] restore file was created by version %c.%c, this is " "version %s\n", buf[0], buf[1], VERSION); if (buf[2] != sizeof(int32_t) % 256 || buf[3] != sizeof(hydra_head *) % 256) { fprintf(stderr, "[ERROR] restore file was created on a different, " "incompatible processor platform!\n"); exit(-1); } fck = (int32_t)fread(&bf_options, sizeof(bf_options), 1, f); fck = (int32_t)fread(mynull, sizeof(mynull), 1, f); if (debug) printf("[DEBUG] reading restore file: Step 1 complete\n"); if (mynull[0] + mynull[1] + mynull[2] + mynull[3] == 0) { bf_options.crs = NULL; } else { bf_options.crs = malloc(BF_CHARSMAX); memcpy(bf_options.crs, mynull, sizeof(mynull)); fck = fread(bf_options.crs + sizeof(mynull), BF_CHARSMAX - sizeof(mynull), 1, f); } if (debug) printf("[DEBUG] reading restore file: Step 2 complete\n"); fck = (int32_t)fread(&hydra_brains, sizeof(hydra_brain), 1, f); hydra_brains.ofp = stdout; fck = (int32_t)fread(&hydra_options, sizeof(hydra_option), 1, f); hydra_options.restore = 1; verbose = hydra_options.verbose; debug = hydra_options.debug; if (debug || orig_debug) printf("[DEBUG] run_debug %d, orig_debug %d\n", debug, orig_debug); if (orig_debug) { debug = 1; hydra_options.debug = 1; } waittime = hydra_options.waittime; conwait = hydra_options.conwait; port = hydra_options.port; sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_options.server = strdup(out); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (debug) printf("[DEBUG] reading restore file: Step 3 complete\n"); if (strlen(out) > 0) { hydra_options.outfile_ptr = malloc(strlen(out) + 1); strcpy(hydra_options.outfile_ptr, out); } else hydra_options.outfile_ptr = NULL; if (debug) printf("[DEBUG] reading restore file: Step 4 complete\n"); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (debug) printf("[DEBUG] reading restore file: Step 5 complete\n"); if (strlen(out) == 0) hydra_options.miscptr = NULL; else { hydra_options.miscptr = malloc(strlen(out) + 1); strcpy(hydra_options.miscptr, out); } if (debug) printf("[DEBUG] reading restore file: Step 6 complete\n"); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (debug) printf("[DEBUG] reading restore file: Step 7 complete\n"); hydra_options.service = malloc(strlen(out) + 1); strcpy(hydra_options.service, out); if (debug) printf("[DEBUG] reading restore file: Step 8 complete\n"); login_ptr = malloc(hydra_brains.sizelogin + hydra_brains.countlogin + 8); if (!login_ptr) { fprintf(stderr, "Error: malloc(%lu) failed\n", hydra_brains.sizelogin + hydra_brains.countlogin + 8); exit(-1); } fck = (int32_t)fread(login_ptr, hydra_brains.sizelogin + hydra_brains.countlogin + 8, 1, f); if (debug) printf("[DEBUG] reading restore file: Step 9 complete\n"); if (!check_flag(hydra_options.mode, MODE_COLON_FILE)) { // NOT colonfile mode pass_ptr = malloc(hydra_brains.sizepass + hydra_brains.countpass + 8); if (!pass_ptr) { fprintf(stderr, "Error: malloc(%lu) failed\n", hydra_brains.sizepass + hydra_brains.countpass + 8); exit(-1); } fck = (int32_t)fread(pass_ptr, hydra_brains.sizepass + hydra_brains.countpass + 8, 1, f); } else { // colonfile mode hydra_options.colonfile = empty_login; // dummy pass_ptr = csv_ptr = login_ptr; } if (debug) printf("[DEBUG] reading restore file: Step 10 complete\n"); hydra_targets = (hydra_target **)malloc((hydra_brains.targets + 3) * sizeof(hydra_target *)); if (!hydra_targets) { fprintf(stderr, "Error: malloc(%lu) failed\n", (hydra_brains.targets + 3) * sizeof(hydra_target *)); exit(-1); } for (j = 0; j < hydra_brains.targets; j++) { hydra_targets[j] = malloc(sizeof(hydra_target)); if (!hydra_targets[j]) { fprintf(stderr, "Error: malloc(%lu) failed\n", sizeof(hydra_target)); exit(-1); } fck = (int32_t)fread(hydra_targets[j], sizeof(hydra_target), 1, f); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_targets[j]->target = malloc(strlen(out) + 1); strcpy(hydra_targets[j]->target, out); sck = fgets(out, sizeof(out), f); hydra_targets[j]->login_ptr = login_ptr + atoi(out); sck = fgets(out, sizeof(out), f); hydra_targets[j]->pass_ptr = pass_ptr + atoi(out); sck = fgets(out, sizeof(out), f); // target login_ptr, ignord sck = fgets(out, sizeof(out), f); if (hydra_options.bfg) { if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_targets[j]->pass_ptr = malloc(strlen(out) + 1); strcpy(hydra_targets[j]->pass_ptr, out); } if (hydra_targets[j]->redo > 0) { if (debug) printf("[DEBUG] target %d redo %d\n", j, hydra_targets[j]->redo); for (i = 0; i < hydra_targets[j]->redo; i++) { sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_targets[j]->redo_login[i] = malloc(strlen(out) + 1); strcpy(hydra_targets[j]->redo_login[i], out); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_targets[j]->redo_pass[i] = malloc(strlen(out) + 1); strcpy(hydra_targets[j]->redo_pass[i], out); } } if (hydra_targets[j]->skipcnt >= hydra_brains.countlogin) hydra_targets[j]->skipcnt = 0; if (hydra_targets[j]->skipcnt > 0) for (i = 0; i < hydra_targets[j]->skipcnt; i++) { sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_targets[j]->skiplogin[i] = malloc(strlen(out) + 1); strcpy(hydra_targets[j]->skiplogin[i], out); } hydra_targets[j]->fail_count = 0; hydra_targets[j]->use_count = 0; hydra_targets[j]->failed = 0; } if (debug) printf("[DEBUG] reading restore file: Step 11 complete\n"); hydra_heads = malloc(sizeof(hydra_head *) * hydra_options.max_use); if (!hydra_heads) { fprintf(stderr, "Error: malloc(%lu) failed\n", sizeof(hydra_head *) * hydra_options.max_use); exit(-1); } for (j = 0; j < hydra_options.max_use; j++) { hydra_heads[j] = malloc(sizeof(hydra_head)); if (!hydra_heads[j]) { fprintf(stderr, "Error: malloc(%lu) failed\n", sizeof(hydra_head)); exit(-1); } fck = (int32_t)fread(hydra_heads[j], sizeof(hydra_head), 1, f); hydra_heads[j]->sp[0] = -1; hydra_heads[j]->sp[1] = -1; sck = fgets(out, sizeof(out), f); if (hydra_heads[j]->redo) { if (debug) printf("[DEBUG] head %d redo\n", j); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; hydra_heads[j]->current_login_ptr = malloc(strlen(out) + 1); strcpy(hydra_heads[j]->current_login_ptr, out); } sck = fgets(out, sizeof(out), f); if (hydra_heads[j]->redo) { if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (debug) printf("[DEBUG] TEMP head %d: pass == %s, login == %s\n", j, out, hydra_heads[j]->current_login_ptr); if (out[0] != 0 || hydra_heads[j]->current_login_ptr[0] != 0) { hydra_heads[j]->current_pass_ptr = malloc(strlen(out) + 1); strcpy(hydra_heads[j]->current_pass_ptr, out); if (debug) printf("[DEBUG] redo: %d %s/%s\n", j, hydra_heads[j]->current_login_ptr, hydra_heads[j]->current_pass_ptr); } else { hydra_heads[j]->redo = 0; free(hydra_heads[j]->current_login_ptr); hydra_heads[j]->current_login_ptr = hydra_heads[j]->current_pass_ptr = empty_login; } } else { hydra_heads[j]->current_login_ptr = hydra_heads[j]->current_pass_ptr = empty_login; } } if (debug) printf("[DEBUG] reading restore file: Step 12 complete\n"); sck = fgets(out, sizeof(out), f); if (out[0] != 0 && out[strlen(out) - 1] == '\n') out[strlen(out) - 1] = 0; if (strcmp(out, PROGRAM) != 0) { fprintf(stderr, "[ERROR] invalid restore file (end)\n"); exit(-1); } fclose(f); hydra_debug(0, "hydra_restore_read"); } void killed_childs(int32_t signo) { int32_t pid, i; killed++; pid = waitpid(-1, NULL, WNOHANG); for (i = 0; i < hydra_options.max_use; i++) { if (pid == hydra_heads[i]->pid) { hydra_heads[i]->pid = -1; hydra_kill_head(i, 1, 0); return; } } } void killed_childs_report(int32_t signo) { // if (debug) printf("[ERROR] children crashed! (%d)\n", child_head_no); fck = write(child_socket, "E", 1); _exit(-1); } void kill_children(int32_t signo) { int32_t i; if (verbose) fprintf(stderr, "[ERROR] Received signal %d, going down ...\n", signo); if (process_restore == 1) hydra_restore_write(1); if (hydra_heads != NULL) { for (i = 0; i < hydra_options.max_use; i++) if (hydra_heads[i] != NULL && hydra_heads[i]->pid > 0) kill(hydra_heads[i]->pid, SIGTERM); for (i = 0; i < hydra_options.max_use; i++) if (hydra_heads[i] != NULL && hydra_heads[i]->pid > 0) kill(hydra_heads[i]->pid, SIGKILL); } exit(0); } uint64_t countlines(FILE *fd, int32_t colonmode) { size_t clines = 0; char *buf = malloc(MAXLINESIZE); int32_t only_one_empty_line = 0; #ifdef HAVE_ZLIB gzFile fp = gzdopen(fileno(fd), "r"); #else FILE *fp = fd; #endif size_of_data = 0; #ifdef HAVE_ZLIB while (!gzeof(fp)) { if (gzgets(fp, buf, MAXLINESIZE) != NULL) { #else while (!feof(fp)) { if (fgets(buf, MAXLINESIZE, fp) != NULL) { #endif size_of_data += strlen(buf); if (buf[0] != 0) { if (buf[0] == '\r' || buf[0] == '\n') { if (only_one_empty_line == 0) { only_one_empty_line = 1; clines++; } } else { clines++; } } } } #ifdef HAVE_ZLIB gzrewind(fp); #else rewind(fp); #endif free(buf); return clines; } void fill_mem(char *ptr, FILE *fd, int32_t colonmode) { char tmp[MAXBUF + 4] = "", *ptr2; uint32_t len; int32_t only_one_empty_line = 0; int read_flag = 0; #ifdef HAVE_ZLIB gzFile fp = gzdopen(fileno(fd), "r"); while (!gzeof(fp) && !read_flag) { if (gzgets(fp, tmp, MAXLINESIZE) != NULL) { #else FILE *fp = fd; while (!feof(fp) && !read_flag) { if (fgets(tmp, MAXLINESIZE, fp) != NULL) { #endif if (tmp[0] != 0) { if (tmp[strlen(tmp) - 1] == '\n') tmp[strlen(tmp) - 1] = '\0'; if (tmp[0] != 0 && tmp[strlen(tmp) - 1] == '\r') tmp[strlen(tmp) - 1] = '\0'; if ((len = strlen(tmp)) > 0 || (only_one_empty_line == 0 && colonmode == 0)) { if (len == 0 && colonmode == 0) { only_one_empty_line = 1; len = 1; tmp[len] = 0; } if (colonmode) { if ((ptr2 = strchr(tmp, ':')) == NULL) { fprintf(stderr, "[ERROR] invalid line in colon file (-C), missing colon " "in line: %s\n", tmp); exit(-1); } else { *ptr2 = 0; } } memcpy(ptr, tmp, len); ptr += len; *ptr = '\0'; ptr++; } } } else { read_flag = 1; } } #ifdef HAVE_ZLIB gzclose(fp); #else fclose(fp); #endif } char *hydra_build_time() { static char datetime[24]; struct tm *the_time; time_t epoch; time(&epoch); the_time = localtime(&epoch); strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", the_time); return (char *)&datetime; } void hydra_service_init(int32_t target_no) { int32_t x = 99; int32_t i; hydra_target *t = hydra_targets[target_no]; FILE *ofp = hydra_brains.ofp; for (i = 0; x == 99 && i < sizeof(services) / sizeof(services[0]); i++) { if (strcmp(hydra_options.service, services[i].name) == 0) { if (services[i].init) { x = services[i].init(t->ip, -1, options, t->miscptr, ofp, t->port, t->target); break; } } } // dirty workaround here: #ifdef LIBSSH if (strcmp(hydra_options.service, "ssh") == 0) x = service_ssh_init(t->ip, -1, options, login_ptr, ofp, t->port, t->target); #endif if (x != 0 && x != 99) { if (x > 0 && x < 4) hydra_targets[target_no]->done = x; else hydra_targets[target_no]->done = TARGET_ERROR; hydra_brains.finished++; if (hydra_brains.targets == 1) { if (hydra_brains.ofp != NULL && hydra_brains.ofp != stdout) { if (hydra_options.outfile_format == FORMAT_JSONV1) { char json_error[120]; snprintf(json_error, sizeof(json_error), "[ERROR] unexpected result connecting to target %s port %d", hydra_address2string_beautiful(t->ip), t->port); fprintf(hydra_brains.ofp, "\n\t],\n\"success\": false,\n\"errormessages\": [ \"%s\" " "],\n\"quantityfound\": %" hPRIu64 " }\n", json_error, hydra_brains.found); } fclose(hydra_brains.ofp); } exit(-1); } } } int32_t hydra_spawn_head(int32_t head_no, int32_t target_no) { int32_t i; if (head_no < 0 || head_no >= hydra_options.max_use || target_no < 0 || target_no >= hydra_brains.targets) { if (verbose > 1 || debug) printf("[DEBUG-ERROR] spawn_head: head_no %d, target_no %d\n", head_no, target_no); return -1; } if (hydra_heads[head_no]->active == HEAD_DISABLED) { printf("[DEBUG-ERROR] child %d should not be respawned!\n", head_no); return -1; } if (socketpair(PF_UNIX, SOCK_STREAM, 0, hydra_heads[head_no]->sp) == 0) { child_head_no = head_no; if ((hydra_heads[head_no]->pid = fork()) == 0) { // THIS IS THE CHILD // set new signals for child process_restore = 0; child_socket = hydra_heads[head_no]->sp[1]; signal(SIGCHLD, killed_childs); signal(SIGTERM, exit); #ifdef SIGBUS signal(SIGBUS, exit); #endif signal(SIGSEGV, killed_childs_report); signal(SIGHUP, exit); signal(SIGINT, exit); signal(SIGPIPE, exit); // free structures to make memory available cmdlinetarget = hydra_targets[target_no]->target; for (i = 0; i < hydra_options.max_use; i++) if (i != head_no) free(hydra_heads[i]); for (i = 0; i < hydra_brains.targets; i++) if (i != target_no) free(hydra_targets[i]); if (hydra_options.loginfile != NULL) free(login_ptr); if (hydra_options.passfile != NULL) free(pass_ptr); if (hydra_options.colonfile != NULL && hydra_options.colonfile != empty_login) free(csv_ptr); // we must keep servers_ptr for cmdlinetarget to work if (debug) printf("[DEBUG] head_no %d has pid %d\n", head_no, getpid()); hydra_target *t = hydra_targets[target_no]; int32_t sp = hydra_heads[head_no]->sp[1]; // char *miscptr = hydra_options.miscptr; FILE *ofp = hydra_brains.ofp; hydra_target *head_target = hydra_targets[hydra_heads[head_no]->target_no]; for (i = 0; i < sizeof(services) / sizeof(services[0]); i++) { if (strcmp(hydra_options.service, services[i].name) == 0) { if (services[i].exec) { services[i].exec(t->ip, sp, options, t->miscptr, ofp, t->port, head_target->target); // just in case a module returns (which it shouldnt) we let it exit // here exit(-1); } } } // FIXME: dirty workaround here if (strcmp(hydra_options.service, "xmpp") == 0) { service_xmpp(hydra_targets[target_no]->target, hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); } // just in case a module returns (which it shouldnt) we let it exit here exit(-1); } else { child_head_no = -1; if (hydra_heads[head_no]->pid > 0) { fck = write(hydra_heads[head_no]->sp[1], "n", 1); // yes, a small "n" - this way we can distinguish later // if the client successfully tested a pair and is // requesting a new one or the mother did that (void)fcntl(hydra_heads[head_no]->sp[0], F_SETFL, O_NONBLOCK); if (hydra_heads[head_no]->redo != 1) hydra_heads[head_no]->target_no = target_no; hydra_heads[head_no]->active = HEAD_ACTIVE; hydra_targets[hydra_heads[head_no]->target_no]->use_count++; hydra_brains.active++; hydra_heads[head_no]->last_seen = time(NULL); if (debug) printf("[DEBUG] child %d spawned for target %d with pid %d\n", head_no, hydra_heads[head_no]->target_no, hydra_heads[head_no]->pid); } else { perror("[ERROR] Fork for children failed"); hydra_heads[head_no]->sp[0] = -1; hydra_heads[head_no]->active = HEAD_UNUSED; return -1; } } } else { perror("[ERROR] socketpair creation failed"); hydra_heads[head_no]->sp[0] = -1; hydra_heads[head_no]->active = HEAD_UNUSED; return -1; } return 0; } int32_t hydra_lookup_port(char *service) { int32_t i = 0, port = -2; hydra_portlist hydra_portlists[] = {{"ftp", PORT_FTP, PORT_FTP_SSL}, {"ftps", PORT_FTP, PORT_FTP_SSL}, {"http-head", PORT_HTTP, PORT_HTTP_SSL}, {"http-post", PORT_HTTP, PORT_HTTP_SSL}, {"http-get", PORT_HTTP, PORT_HTTP_SSL}, {"http-get-form", PORT_HTTP, PORT_HTTP_SSL}, {"http-post-form", PORT_HTTP, PORT_HTTP_SSL}, {"https-get-form", PORT_HTTP, PORT_HTTP_SSL}, {"https-post-form", PORT_HTTP, PORT_HTTP_SSL}, {"https-head", PORT_HTTP, PORT_HTTP_SSL}, {"https-get", PORT_HTTP, PORT_HTTP_SSL}, {"http-proxy", PORT_HTTP_PROXY, PORT_HTTP_PROXY_SSL}, {"http-proxy-urlenum", PORT_HTTP_PROXY, PORT_HTTP_PROXY_SSL}, {"icq", PORT_ICQ, PORT_ICQ_SSL}, {"imap", PORT_IMAP, PORT_IMAP_SSL}, {"ldap2", PORT_LDAP, PORT_LDAP_SSL}, {"ldap3", PORT_LDAP, PORT_LDAP_SSL}, {"ldap3-crammd5", PORT_LDAP, PORT_LDAP_SSL}, {"ldap3-digestmd5", PORT_LDAP, PORT_LDAP_SSL}, {"oracle-listener", PORT_ORACLE, PORT_ORACLE_SSL}, {"oracle-sid", PORT_ORACLE, PORT_ORACLE_SSL}, {"oracle", PORT_ORACLE, PORT_ORACLE_SSL}, {"memcached", PORT_MCACHED, PORT_MCACHED_SSL}, {"mongodb", PORT_MONGODB, PORT_MONGODB}, {"mssql", PORT_MSSQL, PORT_MSSQL_SSL}, {"cobaltstrike", PORT_COBALTSTRIKE, PORT_COBALTSTRIKE_SSL}, {"mysql", PORT_MYSQL, PORT_MYSQL_SSL}, {"postgres", PORT_POSTGRES, PORT_POSTGRES_SSL}, {"pcanywhere", PORT_PCANYWHERE, PORT_PCANYWHERE_SSL}, {"nntp", PORT_NNTP, PORT_NNTP_SSL}, {"pcnfs", PORT_PCNFS, PORT_PCNFS_SSL}, {"pop3", PORT_POP3, PORT_POP3_SSL}, {"redis", PORT_REDIS, PORT_REDIS_SSL}, {"rexec", PORT_REXEC, PORT_REXEC_SSL}, {"rlogin", PORT_RLOGIN, PORT_RLOGIN_SSL}, {"rsh", PORT_RSH, PORT_RSH_SSL}, {"sapr3", PORT_SAPR3, PORT_SAPR3_SSL}, {"smb", PORT_SMBNT, PORT_SMBNT_SSL}, {"smb2", PORT_SMBNT, PORT_SMBNT_SSL}, {"smbnt", PORT_SMBNT, PORT_SMBNT_SSL}, {"socks5", PORT_SOCKS5, PORT_SOCKS5_SSL}, {"ssh", PORT_SSH, PORT_SSH_SSL}, {"sshkey", PORT_SSH, PORT_SSH_SSL}, {"telnet", PORT_TELNET, PORT_TELNET_SSL}, {"adam6500", PORT_ADAM6500, PORT_ADAM6500_SSL}, {"cisco", PORT_TELNET, PORT_TELNET_SSL}, {"cisco-enable", PORT_TELNET, PORT_TELNET_SSL}, {"vnc", PORT_VNC, PORT_VNC_SSL}, {"snmp", PORT_SNMP, PORT_SNMP_SSL}, {"cvs", PORT_CVS, PORT_CVS_SSL}, {"svn", PORT_SVN, PORT_SVN_SSL}, {"firebird", PORT_FIREBIRD, PORT_FIREBIRD_SSL}, {"afp", PORT_AFP, PORT_AFP_SSL}, {"ncp", PORT_NCP, PORT_NCP_SSL}, {"smtp", PORT_SMTP, PORT_SMTP_SSL}, {"smtp-enum", PORT_SMTP, PORT_SMTP_SSL}, {"teamspeak", PORT_TEAMSPEAK, PORT_TEAMSPEAK_SSL}, {"sip", PORT_SIP, PORT_SIP_SSL}, {"vmauthd", PORT_VMAUTHD, PORT_VMAUTHD_SSL}, {"xmpp", PORT_XMPP, PORT_XMPP_SSL}, {"irc", PORT_IRC, PORT_IRC_SSL}, {"rdp", PORT_RDP, PORT_RDP_SSL}, {"asterisk", PORT_ASTERISK, PORT_ASTERISK_SSL}, {"s7-300", PORT_S7_300, PORT_S7_300_SSL}, {"rtsp", PORT_RTSP, PORT_RTSP_SSL}, {"rpcap", PORT_RPCAP, PORT_RPCAP_SSL}, {"radmin2", PORT_RADMIN2, PORT_RADMIN2}, // ADD NEW SERVICES HERE - add new port numbers to hydra.h {"", PORT_NOPORT, PORT_NOPORT}}; while (strlen(hydra_portlists[i].name) > 0 && port == -2) { if (strcmp(service, hydra_portlists[i].name) == 0) { if (hydra_options.ssl) port = hydra_portlists[i].port_ssl; else port = hydra_portlists[i].port; } i++; } if (port < 1) return -1; else return port; } // killit = 1 : kill(pid); fail = 1 : redo, fail = 2/3 : disable void hydra_kill_head(int32_t head_no, int32_t killit, int32_t fail) { if (debug) printf("[DEBUG] head_no %d, kill %d, fail %d\n", head_no, killit, fail); if (head_no < 0) return; if (hydra_heads[head_no]->active == HEAD_ACTIVE || (hydra_heads[head_no]->sp[0] > 2 && hydra_heads[head_no]->sp[1] > 2)) { close(hydra_heads[head_no]->sp[0]); close(hydra_heads[head_no]->sp[1]); } if (killit) { if (hydra_heads[head_no]->pid > 0) kill(hydra_heads[head_no]->pid, SIGTERM); hydra_brains.active--; } if (hydra_heads[head_no]->active == HEAD_ACTIVE) { hydra_heads[head_no]->active = HEAD_UNUSED; hydra_targets[hydra_heads[head_no]->target_no]->use_count--; } if (fail == 1) { if (hydra_options.cidr != 1) hydra_heads[head_no]->redo = 1; } else if (fail == 2) { if (hydra_options.cidr != 1) hydra_heads[head_no]->active = HEAD_DISABLED; if (hydra_heads[head_no]->target_no >= 0) hydra_targets[hydra_heads[head_no]->target_no]->failed++; } else if (fail == 3) { hydra_heads[head_no]->active = HEAD_DISABLED; if (hydra_heads[head_no]->target_no >= 0) hydra_targets[hydra_heads[head_no]->target_no]->failed++; } if (hydra_heads[head_no]->pid > 0 && killit) kill(hydra_heads[head_no]->pid, SIGKILL); hydra_heads[head_no]->pid = -1; if (fail < 1 && hydra_heads[head_no]->target_no >= 0 && hydra_options.bfg && hydra_targets[hydra_heads[head_no]->target_no]->pass_state == 3 && strlen(hydra_heads[head_no]->current_pass_ptr) > 0 && hydra_heads[head_no]->current_pass_ptr != hydra_heads[head_no]->current_login_ptr) { free(hydra_heads[head_no]->current_pass_ptr); hydra_heads[head_no]->current_pass_ptr = empty_login; // hydra_bfg_remove(head_no); // hydra_targets[hydra_heads[head_no]->target_no]->bfg_ptr[head_no] = // NULL; } (void)waitpid(-1, NULL, WNOHANG); } void hydra_increase_fail_count(int32_t target_no, int32_t head_no) { int32_t i, k, maxfail = 0; if (target_no < 0 || hydra_options.skip_redo) return; if (hydra_targets[target_no]->ok) { const int32_t tasks = hydra_options.tasks; const int32_t success = tasks - hydra_targets[target_no]->failed; const int32_t t = tasks < 5 ? 6 - tasks : 1; const int32_t s = success < 5 ? 6 - success : 1; maxfail = MAXFAIL + t + s + 2; } hydra_targets[target_no]->fail_count++; if (debug) printf("[DEBUG] hydra_increase_fail_count: %d >= %d => disable\n", hydra_targets[target_no]->fail_count, maxfail); if (hydra_targets[target_no]->fail_count >= maxfail) { k = 0; for (i = 0; i < hydra_options.max_use; i++) if (hydra_heads[i]->active >= HEAD_UNUSED && hydra_heads[i]->target_no == target_no) k++; if (k <= 1) { // we need to put this in a list, otherwise we fail one login+pw test if (hydra_targets[target_no]->done == TARGET_ACTIVE && hydra_options.skip_redo == 0 && hydra_targets[target_no]->redo <= hydra_options.max_use * 2 && ((hydra_heads[head_no]->current_login_ptr != empty_login && hydra_heads[head_no]->current_pass_ptr != empty_login) || (hydra_heads[head_no]->current_login_ptr != NULL && hydra_heads[head_no]->current_pass_ptr != NULL))) { hydra_targets[target_no]->redo_login[hydra_targets[target_no]->redo] = hydra_heads[head_no]->current_login_ptr; hydra_targets[target_no]->redo_pass[hydra_targets[target_no]->redo] = hydra_heads[head_no]->current_pass_ptr; hydra_targets[target_no]->redo++; total_redo_count++; if (debug) printf("[DEBUG] - will be retried at the end: ip %s - login %s - " "pass %s - child %d\n", hydra_targets[target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, head_no); hydra_heads[head_no]->current_login_ptr = empty_login; hydra_heads[head_no]->current_pass_ptr = empty_login; } if (hydra_targets[target_no]->fail_count >= MAXFAIL + hydra_options.tasks * hydra_targets[target_no]->ok) { if (hydra_targets[target_no]->done == TARGET_ACTIVE && hydra_options.max_use <= hydra_targets[target_no]->failed) { if (hydra_targets[target_no]->ok == 1) hydra_targets[target_no]->done = TARGET_ERROR; // mark target as done by errors else hydra_targets[target_no]->done = TARGET_UNRESOLVED; // mark target as done by unable to connect hydra_brains.finished++; fprintf(stderr, "[ERROR] Too many connect errors to target, disabling " "%s://%s%s%s:%d\n", hydra_options.service, hydra_targets[target_no]->ip[0] == 16 && strchr(hydra_targets[target_no]->target, ':') != NULL ? "[" : "", hydra_targets[target_no]->target, hydra_targets[target_no]->ip[0] == 16 && strchr(hydra_targets[target_no]->target, ':') != NULL ? "]" : "", hydra_targets[target_no]->port); } else { hydra_targets[target_no]->failed++; } if (hydra_brains.targets <= hydra_brains.finished) hydra_kill_head(head_no, 1, 0); else hydra_kill_head(head_no, 1, 2); } // we keep the last one alive as long as it make sense } else { // we need to put this in a list, otherwise we fail one login+pw test if (hydra_targets[target_no]->done == TARGET_ACTIVE && hydra_options.skip_redo == 0 && hydra_targets[target_no]->redo <= hydra_options.max_use * 2 && ((hydra_heads[head_no]->current_login_ptr != empty_login && hydra_heads[head_no]->current_pass_ptr != empty_login) || (hydra_heads[head_no]->current_login_ptr != NULL && hydra_heads[head_no]->current_pass_ptr != NULL))) { hydra_targets[target_no]->redo_login[hydra_targets[target_no]->redo] = hydra_heads[head_no]->current_login_ptr; hydra_targets[target_no]->redo_pass[hydra_targets[target_no]->redo] = hydra_heads[head_no]->current_pass_ptr; hydra_targets[target_no]->redo++; total_redo_count++; if (debug) printf("[DEBUG] - will be retried at the end: ip %s - login %s - " "pass %s - child %d\n", hydra_targets[target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, head_no); hydra_heads[head_no]->current_login_ptr = empty_login; hydra_heads[head_no]->current_pass_ptr = empty_login; } /* hydra_targets[target_no]->fail_count--; if (k < 5 && hydra_targets[target_no]->ok) hydra_targets[target_no]->fail_count--; if (k == 2 && hydra_targets[target_no]->ok) hydra_targets[target_no]->fail_count--; */ if (hydra_brains.targets <= hydra_brains.finished) hydra_kill_head(head_no, 1, 0); else { hydra_kill_head(head_no, 1, 2); if (verbose) printf("[VERBOSE] Disabled child %d because of too many errors\n", head_no); } } } else { hydra_kill_head(head_no, 1, 1); if (verbose) printf("[VERBOSE] Retrying connection for child %d\n", head_no); } } char *hydra_reverse_login(int32_t head_no, char *login) { int32_t i, j; char *start, *pos; unsigned char keep; if (login == NULL || (j = strlen(login)) < 1) return empty_login; if (j > 248) j = 248; for (i = 0; i < j; i++) hydra_heads[head_no]->reverse[i] = login[j - (i + 1)]; hydra_heads[head_no]->reverse[j] = 0; // UTF stuff now start = hydra_heads[head_no]->reverse; pos = start + j; while (start < --pos) { switch ((*pos & 0xF0) >> 4) { case 0xF: /* U+010000-U+10FFFF: four bytes. */ keep = *pos; *pos = *(pos - 3); *(pos - 3) = keep; keep = *(pos - 1); *(pos - 1) = *(pos - 2); *(pos - 2) = keep; pos -= 3; break; case 0xE: /* U+000800-U+00FFFF: three bytes. */ keep = *pos; *pos = *(pos - 2); *(pos - 2) = keep; pos -= 2; break; case 0xC: /* fall-through */ case 0xD: /* U+000080-U+0007FF: two bytes. */ keep = *pos; *pos = *(pos - 1); *(pos - 1) = keep; pos--; break; } } return hydra_heads[head_no]->reverse; } void delete_junk_files(){ remove(junk_file); } FILE *hydra_divide_file(FILE *file, uint32_t my_segment, uint32_t num_segments){ if(my_segment > num_segments){ fprintf(stderr, "[ERROR] in option -D XofY, X must not be greater than Y: %s\n", hydra_options.passfile); return NULL; } FILE *output_file; char line[500]; char output_file_name[50]; uint32_t line_number = 0; double total_lines = countlines(file,0); if(num_segments > total_lines){ fprintf(stderr, "[ERROR] in option -D XofY, Y must not be greater than the total number of lines in the file to be divided: %s\n", hydra_options.passfile); return NULL; } double segment_size_double = total_lines / num_segments; // round up segment_size_float to integer uint64_t segment_size = (uint64_t)segment_size_double; if(segment_size < segment_size_double) segment_size++; uint64_t segment_start = segment_size * (my_segment - 1) + 1; uint64_t segment_end = segment_size * my_segment; srand(time(NULL)); int filetag = rand(); sprintf(output_file_name, "segment_%d_%d.txt",filetag, my_segment); output_file = fopen(output_file_name, "w"); if(!output_file){ fprintf(stderr, "[ERROR] Segment file empty: %s\n", hydra_options.passfile); return NULL; } strcpy(junk_file, output_file_name); atexit(delete_junk_files); while(fgets(line, sizeof line, file) != NULL && line_number < segment_end){ line_number++; if(line_number >= segment_start && line_number <= segment_end) fprintf(output_file, "%s", line); } rewind(file); fclose(output_file); output_file = fopen(output_file_name, "r"); return output_file; } int32_t hydra_send_next_pair(int32_t target_no, int32_t head_no) { // variables moved to save stack snpdone = 0; snp_is_redo = 0; snpdont = 0; loop_cnt++; if (hydra_heads[head_no]->redo == 1 && hydra_heads[head_no]->current_login_ptr != NULL && hydra_heads[head_no]->current_pass_ptr != NULL) { hydra_heads[head_no]->redo = 0; snp_is_redo = 1; snpdone = 1; } else { if (hydra_targets[target_no]->sent >= hydra_brains.todo + hydra_targets[target_no]->redo) { if (hydra_targets[target_no]->done == TARGET_ACTIVE) { hydra_targets[target_no]->done = TARGET_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to " "complete tests)\n", hydra_targets[target_no]->target); } return -1; } } if (debug) printf("[DEBUG] send_next_pair_init target %d, head %d, redo %d, " "redo_state %d, pass_state %d. loop_mode %d, curlogin %s, curpass " "%s, tlogin %s, tpass %s, logincnt %" hPRIu64 "/%" hPRIu64 ", passcnt %" hPRIu64 "/%" hPRIu64 ", loop_cnt %d\n", target_no, head_no, hydra_targets[target_no]->redo, hydra_targets[target_no]->redo_state, hydra_targets[target_no]->pass_state, hydra_options.loop_mode, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, hydra_targets[target_no]->login_ptr, hydra_targets[target_no]->pass_ptr, hydra_targets[target_no]->login_no, hydra_brains.countlogin, hydra_targets[target_no]->pass_no, hydra_brains.countpass, loop_cnt); if (loop_cnt > (hydra_brains.countlogin * 2) + 1 && loop_cnt > (hydra_brains.countpass * 2) + 1) { if (debug) printf("[DEBUG] too many loops in send_next_pair, returning -1 (loop_cnt " "%d, sent %" hPRIu64 ", todo %" hPRIu64 ")\n", loop_cnt, hydra_targets[target_no]->sent, hydra_brains.todo); return -1; } if (hydra_heads[head_no]->redo == 1 && hydra_heads[head_no]->current_login_ptr != NULL && hydra_heads[head_no]->current_pass_ptr != NULL) { hydra_heads[head_no]->redo = 0; snp_is_redo = 1; snpdone = 1; } else { if (debug && (hydra_heads[head_no]->current_login_ptr != NULL || hydra_heads[head_no]->current_pass_ptr != NULL)) printf("[COMPLETED] target %s - login \"%s\" - pass \"%s\" - child %d - " "%" hPRIu64 " of %" hPRIu64 "\n", hydra_targets[target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, head_no, hydra_targets[target_no]->sent, hydra_brains.todo + hydra_targets[target_no]->redo); // hydra_heads[head_no]->redo = 0; if (hydra_targets[target_no]->redo_state > 0) { if (hydra_targets[target_no]->redo_state <= hydra_targets[target_no]->redo) { hydra_heads[head_no]->current_pass_ptr = hydra_targets[target_no]->redo_pass[hydra_targets[target_no]->redo_state - 1]; hydra_heads[head_no]->current_login_ptr = hydra_targets[target_no]->redo_login[hydra_targets[target_no]->redo_state - 1]; hydra_targets[target_no]->redo_state++; snpdone = 1; } else { // if a pair does not complete after this point it is lost if (hydra_targets[target_no]->done == TARGET_ACTIVE) { hydra_targets[target_no]->done = TARGET_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to " "complete tests)\n", hydra_targets[target_no]->target); } loop_cnt = 0; return -1; } } else { // normale state, no redo if (hydra_targets[target_no]->done != TARGET_ACTIVE) { loop_cnt = 0; return -1; // head will be disabled by main while() } if (hydra_options.loop_mode == 0) { // one user after another if (hydra_targets[target_no]->login_no < hydra_brains.countlogin) { // as we loop password in mode == 0 we set the current login first hydra_heads[head_no]->current_login_ptr = hydra_targets[target_no]->login_ptr; // then we do the extra options -e ns handling if (hydra_targets[target_no]->pass_state == 0 && snpdone == 0) { if (hydra_options.try_password_same_as_login) { hydra_heads[head_no]->current_pass_ptr = hydra_targets[target_no]->login_ptr; snpdone = 1; hydra_targets[target_no]->pass_no++; } hydra_targets[target_no]->pass_state++; } if (hydra_targets[target_no]->pass_state == 1 && snpdone == 0) { // small check that there is a login name (could also be emtpy) and // if we already tried empty password it would be a double if (hydra_options.try_null_password) { if (hydra_options.try_password_same_as_login == 0 || (hydra_targets[target_no]->login_ptr != NULL && strlen(hydra_targets[target_no]->login_ptr) > 0)) { hydra_heads[head_no]->current_pass_ptr = empty_login; snpdone = 1; } else { hydra_brains.sent++; hydra_targets[target_no]->sent++; } hydra_targets[target_no]->pass_no++; } hydra_targets[target_no]->pass_state++; } if (hydra_targets[target_no]->pass_state == 2 && snpdone == 0) { // small check that there is a login name (could also be emtpy) and // if we already tried empty password it would be a double if (hydra_options.try_password_reverse_login) { if ((hydra_options.try_password_same_as_login == 0 || strcmp(hydra_targets[target_no]->login_ptr, hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr)) != 0) && (hydra_options.try_null_password == 0 || (hydra_targets[target_no]->login_ptr != NULL && strlen(hydra_targets[target_no]->login_ptr) > 0))) { hydra_heads[head_no]->current_pass_ptr = hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr); snpdone = 1; } else { hydra_brains.sent++; hydra_targets[target_no]->sent++; } hydra_targets[target_no]->pass_no++; } hydra_targets[target_no]->pass_state++; } // now we handle the -C -l/-L -p/-P data if (hydra_targets[target_no]->pass_state == 3 && snpdone == 0) { if (check_flag(hydra_options.mode, MODE_COLON_FILE)) { // colon mode hydra_heads[head_no]->current_login_ptr = hydra_targets[target_no]->login_ptr; hydra_heads[head_no]->current_pass_ptr = hydra_targets[target_no]->pass_ptr; hydra_targets[target_no]->login_no++; snpdone = 1; hydra_targets[target_no]->login_ptr = hydra_targets[target_no]->pass_ptr; // hydra_targets[target_no]->login_ptr++; while (*hydra_targets[target_no]->login_ptr != 0) hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->pass_ptr = hydra_targets[target_no]->login_ptr; // hydra_targets[target_no]->pass_ptr++; while (*hydra_targets[target_no]->pass_ptr != 0) hydra_targets[target_no]->pass_ptr++; hydra_targets[target_no]->pass_ptr++; if (strcmp(hydra_targets[target_no]->login_ptr, hydra_heads[head_no]->current_login_ptr) != 0) hydra_targets[target_no]->pass_state = 0; if ((hydra_options.try_password_same_as_login && strcmp(hydra_heads[head_no]->current_pass_ptr, hydra_heads[head_no]->current_login_ptr) == 0) || (hydra_options.try_null_password && strlen(hydra_heads[head_no]->current_pass_ptr) == 0) || (hydra_options.try_password_reverse_login && strcmp(hydra_heads[head_no]->current_pass_ptr, hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr)) == 0)) { hydra_brains.sent++; hydra_targets[target_no]->sent++; if (debug) printf("[DEBUG] double detected (-C)\n"); return hydra_send_next_pair(target_no, head_no); // little trick to keep the code small } } else { // standard -l -L -p -P mode hydra_heads[head_no]->current_pass_ptr = hydra_targets[target_no]->pass_ptr; hydra_targets[target_no]->pass_no++; // double check if (hydra_targets[target_no]->pass_no >= hydra_brains.countpass) { // all passwords done, next user for next password hydra_targets[target_no]->login_ptr++; while (*hydra_targets[target_no]->login_ptr != 0) hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->pass_ptr = pass_ptr; hydra_targets[target_no]->login_no++; hydra_targets[target_no]->pass_no = 0; hydra_targets[target_no]->pass_state = 0; if (hydra_brains.countpass == hydra_options.try_password_reverse_login + hydra_options.try_null_password + hydra_options.try_password_same_as_login) return hydra_send_next_pair(target_no, head_no); } else { hydra_targets[target_no]->pass_ptr++; while (*hydra_targets[target_no]->pass_ptr != 0) hydra_targets[target_no]->pass_ptr++; hydra_targets[target_no]->pass_ptr++; } if ((hydra_options.try_password_same_as_login && strcmp(hydra_heads[head_no]->current_pass_ptr, hydra_heads[head_no]->current_login_ptr) == 0) || (hydra_options.try_null_password && strlen(hydra_heads[head_no]->current_pass_ptr) == 0) || (hydra_options.try_password_reverse_login && strcmp(hydra_heads[head_no]->current_pass_ptr, hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr)) == 0)) { hydra_brains.sent++; hydra_targets[target_no]->sent++; if (debug) printf("[DEBUG] double detected (-Pp)\n"); return hydra_send_next_pair(target_no, head_no); // little trick to keep the code small } snpdone = 1; } } } } else { // loop_mode == 1 if (hydra_targets[target_no]->pass_no < hydra_brains.countpass) { hydra_heads[head_no]->current_login_ptr = hydra_targets[target_no]->login_ptr; if (hydra_targets[target_no]->pass_state == 0) { if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(hydra_heads[head_no]->current_login_ptr); else hydra_heads[head_no]->current_pass_ptr = hydra_heads[head_no]->current_login_ptr; } else if (hydra_targets[target_no]->pass_state == 1) { if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(empty_login); else hydra_heads[head_no]->current_pass_ptr = empty_login; } else if (hydra_targets[target_no]->pass_state == 2) { if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr)); else hydra_heads[head_no]->current_pass_ptr = hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr); } else { if (hydra_options.bfg && hydra_targets[target_no]->pass_state == 3 && hydra_heads[head_no]->current_pass_ptr != NULL && strlen(hydra_heads[head_no]->current_pass_ptr) > 0 && hydra_heads[head_no]->current_pass_ptr != hydra_heads[head_no]->current_login_ptr) free(hydra_heads[head_no]->current_pass_ptr); hydra_heads[head_no]->current_pass_ptr = strdup(hydra_targets[target_no]->pass_ptr); } hydra_targets[target_no]->login_no++; snpdone = 1; if (hydra_targets[target_no]->login_no >= hydra_brains.countlogin) { if (hydra_targets[target_no]->pass_state < 3) { hydra_targets[target_no]->pass_state++; if (hydra_targets[target_no]->pass_state == 1 && hydra_options.try_null_password == 0) hydra_targets[target_no]->pass_state++; if (hydra_targets[target_no]->pass_state == 2 && hydra_options.try_password_reverse_login == 0) hydra_targets[target_no]->pass_state++; if (hydra_targets[target_no]->pass_state == 3) snpdont = 1; hydra_targets[target_no]->pass_no++; } if (hydra_targets[target_no]->pass_state == 3) { if (snpdont) { hydra_targets[target_no]->pass_ptr = pass_ptr; } else { if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) { #ifndef HAVE_MATH_H sleep(1); #else hydra_targets[target_no]->pass_ptr = bf_next(); if (debug) printf("[DEBUG] bfg new password for next child: %s\n", hydra_targets[target_no]->pass_ptr); #endif } else { // -p -P mode hydra_targets[target_no]->pass_ptr++; while (*hydra_targets[target_no]->pass_ptr != 0) hydra_targets[target_no]->pass_ptr++; hydra_targets[target_no]->pass_ptr++; } hydra_targets[target_no]->pass_no++; } } hydra_targets[target_no]->login_no = 0; hydra_targets[target_no]->login_ptr = login_ptr; } else { hydra_targets[target_no]->login_ptr++; while (*hydra_targets[target_no]->login_ptr != 0) hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->login_ptr++; } if (hydra_targets[target_no]->pass_state == 3 && snpdont == 0) { if ((hydra_options.try_null_password && strlen(hydra_heads[head_no]->current_pass_ptr) < 1) || (hydra_options.try_password_same_as_login && strcmp(hydra_heads[head_no]->current_pass_ptr, hydra_heads[head_no]->current_login_ptr) == 0) || (hydra_options.try_password_reverse_login && strcmp(hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr) == 0)) { hydra_brains.sent++; hydra_targets[target_no]->sent++; if (debug) printf("[DEBUG] double detected (1)\n"); return hydra_send_next_pair(target_no, head_no); // little trick to keep the code small } } } } } if (debug) printf("[DEBUG] send_next_pair_mid done %d, pass_state %d, clogin %s, " "cpass %s, tlogin %s, tpass %s, redo %d\n", snpdone, hydra_targets[target_no]->pass_state, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, hydra_targets[target_no]->login_ptr, hydra_targets[target_no]->pass_ptr, hydra_targets[target_no]->redo); // no pair? then we go for redo state if (!snpdone && hydra_targets[target_no]->redo_state == 0 && hydra_targets[target_no]->redo > 0) { if (debug) printf("[DEBUG] Entering redo_state\n"); hydra_targets[target_no]->redo_state++; return hydra_send_next_pair(target_no, head_no); // little trick to keep the code small } } if (!snpdone || hydra_targets[target_no]->skipcnt >= hydra_brains.countlogin) { fck = write(hydra_heads[head_no]->sp[0], HYDRA_EXIT, sizeof(HYDRA_EXIT)); if (hydra_targets[target_no]->use_count <= 1) { if (hydra_targets[target_no]->done == TARGET_ACTIVE) { hydra_targets[target_no]->done = TARGET_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to " "complete tests)\n", hydra_targets[target_no]->target); } } if (hydra_brains.targets > hydra_brains.finished) hydra_kill_head(head_no, 1, 0); // otherwise done in main while loop } else { if (hydra_targets[target_no]->skipcnt > 0) { snpj = 0; for (snpi = 0; snpi < hydra_targets[target_no]->skipcnt && snpj == 0; snpi++) if (strcmp(hydra_heads[head_no]->current_login_ptr, hydra_targets[target_no]->skiplogin[snpi]) == 0) snpj = 1; if (snpj) { if (snp_is_redo == 0) { hydra_brains.sent++; hydra_targets[target_no]->sent++; } if (debug) printf("[DEBUG] double found for %s == %s, skipping\n", hydra_heads[head_no]->current_login_ptr, hydra_targets[target_no]->skiplogin[snpi - 1]); // only if -l/L -p/P with -u and if loginptr was not justed increased if (!check_flag(hydra_options.mode, MODE_COLON_FILE) && hydra_options.loop_mode == 0 && hydra_targets[target_no]->pass_no > 0) { // -l -P (not! -u) // increase login_ptr to next hydra_targets[target_no]->login_no++; if (hydra_targets[target_no]->login_no < hydra_brains.countlogin) { hydra_targets[target_no]->login_ptr++; while (*hydra_targets[target_no]->login_ptr != 0) hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->login_ptr++; } // add count hydra_brains.sent += hydra_brains.countpass - hydra_targets[target_no]->pass_no; hydra_targets[target_no]->sent += hydra_brains.countpass - hydra_targets[target_no]->pass_no; // reset password list hydra_targets[target_no]->pass_ptr = pass_ptr; hydra_targets[target_no]->pass_no = 0; hydra_targets[target_no]->pass_state = 0; } return hydra_send_next_pair(target_no, head_no); // little trick to keep the code small } } memset(&snpbuf, 0, sizeof(snpbuf)); strncpy(snpbuf, hydra_heads[head_no]->current_login_ptr, MAXLINESIZE - 3); if (strlen(hydra_heads[head_no]->current_login_ptr) > MAXLINESIZE - 3) snpbuflen = MAXLINESIZE - 2; else snpbuflen = strlen(hydra_heads[head_no]->current_login_ptr) + 1; strncpy(snpbuf + snpbuflen, hydra_heads[head_no]->current_pass_ptr, MAXLINESIZE - snpbuflen - 1); if (strlen(hydra_heads[head_no]->current_pass_ptr) > MAXLINESIZE - snpbuflen - 1) snpbuflen += MAXLINESIZE - snpbuflen - 1; else snpbuflen += strlen(hydra_heads[head_no]->current_pass_ptr) + 1; if (snp_is_redo == 0) { hydra_brains.sent++; hydra_targets[target_no]->sent++; } else if (debug) printf("[DEBUG] send_next_pair_redo done %d, pass_state %d, clogin %s, " "cpass %s, tlogin %s, tpass %s, is_redo %d\n", snpdone, hydra_targets[target_no]->pass_state, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, hydra_targets[target_no]->login_ptr, hydra_targets[target_no]->pass_ptr, snp_is_redo); // hydra_dump_data(snpbuf, snpbuflen, "SENT"); fck = write(hydra_heads[head_no]->sp[0], snpbuf, snpbuflen); if (fck < snpbuflen) { if (verbose) fprintf(stderr, "[ERROR] can not write to child %d, restarting it ...\n", head_no); hydra_increase_fail_count(target_no, head_no); loop_cnt = 0; return 0; // not prevent disabling it, if its needed its already done in // the above line } if (debug || hydra_options.showAttempt) { printf("[%sATTEMPT] target %s - login \"%s\" - pass \"%s\" - %" hPRIu64 " of %" hPRIu64 " [child %d] (%d/%d)\n", hydra_targets[target_no]->redo_state ? "REDO-" : snp_is_redo ? "RE-" : "", hydra_targets[target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, hydra_targets[target_no]->sent, hydra_brains.todo + hydra_targets[target_no]->redo, head_no, hydra_targets[target_no]->redo_state ? hydra_targets[target_no]->redo_state - 1 : 0, hydra_targets[target_no]->redo); } loop_cnt = 0; return 0; } loop_cnt = 0; return -1; } void hydra_skip_user(int32_t target_no, char *username) { int32_t i; if (username == NULL || *username == 0) return; // double check for (i = 0; i < hydra_targets[target_no]->skipcnt; i++) if (strcmp(username, hydra_targets[target_no]->skiplogin[i]) == 0) return; if (hydra_targets[target_no]->skipcnt < SKIPLOGIN && (hydra_targets[target_no]->skiplogin[hydra_targets[target_no]->skipcnt] = malloc(strlen(username) + 1)) != NULL) { strcpy(hydra_targets[target_no]->skiplogin[hydra_targets[target_no]->skipcnt], username); hydra_targets[target_no]->skipcnt++; } if (hydra_options.loop_mode == 0 && !check_flag(hydra_options.mode, MODE_COLON_FILE)) { if (strcmp(username, hydra_targets[target_no]->login_ptr) == 0) { if (debug) printf("[DEBUG] skipping username %s\n", username); // increase count hydra_brains.sent += hydra_brains.countpass - hydra_targets[target_no]->pass_no; hydra_targets[target_no]->sent += hydra_brains.countpass - hydra_targets[target_no]->pass_no; // step to next login hydra_targets[target_no]->login_no++; if (hydra_targets[target_no]->login_no < hydra_brains.countlogin) { hydra_targets[target_no]->login_ptr++; while (*hydra_targets[target_no]->login_ptr != 0) hydra_targets[target_no]->login_ptr++; hydra_targets[target_no]->login_ptr++; } // reset password state hydra_targets[target_no]->pass_ptr = pass_ptr; hydra_targets[target_no]->pass_no = 0; hydra_targets[target_no]->pass_state = 0; } } } int32_t hydra_check_for_exit_condition() { int32_t i, k = 0; if (hydra_brains.exit) { if (debug) printf("[DEBUG] exit was forced\n"); return -1; } if (hydra_brains.targets <= hydra_brains.finished && hydra_brains.active < 1) { if (debug) printf("[DEBUG] all targets done and all heads finished\n"); return 1; } if (hydra_brains.active < 1) { // no head active?! check if they are all disabled, if so, we are done for (i = 0; i < hydra_options.max_use && k == 0; i++) if (hydra_heads[i]->active >= HEAD_UNUSED) k = 1; if (k == 0) { fprintf(stderr, "[ERROR] all children were disabled due too many " "connection errors\n"); return -1; } } return 0; } int32_t hydra_select_target() { int32_t target_no = -1, i, j = -1000; for (i = 0; i < hydra_brains.targets; i++) if (hydra_targets[i]->use_count < hydra_options.tasks && hydra_targets[i]->done == TARGET_ACTIVE) if (j < hydra_options.tasks - hydra_targets[i]->failed - hydra_targets[i]->use_count) { target_no = i; j = hydra_options.tasks - hydra_targets[i]->failed - hydra_targets[i]->use_count; } return target_no; } void process_proxy_line(int32_t type, char *string) { char *type_string = string, *target_string, *port_string, *auth_string = NULL, *device_string = NULL, *sep; int32_t port; struct addrinfo hints, *res, *p; struct sockaddr_in6 *ipv6 = NULL; struct sockaddr_in *ipv4 = NULL; if (string == NULL || string[0] == 0 || string[0] == '#') return; while (*string == ' ' || *string == '\t') string++; if (*string == '#' || *string == ';' || strlen(string) < 5) return; if (string[strlen(string) - 1] == '\n') string[strlen(string) - 1] = 0; if (string[strlen(string) - 1] == '\r') string[strlen(string) - 1] = 0; if (proxy_count >= MAX_PROXY_COUNT) { fprintf(stderr, "[WARNING] maximum amount of proxies loaded, ignoring this entry: %s\n", string); return; } if (debug) printf("[DEBUG] proxy line: %s\n", string); if ((sep = strstr(string, "://")) == NULL) { fprintf(stderr, "[WARNING] invalid proxy definition: %s (ignored)\n", string); return; } *sep = 0; target_string = sep + 3; if ((sep = strchr(target_string, '@')) != NULL) { auth_string = target_string; *sep = 0; target_string = sep + 1; if (strchr(auth_string, ':') == NULL) { fprintf(stderr, "[WARNING] %s has an invalid authentication definition %s, must " "be in the format login:pass, entry ignored\n", target_string, auth_string); return; } } if ((sep = strchr(target_string, ':')) != NULL) { *sep = 0; port_string = sep + 1; if ((sep = strchr(port_string, '%')) != NULL) { *sep = 0; device_string = sep + 1; } if ((sep = strchr(port_string, '/')) != NULL) *sep = 0; port = atoi(port_string); if (port < 1 || port > 65535) { fprintf(stderr, "[WARNING] %s has an invalid port definition %d, entry ignored\n", target_string, port); return; } } else { fprintf(stderr, "[WARNING] %s has not port definition which is required, entry " "ignored\n", target_string); return; } if (use_proxy == 1 && strcmp(type_string, "http") != 0) { fprintf(stderr, "[WARNING] %s:// is an invalid type, must be http:// if you use " "HYDRA_PROXY_HTTP, entry ignored\n", type_string); return; } if (use_proxy == 2 && strcmp(type_string, "connect") != 0 && strcmp(type_string, "socks4") != 0 && strcmp(type_string, "socks5") != 0) { fprintf(stderr, "[WARNING] %s:// is an invalid type, must be connect://, socks4:// " "or socks5:// if you use HYDRA_PROXY, entry ignored\n", type_string); return; } memset(&hints, 0, sizeof hints); if (getaddrinfo(target_string, NULL, &hints, &res) != 0) { fprintf(stderr, "[ERROR] could not resolve proxy target %s, entry ignored\n", target_string); return; } for (p = res; p != NULL; p = p->ai_next) { #ifdef AF_INET6 if (p->ai_family == AF_INET6) { if (ipv6 == NULL || memcmp((char *)&ipv6->sin6_addr, fe80, 2) == 0) ipv6 = (struct sockaddr_in6 *)p->ai_addr; } else #endif if (p->ai_family == AF_INET) { if (ipv4 == NULL) ipv4 = (struct sockaddr_in *)p->ai_addr; } } freeaddrinfo(res); // now fill the stuff #ifdef AF_INET6 if (ipv6 != NULL && (ipv4 == NULL || prefer_ipv6)) { if (memcmp(proxy_string_ip[proxy_count] + 1, fe80, 2) == 0 && device_string == NULL) { fprintf(stderr, "[WARNING] The proxy address %s is a link local address, link " "local addresses require the interface being defined like this: " "fe80::1%%eth0, entry ignored\n", target_string); return; } proxy_string_ip[proxy_count][0] = 16; memcpy(proxy_string_ip[proxy_count] + 1, (char *)&ipv6->sin6_addr, 16); if (device_string != NULL && strlen(device_string) <= 16) strcpy(proxy_string_ip[proxy_count] + 17, device_string); } else #endif if (ipv4 != NULL) { proxy_string_ip[proxy_count][0] = 4; memcpy(proxy_string_ip[proxy_count] + 1, (char *)&ipv4->sin_addr, 4); } else { fprintf(stderr, "[WARNING] Could not resolve proxy address: %s, entry ignored\n", target_string); return; } if (auth_string != NULL) { if ((proxy_authentication[proxy_count] = malloc(strlen(auth_string) * 2 + 8)) == NULL) { perror("malloc"); return; } strcpy(proxy_authentication[proxy_count], auth_string); if (strncmp(type_string, "socks", 5) != 0) // so it is web hydra_tobase64((unsigned char *)proxy_authentication[proxy_count], strlen(proxy_authentication[proxy_count]), strlen(auth_string) * 2 + 8); } else proxy_authentication[proxy_count] = NULL; strcpy(proxy_string_type[proxy_count], type_string); proxy_string_port[proxy_count] = port; if (debug) printf("[DEBUG] count %d type %s target %s port %d auth %s\n", proxy_count, proxy_string_type[proxy_count], target_string, proxy_string_port[proxy_count], proxy_authentication[proxy_count]); proxy_count++; } int main(int argc, char *argv[]) { char *proxy_string = NULL, *device = NULL, *memcheck; char *outfile_format_tmp; FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL, *proxyfp, *filecloser=NULL; size_t countinfile = 1, sizeinfile = 0; uint64_t math2; int32_t i = 0, j = 0, k, error = 0, modusage = 0, ignore_restore = 0, do_switch; int32_t head_no = 0, target_no = 0, exit_condition = 0, readres; time_t starttime, elapsed_status, elapsed_restore, status_print = 59, tmp_time; char *tmpptr, *tmpptr2, *tmpptr3; char rc, buf[MAXBUF]; time_t last_attempt = 0; fd_set fdreadheads; int32_t max_fd; struct addrinfo hints, *res, *p; struct sockaddr_in6 *ipv6 = NULL; struct sockaddr_in *ipv4 = NULL; printf("%s %s (c) 2023 by %s & %s - Please do not use in military or secret " "service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).\n\n", PROGRAM, VERSION, AUTHOR, AUTHOR2); #ifndef LIBAFP SERVICES = hydra_string_replace(SERVICES, "afp ", ""); strcat(unsupported, "afp "); #endif #ifndef LIBFIREBIRD SERVICES = hydra_string_replace(SERVICES, "firebird ", ""); strcat(unsupported, "firebird "); #endif #ifndef LIBMCACHED SERVICES = hydra_string_replace(SERVICES, "memcached ", ""); strcat(unsupported, "memcached "); #endif #ifndef LIBMONGODB SERVICES = hydra_string_replace(SERVICES, "mongodb ", ""); strcat(unsupported, "mongodb "); #endif #ifndef LIBMYSQLCLIENT SERVICES = hydra_string_replace(SERVICES, "mysql ", "mysql(v4) "); strcat(unsupported, "mysql5 "); #endif #ifndef LIBNCP SERVICES = hydra_string_replace(SERVICES, "ncp ", ""); strcat(unsupported, "ncp "); #endif #ifndef LIBORACLE SERVICES = hydra_string_replace(SERVICES, "oracle ", ""); strcat(unsupported, "oracle "); #endif #ifndef LIBPOSTGRES SERVICES = hydra_string_replace(SERVICES, "postgres ", ""); strcat(unsupported, "postgres "); #endif #ifndef HAVE_GCRYPT SERVICES = hydra_string_replace(SERVICES, "radmin2 ", ""); strcat(unsupported, "radmin2 "); #endif #ifndef LIBFREERDP SERVICES = hydra_string_replace(SERVICES, "rdp ", ""); strcat(unsupported, "rdp "); #endif #ifndef LIBSAPR3 SERVICES = hydra_string_replace(SERVICES, "sapr3 ", ""); strcat(unsupported, "sapr3 "); #endif #ifndef LIBSSH SERVICES = hydra_string_replace(SERVICES, "ssh ", ""); strcat(unsupported, "ssh "); SERVICES = hydra_string_replace(SERVICES, "sshkey ", ""); strcat(unsupported, "sshkey "); #endif #ifndef LIBSVN SERVICES = hydra_string_replace(SERVICES, "svn ", ""); strcat(unsupported, "svn "); #endif #if !defined(LIBSMBCLIENT) SERVICES = hydra_string_replace(SERVICES, "smb2 ", ""); strcat(unsupported, "smb2 "); #endif #ifndef LIBOPENSSL // for ftps SERVICES = hydra_string_replace(SERVICES, "ftp[s]", "ftp"); // for pop3 SERVICES = hydra_string_replace(SERVICES, "pop3[s]", "pop3"); // for imap SERVICES = hydra_string_replace(SERVICES, "imap[s]", "imap"); // for smtp SERVICES = hydra_string_replace(SERVICES, "smtp[s]", "smtp"); // for telnet SERVICES = hydra_string_replace(SERVICES, "telnet[s]", "telnet"); // for http[s]-{head|get} SERVICES = hydra_string_replace(SERVICES, "http[s]", "http"); // for http[s]-{get|post}-form SERVICES = hydra_string_replace(SERVICES, "http[s]", "http"); // for ldap3 SERVICES = hydra_string_replace(SERVICES, "[-{cram|digest}md5]", ""); // for sip SERVICES = hydra_string_replace(SERVICES, " sip", ""); // for oracle-listener SERVICES = hydra_string_replace(SERVICES, " oracle-listener", ""); // general SERVICES = hydra_string_replace(SERVICES, "[s]", ""); // for oracle-sid SERVICES = hydra_string_replace(SERVICES, " oracle-sid", ""); strcat(unsupported, "SSL-services (ftps, sip, rdp, oracle-services, ...) "); #endif #ifndef HAVE_MATH_H if (strlen(unsupported) > 0) strcat(unsupported, "and "); strcat(unsupported, "password bruteforce generation "); #endif #ifndef HAVE_PCRE if (strlen(unsupported) > 0) strcat(unsupported, "and "); strcat(unsupported, "regex support "); #endif (void)setvbuf(stdout, NULL, _IONBF, 0); (void)setvbuf(stderr, NULL, _IONBF, 0); // set defaults memset(&hydra_options, 0, sizeof(hydra_options)); memset(&hydra_brains, 0, sizeof(hydra_brains)); prg = argv[0]; hydra_options.debug = debug = 0; hydra_options.verbose = verbose = 0; found = 0; use_proxy = 0; proxy_count = 0; selected_proxy = -1; proxy_string_ip[0][0] = 0; proxy_string_port[0] = 0; strcpy(proxy_string_type[0], "connect"); proxy_authentication[0] = cmdlinetarget = NULL; hydra_options.login = NULL; hydra_options.loginfile = NULL; hydra_options.pass = NULL; hydra_options.passfile = NULL; hydra_options.distributed = NULL; hydra_options.tasks = TASKS; hydra_options.max_use = MAXTASKS; hydra_options.outfile_format = FORMAT_PLAIN_TEXT; hydra_brains.ofp = stdout; hydra_brains.targets = 1; hydra_options.waittime = waittime = WAITTIME; bf_options.disable_symbols = 0; // command line processing if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) help(1); if (argc < 2) help(0); while ((i = getopt(argc, argv, "hIq64Rrde:vVl:fFg:D:L:p:OP:o:b:M:C:t:T:m:w:W:s:SUux:yc:K")) >= 0) { switch (i) { case 'D': hydra_options.distributed = optarg; if (sscanf(hydra_options.distributed, "%dof%d", &my_segment, &num_segments) != 2) { fprintf(stderr, "Invalid format. Expected format -D XofY where X and Y are integers.\n"); exit(EXIT_FAILURE); } else{ fprintf(stdout, "Option \'D\': successfully set X to %d and Y to %d\n", my_segment, num_segments); } break; case 'h': help(1); break; case 'q': quiet = 1; break; case 'K': hydra_options.skip_redo = 1; break; case 'O': old_ssl = 1; break; case 'u': hydra_options.loop_mode = 1; break; case '6': prefer_ipv6 = 1; break; case '4': prefer_ipv6 = 0; break; case 'R': hydra_options.restore = 1; hydra_restore_read(); break; case 'r': fprintf(stderr, "Warning: the option -r has been removed.\n"); break; case 'I': ignore_restore = 1; // this is not to be saved in hydra_options! break; case 'd': hydra_options.debug = ++debug; ++verbose; break; case 'e': i = 0; while (i < strlen(optarg)) { switch (optarg[i]) { case 'r': hydra_options.try_password_reverse_login = 1; hydra_options.mode = hydra_options.mode | MODE_PASSWORD_REVERSE; break; case 'n': hydra_options.try_null_password = 1; hydra_options.mode = hydra_options.mode | MODE_PASSWORD_NULL; break; case 's': hydra_options.try_password_same_as_login = 1; hydra_options.mode = hydra_options.mode | MODE_PASSWORD_SAME; break; default: fprintf(stderr, "[ERROR] unknown mode %c for option -e, only supporting " "\"n\", \"s\" and \"r\"\n", optarg[i]); exit(-1); } i++; } break; case 'v': hydra_options.verbose = verbose = 1; break; case 'V': hydra_options.showAttempt = 1; break; case 'l': hydra_options.login = optarg; break; case 'L': hydra_options.loginfile = optarg; hydra_options.mode = hydra_options.mode | MODE_LOGIN_LIST; break; case 'p': hydra_options.pass = optarg; break; case 'P': hydra_options.passfile = optarg; hydra_options.mode = hydra_options.mode | MODE_PASSWORD_LIST; break; case 'f': hydra_options.exit_found = 1; break; case 'F': hydra_options.exit_found = 2; break; case 'o': hydra_options.outfile_ptr = optarg; // colored_output = 0; break; case 'b': outfile_format_tmp = optarg; if (strcasecmp(outfile_format_tmp, "text") == 0) hydra_options.outfile_format = FORMAT_PLAIN_TEXT; else if (strcasecmp(outfile_format_tmp, "json") == 0) // latest json formatting. hydra_options.outfile_format = FORMAT_JSONV1; else if (strcasecmp(outfile_format_tmp, "jsonv1") == 0) hydra_options.outfile_format = FORMAT_JSONV1; else { fprintf(stderr, "[ERROR] Output file format must be (text, json, jsonv1)\n"); exit(-1); } // colored_output = 0; break; case 'M': hydra_options.infile_ptr = optarg; break; case 'C': hydra_options.colonfile = optarg; hydra_options.mode = MODE_COLON_FILE; break; case 'm': hydra_options.miscptr = optarg; break; case 'w': hydra_options.waittime = waittime = atoi(optarg); if (waittime < 1) { fprintf(stderr, "[ERROR] waittime must be larger than 0\n"); exit(-1); } else if (waittime < 5) fprintf(stderr, "[WARNING] the waittime you set is low, this can " "result in errornous results\n"); break; case 'W': hydra_options.conwait = conwait = atoi(optarg); break; case 's': hydra_options.port = port = atoi(optarg); break; case 'c': #ifdef MSG_PEEK hydra_options.time_next_attempt = atoi(optarg); if (hydra_options.time_next_attempt < 0) { fprintf(stderr, "[ERROR] -c option value can not be negative\n"); exit(-1); } #else fprintf(stderr, "[WARNING] -c option can not be used as your operating " "system is missing the MSG_PEEK feature\n"); #endif break; case 'S': #ifndef LIBOPENSSL fprintf(stderr, "[WARNING] hydra was compiled without SSL support. " "Install openssl and recompile! Option ignored...\n"); hydra_options.ssl = 0; break; #else hydra_options.ssl = 1; break; #endif case 't': hydra_options.tasks = atoi(optarg); break; case 'T': hydra_options.max_use = atoi(optarg); break; case 'U': modusage = 1; break; case 'x': #ifndef HAVE_MATH_H fprintf(stderr, "[ERROR] -x option is not available as math.h was not " "found at compile time\n"); exit(-1); #else if (strcmp(optarg, "-h") == 0) help_bfg(); bf_options.arg = optarg; hydra_options.bfg = 1; hydra_options.mode = hydra_options.mode | MODE_PASSWORD_BRUTE; hydra_options.loop_mode = 1; break; #endif case 'y': bf_options.disable_symbols = 1; break; default: exit(-1); } } if (hydra_options.time_next_attempt > 0 && hydra_options.tasks != 1) { printf("[INFO] setting max tasks per host to 1 due to -c option usage\n"); hydra_options.tasks = 1; } // check if output is redirected from the shell or in a file if (colored_output && !isatty(fileno(stdout))) colored_output = 0; #ifdef LIBNCURSES // then check if the term is color enabled using ncurses lib if (colored_output) { if (!setupterm(NULL, 1, NULL) && (tigetnum("colors") <= 0)) { colored_output = 0; } if (cur_term) { del_curterm(cur_term); } } #else // don't want border line effect so disabling color output // if we are not sure about the term colored_output = 0; #endif if (debug) printf("[DEBUG] Output color flag is %d\n", colored_output); if (hydra_options.restore && argc > 2 + debug + verbose) fprintf(stderr, "[WARNING] options after -R are now honored (since v8.6)\n"); // bail("no option may be supplied together with -R"); printf("%s (%s) starting at %s\n", PROGRAM, RESOURCE, hydra_build_time()); if (debug) { printf("[DEBUG] cmdline: "); for (i = 0; i < argc; i++) printf("%s ", argv[i]); printf("\n"); } if (hydra_options.tasks > 1 && hydra_options.time_next_attempt) fprintf(stderr, "[WARNING] when using the -c option, you should also set " "the task per target to one (-t 1)\n"); if (hydra_options.login != NULL && hydra_options.loginfile != NULL) bail("You can only use -L OR -l, not both\n"); if (hydra_options.pass != NULL && hydra_options.passfile != NULL) bail("You can only use -P OR -p, not both\n"); if (hydra_options.outfile_format != FORMAT_PLAIN_TEXT && hydra_options.outfile_ptr == NULL) fprintf(stderr, "[WARNING] output file format specified (-b) - but no " "output file (-o)\n"); if (hydra_options.restore) { // hydra_restore_read(); // stuff we have to copy from the non-restore part if (strncmp(hydra_options.service, "http-", 5) == 0) { if (getenv("HYDRA_PROXY_HTTP") && getenv("HYDRA_PROXY")) bail("Found HYDRA_PROXY_HTTP *and* HYDRA_PROXY environment variables - " "you can use only ONE for the service " "http-head/http-get/http-post!"); if (getenv("HYDRA_PROXY_HTTP")) { printf("[INFO] Using HTTP Proxy: %s\n", getenv("HYDRA_PROXY_HTTP")); use_proxy = 1; } } } else { // normal mode, aka non-restore mode if (hydra_options.colonfile) hydra_options.loop_mode = 0; // just to be sure if (hydra_options.infile_ptr != NULL) { if (optind + 2 < argc) bail("The -M FILE option can not be used together with a host on the " "commandline"); if (optind + 1 > argc) bail("You need to define a service to attack"); if (optind + 2 == argc) fprintf(stderr, "[WARNING] With the -M FILE option you can not specify a server on " "the commandline. Lets hope you did everything right!\n"); hydra_options.server = NULL; hydra_options.service = argv[optind]; if (optind + 2 == argc) hydra_options.miscptr = argv[optind + 1]; } else if (optind + 2 != argc && optind + 3 != argc && optind < argc) { // check if targetdef follow syntax // ://[:][/] or it's a // syntax error char *targetdef = strdup(argv[optind]); char *service_pos, *target_pos, *port_pos = NULL, *param_pos = NULL; cmdlinetarget = argv[optind]; if ((targetdef != NULL) && (strstr(targetdef, "://") != NULL)) { service_pos = strstr(targetdef, "://"); if ((service_pos - targetdef) == 0) bail("could not identify service"); if ((hydra_options.service = malloc(1 + service_pos - targetdef)) == NULL) bail("could not alloc memory"); strncpy(hydra_options.service, targetdef, service_pos - targetdef); hydra_options.service[service_pos - targetdef] = 0; target_pos = targetdef + (service_pos - targetdef + 3); if (*target_pos == '[') { target_pos++; if ((param_pos = strchr(target_pos, ']')) == NULL) bail("no closing ']' found in target definition"); *param_pos++ = 0; if (*param_pos == ':') port_pos = ++param_pos; if ((param_pos = strchr(param_pos, '/')) != NULL) *param_pos++ = 0; } else { port_pos = strchr(target_pos, ':'); param_pos = strchr(target_pos, '/'); if (port_pos != NULL && param_pos != NULL && port_pos > param_pos) port_pos = NULL; if (port_pos != NULL) *port_pos++ = 0; if (param_pos != NULL) *param_pos++ = 0; if (port_pos != NULL && strchr(port_pos, ':') != NULL) { if (prefer_ipv6) bail("Illegal IPv6 target definition must be written within '[' " "']'"); else bail("Illegal port definition"); } } if (*target_pos == 0) hydra_options.server = NULL; else hydra_options.server = target_pos; if (port_pos != NULL) hydra_options.port = port = atoi(port_pos); if (param_pos != NULL) { if (strstr(hydra_options.service, "http") != NULL && strstr(hydra_options.service, "http-proxy") == NULL && param_pos[1] != '/') *--param_pos = '/'; hydra_options.miscptr = strdup(param_pos); } // printf("target: %s service: %s port: %s opt: %s\n", target_pos, // hydra_options.service, port_pos, param_pos); if (debug) printf("[DEBUG] opt:%d argc:%d mod:%s tgt:%s port:%u misc:%s\n", optind, argc, hydra_options.service, hydra_options.server, hydra_options.port, hydra_options.miscptr); } else { hydra_options.server = NULL; hydra_options.service = NULL; if (modusage) { hydra_options.service = targetdef; } else help(0); } } else { if (modusage && argv[optind] == NULL) { printf("[ERROR] you must supply a service name after the -U help " "switch\n"); exit(-1); } if (argv[optind] == NULL || strstr(argv[optind], "://") != NULL) { printf("[ERROR] Invalid target definition!\n"); printf("[ERROR] Either you use \"www.example.com module " "[optional-module-parameters]\" *or* you use the " "\"module://www.example.com/optional-module-parameters\" " "syntax!\n"); exit(-1); } hydra_options.server = argv[optind]; cmdlinetarget = argv[optind]; hydra_options.service = argv[optind + 1]; if (optind + 3 == argc) hydra_options.miscptr = argv[optind + 2]; } if (getenv("HYDRA_PROXY_CONNECT")) fprintf(stderr, "[WARNING] The environment variable HYDRA_PROXY_CONNECT " "is not used! Use HYDRA_PROXY instead!\n"); // wrong option use patch if (hydra_options.ssl && (((strcmp(hydra_options.service, "smtp") == 0 || strcmp(hydra_options.service, "smtp-enum") == 0) && hydra_options.port != 465) || (strcmp(hydra_options.service, "pop3") == 0 && hydra_options.port != 995) || (strcmp(hydra_options.service, "imap") == 0 && hydra_options.port != 993))) fprintf(stderr, "[WARNING] you want to access SMTP/POP3/IMAP with SSL. Are you sure " "you want to use direct SSL (-S) instead of STARTTLS (-m TLS)?\n"); if (strcmp(hydra_options.service, "http") == 0 || strcmp(hydra_options.service, "https") == 0) { fprintf(stderr, "[ERROR] There is no service \"%s\", most likely you mean one of the " "many web modules, e.g. http-get or http-form-post. Read it up!\n", hydra_options.service); exit(-1); } if (strcmp(hydra_options.service, "pop3s") == 0 || strcmp(hydra_options.service, "smtps") == 0 || strcmp(hydra_options.service, "imaps") == 0 || strcmp(hydra_options.service, "telnets") == 0 || (strncmp(hydra_options.service, "ldap", 4) == 0 && hydra_options.service[strlen(hydra_options.service) - 1] == 's')) { hydra_options.ssl = 1; hydra_options.service[strlen(hydra_options.service) - 1] = 0; } if (getenv("HYDRA_PROXY_HTTP") || getenv("HYDRA_PROXY")) { if (strcmp(hydra_options.service, "afp") == 0 || strcmp(hydra_options.service, "firebird") == 0 || strncmp(hydra_options.service, "mysql", 5) == 0 || strcmp(hydra_options.service, "ncp") == 0 || strcmp(hydra_options.service, "oracle") == 0 || strcmp(hydra_options.service, "postgres") == 0 || strncmp(hydra_options.service, "ssh", 3) == 0 || strcmp(hydra_options.service, "sshkey") == 0 || strcmp(hydra_options.service, "svn") == 0 || strcmp(hydra_options.service, "sapr3") == 0 || strcmp(hydra_options.service, "memcached") == 0 || strcmp(hydra_options.service, "mongodb") == 0) { fprintf(stderr, "[WARNING] module %s does not support HYDRA_PROXY* !\n", hydra_options.service); proxy_string = NULL; } } /* here start the services */ if (strcmp(hydra_options.service, "ssl") == 0 || strcmp(hydra_options.service, "www") == 0 || strcmp(hydra_options.service, "http") == 0 || strcmp(hydra_options.service, "https") == 0) { fprintf(stderr, "[WARNING] The service http has been replaced with http-head and " "http-get, using by default GET method. Same for https.\n"); if (strcmp(hydra_options.service, "http") == 0) { hydra_options.service = malloc(strlen("http-get") + 1); strcpy(hydra_options.service, "http-get"); } if (strcmp(hydra_options.service, "https") == 0) { hydra_options.service = malloc(strlen("https-get") + 1); strcpy(hydra_options.service, "https-get"); } } if (strcmp(hydra_options.service, "http-form-get") == 0) strcpy(hydra_options.service, "http-get-form"); if (strcmp(hydra_options.service, "https-form-get") == 0) strcpy(hydra_options.service, "https-get-form"); if (strcmp(hydra_options.service, "http-form-post") == 0) strcpy(hydra_options.service, "http-post-form"); if (strcmp(hydra_options.service, "https-form-post") == 0) strcpy(hydra_options.service, "https-post-form"); if (modusage == 1) { if (hydra_options.service == NULL) { printf("[ERROR] you must supply a service name after the -U help " "switch\n"); exit(-1); } module_usage(); } i = 0; if (strcmp(hydra_options.service, "telnet") == 0) { fprintf(stderr, "[WARNING] telnet is by its nature unreliable to analyze, if " "possible better choose FTP, SSH, etc. if available\n"); i = 1; } if (strcmp(hydra_options.service, "ftp") == 0) i = 1; if (strcmp(hydra_options.service, "ftps") == 0) { fprintf(stderr, "[WARNING] you enabled ftp-SSL (auth tls) mode. If you want to " "use direct SSL ftp, use -S and the ftp module instead.\n"); i = 1; } if (strcmp(hydra_options.service, "pop3") == 0) { fprintf(stderr, "[INFO] several providers have implemented cracking protection, " "check with a small wordlist first - and stay legal!\n"); i = 1; } if (strcmp(hydra_options.service, "imap") == 0) { fprintf(stderr, "[INFO] several providers have implemented cracking protection, " "check with a small wordlist first - and stay legal!\n"); i = 1; } if (strcmp(hydra_options.service, "redis") == 0) i = 2; if (strcmp(hydra_options.service, "asterisk") == 0) i = 1; if (strcmp(hydra_options.service, "vmauthd") == 0) i = 1; if (strcmp(hydra_options.service, "rexec") == 0) i = 1; if (strcmp(hydra_options.service, "rlogin") == 0) i = 1; if (strcmp(hydra_options.service, "rsh") == 0) i = 3; if (strcmp(hydra_options.service, "nntp") == 0) i = 1; if (strcmp(hydra_options.service, "socks5") == 0) i = 1; if (strcmp(hydra_options.service, "icq") == 0) { fprintf(stderr, "[WARNING] The icq module is not working with the modern " "protocol version! (somebody else will need to fix this " "as I don't care for icq)\n"); i = 1; } if (strcmp(hydra_options.service, "memcached") == 0) #ifdef LIBMCACHED i = 1; #else bail("Compiled without LIBMCACHED support, module not available!"); #endif if (strcmp(hydra_options.service, "mongodb") == 0) #ifdef LIBMONGODB { i = 1; if (hydra_options.miscptr == NULL || (strlen(hydra_options.miscptr) == 0)) fprintf(stderr, "[INFO] The mongodb db wasn't passed so using admin by default\n"); } #else bail("Compiled without LIBMONGODB support, module not available!"); #endif if (strcmp(hydra_options.service, "mysql") == 0) { i = 1; if (hydra_options.tasks > 4) { fprintf(stderr, "[INFO] Reduced number of tasks to 4 (mysql does not " "like many parallel connections)\n"); hydra_options.tasks = 4; } } if (strcmp(hydra_options.service, "mssql") == 0) i = 1; if (strcmp(hydra_options.service, "cobaltstrike") == 0) i = 2; if ((strcmp(hydra_options.service, "oracle-listener") == 0) || (strcmp(hydra_options.service, "tns") == 0)) { i = 2; hydra_options.service = malloc(strlen("oracle-listener") + 1); strcpy(hydra_options.service, "oracle-listener"); } if ((strcmp(hydra_options.service, "oracle-sid") == 0) || (strcmp(hydra_options.service, "sid") == 0)) { i = 3; hydra_options.service = malloc(strlen("oracle-sid") + 1); strcpy(hydra_options.service, "oracle-sid"); } #ifdef LIBORACLE if ((strcmp(hydra_options.service, "oracle") == 0) || (strcmp(hydra_options.service, "ora") == 0)) { i = 1; hydra_options.service = malloc(strlen("oracle") + 1); strcpy(hydra_options.service, "oracle"); } #endif if (strcmp(hydra_options.service, "postgres") == 0) #ifdef LIBPOSTGRES i = 1; #else bail("Compiled without LIBPOSTGRES support, module not available!"); #endif if (strcmp(hydra_options.service, "firebird") == 0) #ifdef LIBFIREBIRD i = 1; #else bail("Compiled without LIBFIREBIRD support, module not available!"); #endif if (strcmp(hydra_options.service, "afp") == 0) #ifdef LIBAFP i = 1; #else bail("Compiled without LIBAFP support, module not available!"); #endif if (strcmp(hydra_options.service, "svn") == 0) #ifdef LIBSVN i = 1; #else bail("Compiled without LIBSVN support, module not available!"); #endif if (strcmp(hydra_options.service, "ncp") == 0) #ifdef LIBNCP i = 1; #else bail("Compiled without LIBNCP support, module not available!"); #endif if (strcmp(hydra_options.service, "pcanywhere") == 0) i = 1; if (strcmp(hydra_options.service, "http-proxy") == 0) { i = 1; if (hydra_options.miscptr != NULL && strncmp(hydra_options.miscptr, "http://", 7) != 0) bail("module option must start with http://"); } if (strcmp(hydra_options.service, "cvs") == 0) { i = 1; if (hydra_options.miscptr == NULL || (strlen(hydra_options.miscptr) == 0)) { fprintf(stderr, "[INFO] The CVS repository path wasn't passed so using " "/root by default\n"); } } if (strcmp(hydra_options.service, "svn") == 0) { i = 1; if (hydra_options.miscptr == NULL || (strlen(hydra_options.miscptr) == 0)) { fprintf(stderr, "[INFO] The SVN repository path wasn't passed so using " "/trunk by default\n"); } } if (strcmp(hydra_options.service, "ssh") == 0 || strcmp(hydra_options.service, "sshkey") == 0) { if (hydra_options.tasks > 8) fprintf(stderr, "[WARNING] Many SSH configurations limit the number of parallel " "tasks, it is recommended to reduce the tasks: use -t 4\n"); #ifdef LIBSSH i = 1; #else bail("Compiled without LIBSSH v0.4.x support, module is not available!"); #endif } if (strcmp(hydra_options.service, "smtp") == 0) { fprintf(stderr, "[INFO] several providers have implemented cracking protection, " "check with a small wordlist first - and stay legal!\n"); i = 1; } if (strcmp(hydra_options.service, "smtp-enum") == 0) i = 1; if (strcmp(hydra_options.service, "teamspeak") == 0) i = 1; if ((strcmp(hydra_options.service, "smb") == 0) || (strcmp(hydra_options.service, "smbnt") == 0)) { if (hydra_options.tasks > 1) { fprintf(stderr, "[INFO] Reduced number of tasks to 1 (smb does not " "like parallel connections)\n"); hydra_options.tasks = 1; } if (hydra_options.login != NULL && (strchr(hydra_options.login, '\\') != NULL || strchr(hydra_options.login, '/') != NULL)) fprintf(stderr, "[WARNING] potential windows domain specification found in " "login. You must use the -m option to pass a domain.\n"); i = 1; } if ((strcmp(hydra_options.service, "smb") == 0) || (strcmp(hydra_options.service, "smbnt") == 0)) { #ifdef LIBOPENSSL if (hydra_options.tasks > 1) { fprintf(stderr, "[INFO] Reduced number of tasks to 1 (smb does not " "like parallel connections)\n"); hydra_options.tasks = 1; } i = 1; #endif } if ((strcmp(hydra_options.service, "smb") == 0) || (strcmp(hydra_options.service, "smbnt") == 0) || (strcmp(hydra_options.service, "sip") == 0) || (strcmp(hydra_options.service, "oracle-listener") == 0) || (strcmp(hydra_options.service, "oracle-sid") == 0)) { #ifndef LIBOPENSSL bail("Compiled without OPENSSL support, module not available!"); #endif } if (strcmp(hydra_options.service, "smb2") == 0) { #if !defined(LIBSMBCLIENT) bail("Compiled without LIBSMBCLIENT support, module not available!"); #else if (hydra_options.login != NULL && (strchr(hydra_options.login, '\\') != NULL || strchr(hydra_options.login, '/') != NULL)) fprintf(stderr, "[WARNING] potential windows domain specification found in " "login. You must use the -m option to pass a domain.\n"); if (hydra_options.miscptr == NULL || (strlen(hydra_options.miscptr) == 0)) { fprintf(stderr, "[WARNING] Workgroup was not specified, using \"WORKGROUP\"\n"); } i = 1; #endif } if (strcmp(hydra_options.service, "rdp") == 0) { #ifndef LIBFREERDP bail("Compiled without FREERDP support, modules not available!"); #endif } if (strcmp(hydra_options.service, "pcnfs") == 0) { i = 1; if (port == 0) bail("You must set the port for pcnfs with -s (run \"rpcinfo -p %s\" " "and look for the pcnfs v2 UDP port)"); } if (strcmp(hydra_options.service, "sapr3") == 0) { #ifdef LIBSAPR3 i = 1; if (port == PORT_SAPR3) bail("You must set the port for sapr3 with -s , it should lie " "between 3200 and 3699."); if (port < 3200 || port > 3699) fprintf(stderr, "[WARNING] The port is not in the range 3200 to 3399 - " "please ensure it is ok!\n"); if (hydra_options.miscptr == NULL || atoi(hydra_options.miscptr) < 0 || atoi(hydra_options.miscptr) > 999 || !isdigit(hydra_options.miscptr[0])) bail("You must set the client ID (0-999) as an additional option or " "via -m"); #else bail("Compiled without LIBSAPR3 support, module not available!"); #endif } if (strcmp(hydra_options.service, "cisco") == 0) { i = 2; if (hydra_options.tasks > 4) fprintf(stderr, "[WARNING] you should set the number of parallel task " "to 4 for cisco services.\n"); } if (strcmp(hydra_options.service, "adam6500") == 0) { i = 2; fprintf(stderr, "[WARNING] the module adam6500 is work in progress! " "please submit a pcap of a successful login as well as " "false positives to vh@thc.org\n"); if (hydra_options.tasks > 1) fprintf(stderr, "[WARNING] reset the number of parallel task to 1 for " "adam6500 modbus authentication\n"); hydra_options.tasks = 1; } if (strncmp(hydra_options.service, "snmpv", 5) == 0) { hydra_options.service[4] = hydra_options.service[5]; hydra_options.service[5] = 0; } if (strcmp(hydra_options.service, "snmp") == 0 || strcmp(hydra_options.service, "snmp1") == 0) { hydra_options.service[4] = 0; i = 2; } if (strcmp(hydra_options.service, "snmp2") == 0 || strcmp(hydra_options.service, "snmp3") == 0) { if (hydra_options.miscptr == NULL) hydra_options.miscptr = strdup(hydra_options.service + 4); else { tmpptr = malloc(strlen(hydra_options.miscptr) + 4); strcpy(tmpptr, hydra_options.miscptr); strcat(tmpptr, ":"); strcat(tmpptr, hydra_options.service + 4); hydra_options.miscptr = tmpptr; } hydra_options.service[4] = 0; i = 2; } if (strcmp(hydra_options.service, "snmp") == 0 && hydra_options.miscptr != NULL) { char *lptr; j = 1; tmpptr = strdup(hydra_options.miscptr); lptr = strtok(tmpptr, ":"); while (lptr != NULL) { i = 0; if (strcasecmp(lptr, "1") == 0 || strcasecmp(lptr, "2") == 0 || strcasecmp(lptr, "3") == 0) { i = 1; j = lptr[0] - '0' + (j & 252); } else if (strcasecmp(lptr, "READ") == 0 || strcasecmp(lptr, "WRITE") == 0 || strcasecmp(lptr, "PLAIN") == 0) i = 1; else if (strcasecmp(lptr, "MD5") == 0) { i = 1; j = 4 + (j & 51); } else if (strcasecmp(lptr, "SHA") == 0 || strcasecmp(lptr, "SHA1") == 0) { i = 1; j = 8 + (j & 51); } else if (strcasecmp(lptr, "DES") == 0) { i = 1; j = 16 + (j & 15); } else if (strcasecmp(lptr, "AES") == 0) { i = 1; j = 32 + (j & 15); } if (i == 0) { fprintf(stderr, "[ERROR] unknown parameter in module option: %s\n", lptr); exit(-1); } lptr = strtok(NULL, ":"); } i = 2; if ((j & 3) < 3 && j > 2) fprintf(stderr, "[WARNING] SNMPv1 and SNMPv2 do not support hash and " "encryption, ignored\n"); if ((j & 3) == 3) { fprintf(stderr, "[WARNING] SNMPv3 is still in beta state, use at own " "risk and report problems\n"); if (j >= 16) bail("The SNMPv3 module so far only support authentication " "(md5/sha), not yet encryption\n"); if (hydra_options.colonfile == NULL && ((hydra_options.login == NULL && hydra_options.loginfile == NULL) || (hydra_options.pass == NULL && hydra_options.passfile == NULL && hydra_options.bfg == 0))) { if (j > 3) { fprintf(stderr, "[ERROR] you specified SNMPv3, defined hashing/encryption but " "only gave one of login or password list. Either supply both " "logins and passwords (this is what is usually used in " "SNMPv3), or remove the hashing/encryption option (unusual)\n"); exit(-1); } fprintf(stderr, "[WARNING] you specified SNMPv3 but gave no logins, " "NoAuthNoPriv is assumed. This is an unusual case, " "you should know what you are doing\n"); tmpptr = malloc(strlen(hydra_options.miscptr) + 8); strcpy(tmpptr, hydra_options.miscptr); strcat(tmpptr, ":"); strcat(tmpptr, "PLAIN"); hydra_options.miscptr = tmpptr; } else { i = 1; // snmpv3 with login+pass mode #ifndef LIBOPENSSL bail("hydra was not compiled with OPENSSL support, snmpv3 can only " "be used on NoAuthNoPriv mode (only logins, no passwords)!"); #endif printf("[INFO] Using %s SNMPv3 with %s authentication and %s privacy\n", j > 16 ? "AuthPriv" : "AuthNoPriv", (j & 8) == 8 ? "SHA" : "MD5", (j & 16) == 16 ? "DES" : (j > 16) ? "AES" : "no"); } } } if (strcmp(hydra_options.service, "sip") == 0) { if (hydra_options.miscptr == NULL) { if (hydra_options.server != NULL) { hydra_options.miscptr = hydra_options.server; i = 1; } else { bail("The sip module does not work with multiple servers (-M)\n"); } } else { i = 1; } } if (strcmp(hydra_options.service, "ldap") == 0) { bail("Please select ldap2 or ldap3 for simple authentication or " "ldap3-crammd5 or ldap3-digestmd5\n"); } if (strcmp(hydra_options.service, "ldap2") == 0 || strcmp(hydra_options.service, "ldap3") == 0) { i = 1; if ((hydra_options.miscptr != NULL && hydra_options.login != NULL) || (hydra_options.miscptr != NULL && hydra_options.loginfile != NULL) || (hydra_options.login != NULL && hydra_options.loginfile != NULL)) bail("you may only use one of -l, -L or -m\n"); if (hydra_options.login == NULL && hydra_options.loginfile == NULL && hydra_options.miscptr == NULL) fprintf(stderr, "[WARNING] no DN to authenticate is defined, using DN " "of null (use -m, -l or -L to define DNs)\n"); if (hydra_options.login == NULL && hydra_options.loginfile == NULL) { i = 2; } } if (strcmp(hydra_options.service, "ldap3-crammd5") == 0 || strcmp(hydra_options.service, "ldap3-digestmd5") == 0) { i = 1; if (hydra_options.login == NULL && hydra_options.loginfile == NULL) bail("-l or -L option is required to specify the login\n"); if (hydra_options.miscptr == NULL) bail("-m option is required to specify the DN\n"); } if (strcmp(hydra_options.service, "rtsp") == 0) i = 1; if (strcmp(hydra_options.service, "rpcap") == 0) i = 1; if (strcmp(hydra_options.service, "s7-300") == 0) { if (hydra_options.tasks > 8) { fprintf(stderr, "[INFO] Reduced number of tasks to 8 (the PLC does not " "like more connections)\n"); hydra_options.tasks = 8; } i = 2; } if (strcmp(hydra_options.service, "cisco-enable") == 0) { if (hydra_options.login != NULL || hydra_options.loginfile != NULL) i = 1; // login will be the initial Username: login, or line Password: else i = 2; if (hydra_options.miscptr == NULL) fprintf(stderr, "[WARNING] You did not supply the initial support to " "the Cisco via -l, assuming direct console access\n"); if (hydra_options.tasks > 4) fprintf(stderr, "[WARNING] you should set the number of parallel task " "to 4 for cisco enable services.\n"); } if (strcmp(hydra_options.service, "http-proxy-urlenum") == 0) { i = 4; hydra_options.pass = empty_login; if (hydra_options.miscptr == NULL) { fprintf(stderr, "[WARNING] You did not supply proxy credentials via " "the optional parameter\n"); } if (hydra_options.bfg || hydra_options.passfile != NULL) bail("the http-proxy-urlenum does not need the -p/-P or -x option"); } if (strcmp(hydra_options.service, "vnc") == 0) { i = 2; if (hydra_options.tasks > 4) fprintf(stderr, "[WARNING] you should set the number of parallel task " "to 4 for vnc services.\n"); } if (strcmp(hydra_options.service, "https-head") == 0 || strcmp(hydra_options.service, "https-get") == 0 || strcmp(hydra_options.service, "https-post") == 0) { #ifdef LIBOPENSSL i = 1; hydra_options.ssl = 1; if (strcmp(hydra_options.service, "https-head") == 0) strcpy(hydra_options.service, "http-head"); else if (strcmp(hydra_options.service, "https-post") == 0) strcpy(hydra_options.service, "http-post"); else strcpy(hydra_options.service, "http-get"); #else bail("Compiled without SSL support, module not available"); #endif } if (strcmp(hydra_options.service, "http-get") == 0 || strcmp(hydra_options.service, "http-head") == 0 || strcmp(hydra_options.service, "http-post") == 0) { i = 1; if (hydra_options.miscptr == NULL) { fprintf(stderr, "[WARNING] You must supply the web page as an " "additional option or via -m, default path set to /\n"); hydra_options.miscptr = malloc(2); hydra_options.miscptr = "/"; } if (*hydra_options.miscptr != '/' && strstr(hydra_options.miscptr, "://") == NULL) bail("The web page you supplied must start with a \"/\", \"http://\" " "or \"https://\", e.g. \"/protected/login\""); if (getenv("HYDRA_PROXY_HTTP") && getenv("HYDRA_PROXY")) bail("Found HYDRA_PROXY_HTTP *and* HYDRA_PROXY environment variables - " "you can use only ONE for the service http-head/http-get!"); if (getenv("HYDRA_PROXY_HTTP")) { printf("[INFO] Using HTTP Proxy: %s\n", getenv("HYDRA_PROXY_HTTP")); use_proxy = 1; } if (strcmp(hydra_options.service, "http-head") == 0) fprintf(stderr, "[WARNING] http-head auth does not work with every " "server, better use http-get\n"); } if (strcmp(hydra_options.service, "http-get-form") == 0 || strcmp(hydra_options.service, "http-post-form") == 0 || strcmp(hydra_options.service, "https-get-form") == 0 || strcmp(hydra_options.service, "https-post-form") == 0) { char bufferurl[6096 + 24], *url, *variables, *cond, *optional1; // 6096 comes from issue 192 on github. Extra 24 bytes for // null padding. if (strncmp(hydra_options.service, "http-", 5) == 0) { i = 1; } else { // https #ifdef LIBOPENSSL i = 1; hydra_options.ssl = 1; if (strcmp(hydra_options.service, "https-post-form") == 0) strcpy(hydra_options.service, "http-post-form"); else strcpy(hydra_options.service, "http-get-form"); #else bail("Compiled without SSL support, module not available"); #endif } if (hydra_options.infile_ptr == NULL) { if (hydra_options.miscptr == NULL) { fprintf(stderr, "[WARNING] You must supply the web page as an " "additional option or via -m, default path set to /\n"); hydra_options.miscptr = malloc(2); hydra_options.miscptr = "/"; } // if (*hydra_options.miscptr != '/' && strstr(hydra_options.miscptr, // "://") == NULL) // bail("The web page you supplied must start with a \"/\", \"http://\" // or \"https://\", e.g. \"/protected/login\""); if (hydra_options.miscptr[0] != '/') bail("optional parameter must start with a '/' slash!\n"); if (getenv("HYDRA_PROXY_HTTP") && getenv("HYDRA_PROXY")) bail("Found HYDRA_PROXY_HTTP *and* HYDRA_PROXY environment variables - " "you can use only ONE for the service http-head/http-get!"); if (getenv("HYDRA_PROXY_HTTP")) { printf("[INFO] Using HTTP Proxy: %s\n", getenv("HYDRA_PROXY_HTTP")); use_proxy = 1; } if (strstr(hydra_options.miscptr, "\\:") != NULL) { fprintf(stderr, "[INFORMATION] escape sequence \\: detected in module " "option, no parameter verification is performed.\n"); } else { sprintf(bufferurl, "%.6000s", hydra_options.miscptr); url = strtok(bufferurl, ":"); variables = strtok(NULL, ":"); cond = strtok(NULL, ":"); optional1 = strtok(NULL, "\n"); if ((variables == NULL) || (strstr(variables, "^USER^") == NULL && strstr(variables, "^PASS^") == NULL && strstr(variables, "^USER64^") == NULL && strstr(variables, "^PASS64^") == NULL)) { fprintf(stderr, "[ERROR] the variables argument needs at least the strings " "^USER^, ^PASS^, ^USER64^ or ^PASS64^: %s\n", STR_NULL(variables)); exit(-1); } if ((url == NULL) || (cond == NULL)) { fprintf(stderr, "[ERROR] Wrong syntax, requires three arguments separated by " "a colon which may not be null: %s\n", bufferurl); exit(-1); } while ((optional1 = strtok(NULL, ":")) != NULL) { if (optional1[1] != '=' && optional1[1] != ':' && optional1[1] != 0) { fprintf(stderr, "[ERROR] Wrong syntax of optional argument: %s\n", optional1); exit(-1); } switch (optional1[0]) { case 'C': // fall through case 'c': if (optional1[1] != '=' || optional1[2] != '/') { fprintf(stderr, "[ERROR] Wrong syntax of parameter C, must look like " "'C=/url/of/page', not http:// etc.: %s\n", optional1); exit(-1); } break; case 'H': // fall through case 'h': if (optional1[1] != '=' || strtok(NULL, ":") == NULL) { fprintf(stderr, "[ERROR] Wrong syntax of parameter H, must look like " "'H=X-My-Header: MyValue', no http:// : %s\n", optional1); exit(-1); } break; default: fprintf(stderr, "[ERROR] Unknown optional argument: %s\n", optional1); } } } } } if (strcmp(hydra_options.service, "xmpp") == 0) i = 1; if (strcmp(hydra_options.service, "irc") == 0) i = 1; if (strcmp(hydra_options.service, "rdp") == 0) { if (hydra_options.tasks > 4) fprintf(stderr, "[WARNING] rdp servers often don't like many connections, use -t 1 " "or -t 4 to reduce the number of parallel connections and -W 1 or " "-W 3 to wait between connection to allow the server to recover\n"); if (hydra_options.tasks > 4) { fprintf(stderr, "[INFO] Reduced number of tasks to 4 (rdp does not " "like many parallel connections)\n"); hydra_options.tasks = 4; } if (conwait == 0) hydra_options.conwait = conwait = 1; printf("[WARNING] the rdp module is experimental. Please test, report - " "and if possible, fix.\n"); i = 1; } if (strcmp(hydra_options.service, "radmin2") == 0) { #ifdef HAVE_GCRYPT i = 1; #else bail("hydra was not compiled with gcrypt support, radmin2 module not " "available"); #endif } // ADD NEW SERVICES HERE if (i == 0) { fprintf(stderr, "[ERROR] Unknown service: %s\n", hydra_options.service); exit(-1); } if (port < 1 || port > 65535) { if ((port = hydra_lookup_port(hydra_options.service)) < 1) { fprintf(stderr, "[ERROR] No valid port set or no default port " "available. Use the -s Option.\n"); exit(-1); } hydra_options.port = port; } if (hydra_options.login == NULL && hydra_options.loginfile == NULL && hydra_options.colonfile == NULL) hydra_options.exit_found = 1; if (hydra_options.ssl == 0 && hydra_options.port == 443) fprintf(stderr, "[WARNING] you specified port 443 for attacking a http " "service, however did not specify the -S ssl switch nor " "used https-..., therefore using plain HTTP\n"); if (hydra_options.loop_mode && hydra_options.colonfile != NULL) bail("The loop mode option (-u) works with all modes - except colon " "files (-C)\n"); if (strncmp(hydra_options.service, "http-", strlen("http-")) != 0 && strcmp(hydra_options.service, "http-head") != 0 && getenv("HYDRA_PROXY_HTTP") != NULL) fprintf(stderr, "[WARNING] the HYDRA_PROXY_HTTP environment variable works only " "with the http-head/http-get module, ignored...\n"); if (i == 2) { if (hydra_options.colonfile != NULL || ((hydra_options.login != NULL || hydra_options.loginfile != NULL) && (hydra_options.pass != NULL || hydra_options.passfile != NULL || hydra_options.bfg > 0))) bail("The redis, adam6500, cisco, oracle-listener, s7-300, snmp and " "vnc modules are only using the -p or -P option, not login (-l, " "-L) or colon file (-C).\nUse the telnet module for cisco using " "\"Username:\" authentication.\n"); if ((hydra_options.login != NULL || hydra_options.loginfile != NULL) && (hydra_options.pass == NULL || hydra_options.passfile == NULL)) { hydra_options.pass = hydra_options.login; hydra_options.passfile = hydra_options.loginfile; } hydra_options.login = empty_login; hydra_options.loginfile = NULL; } if (i == 3) { if (hydra_options.colonfile != NULL || hydra_options.bfg > 0 || ((hydra_options.login != NULL || hydra_options.loginfile != NULL) && (hydra_options.pass != NULL || hydra_options.passfile != NULL))) bail("The rsh, oracle-sid login is neither using the -p, -P or -x " "options nor colon file (-C)\n"); if ((hydra_options.login == NULL || hydra_options.loginfile == NULL) && (hydra_options.pass != NULL || hydra_options.passfile != NULL)) { hydra_options.login = hydra_options.pass; hydra_options.loginfile = hydra_options.passfile; } hydra_options.pass = empty_login; hydra_options.passfile = NULL; } if (i == 3 && hydra_options.login == NULL && hydra_options.loginfile == NULL) bail("I need at least either the -l or -L option to know the login"); if (i == 2 && hydra_options.pass == NULL && hydra_options.passfile == NULL && hydra_options.bfg == 0) bail("I need at least either the -p, -P or -x option to have a password " "to try"); if (i == 1 && hydra_options.login == NULL && hydra_options.loginfile == NULL && hydra_options.colonfile == NULL) bail("I need at least either the -l, -L or -C option to know the login"); if (hydra_options.colonfile != NULL && ((hydra_options.bfg != 0 || hydra_options.login != NULL || hydra_options.loginfile != NULL) || (hydra_options.pass != NULL && hydra_options.passfile != NULL))) bail("The -C option is standalone, don't use it with -l/L, -p/P or -x!"); if ((hydra_options.bfg) && ((hydra_options.pass != NULL) || (hydra_options.passfile != NULL) || (hydra_options.colonfile != NULL))) bail("The -x (password bruteforce generation option) doesn't work with " "-p/P, -C or -e!\n"); if (hydra_options.try_password_reverse_login == 0 && hydra_options.try_password_same_as_login == 0 && hydra_options.try_null_password == 0 && (i != 3 && (hydra_options.pass == NULL && hydra_options.passfile == NULL && hydra_options.colonfile == NULL)) && hydra_options.bfg == 0) { // test if the service is smtp-enum as it could be used either with a // login+pass or only a login if (strstr(hydra_options.service, "smtp-enum") != NULL) hydra_options.pass = empty_login; else bail("I need at least the -e, -p, -P or -x option to have some " "passwords!"); } if (hydra_options.tasks < 1 || hydra_options.tasks > MAXTASKS) { fprintf(stderr, "[ERROR] Option -t needs to be a number between 1 and %d\n", MAXTASKS); exit(-1); } if (hydra_options.max_use > MAXTASKS) { fprintf(stderr, "[WARNING] reducing maximum tasks to MAXTASKS (%d)\n", MAXTASKS); hydra_options.max_use = MAXTASKS; } // script kiddie patch if (hydra_options.server != NULL && (hydra_strcasestr(hydra_options.server, ".outlook.com") != NULL || hydra_strcasestr(hydra_options.server, ".hotmail.com") != NULL || hydra_strcasestr(hydra_options.server, ".yahoo.") != NULL || hydra_strcasestr(hydra_options.server, ".gmx.") != NULL || hydra_strcasestr(hydra_options.server, ".web.de") != NULL || hydra_strcasestr(hydra_options.server, ".gmail.") != NULL || hydra_strcasestr(hydra_options.server, "googlemail.") != NULL)) { fprintf(stderr, "[WARNING] Google Mail and others have bruteforce and " "hydra detection and send false positives. You are not " "doing anything illegal right?!\n"); fprintf(stderr, "[WARNING] !read the above!\n"); sleep(5); } if (hydra_options.colonfile == NULL) { if (hydra_options.loginfile != NULL) { if ((lfp = fopen(hydra_options.loginfile, "r")) == NULL) { fprintf(stderr, "[ERROR] File for logins not found: %s\n", hydra_options.loginfile); exit(-1); } else if (hydra_options.passfile == NULL){ if(my_segment && num_segments){ filecloser = lfp; lfp = hydra_divide_file(lfp, my_segment, num_segments); fclose(filecloser); } } hydra_brains.countlogin = countlines(lfp, 0); hydra_brains.sizelogin = size_of_data; if (hydra_brains.countlogin == 0) { fprintf(stderr, "[ERROR] File for logins is empty: %s\n", hydra_options.loginfile); exit(-1); } if (hydra_brains.countlogin > MAX_LINES) { fprintf(stderr, "[ERROR] Maximum number of logins is %d, this file has %" hPRIu64 " entries.\n", MAX_LINES, hydra_brains.countlogin); exit(-1); } if (hydra_brains.sizelogin > MAX_BYTES) { fprintf(stderr, "[ERROR] Maximum size of the login file is %d, this file has " "%" hPRIu64 " bytes.\n", MAX_BYTES, (uint64_t)hydra_brains.sizelogin); exit(-1); } login_ptr = malloc(hydra_brains.sizelogin + hydra_brains.countlogin + 8); if (login_ptr == NULL) bail("Could not allocate enough memory for login file data"); memset(login_ptr, 0, hydra_brains.sizelogin + hydra_brains.countlogin + 8); fill_mem(login_ptr, lfp, 0); } else { login_ptr = hydra_options.login; hydra_brains.sizelogin = strlen(hydra_options.login) + 1; hydra_brains.countlogin = 1; } if (hydra_options.passfile != NULL) { if ((pfp = fopen(hydra_options.passfile, "r")) == NULL) { fprintf(stderr, "[ERROR] File for passwords not found: %s\n", hydra_options.passfile); exit(-1); } else if(my_segment && num_segments){ filecloser = pfp; pfp = hydra_divide_file(pfp, my_segment, num_segments); fclose(filecloser); } hydra_brains.countpass = countlines(pfp, 0); hydra_brains.sizepass = size_of_data; if (hydra_brains.countpass == 0) { fprintf(stderr, "[ERROR] File for passwords is empty: %s\n", hydra_options.passfile); exit(-1); } if (hydra_brains.countpass > MAX_LINES) { fprintf(stderr, "[ERROR] Maximum number of passwords is %d, this file has " "%" hPRIu64 " entries.\n", MAX_LINES, hydra_brains.countpass); exit(-1); } if (hydra_brains.sizepass > MAX_BYTES) { fprintf(stderr, "[ERROR] Maximum size of the password file is %d, this file " "has %" hPRIu64 " bytes.\n", MAX_BYTES, (uint64_t)hydra_brains.sizepass); exit(-1); } pass_ptr = malloc(hydra_brains.sizepass + hydra_brains.countpass + 8); if (pass_ptr == NULL) bail("Could not allocate enough memory for password file data"); memset(pass_ptr, 0, hydra_brains.sizepass + hydra_brains.countpass + 8); fill_mem(pass_ptr, pfp, 0); } else { if (hydra_options.pass != NULL) { pass_ptr = hydra_options.pass; hydra_brains.countpass = 1; hydra_brains.sizepass = strlen(hydra_options.pass) + 1; } else { if (hydra_options.bfg) { #ifdef HAVE_MATH_H if (bf_init(bf_options.arg)) exit(-1); // error description is handled by bf_init pass_ptr = bf_next(); hydra_brains.countpass += bf_get_pcount(); hydra_brains.sizepass += BF_BUFLEN; #else sleep(1); #endif } else { pass_ptr = hydra_options.pass = empty_login; hydra_brains.countpass = 0; hydra_brains.sizepass = 1; } } } } else { if ((cfp = fopen(hydra_options.colonfile, "r")) == NULL) { fprintf(stderr, "[ERROR] File for colon files (login:pass) not found: %s\n", hydra_options.colonfile); exit(-1); } else if(my_segment && num_segments){ filecloser = cfp; cfp = hydra_divide_file(cfp, my_segment, num_segments); fclose(filecloser); } hydra_brains.countlogin = countlines(cfp, 1); hydra_brains.sizelogin = size_of_data; if (hydra_brains.countlogin == 0) { fprintf(stderr, "[ERROR] File for colon files (login:pass) is empty: %s\n", hydra_options.colonfile); exit(-1); } if (hydra_brains.countlogin > MAX_LINES / 2) { fprintf(stderr, "[ERROR] Maximum number of colon file entries is %d, this file " "has %" hPRIu64 " entries.\n", MAX_LINES / 2, hydra_brains.countlogin); exit(-1); } if (hydra_brains.sizelogin > MAX_BYTES / 2) { fprintf(stderr, "[ERROR] Maximum size of the colon file is %d, this file has " "%" hPRIu64 " bytes.\n", MAX_BYTES / 2, (uint64_t)hydra_brains.sizelogin); exit(-1); } csv_ptr = malloc(hydra_brains.sizelogin + 2 * hydra_brains.countlogin + 8); if (csv_ptr == NULL) bail("Could not allocate enough memory for colon file data"); memset(csv_ptr, 0, hydra_brains.sizelogin + 2 * hydra_brains.countlogin + 8); fill_mem(csv_ptr, cfp, 1); // printf("count: %d, size: %d\n", hydra_brains.countlogin, // hydra_brains.sizelogin); hydra_dump_data(csv_ptr, // hydra_brains.sizelogin // + hydra_brains.countlogin + 8, "colon data"); hydra_brains.countpass = 1; pass_ptr = login_ptr = csv_ptr; while (*pass_ptr != 0) pass_ptr++; pass_ptr++; } hydra_brains.countpass += hydra_options.try_password_reverse_login + hydra_options.try_password_same_as_login + hydra_options.try_null_password; if ((memcheck = malloc(102400)) == NULL) { fprintf(stderr, "[ERROR] your wordlist is too large, not enough memory!\n"); exit(-1); } free(memcheck); if ((rfp = fopen(RESTOREFILE, "r")) != NULL) { fprintf(stderr, "[WARNING] Restorefile (%s) from a previous session found, to " "prevent overwriting, %s\n", ignore_restore == 1 ? "ignored ..." : "you have 10 seconds to abort... (use " "option -I to skip waiting)", RESTOREFILE); if (ignore_restore != 1) sleep(10); fclose(rfp); } if (hydra_options.infile_ptr != NULL) { if ((ifp = fopen(hydra_options.infile_ptr, "r")) == NULL) { fprintf(stderr, "[ERROR] File for targets not found: %s\n", hydra_options.infile_ptr); exit(-1); } hydra_brains.targets = countservers = countinfile = countlines(ifp, 0); if (countinfile == 0) { fprintf(stderr, "[ERROR] File for targets is empty: %s\n", hydra_options.infile_ptr); exit(-1); } // if (countinfile > 60) fprintf(stderr, "[WARNING] the -M option is not // working correctly at the moment for target lists > 60!\n"); hydra_targets = malloc(sizeof(hydra_target *) * (countservers + 2) + 8); if (hydra_targets == NULL) bail("Could not allocate enough memory for target data"); sizeinfile = size_of_data; if (countinfile > MAX_LINES / 1000) { fprintf(stderr, "[ERROR] Maximum number of target file entries is %d, this " "file has %d entries.\n", MAX_LINES / 1000, (int32_t)countinfile); exit(-1); } if (sizeinfile > MAX_BYTES / 1000) { fprintf(stderr, "[ERROR] Maximum size of the server file is %d, this file has " "%d bytes.\n", MAX_BYTES / 1000, (int32_t)sizeinfile); exit(-1); } if ((servers_ptr = malloc(sizeinfile + countservers + 8)) == NULL) bail("Could not allocate enough memory for target file data"); memset(servers_ptr, 0, sizeinfile + countservers + 8); fill_mem(servers_ptr, ifp, 0); sizeservers = sizeinfile; tmpptr = servers_ptr; for (i = 0; i < countinfile; i++) { hydra_targets[i] = malloc(sizeof(hydra_target)); memset(hydra_targets[i], 0, sizeof(hydra_target)); if (*tmpptr == '[') { tmpptr++; hydra_targets[i]->target = tmpptr; if ((tmpptr2 = strchr(tmpptr, ']')) != NULL) { *tmpptr2++ = 0; tmpptr = tmpptr2; } } else hydra_targets[i]->target = tmpptr; if ((tmpptr2 = strchr(tmpptr, ':')) != NULL) { *tmpptr2++ = 0; tmpptr = tmpptr2; hydra_targets[i]->port = atoi(tmpptr2); if (hydra_targets[i]->port < 1 || hydra_targets[i]->port > 65535) hydra_targets[i]->port = 0; } if (hydra_targets[i]->port == 0) hydra_targets[i]->port = hydra_options.port; if ((tmpptr3 = strchr(tmpptr, '/')) != NULL) { hydra_targets[i]->miscptr = tmpptr3; } else hydra_targets[i]->miscptr = "/"; while (*tmpptr != 0) tmpptr++; tmpptr++; } } else if (hydra_options.server == NULL) { fprintf(stderr, "Error: no target server given, nor -M option used\n"); exit(-1); } else if (strchr(hydra_options.server, '/') != NULL) { if (cmdlinetarget == NULL) bail("You seem to mix up \"service://target:port/options\" syntax with " "\"target service options\" syntax. Read the README on how to use " "hydra correctly!"); if (strstr(cmdlinetarget, "://") != NULL) { tmpptr = strchr(hydra_options.server, '/'); if (tmpptr != NULL) *tmpptr = 0; countservers = hydra_brains.targets = 1; hydra_targets = malloc(sizeof(hydra_target *) * 4); hydra_targets[0] = malloc(sizeof(hydra_target)); memset(hydra_targets[0], 0, sizeof(hydra_target)); hydra_targets[0]->target = servers_ptr = hydra_options.server; hydra_targets[0]->port = hydra_options.port; hydra_targets[0]->miscptr = hydra_options.miscptr; sizeservers = strlen(hydra_options.server) + 1; } else { /* CIDR notation on command line, e.g. 192.168.0.0/24 */ uint32_t four_from, four_to, addr_cur, addr_cur2, k, l; in_addr_t addr4; struct sockaddr_in target; hydra_options.cidr = 1; do_retry = 0; if ((tmpptr = malloc(strlen(hydra_options.server) + 1)) == NULL) { fprintf(stderr, "Error: can not allocate memory\n"); exit(-1); } strcpy(tmpptr, hydra_options.server); tmpptr2 = strchr(tmpptr, '/'); *tmpptr2++ = 0; if ((k = atoi(tmpptr2)) < 16 || k > 31) { fprintf(stderr, "Error: network size may only be between /16 and /31: %s\n", hydra_options.server); exit(-1); } if ((addr4 = htonl(inet_addr(tmpptr))) == 0xffffffff) { fprintf(stderr, "Error: option is not a valid IPv4 address: %s\n", tmpptr); exit(-1); } free(tmpptr); l = 1 << (32 - k); l--; four_to = (addr4 | l); l = 0xffffffff - l; four_from = (addr4 & l); l = 1 << (32 - k); hydra_brains.targets = countservers = l; hydra_targets = (hydra_target **)malloc(sizeof(hydra_target *) * (l + 2) + 8); if (hydra_targets == NULL) bail("Could not allocate enough memory for target data"); i = 0; addr_cur = four_from; while (addr_cur <= four_to && i < l) { hydra_targets[i] = malloc(sizeof(hydra_target)); memset(hydra_targets[i], 0, sizeof(hydra_target)); addr_cur2 = htonl(addr_cur); memcpy(&target.sin_addr.s_addr, (char *)&addr_cur2, 4); hydra_targets[i]->target = strdup(inet_ntoa((struct in_addr)target.sin_addr)); hydra_targets[i]->port = hydra_options.port; hydra_targets[i]->miscptr = hydra_options.miscptr; addr_cur++; i++; } if (verbose) printf("[VERBOSE] CIDR attack from %s to %s\n", hydra_targets[0]->target, hydra_targets[l - 1]->target); printf("[WARNING] The CIDR attack mode is still beta. Please report " "issues.\n"); } } else { // standard: single target on command line countservers = hydra_brains.targets = 1; hydra_targets = malloc(sizeof(hydra_target *) * 4); hydra_targets[0] = malloc(sizeof(hydra_target)); memset(hydra_targets[0], 0, sizeof(hydra_target)); hydra_targets[0]->target = servers_ptr = hydra_options.server; hydra_targets[0]->port = hydra_options.port; hydra_targets[0]->miscptr = hydra_options.miscptr; sizeservers = strlen(hydra_options.server) + 1; } for (i = 0; i < hydra_brains.targets; i++) { hydra_targets[i]->login_ptr = login_ptr; hydra_targets[i]->pass_ptr = pass_ptr; if (hydra_options.loop_mode) { if (hydra_options.try_password_same_as_login) hydra_targets[i]->pass_state = 0; else if (hydra_options.try_null_password) { hydra_targets[i]->pass_ptr = empty_login; hydra_targets[i]->pass_state = 1; } else if (hydra_options.try_password_reverse_login) hydra_targets[i]->pass_state = 2; else hydra_targets[i]->pass_state = 3; } } } // END OF restore == 0 // PROXY PROCESSING if (getenv("HYDRA_PROXY") && use_proxy == 0) { printf("[INFO] Using Connect Proxy: %s\n", getenv("HYDRA_PROXY")); use_proxy = 2; } if (use_proxy == 1) proxy_string = getenv("HYDRA_PROXY_HTTP"); if (use_proxy == 2) proxy_string = getenv("HYDRA_PROXY"); if (use_proxy && getenv("HYDRA_PROXY_AUTH") != NULL) fprintf(stderr, "[WARNING] environment variable HYDRA_PROXY_AUTH is " "deprecated, use authentication in the HYDRA_PROXY " "definitions, e.g. type://auth@target:port\n"); if (use_proxy && proxy_string != NULL) { if (strstr(proxy_string, "://") != NULL) { process_proxy_line(use_proxy, proxy_string); } else { if ((proxyfp = fopen(proxy_string, "r")) == NULL) { fprintf(stderr, "[ERROR] proxy definition %s is neither of the kind " "type://auth@target:port nor a file containing proxy entries!\n", proxy_string); exit(-1); } while (fgets(buf, sizeof(buf), proxyfp) != NULL) process_proxy_line(use_proxy, buf); fclose(proxyfp); } if (proxy_count == 0) bail("proxy defined but not valid, exiting"); } if (hydra_options.restore == 0) { if ((strcmp(hydra_options.service, "rsh") == 0) || (strcmp(hydra_options.service, "oracle-sid") == 0)) math2 = hydra_brains.countlogin; else math2 = hydra_brains.countlogin * hydra_brains.countpass; #ifdef HAVE_MATH_H if (hydra_options.bfg) { math2 = hydra_brains.countlogin * bf_get_pcount(); } #endif hydra_brains.todo = math2; math2 = math2 * hydra_brains.targets; hydra_brains.todo_all = math2; if (hydra_brains.todo_all == 0) bail("No login/password combination given!"); if (hydra_brains.todo < hydra_options.tasks) { if (verbose && hydra_options.tasks != TASKS) printf("[VERBOSE] More tasks defined than login/pass pairs exist. " "Tasks reduced to %" hPRIu64 "\n", hydra_brains.todo); hydra_options.tasks = hydra_brains.todo; } } if (hydra_options.max_use == MAXTASKS) { // only if it was not set via -T if (hydra_options.max_use < hydra_brains.targets * hydra_options.tasks) hydra_options.max_use = hydra_brains.targets * hydra_options.tasks; if (hydra_options.max_use > MAXTASKS) hydra_options.max_use = MAXTASKS; } if ((hydra_options.tasks == TASKS || hydra_options.tasks <= 8) && hydra_options.max_use < hydra_brains.targets * hydra_options.tasks) { if ((hydra_options.tasks = hydra_options.max_use / hydra_brains.targets) == 0) hydra_options.tasks = 1; // fprintf(stderr, "[WARNING] More tasks defined per server than allowed for // maximal connections. Tasks per server reduced to %d.\n", // hydra_options.tasks); } else { if (hydra_options.tasks > MAXTASKS) { // fprintf(stderr, "[WARNING] reducing tasks to MAXTASKS (%d)\n", // MAXTASKS); hydra_options.tasks = MAXTASKS; } } // hydra_options.max_use = hydra_brains.targets * hydra_options.tasks; // if (hydra_options.max_use > MAXTASKS) // hydra_options.max_use = MAXTASKS; if (hydra_options.max_use > hydra_options.tasks * hydra_brains.targets) hydra_options.max_use = hydra_options.tasks * hydra_brains.targets; math2 = (hydra_brains.todo * hydra_brains.targets) / hydra_options.max_use; if ((hydra_brains.todo * hydra_brains.targets) % hydra_options.max_use) math2++; // set options (bits!) options = 0; if (hydra_options.ssl) options = options | OPTION_SSL; printf("[DATA] max %d task%s per %d server%s, overall %d task%s, %" hPRIu64 " login tr", hydra_options.tasks, hydra_options.tasks == 1 ? "" : "s", hydra_brains.targets, hydra_brains.targets == 1 ? "" : "s", hydra_options.max_use, hydra_options.max_use == 1 ? "" : "s", hydra_brains.todo); printf("%s", hydra_brains.todo == 1 ? "y" : "ies"); if (hydra_options.colonfile == NULL) { printf(" (l:%" hPRIu64 "/p:%" hPRIu64 "), ~%" hPRIu64 " tr", (uint64_t)hydra_brains.countlogin, (uint64_t)hydra_brains.countpass, math2); } else { printf(", ~%" hPRIu64 " tr", math2); } printf("%s", math2 == 1 ? "y" : "ies"); printf(" per task\n"); if (hydra_brains.targets == 1) { if (strchr(hydra_targets[0]->target, ':') == NULL) { printf("[DATA] attacking %s%s://%s:", hydra_options.service, hydra_options.ssl == 1 ? "s" : "", hydra_targets[0]->target); printf("%d%s%s\n", port, hydra_options.miscptr == NULL || hydra_options.miscptr[0] != '/' ? "/" : "", hydra_options.miscptr != NULL ? hydra_options.miscptr : ""); } else { printf("[DATA] attacking %s%s://[%s]:", hydra_options.service, hydra_options.ssl == 1 ? "s" : "", hydra_targets[0]->target); printf("%d%s%s\n", port, hydra_options.miscptr == NULL || hydra_options.miscptr[0] != '/' ? "/" : "", hydra_options.miscptr != NULL ? hydra_options.miscptr : ""); } } else { printf("[DATA] attacking %s%s://(%d targets):", hydra_options.service, hydra_options.ssl == 1 ? "s" : "", hydra_brains.targets); printf("%d%s%s\n", port, hydra_options.miscptr == NULL || hydra_options.miscptr[0] != '/' ? "/" : "", hydra_options.miscptr != NULL ? hydra_options.miscptr : ""); } // service %s on port %d%s\n", hydra_options.service, port, hydra_options.ssl // == 1 ? " with SSL" : ""); // if (hydra_options.miscptr != NULL && hydra_options.miscptr[0] != 0) // printf("[DATA] with additional data %s\n", hydra_options.miscptr); if (hydra_options.outfile_ptr != NULL) { char outfile_open_type[] = "a+"; // Default open in a+ mode if (hydra_options.outfile_format == FORMAT_JSONV1 && hydra_options.restore != 1) { outfile_open_type[0] = 'w'; // Creat new outfile, if using JSON output and // not using -R. The open mode should be "w+". } if ((hydra_brains.ofp = fopen(hydra_options.outfile_ptr, outfile_open_type)) == NULL) { perror("[ERROR] Error creating outputfile"); exit(-1); } if (hydra_options.outfile_format == FORMAT_JSONV1) { if (hydra_options.restore != 1) { // No JSON head while using -R fprintf(hydra_brains.ofp, "{ \"generator\": {\n" "\t\"software\": \"%s\", \"version\": \"%s\", \"built\": \"%s\",\n" "\t\"server\": \"%s\", \"service\": \"%s\", \"jsonoutputversion\": " "\"1.00\",\n" "\t\"commandline\": \"%s", PROGRAM, VERSION, hydra_build_time(), hydra_options.server == NULL ? hydra_options.infile_ptr : hydra_options.server, hydra_options.service, prg); for (i = 1; i < argc; i++) { char *t = hydra_string_replace(argv[i], "\"", "\\\""); fprintf(hydra_brains.ofp, " %s", t); free(t); } fprintf(hydra_brains.ofp, "\"\n\t},\n\"results\": ["); } } else { // else default is plain text aka == 0 fprintf(hydra_brains.ofp, "# %s %s run at %s on %s %s (%s", PROGRAM, VERSION, hydra_build_time(), hydra_options.server == NULL ? hydra_options.infile_ptr : hydra_options.server, hydra_options.service, prg); for (i = 1; i < argc; i++) fprintf(hydra_brains.ofp, " %s", argv[i]); fprintf(hydra_brains.ofp, ")\n"); } } // we have to flush all writeable buffered file pointers before forking // set appropriate signals for mother signal(SIGCHLD, killed_childs); if (debug == 0) signal(SIGTERM, kill_children); if (debug == 0) { #ifdef SIGBUS signal(SIGBUS, kill_children); #endif signal(SIGSEGV, kill_children); } signal(SIGHUP, kill_children); signal(SIGINT, kill_children); signal(SIGPIPE, SIG_IGN); if (verbose) printf("[VERBOSE] Resolving addresses ... "); if (debug) printf("\n"); for (i = 0; i < hydra_brains.targets; i++) { if (debug) printf("[DEBUG] resolving %s\n", hydra_targets[i]->target); memset(&hints, 0, sizeof(hints)); ipv4 = NULL; #ifdef AF_INET6 ipv6 = NULL; #endif if ((device = strchr(hydra_targets[i]->target, '%')) != NULL) *device++ = 0; if (getaddrinfo(hydra_targets[i]->target, NULL, &hints, &res) != 0) { if (use_proxy == 0) { if (verbose) printf("[failed for %s] ", hydra_targets[i]->target); else fprintf(stderr, "[ERROR] could not resolve address: %s\n", hydra_targets[i]->target); hydra_targets[i]->done = TARGET_UNRESOLVED; hydra_brains.finished++; } } else { for (p = res; p != NULL; p = p->ai_next) { #ifdef AF_INET6 if (p->ai_family == AF_INET6) { if (ipv6 == NULL) ipv6 = (struct sockaddr_in6 *)p->ai_addr; } else #endif if (p->ai_family == AF_INET) { if (ipv4 == NULL) ipv4 = (struct sockaddr_in *)p->ai_addr; } } #ifdef AF_INET6 if (ipv6 != NULL && (ipv4 == NULL || prefer_ipv6)) { // IPV6 FIXME if ((strcmp(hydra_options.service, "socks5") == 0) || (strcmp(hydra_options.service, "sip") == 0)) { fprintf(stderr, "[ERROR] Target %s resolves to an IPv6 address, however " "module %s does not support this. Maybe try \"-4\" option. " "Sending in patches helps.\n", hydra_targets[i]->target, hydra_options.service); hydra_targets[i]->done = TARGET_UNRESOLVED; hydra_brains.finished++; } else { hydra_targets[i]->ip[0] = 16; memcpy(&hydra_targets[i]->ip[1], (char *)&ipv6->sin6_addr, 16); if (device != NULL && strlen(device) <= 16) strcpy(&hydra_targets[i]->ip[17], device); if (memcmp(&hydra_targets[i]->ip[17], fe80, 2) == 0) { if (device == NULL) { fprintf(stderr, "[ERROR] The target %s address is a link local address, " "link local addresses require the interface being " "defined like this: fe80::1%%eth0\n", hydra_targets[i]->target); exit(-1); } } } } else #endif if (ipv4 != NULL) { hydra_targets[i]->ip[0] = 4; memcpy(&hydra_targets[i]->ip[1], (char *)&ipv4->sin_addr, 4); } else { if (verbose) printf("[failed for %s] ", hydra_targets[i]->target); else fprintf(stderr, "[ERROR] Could not resolve proxy address: %s\n", hydra_targets[i]->target); hydra_targets[i]->done = TARGET_UNRESOLVED; hydra_brains.finished++; } freeaddrinfo(res); } // restore device information if present (overwrite null bytes) if (device != NULL) { char *tmpptr = device - 1; *tmpptr = '%'; // you can ignore the compiler warning fprintf(stderr, "[WARNING] not all modules support BINDTODEVICE for IPv6 " "link local addresses, e.g. SSH does not\n"); } } if (verbose) printf("[VERBOSE] resolving done\n"); if (hydra_brains.targets == 0) bail("No server to scan!"); #ifndef SO_BINDTODEVICE if (device != NULL) { fprintf(stderr, "[ERROR] your operating system does not support SO_BINDTODEVICE or " "IP_FORCE_OUT_IFP, dunno how to bind the IPv6 address to the " "interface %s!\n", device); } #endif if (hydra_options.restore == 0) { hydra_heads = malloc(sizeof(hydra_head *) * hydra_options.max_use); target_no = 0; for (i = 0; i < hydra_options.max_use; i++) { hydra_heads[i] = malloc(sizeof(hydra_head)); memset(hydra_heads[i], 0, sizeof(hydra_head)); } } // here we call the init function of the relevant service module // should we do the init centrally or should each child do that? // that depends largely on the number of targets and maximum tasks // if (hydra_brains.targets == 1 || (hydra_brains.targets < 4 && // hydra_options.tasks / hydra_brains.targets > 4 && hydra_brains.todo > 15)) for (i = 0; i < hydra_brains.targets; i++) hydra_service_init(i); starttime = elapsed_status = elapsed_restore = time(NULL); fflush(stdout); fflush(stderr); fflush(hydra_brains.ofp); #if OPENSSL_VERSION_NUMBER >= 0x10100000L if (hydra_options.ssl) { fprintf(stderr, "[WARNING] *****************************************************\n"); fprintf(stderr, "[WARNING] OPENSSL v1.1 development changes are active - modules " "SMB, SNMP, RDP, ORACLE LISTENER and SSL in general might not work " "properly! Please test and report to vh@thc.org.\n"); fprintf(stderr, "[WARNING] *****************************************************\n"); } #endif hydra_debug(0, "attack"); process_restore = 1; // this is the big function which starts the attacking children, feeds // login/password pairs, etc.! while (exit_condition == 0) { memset(&fdreadheads, 0, sizeof(fdreadheads)); max_fd = 0; FD_ZERO(&fdreadheads); for (head_no = 0, max_fd = 1; head_no < hydra_options.max_use; head_no++) { if (hydra_heads[head_no]->active == HEAD_ACTIVE) { FD_SET(hydra_heads[head_no]->sp[0], &fdreadheads); if (max_fd < hydra_heads[head_no]->sp[0]) max_fd = hydra_heads[head_no]->sp[0]; } } my_select(max_fd + 1, &fdreadheads, NULL, NULL, 0, 200000); tmp_time = time(NULL); for (head_no = 0; head_no < hydra_options.max_use; head_no++) { if (debug > 1 && hydra_heads[head_no]->active != HEAD_DISABLED) printf("[DEBUG] head_no[%d] to target_no %d active %d\n", head_no, hydra_heads[head_no]->target_no, hydra_heads[head_no]->active); switch (hydra_heads[head_no]->active) { case HEAD_DISABLED: break; case HEAD_UNUSED: if (hydra_heads[head_no]->redo) { hydra_spawn_head(head_no, hydra_heads[head_no]->target_no); } else { if (hydra_brains.targets > hydra_brains.finished) hydra_heads[head_no]->target_no = hydra_select_target(); else hydra_heads[head_no]->target_no = -1; if (debug) printf("[DEBUG] child %d got target %d selected\n", head_no, hydra_heads[head_no]->target_no); if (hydra_heads[head_no]->target_no < 0) { if (debug) printf("[DEBUG] hydra_select_target() reports no more targets " "left\n"); hydra_kill_head(head_no, 0, 3); } else hydra_spawn_head(head_no, hydra_heads[head_no]->target_no); // target_no is ignored if head->redo == 1 } break; case HEAD_ACTIVE: if (FD_ISSET(hydra_heads[head_no]->sp[0], &fdreadheads)) { do_switch = 1; if (hydra_options.time_next_attempt > 0) { if (last_attempt + hydra_options.time_next_attempt >= time(NULL)) { if (recv(hydra_heads[head_no]->sp[0], &rc, 1, MSG_PEEK) == 1 && (rc == 'N' || rc == 'n')) do_switch = 0; } else last_attempt = time(NULL); } if (do_switch) { readres = read_safe(hydra_heads[head_no]->sp[0], &rc, 1); if (readres > 0) { FD_CLR(hydra_heads[head_no]->sp[0], &fdreadheads); hydra_heads[head_no]->last_seen = tmp_time; if (debug) printf("[DEBUG] head_no[%d] read %c\n", head_no, rc); switch (rc) { // Valid Results: // n - mother says to itself that child requests next // login/password pair N - child requests next login/password // pair Q - child reports that it is quitting C - child reports // connect error (and is quitting) E - child reports protocol // error (and is quitting) f - child reports that the username // does not exist F - child reports that it found a valid // login/password pair // and requests next pair. Sends login/pw pair with next // msg! case 'N': // head wants next pair hydra_targets[hydra_heads[head_no]->target_no]->ok = 1; if (hydra_targets[hydra_heads[head_no]->target_no]->fail_count > 0) hydra_targets[hydra_heads[head_no]->target_no]->fail_count--; // no break here case 'n': // mother sends this to itself initially loop_cnt = 0; if (hydra_send_next_pair(hydra_heads[head_no]->target_no, head_no) == -1) hydra_kill_head(head_no, 1, 0); break; case 'F': // valid password found hydra_brains.found++; if (colored_output) { if (hydra_heads[head_no]->current_login_ptr == NULL || strlen(hydra_heads[head_no]->current_login_ptr) == 0) { if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) printf("[\e[1;32m%d\e[0m][\e[1;32m%s\e[0m] host: " "\e[1;32m%s\e[0m\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target); else printf("[\e[1;32m%d\e[0m][\e[1;32m%s\e[0m] host: " "\e[1;32m%s\e[0m password: \e[1;32m%s\e[0m\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_pass_ptr); } else if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) { printf("[\e[1;32m%d\e[0m][\e[1;32m%s\e[0m] host: " "\e[1;32m%s\e[0m login: \e[1;32m%s\e[0m\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr); } else printf("[\e[1;32m%d\e[0m][\e[1;32m%s\e[0m] host: " "\e[1;32m%s\e[0m login: \e[1;32m%s\e[0m password: " "\e[1;32m%s\e[0m\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr); } else { if (hydra_heads[head_no]->current_login_ptr == NULL || strlen(hydra_heads[head_no]->current_login_ptr) == 0) { if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) printf("[%d][%s] host: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target); else printf("[%d][%s] host: %s password: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_pass_ptr); } else if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) { printf("[%d][%s] host: %s login: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr); } else printf("[%d][%s] host: %s misc: %s login: %s password: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_targets[hydra_heads[head_no]->target_no]->miscptr, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr); } if (hydra_options.outfile_format == FORMAT_JSONV1 && hydra_options.outfile_ptr != NULL && hydra_brains.ofp != NULL) { fprintf(hydra_brains.ofp, "%s\n\t{\"port\": %d, \"service\": \"%s\", \"host\": " "\"%s\", \"login\": \"%s\", \"password\": \"%s\"}", hydra_brains.found == 1 ? "" : ",", // prefix a comma if not first finding hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target != NULL ? hydra_targets[hydra_heads[head_no]->target_no]->target : "", hydra_heads[head_no]->current_login_ptr != NULL ? hydra_string_replace(hydra_heads[head_no]->current_login_ptr, "\"", "\\\"") : "", hydra_heads[head_no]->current_pass_ptr != NULL ? hydra_string_replace(hydra_heads[head_no]->current_pass_ptr, "\"", "\\\"") : ""); fflush(hydra_brains.ofp); } else if (hydra_options.outfile_ptr != NULL && hydra_brains.ofp != NULL) { // else output format == 0 aka text if (hydra_heads[head_no]->current_login_ptr == NULL || strlen(hydra_heads[head_no]->current_login_ptr) == 0) { if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) fprintf(hydra_brains.ofp, "[%d][%s] host: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target); else fprintf(hydra_brains.ofp, "[%d][%s] host: %s password: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_pass_ptr); } else if (hydra_heads[head_no]->current_pass_ptr == NULL || strlen(hydra_heads[head_no]->current_pass_ptr) == 0) { fprintf(hydra_brains.ofp, "[%d][%s] host: %s login: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr); } else fprintf(hydra_brains.ofp, "[%d][%s] host: %s login: %s password: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr); fflush(hydra_brains.ofp); } if (hydra_options.exit_found) { // option set says quit target after on // valid login/pass pair is found if (hydra_targets[hydra_heads[head_no]->target_no]->done == TARGET_ACTIVE) { hydra_targets[hydra_heads[head_no]->target_no]->done = TARGET_FINISHED; // mark target as done hydra_brains.finished++; printf("[STATUS] attack finished for %s (valid pair found)\n", hydra_targets[hydra_heads[head_no]->target_no]->target); } if (hydra_options.exit_found == 2) { for (j = 0; j < hydra_brains.targets; j++) if (hydra_targets[j]->done == TARGET_ACTIVE) { hydra_targets[j]->done = TARGET_FINISHED; hydra_brains.finished++; } } for (j = 0; j < hydra_options.max_use; j++) if (hydra_heads[j]->active >= 0 && (hydra_heads[j]->target_no == target_no || hydra_options.exit_found == 2)) { if (hydra_brains.targets > hydra_brains.finished && hydra_options.exit_found < 2) hydra_kill_head(j, 1, 0); // kill all heads working on the target else hydra_kill_head(j, 1, 2); // kill all heads working on the target } continue; } // fall through case 'f': // username identified as invalid hydra_targets[hydra_heads[head_no]->target_no]->ok = 1; if (hydra_targets[hydra_heads[head_no]->target_no]->fail_count > 0) hydra_targets[hydra_heads[head_no]->target_no]->fail_count--; memset(buf, 0, sizeof(buf)); read_safe(hydra_heads[head_no]->sp[0], buf, MAXBUF); hydra_skip_user(hydra_heads[head_no]->target_no, buf); fck = write(hydra_heads[head_no]->sp[1], "n", 1); // small hack break; case 'D': // disable target, unknown protocol or feature for (j = 0; j < hydra_brains.targets; j++) if (hydra_targets[j]->done == TARGET_ACTIVE) { hydra_targets[j]->done = TARGET_FINISHED; hydra_brains.finished++; } for (j = 0; j < hydra_options.max_use; j++) if (hydra_heads[j]->active >= 0 && hydra_heads[j]->target_no == target_no) { if (hydra_brains.targets > hydra_brains.finished) hydra_kill_head(j, 1, 0); // kill all heads working on the target else hydra_kill_head(j, 1, 2); // kill all heads working on the target } break; // we do not make a difference between 'C' and 'E' results - yet case 'E': // head reports protocol error case 'C': // head reports connect error fck = write(hydra_heads[head_no]->sp[0], "Q", 1); if (debug) { printf("[ATTEMPT-ERROR] target %s - login \"%s\" - pass " "\"%s\" - child %d - %" hPRIu64 " of %" hPRIu64 "\n", hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr, head_no, hydra_targets[hydra_heads[head_no]->target_no]->sent, hydra_brains.todo); } hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); break; case 'Q': // head reports its quitting fck = write(hydra_heads[head_no]->sp[0], "Q", 1); if (debug) printf("[DEBUG] child %d reported it quit\n", head_no); hydra_kill_head(head_no, 1, 0); break; default: fprintf(stderr, "[ERROR] child %d sent nonsense data, killing and " "restarting it!\n", head_no); hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); } // end switch } // readres if (readres == -1) { if (verbose) fprintf(stderr, "[WARNING] child %d seems to have died, restarting " "(this only happens if a module is bad) ... \n", head_no); hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); } } // end do_switch } else { if (hydra_heads[head_no]->last_seen + hydra_options.waittime > tmp_time) { // check if recover of timed-out head is necessary if (tmp_time > waittime + hydra_heads[head_no]->last_seen) { if (kill(hydra_heads[head_no]->pid, 0) < 0) { if (verbose) fprintf(stderr, "[WARNING] child %d seems to be dead, restarting it " "...\n", head_no); hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); } } // if we do not get to hear anything for a longer time assume its // dead if (tmp_time > waittime * 2 + hydra_heads[head_no]->last_seen) { if (verbose) fprintf(stderr, "[WARNING] timeout from child %d, restarting\n", head_no); hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); } } } break; default: fprintf(stderr, "[ERROR] child %d in unknown state, restarting!\n", head_no); hydra_increase_fail_count(hydra_heads[head_no]->target_no, head_no); } } // if (debug) printf("DEBUG: bug hunt: %lu %lu\n", hydra_brains.todo_all, // hydra_brains.sent); usleepn(USLEEP_LOOP); (void)waitpid(-1, NULL, WNOHANG); // write restore file and report status if (process_restore == 1 && time(NULL) - elapsed_restore > 299) { hydra_restore_write(0); elapsed_restore = time(NULL); } if (time(NULL) - elapsed_status > status_print) { elapsed_status = time(NULL); tmp_time = elapsed_status - starttime; if (tmp_time < 1) tmp_time = 1; tmp_time = hydra_brains.sent / tmp_time; if (tmp_time < 1) tmp_time = 1; if (debug == 0) { if (status_print < 15 * 59) status_print = ((status_print + 1) * 2) - 1; if (status_print > 299 && ((hydra_brains.todo_all + total_redo_count) - hydra_brains.sent) / tmp_time < 1500) status_print = 299; if ((((hydra_brains.todo_all + total_redo_count) - hydra_brains.sent) / tmp_time) < 150) status_print = 59; } k = 0; for (j = 0; j < hydra_options.max_use; j++) if (hydra_heads[j]->active >= HEAD_UNUSED) k++; printf("[STATUS] %.2f tries/min, %" hPRIu64 " tries in %02" hPRIu64 ":%02" hPRIu64 "h, %" hPRIu64 " to do in %02" hPRIu64 ":%02" hPRIu64 "h, %d active\n", (1.0 * hydra_brains.sent) / (((elapsed_status - starttime) * 1.0) / 60), // tries/min hydra_brains.sent, // tries (uint64_t)((elapsed_status - starttime) / 3600), // hours (uint64_t)(((elapsed_status - starttime) % 3600) / 60), // minutes (hydra_brains.todo_all + total_redo_count) - hydra_brains.sent != 0 ? (hydra_brains.todo_all + total_redo_count) - hydra_brains.sent : 1, // left todo (uint64_t)(((double)(hydra_brains.todo_all + total_redo_count) - hydra_brains.sent) / ((double)hydra_brains.sent / (elapsed_status - starttime))) / 3600, // hours (((uint64_t)(((double)(hydra_brains.todo_all + total_redo_count) - hydra_brains.sent) / ((double)hydra_brains.sent / (elapsed_status - starttime))) % 3600) / 60) + 1, // min k); hydra_debug(0, "STATUS"); } exit_condition = hydra_check_for_exit_condition(); } process_restore = 0; if (debug) printf("[DEBUG] while loop left with %d\n", exit_condition); j = k = error = 0; for (i = 0; i < hydra_brains.targets; i++) switch (hydra_targets[i]->done) { case TARGET_UNRESOLVED: k++; break; case TARGET_ERROR: if (hydra_targets[i]->ok == 0) k++; else error++; break; case TARGET_FINISHED: break; case TARGET_ACTIVE: if (hydra_targets[i]->ok == 0) k++; else j++; break; default: error++; fprintf(stderr, "[ERROR] illegal target result value (%d=>%d)\n", i, hydra_targets[i]->done); } printf("%d of %d target%s%scompleted, %" hPRIu64 " valid password", hydra_brains.targets - j - k - error, hydra_brains.targets, hydra_brains.targets == 1 ? " " : "s ", hydra_brains.found > 0 ? "successfully " : "", hydra_brains.found); printf("%s", hydra_brains.found < 2 ? "" : "s"); printf(" found\n"); error += j; k = 0; for (i = 0; i < hydra_options.max_use; i++) if (hydra_heads[i]->active == HEAD_ACTIVE) k++; if (error == 0 && k == 0) { process_restore = 0; unlink(RESTOREFILE); } else { if (hydra_options.cidr == 0 && k == 0) { printf("[INFO] Writing restore file because %d server scan%s could not " "be completed\n", j + error, j + error == 1 ? "" : "s"); hydra_restore_write(1); } else if (k > 0) { printf("[WARNING] Writing restore file because %d final worker threads " "did not complete until end.\n", k); hydra_restore_write(1); } } if (debug) printf("[DEBUG] killing all remaining children now that might be stuck\n"); for (i = 0; i < hydra_options.max_use; i++) if (hydra_heads[i]->active == HEAD_ACTIVE && hydra_heads[i]->pid > 0) hydra_kill_head(i, 1, 3); (void)waitpid(-1, NULL, WNOHANG); #define STRMAX (10 * 1024) char json_error[STRMAX + 2], tmp_str[STRMAX + 2]; memset(json_error, 0, STRMAX + 2); memset(tmp_str, 0, STRMAX + 2); if (error) { snprintf(tmp_str, STRMAX, "[ERROR] %d target%s disabled because of too many errors", error, error == 1 ? " was" : "s were"); fprintf(stderr, "%s\n", tmp_str); strncat(json_error, "\"", STRMAX); strncat(json_error, tmp_str, STRMAX); strncat(json_error, "\"", STRMAX); error = 1; } if (k) { snprintf(tmp_str, STRMAX, "[ERROR] %d target%s did not resolve or could not be connected", k, k == 1 ? "" : "s"); fprintf(stderr, "%s\n", tmp_str); if (*json_error) { strncat(json_error, ", ", STRMAX); } strncat(json_error, "\"", STRMAX); strncat(json_error, tmp_str, STRMAX); strncat(json_error, "\"", STRMAX); error = 1; } if (error) { snprintf(tmp_str, STRMAX, "[ERROR] %d target%s did not complete", j, j < 1 ? "" : "s"); fprintf(stderr, "%s\n", tmp_str); if (*json_error) { strncat(json_error, ", ", STRMAX); } strncat(json_error, "\"", STRMAX); strncat(json_error, tmp_str, STRMAX); strncat(json_error, "\"", STRMAX); error = 1; hydra_restore_write(1); } // yeah we did it printf("%s (%s) finished at %s\n", PROGRAM, RESOURCE, hydra_build_time()); if (hydra_brains.ofp != NULL && hydra_brains.ofp != stdout) { if (hydra_options.outfile_format == FORMAT_JSONV1) { fprintf(hydra_brains.ofp, "\n\t],\n\"success\": %s,\n\"errormessages\": [ %s " "],\n\"quantityfound\": %" hPRIu64 " }\n", (error ? "false" : "true"), json_error, hydra_brains.found); } fclose(hydra_brains.ofp); } fflush(NULL); if (error || j != 0 || exit_condition < 0) return -1; else return 0; }