mirror of
https://github.com/vanhauser-thc/thc-hydra.git
synced 2025-03-12 04:36:23 -07:00
4307 lines
214 KiB
C
4307 lines
214 KiB
C
/*
|
|
* hydra (c) 2001-2017 by van Hauser / THC <vh@thc.org>
|
|
* http://www.thc.org
|
|
*
|
|
* Parallized network login hacker.
|
|
* Don't use in military or secret service organizations, or for illegal purposes.
|
|
*
|
|
* License: GNU AFFERO GENERAL PUBLIC LICENSE v3.0, see LICENSE file
|
|
*/
|
|
#include "hydra.h"
|
|
#include "bfg.h"
|
|
|
|
#ifdef LIBNCURSES
|
|
#include <curses.h>
|
|
#include <term.h>
|
|
#endif
|
|
|
|
extern void service_asterisk(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_telnet(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ftp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ftps(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_pop3(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_vmauthd(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_imap(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ldap2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ldap3(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ldap3_cram_md5(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_ldap3_digest_md5(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_adam6500(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_cisco(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_cisco_enable(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_vnc(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_socks5(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rexec(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rlogin(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rsh(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_nntp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_head(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_get(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_post(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_get_form(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_post_form(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_icq(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_pcnfs(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_mssql(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_cvs(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_snmp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_smtp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_smtp_enum(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_teamspeak(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_pcanywhere(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_proxy(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_xmpp(char *target, char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_irc(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_redis(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_http_proxy_urlenum(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_s7_300(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rpcap(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
|
|
// ADD NEW SERVICES HERE
|
|
|
|
|
|
#ifdef HAVE_MATH_H
|
|
extern void service_mysql(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_mysql_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBPOSTGRES
|
|
extern void service_postgres(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_postgres_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBOPENSSL
|
|
extern void service_smb(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_smb_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_oracle_listener(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_oracle_listener_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_oracle_sid(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_oracle_sid_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_sip(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_sip_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_rdp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rdp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBSAPR3
|
|
extern void service_sapr3(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_sapr3_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBFIREBIRD
|
|
extern void service_firebird(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_firebird_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBAFP
|
|
extern void service_afp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_afp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBNCP
|
|
extern void service_ncp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_ncp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBSSH
|
|
extern void service_ssh(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_ssh_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern void service_sshkey(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_sshkey_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBSVN
|
|
extern void service_svn(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_svn_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
#ifdef LIBORACLE
|
|
extern void service_oracle(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_oracle_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
#endif
|
|
|
|
extern int service_adam6500_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_cisco_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_cisco_enable_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_cvs_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_smtp_enum_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_http_form_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_ftp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_http_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_icq_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_imap_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_irc_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_ldap_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_mssql_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_nntp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_pcanywhere_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_pcnfs_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_pop3_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_http_proxy_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_asterisk_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_redis_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rexec_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rlogin_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rsh_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_smtp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_snmp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_socks5_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_teamspeak_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_telnet_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_http_proxy_urlenum_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_vmauthd_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_vnc_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_xmpp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_s7_300_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
extern int service_rpcap_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname);
|
|
|
|
// ADD NEW SERVICES HERE
|
|
|
|
|
|
// ADD NEW SERVICES HERE
|
|
char *SERVICES =
|
|
"adam6500 asterisk afp cisco cisco-enable cvs firebird ftp ftps 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] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rpcap rsh rtsp s7-300 sapr3 sip smb 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 "v8.5"
|
|
#define AUTHOR "van Hauser/THC"
|
|
#define EMAIL "<vh@thc.org>"
|
|
#define RESOURCE "http://www.thc.org/thc-hydra"
|
|
|
|
extern char *hydra_strcasestr(const char *haystack, const char *needle);
|
|
extern void hydra_tobase64(unsigned char *buf, int buflen, int bufsize);
|
|
extern char *hydra_string_replace(const char *string, const char *substr, const char *replacement);
|
|
extern char *hydra_address2string(char *address);
|
|
extern int colored_output;
|
|
extern char quiet;
|
|
extern int do_retry;
|
|
extern int old_ssl;
|
|
|
|
void hydra_kill_head(int head_no, int killit, int fail);
|
|
|
|
// some structure definitions
|
|
typedef struct {
|
|
pid_t pid;
|
|
int sp[2];
|
|
int target_no;
|
|
char *current_login_ptr;
|
|
char *current_pass_ptr;
|
|
char reverse[256];
|
|
int active;
|
|
int redo;
|
|
time_t last_seen;
|
|
} hydra_head;
|
|
|
|
typedef struct {
|
|
char *target;
|
|
char ip[36];
|
|
char *login_ptr;
|
|
char *pass_ptr;
|
|
unsigned long int login_no;
|
|
unsigned long int pass_no;
|
|
unsigned long int sent;
|
|
int pass_state;
|
|
int use_count;
|
|
int done; // 0 if active, 1 if finished scanning, 2 if error (for RESTOREFILE), 3 could not be resolved
|
|
int fail_count;
|
|
int redo_state;
|
|
int redo;
|
|
int ok;
|
|
int failed;
|
|
int skipcnt;
|
|
int port;
|
|
char *redo_login[MAXTASKS * 2 + 2];
|
|
char *redo_pass[MAXTASKS * 2 + 2];
|
|
char *skiplogin[SKIPLOGIN];
|
|
// char *bfg_ptr[MAXTASKS];
|
|
} hydra_target;
|
|
|
|
typedef struct {
|
|
int active; // active tasks of hydra_options.max_use
|
|
int targets;
|
|
int finished;
|
|
int exit;
|
|
unsigned long int todo_all;
|
|
unsigned long int todo;
|
|
unsigned long int sent;
|
|
unsigned long int found;
|
|
unsigned long int countlogin;
|
|
unsigned long int countpass;
|
|
size_t sizelogin;
|
|
size_t sizepass;
|
|
FILE *ofp;
|
|
} hydra_brain;
|
|
|
|
typedef struct {
|
|
int mode; // valid modes: 0 = -l -p, 1 = -l -P, 2 = -L -p, 3 = -L -P, 4 = -l -x, 6 = -L -x, +8 if -e r, +16 if -e n, +32 if -e s, 64 = -C | bit 128 undefined
|
|
int loop_mode; // valid modes: 0 = password, 1 = user
|
|
int ssl;
|
|
int restore;
|
|
int debug; // is external - for restore
|
|
int verbose; // is external - for restore
|
|
int showAttempt;
|
|
int tasks;
|
|
int try_null_password;
|
|
int try_password_same_as_login;
|
|
int try_password_reverse_login;
|
|
int exit_found;
|
|
int max_use;
|
|
int cidr;
|
|
int outfile_format; // 0 = plain text, 1 = JSONv1, [future --> ] 2 = JSONv2, 3=XMLv1, 4=...
|
|
char *login;
|
|
char *loginfile;
|
|
char *pass;
|
|
char *passfile;
|
|
char *outfile_ptr;
|
|
char *infile_ptr;
|
|
char *colonfile;
|
|
int waittime; // is external - for restore
|
|
int conwait; // is external - for restore
|
|
unsigned int port; // is external - for restore
|
|
char *miscptr;
|
|
char *server;
|
|
char *service;
|
|
char bfg;
|
|
} hydra_option;
|
|
|
|
typedef struct {
|
|
char *name;
|
|
int port;
|
|
int port_ssl;
|
|
} hydra_portlist;
|
|
|
|
// external vars
|
|
extern char HYDRA_EXIT[5];
|
|
|
|
#if !defined(ANDROID) && !defined(__BIONIC__)
|
|
extern int errno;
|
|
#endif
|
|
extern int debug;
|
|
extern int verbose;
|
|
extern int waittime;
|
|
extern int port;
|
|
extern int found;
|
|
extern int use_proxy;
|
|
extern int proxy_count;
|
|
extern int selected_proxy;
|
|
extern int 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;
|
|
int prefer_ipv6 = 0, conwait = 0, loop_cnt = 0, fck = 0, options = 0, killed = 0;
|
|
int child_head_no = -1, child_socket;
|
|
int total_redo_count = 0;
|
|
|
|
// moved for restore feature
|
|
int 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];
|
|
int snpdone, snp_is_redo, snpbuflen, snpi, snpj, snpdont;
|
|
|
|
#include "performance.h"
|
|
|
|
void help(int ext) {
|
|
printf("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
|
|
" [-ISOuvVd46] "
|
|
//"[server service [OPT]]|"
|
|
"[service://server[:PORT][/OPT]]\n");
|
|
printf("\nOptions:\n");
|
|
if (ext)
|
|
printf(" -R restore a previous aborted/crashed session\n");
|
|
if (ext)
|
|
printf(" -I ignore an existing restore file (dont wait 10 seconds)\n");
|
|
#ifdef LIBOPENSSL
|
|
if (ext)
|
|
printf(" -S perform an SSL connect\n");
|
|
#endif
|
|
if (ext)
|
|
printf(" -s PORT if the service is on a different default port, define it here\n");
|
|
printf(" -l LOGIN or -L FILE login with LOGIN name, or load several logins from FILE\n");
|
|
printf(" -p PASS or -P FILE try password PASS, or load several passwords from FILE\n");
|
|
#ifdef HAVE_MATH_H
|
|
if (ext) {
|
|
printf(" -x MIN:MAX:CHARSET password bruteforce generation, type \"-x -h\" to get help\n");
|
|
printf(" -y disable use of symbols in bruteforce, see above\n");
|
|
}
|
|
#endif
|
|
if (ext)
|
|
printf(" -e nsr try \"n\" null password, \"s\" login as pass and/or \"r\" reversed login\n");
|
|
if (ext)
|
|
printf(" -u loop around users, not passwords (effective! implied with -x)\n");
|
|
printf(" -C FILE colon separated \"login:pass\" format, instead of -L/-P options\n");
|
|
printf(" -M FILE list of servers to attack, one entry per line, ':' to specify port\n");
|
|
if (ext)
|
|
printf(" -o FILE write found login/password pairs to FILE instead of stdout\n");
|
|
if (ext)
|
|
printf(" -b FORMAT specify the format for the -o FILE: text(default), json, jsonv1\n");
|
|
if (ext)
|
|
printf(" -f / -F exit when a login/pass pair is found (-M: -f per host, -F global)\n");
|
|
printf(" -t TASKS run TASKS number of connects in parallel per target (default: %d)\n", TASKS);
|
|
if (ext)
|
|
printf(" -T TASKS run TASKS connects in parallel overall (for -M, default: %d)\n", MAXTASKS);
|
|
if (ext)
|
|
printf(" -w / -W TIME waittime for responses (%d) / between connects per thread (%d)\n", WAITTIME, conwait);
|
|
if (ext)
|
|
printf(" -4 / -6 use IPv4 (default) / IPv6 addresses (put always in [] also in -M)\n");
|
|
if (ext)
|
|
printf(" -v / -V / -d verbose mode / show login+pass for each attempt / debug mode \n");
|
|
if (ext)
|
|
printf(" -O use old SSL v2 and v3\n");
|
|
if (ext)
|
|
printf(" -q do not print messages about connection errors\n");
|
|
printf(" -U service module usage details\n");
|
|
if (ext == 0)
|
|
printf(" -h more command line options (COMPLETE HELP)\n");
|
|
printf(" server the target: DNS, IP or 192.168.0.0/24 (this OR the -M option)\n");
|
|
printf(" service the service to crack (see below for supported protocols)\n");
|
|
printf(" OPT some service modules support additional input (-U for module help)\n");
|
|
|
|
printf("\nSupported services: %s\n", SERVICES);
|
|
printf("\n%s is a tool to guess/crack valid login/password pairs. Licensed under AGPL\nv3.0. The newest version is always available at %s\n", PROGRAM, RESOURCE);
|
|
printf("Don't use in military or secret service organizations, or for illegal purposes.\n");
|
|
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);
|
|
}
|
|
if (ext) {
|
|
printf("\nUse HYDRA_PROXY_HTTP or HYDRA_PROXY environment variables for a proxy setup.\n");
|
|
printf("E.g. %% export HYDRA_PROXY=socks5://l:p@127.0.0.1:9150 (or: socks4:// connect://)\n");
|
|
printf(" %% export HYDRA_PROXY=connect_and_socks_proxylist.txt (up to 64 entries)\n");
|
|
printf(" %% export HYDRA_PROXY_HTTP=http://login:pass@proxy:8080\n");
|
|
printf(" %% export HYDRA_PROXY_HTTP=proxylist.txt (up to 64 entries)\n");
|
|
}
|
|
|
|
printf("\nExample%s:%s hydra -l user -P passlist.txt ftp://192.168.0.1\n", ext == 0 ? "" : "s", ext == 0 ? "" : "\n");
|
|
if (ext) {
|
|
printf(" hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN\n");
|
|
printf(" hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5\n");
|
|
printf(" hydra -l admin -p password ftp://[192.168.0.0/24]/\n");
|
|
printf(" 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 if the above letters as placeholders\n\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");
|
|
printf("\nThe bruteforce mode was made by Jan Dlabal, http://houbysoft.com/bfg/\n");
|
|
exit(-1);
|
|
}
|
|
|
|
void module_usage() {
|
|
int find = 0;
|
|
|
|
if (hydra_options.service) {
|
|
printf("\nHelp for module %s:\n============================================================================\n", hydra_options.service);
|
|
if ((strcmp(hydra_options.service, "oracle") == 0) || (strcmp(hydra_options.service, "ora") == 0)) {
|
|
printf("Module oracle / ora is optionally taking the ORACLE SID, default is \"ORCL\"\n\n");
|
|
find = 1;
|
|
}
|
|
if ((strcmp(hydra_options.service, "oracle-listener") == 0) || (strcmp(hydra_options.service, "tns") == 0)) {
|
|
printf("Module oracle-listener / tns is optionally taking the mode the password is stored as, could be PLAIN (default) or CLEAR\n\n");
|
|
find = 1;
|
|
}
|
|
if (strcmp(hydra_options.service, "cvs") == 0) {
|
|
printf("Module cvs is optionally taking the repository name to attack, default is \"/root\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (strcmp(hydra_options.service, "xmpp") == 0) {
|
|
printf("Module xmpp is optionally taking one authentication type of:\n"
|
|
" LOGIN (default), PLAIN, CRAM-MD5, DIGEST-MD5, SCRAM-SHA1\n\n"
|
|
"Note, the target passed should be a fdqn as the value is used in the Jabber init request, example: hermes.jabber.org\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "pop3") == 0)) {
|
|
printf("Module pop3 is optionally taking one authentication type of:\n"
|
|
" CLEAR (default), LOGIN, PLAIN, CRAM-MD5, CRAM-SHA1,\n"
|
|
" CRAM-SHA256, DIGEST-MD5, NTLM.\n" "Additionally TLS encryption via STLS can be enforced with the TLS option.\n\n" "Example: pop3://target/TLS:PLAIN\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "rdp") == 0)) {
|
|
printf("Module rdp is optionally taking the windows domain name.\n" "For example:\nhydra rdp://192.168.0.1/firstdomainname -l john -p doe\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "s7-300") == 0)) {
|
|
printf("Module S7-300 is for a special Siemens PLC. It either requires only a password or no authentication, so just use the -p or -P option.\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "nntp") == 0)) {
|
|
printf("Module nntp is optionally taking one authentication type of:\n" " USER (default), LOGIN, PLAIN, CRAM-MD5, DIGEST-MD5, NTLM\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "imap") == 0)) {
|
|
printf("Module imap is optionally taking one authentication type of:\n"
|
|
" CLEAR or APOP (default), LOGIN, PLAIN, CRAM-MD5, CRAM-SHA1,\n"
|
|
" CRAM-SHA256, DIGEST-MD5, NTLM\n" "Additionally TLS encryption via STARTTLS can be enforced with the TLS option.\n\n" "Example: imap://target/TLS:PLAIN\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "smtp-enum")) == 0) {
|
|
printf("Module smtp-enum is optionally taking one SMTP command of:\n\n"
|
|
"VRFY (default), EXPN, RCPT (which will connect using \"root\" account)\n"
|
|
"login parameter is used as username and password parameter as the domain name\n"
|
|
"For example to test if john@localhost exists on 192.168.0.1:\n" "hydra smtp-enum://192.168.0.1/vrfy -l john -p localhost\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "smtp")) == 0) {
|
|
printf("Module smtp is optionally taking one authentication type of:\n"
|
|
" LOGIN (default), PLAIN, CRAM-MD5, DIGEST-MD5, NTLM\n\n"
|
|
"Additionally TLS encryption via STARTTLS can be enforced with the TLS option.\n\n" "Example: smtp://target/TLS:PLAIN\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "svn") == 0)) {
|
|
printf("Module svn is optionally taking the repository name to attack, default is \"trunk\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "ncp") == 0)) {
|
|
printf("Module ncp is optionally taking the full context, for example \".O=cx\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "firebird") == 0)) {
|
|
printf("Module firebird is optionally taking the database path to attack,\n" "default is \"C:\\Program Files\\Firebird\\Firebird_1_5\\security.fdb\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "mysql") == 0)) {
|
|
printf("Module mysql is optionally taking the database to attack, default is \"mysql\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "irc") == 0)) {
|
|
printf("Module irc is optionally taking the general server password, if the server is requiring one\n" "and none is passed the password from -p/-P will be used\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "postgres") == 0)) {
|
|
printf("Module postgres is optionally taking the database to attack, default is \"template1\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "telnet") == 0)) {
|
|
printf("Module telnet is optionally taking the string which is displayed after\n"
|
|
"a successful login (case insensitive), use if the default in the telnet\n" "module produces too many false positives\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "sapr3") == 0)) {
|
|
printf("Module sapr3 requires the client id, a number between 0 and 99\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "sshkey") == 0)) {
|
|
printf("Module sshkey does not provide additional options, although the semantic for\n"
|
|
"options -p and -P is changed:\n"
|
|
" -p expects a path to an unencrypted private key in PEM format.\n"
|
|
" -P expects a filename containing a list of path to some unencrypted\n" " private keys in PEM format.\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "cisco-enable") == 0)) {
|
|
printf("Module cisco-enable is optionally taking the logon password for the cisco device\n"
|
|
"Note: if AAA authentication is used, use the -l option for the username\n"
|
|
"and the optional parameter for the password of the user.\n"
|
|
"Examples:\n"
|
|
" hydra -P pass.txt target cisco-enable (direct console access)\n"
|
|
" hydra -P pass.txt -m cisco target cisco-enable (Logon password cisco)\n"
|
|
" hydra -l foo -m bar -P pass.txt target cisco-enable (AAA Login foo, password bar)\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "cisco") == 0)) {
|
|
printf("Module cisco is optionally taking the keyword ENTER, it then sends an initial\n" "ENTER when connecting to the service.\n");
|
|
find = 1;
|
|
}
|
|
if (!find && ((strcmp(hydra_options.service, "ldap2") == 0)
|
|
|| (strcmp(hydra_options.service, "ldap3") == 0)
|
|
|| (strcmp(hydra_options.service, "ldap3-crammd5") == 0)
|
|
|| (strcmp(hydra_options.service, "ldap3-digestmd5") == 0))
|
|
) {
|
|
printf("Module %s is optionally taking the DN (depending of the auth method choosed\n"
|
|
"Note: you can also specify the DN as login when Simple auth method is used).\n"
|
|
"The keyword \"^USER^\" is replaced with the login.\n"
|
|
"Special notes for Simple method has 3 operation modes: anonymous, (no user no pass),\n"
|
|
"unauthenticated (user but no pass), user/pass authenticated (user and pass).\n"
|
|
"So don't forget to set empty string as user/pass to test all modes.\n"
|
|
"Hint: to authenticate to a windows active directy ldap, this is usually\n"
|
|
" cn=^USER^,cn=users,dc=foo,dc=bar,dc=com for domain foo.bar.com\n\n", hydra_options.service);
|
|
find = 1;
|
|
}
|
|
if (!find && ((strcmp(hydra_options.service, "smb") == 0) || (strcmp(hydra_options.service, "smbnt") == 0))) {
|
|
printf("Module smb default value is set to test both local and domain account, using a simple password with NTLM dialect.\n"
|
|
"Note: you can set the group type using LOCAL or DOMAIN keyword\n"
|
|
" or other_domain:{value} to specify a trusted domain.\n"
|
|
" you can set the password type using HASH or MACHINE keyword\n"
|
|
" (to use the Machine's NetBIOS name as the password).\n"
|
|
" you can set the dialect using NTLMV2, NTLM, LMV2, LM keyword.\n"
|
|
"Example: \n"
|
|
" hydra smb://microsoft.com -l admin -p tooeasy -m \"local lmv2\"\n"
|
|
" hydra smb://microsoft.com -l admin -p D5731CFC6C2A069C21FD0D49CAEBC9EA:2126EE7712D37E265FD63F2C84D2B13D::: -m \"local hash\"\n"
|
|
" hydra smb://microsoft.com -l admin -p tooeasy -m \"other_domain:SECONDDOMAIN\"\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && ((strcmp(hydra_options.service, "http-get-form") == 0)
|
|
|| (strcmp(hydra_options.service, "https-get-form") == 0)
|
|
|| (strcmp(hydra_options.service, "http-post-form") == 0)
|
|
|| (strcmp(hydra_options.service, "https-post-form") == 0)
|
|
|| (strncmp(hydra_options.service, "http-form", 9) == 0)
|
|
|| (strncmp(hydra_options.service, "https-form", 10) == 0)
|
|
)
|
|
) {
|
|
printf("Module %s requires the page and the parameters for the web form.\n\n"
|
|
"By default this module is configured to follow a maximum of 5 redirections in\n"
|
|
"a row. It always gathers a new cookie from the same URL without variables\n"
|
|
"The parameters take three \":\" separated values, plus optional values.\n"
|
|
"(Note: if you need a colon in the option string as value, escape it with \"\\:\", but do not escape a \"\\\" with \"\\\\\".)\n"
|
|
"\nSyntax: <url>:<form parameters>:<condition string>[:<optional>[:<optional>]\n"
|
|
"First is the page on the server to GET or POST to (URL).\n"
|
|
"Second is the POST/GET variables (taken from either the browser, proxy, etc.\n"
|
|
" with usernames and passwords being replaced in the \"^USER^\" and \"^PASS^\"\n"
|
|
" placeholders (FORM PARAMETERS)\n"
|
|
"Third is the string that it checks for an *invalid* login (by default)\n"
|
|
" Invalid condition login check can be preceded by \"F=\", successful condition\n"
|
|
" login check must be preceded by \"S=\".\n"
|
|
" This is where most people get it wrong. You have to check the webapp what a\n"
|
|
" failed string looks like and put it in this parameter!\n"
|
|
"The following parameters are optional:\n"
|
|
" C=/page/uri to define a different page to gather initial cookies from\n"
|
|
" (h|H)=My-Hdr\\: foo to send a user defined HTTP header with each request\n"
|
|
" ^USER^ and ^PASS^ can also be put into these headers!\n"
|
|
" Note: 'h' will add the user-defined header at the end\n"
|
|
" regardless it's already being sent by Hydra or not.\n"
|
|
" 'H' will replace the value of that header if it exists, by the\n"
|
|
" one supplied by the user, or add the header at the end\n"
|
|
"Note that if you are going to put colons (:) in your headers you should escape them with a backslash (\\).\n"
|
|
" All colons that are not option separators should be escaped (see the examples above and below).\n"
|
|
" You can specify a header without escaping the colons, but that way you will not be able to put colons\n"
|
|
" in the header value itself, as they will be interpreted by hydra as option separators.\n"
|
|
"\nExamples:\n"
|
|
" \"/login.php:user=^USER^&pass=^PASS^:incorrect\"\n"
|
|
" \"/login.php:user=^USER^&pass=^PASS^&colon=colon\\:escape:S=authlog=.*success\"\n"
|
|
" \"/login.php:user=^USER^&pass=^PASS^&mid=123:authlog=.*failed\"\n"
|
|
" \"/:user=^USER&pass=^PASS^:failed:H=Authorization\\: Basic dT1w:H=Cookie\\: sessid=aaaa:h=X-User\\: ^USER^:H=User-Agent\\: wget\"\n"
|
|
" \"/exchweb/bin/auth/owaauth.dll:destination=http%%3A%%2F%%2F<target>%%2Fexchange&flags=0&username=<domain>%%5C^USER^&password=^PASS^&SubmitCreds=x&trusted=0:reason=:C=/exchweb\"\n",
|
|
hydra_options.service);
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "http-proxy") == 0)) {
|
|
printf("Module http-proxy is optionally taking the page to authenticate at.\n"
|
|
"Default is http://www.microsoft.com/)\n" "Basic, DIGEST-MD5 and NTLM are supported and negotiated automatically.\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strcmp(hydra_options.service, "http-proxy-urlenum") == 0)) {
|
|
printf("Module http-proxy-urlenum only uses the -L option, not -x or -p/-P option.\n"
|
|
"The -L loginfile must contain the URL list to try through the proxy.\n"
|
|
"The proxy credentials cann be put as the optional parameter, e.g.\n"
|
|
" hydra -L urllist.txt -s 3128 target.com http-proxy-urlenum user:pass\n" " hydra -L urllist.txt http-proxy-urlenum://target.com:3128/user:pass\n\n");
|
|
find = 1;
|
|
}
|
|
if (!find && (strncmp(hydra_options.service, "snmp", 4) == 0)) {
|
|
printf("Module snmp is optionally taking the following parameters:\n");
|
|
printf(" READ perform read requests (default)\n");
|
|
printf(" WRITE perform write requests\n");
|
|
printf(" 1 use SNMP version 1 (default)\n");
|
|
printf(" 2 use SNMP version 2\n");
|
|
printf(" 3 use SNMP version 3\n");
|
|
printf(" Note that SNMP version 3 usually uses both login and passwords!\n");
|
|
printf(" SNMP version 3 has the following optional sub parameters:\n");
|
|
printf(" MD5 use MD5 authentication (default)\n");
|
|
printf(" SHA use SHA authentication\n");
|
|
printf(" DES use DES encryption\n");
|
|
printf(" AES use AES encryption\n");
|
|
printf(" if no -p/-P parameter is given, SNMPv3 noauth is performed, which\n");
|
|
printf(" only requires a password (or username) not both.\n");
|
|
printf("To combine the options, use colons (\":\"), e.g.:\n");
|
|
printf(" hydra -L user.txt -P pass.txt -m 3:SHA:AES:READ target.com snmp\n");
|
|
printf(" hydra -P pass.txt -m 2 target.com snmp\n");
|
|
find = 1;
|
|
}
|
|
if (!find && ((strcmp(hydra_options.service, "http-get") == 0)
|
|
|| (strcmp(hydra_options.service, "https-get") == 0)
|
|
|| (strcmp(hydra_options.service, "http-post") == 0)
|
|
|| (strcmp(hydra_options.service, "https-post") == 0))
|
|
) {
|
|
printf("Module %s requires the page to authenticate.\n"
|
|
"For example: \"/secret\" or \"http://bla.com/foo/bar\" or \"https://test.com:8080/members\"\n\n", hydra_options.service);
|
|
find = 1;
|
|
}
|
|
}
|
|
if (!find) // this is also printed if the module does not exist at all
|
|
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(int force, char *string) {
|
|
int active = 0, inactive = 0, i;
|
|
|
|
if (!debug && !force)
|
|
return;
|
|
|
|
printf("[DEBUG] Code: %s Time: %lu\n", string, (unsigned long int) 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 %lu todo %lu sent %lu found %lu countlogin %lu sizelogin %lu countpass %lu sizepass %lu\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,
|
|
(unsigned long int) hydra_brains.countlogin,
|
|
(unsigned long int) hydra_brains.sizelogin,
|
|
(unsigned long int) hydra_brains.countpass,
|
|
(unsigned long int) 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 %lu pass_no %lu sent %lu 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(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 >= 0) {
|
|
printf("[DEBUG] Task %d - pid %d active %d redo %d current_login_ptr %s current_pass_ptr %s\n",
|
|
i, (int) 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 == 0)
|
|
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(int print_msg) {
|
|
FILE *f;
|
|
hydra_brain brain;
|
|
char mynull[4] = { 0, 0, 0, 0 }, buf[4];
|
|
int 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 != 1 && hydra_targets[j]->done != 3)
|
|
j++;
|
|
if (j == 0) {
|
|
process_restore = 0;
|
|
return;
|
|
}
|
|
|
|
if ((f = fopen(RESTOREFILE, "w")) == NULL) {
|
|
fprintf(stderr, "[ERROR] Can not create restore file (%s) - \n", 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(int) % 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, 1, f);
|
|
if (hydra_options.colonfile == NULL || hydra_options.colonfile == empty_login)
|
|
fck = fwrite(pass_ptr, hydra_brains.sizepass, 1, f);
|
|
for (j = 0; j < hydra_brains.targets; j++)
|
|
if (hydra_targets[j]->done != 1) {
|
|
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, (int) (hydra_targets[j]->login_ptr - login_ptr),
|
|
(int) (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];
|
|
int i, j, orig_debug = debug;
|
|
char out[1024];
|
|
|
|
if (debug)
|
|
printf("[DEBUG] 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 = (int) 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[2], VERSION);
|
|
if (buf[2] != sizeof(int) % 256 || buf[3] != sizeof(hydra_head*) % 256) {
|
|
fprintf(stderr, "[ERROR] restore file was created on a different, incompatible processor platform!\n");
|
|
exit(-1);
|
|
}
|
|
|
|
fck = (int) fread(&bf_options, sizeof(bf_options), 1, f);
|
|
fck = (int) 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 = (int) fread(&hydra_brains, sizeof(hydra_brain), 1, f);
|
|
hydra_brains.ofp = stdout;
|
|
fck = (int) 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);
|
|
fck = (int) fread(login_ptr, hydra_brains.sizelogin, 1, f);
|
|
if (debug)
|
|
printf("[DEBUG] reading restore file: Step 9 complete\n");
|
|
if ((hydra_options.mode & 64) != 64) { // NOT colonfile mode
|
|
pass_ptr = malloc(hydra_brains.sizepass);
|
|
fck = (int) fread(pass_ptr, hydra_brains.sizepass, 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 = malloc((hydra_brains.targets + 3) * sizeof(hydra_targets));
|
|
for (j = 0; j < hydra_brains.targets; j++) {
|
|
hydra_targets[j] = malloc(sizeof(hydra_target));
|
|
fck = (int) 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);
|
|
for (j = 0; j < hydra_options.max_use; j++) {
|
|
hydra_heads[j] = malloc(sizeof(hydra_head));
|
|
fck = (int) 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(int signo) {
|
|
int pid, i;
|
|
|
|
killed++;
|
|
pid = wait3(NULL, WNOHANG, NULL);
|
|
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(int signo) {
|
|
if (debug)
|
|
printf("[DEBUG] children crashed! (%d)\n", child_head_no);
|
|
fck = write(child_socket, "E", 1);
|
|
_exit(-1);
|
|
}
|
|
|
|
void kill_children(int signo) {
|
|
int 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);
|
|
}
|
|
|
|
unsigned long int countlines(FILE * fd, int colonmode) {
|
|
size_t clines = 0;
|
|
char *buf = malloc(MAXLINESIZE);
|
|
int 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, int colonmode) {
|
|
char tmp[MAXBUF + 4] = "", *ptr2;
|
|
unsigned int len;
|
|
int only_one_empty_line = 0;
|
|
#ifdef HAVE_ZLIB
|
|
gzFile fp = gzdopen(fileno(fd), "r");
|
|
|
|
while (!gzeof(fp)) {
|
|
if (gzgets(fp, tmp, MAXLINESIZE) != NULL) {
|
|
#else
|
|
FILE *fp = fd;
|
|
|
|
while (!feof(fp)) {
|
|
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 = index(tmp, ':')) == NULL) {
|
|
fprintf(stderr, "[ERROR] invalid line in colon file (-C), missing colon in line: %s\n", tmp);
|
|
exit(-1);
|
|
} else {
|
|
// if (tmp[0] == ':') {
|
|
// *ptr = 0;
|
|
// ptr++;
|
|
// }
|
|
// if (tmp[len - 1] == ':' && len > 1) {
|
|
// len++;
|
|
// tmp[len - 1] = 0;
|
|
// }
|
|
*ptr2 = 0;
|
|
}
|
|
}
|
|
memcpy(ptr, tmp, len);
|
|
ptr += len;
|
|
*ptr = '\0';
|
|
ptr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#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(int target_no) {
|
|
int x = 99;
|
|
|
|
#ifdef LIBAFP
|
|
if (strcmp(hydra_options.service, "afp") == 0)
|
|
x = service_afp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "asterisk") == 0)
|
|
x = service_asterisk_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "cisco-enable") == 0)
|
|
x = service_cisco_enable_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "cvs") == 0)
|
|
x = service_cvs_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "adam6500") == 0)
|
|
x = service_adam6500_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "cisco") == 0)
|
|
x = service_cisco_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBFIREBIRD
|
|
if (strcmp(hydra_options.service, "firebird") == 0)
|
|
x = service_firebird_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "ftp") == 0 || strcmp(hydra_options.service, "ftps") == 0)
|
|
x = service_ftp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "redis") == 0 || strcmp(hydra_options.service, "redis") == 0)
|
|
x = service_redis_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "http-get") == 0 || strcmp(hydra_options.service, "http-head") == 0)
|
|
x = service_http_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "http-form") == 0 || strcmp(hydra_options.service, "http-get-form") == 0 || strcmp(hydra_options.service, "http-post-form") == 0)
|
|
x = service_http_form_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "http-proxy") == 0)
|
|
x = service_http_proxy_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "http-proxy-urlenum") == 0)
|
|
x = service_http_proxy_urlenum_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "icq") == 0)
|
|
x = service_icq_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "imap") == 0)
|
|
x = service_imap_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "irc") == 0)
|
|
x = service_irc_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strncmp(hydra_options.service, "ldap", 4) == 0)
|
|
x = service_ldap_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBOPENSSL
|
|
if (strcmp(hydra_options.service, "sip") == 0)
|
|
x = service_sip_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "smb") == 0 || strcmp(hydra_options.service, "smbnt") == 0)
|
|
x = service_smb_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "oracle-listener") == 0)
|
|
x = service_oracle_listener_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "oracle-sid") == 0)
|
|
x = service_oracle_sid_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "rdp") == 0)
|
|
x = service_rdp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "mssql") == 0)
|
|
x = service_mssql_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef HAVE_MATH_H
|
|
if (strcmp(hydra_options.service, "mysql") == 0)
|
|
x = service_mysql_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
#ifdef LIBNCP
|
|
if (strcmp(hydra_options.service, "ncp") == 0)
|
|
x = service_ncp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "nntp") == 0)
|
|
x = service_nntp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBORACLE
|
|
if (strcmp(hydra_options.service, "oracle") == 0)
|
|
x = service_oracle_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "pcanywhere") == 0)
|
|
x = service_pcanywhere_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "pcnfs") == 0)
|
|
x = service_pcnfs_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "pop3") == 0)
|
|
x = service_pop3_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBPOSTGRES
|
|
if (strcmp(hydra_options.service, "postgres") == 0)
|
|
x = service_postgres_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "rexec") == 0)
|
|
x = service_rexec_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "rlogin") == 0)
|
|
x = service_rlogin_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "rsh") == 0)
|
|
x = service_rsh_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBSAPR3
|
|
if (strcmp(hydra_options.service, "sapr3") == 0)
|
|
x = service_sapr3_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "smtp") == 0)
|
|
x = service_smtp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "smtp-enum") == 0)
|
|
x = service_smtp_enum_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "snmp") == 0)
|
|
x = service_snmp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "socks5") == 0)
|
|
x = service_socks5_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#ifdef LIBSSH
|
|
// dirty workaround here:
|
|
if (strcmp(hydra_options.service, "ssh") == 0)
|
|
x = service_ssh_init(hydra_targets[target_no]->ip, -1, options, login_ptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "sshkey") == 0)
|
|
x = service_sshkey_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
#ifdef LIBSVN
|
|
if (strcmp(hydra_options.service, "svn") == 0)
|
|
x = service_svn_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "teamspeak") == 0)
|
|
x = service_teamspeak_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "telnet") == 0)
|
|
x = service_telnet_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "vmauthd") == 0)
|
|
x = service_vmauthd_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "vnc") == 0)
|
|
x = service_vnc_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "xmpp") == 0)
|
|
x = service_xmpp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "s7-300") == 0)
|
|
x = service_s7_300_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "rtsp") == 0)
|
|
x = service_rtsp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
if (strcmp(hydra_options.service, "rpcap") == 0)
|
|
x = service_rpcap_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target);
|
|
// ADD NEW SERVICES HERE
|
|
|
|
|
|
if (x != 0 && x != 99) {
|
|
if (x > 0 && x < 4)
|
|
hydra_targets[target_no]->done = x;
|
|
else
|
|
hydra_targets[target_no]->done = 2;
|
|
hydra_brains.finished++;
|
|
if (hydra_brains.targets == 1)
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
|
|
int hydra_spawn_head(int head_no, int target_no) {
|
|
int 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 < 0) {
|
|
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());
|
|
|
|
// now call crack module
|
|
if (strcmp(hydra_options.service, "asterisk") == 0)
|
|
service_asterisk(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);
|
|
if (strcmp(hydra_options.service, "telnet") == 0)
|
|
service_telnet(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);
|
|
if (strcmp(hydra_options.service, "ftp") == 0) {
|
|
|
|
service_ftp(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);
|
|
|
|
}
|
|
if (strcmp(hydra_options.service, "ftps") == 0)
|
|
service_ftps(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);
|
|
if (strcmp(hydra_options.service, "redis") == 0)
|
|
service_redis(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);
|
|
if (strcmp(hydra_options.service, "pop3") == 0)
|
|
service_pop3(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);
|
|
if (strcmp(hydra_options.service, "imap") == 0)
|
|
service_imap(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);
|
|
if (strcmp(hydra_options.service, "vmauthd") == 0)
|
|
service_vmauthd(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);
|
|
if (strcmp(hydra_options.service, "ldap2") == 0)
|
|
service_ldap2(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);
|
|
if (strcmp(hydra_options.service, "ldap3") == 0)
|
|
service_ldap3(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);
|
|
if (strcmp(hydra_options.service, "http-head") == 0)
|
|
service_http_head(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);
|
|
if (strcmp(hydra_options.service, "ldap3-crammd5") == 0)
|
|
service_ldap3_cram_md5(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);
|
|
if (strcmp(hydra_options.service, "ldap3-digestmd5") == 0)
|
|
service_ldap3_digest_md5(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);
|
|
if (strcmp(hydra_options.service, "http-post") == 0)
|
|
service_http_post(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);
|
|
if (strcmp(hydra_options.service, "http-get") == 0)
|
|
service_http_get(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);
|
|
if (strcmp(hydra_options.service, "http-get-form") == 0)
|
|
service_http_get_form(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);
|
|
if (strcmp(hydra_options.service, "http-post-form") == 0)
|
|
service_http_post_form(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);
|
|
if (strcmp(hydra_options.service, "http-proxy") == 0)
|
|
service_http_proxy(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);
|
|
if (strcmp(hydra_options.service, "http-proxy-urlenum") == 0)
|
|
service_http_proxy_urlenum(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);
|
|
if (strcmp(hydra_options.service, "adam6500") == 0)
|
|
service_adam6500(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);
|
|
if (strcmp(hydra_options.service, "cisco") == 0)
|
|
service_cisco(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);
|
|
if (strcmp(hydra_options.service, "cisco-enable") == 0)
|
|
service_cisco_enable(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);
|
|
if (strcmp(hydra_options.service, "socks5") == 0)
|
|
service_socks5(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);
|
|
if (strcmp(hydra_options.service, "vnc") == 0)
|
|
service_vnc(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);
|
|
if (strcmp(hydra_options.service, "rexec") == 0)
|
|
service_rexec(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);
|
|
if (strcmp(hydra_options.service, "rlogin") == 0)
|
|
service_rlogin(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);
|
|
if (strcmp(hydra_options.service, "rsh") == 0)
|
|
service_rsh(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);
|
|
if (strcmp(hydra_options.service, "nntp") == 0)
|
|
service_nntp(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);
|
|
if (strcmp(hydra_options.service, "icq") == 0)
|
|
service_icq(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);
|
|
if (strcmp(hydra_options.service, "pcnfs") == 0)
|
|
service_pcnfs(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);
|
|
#ifdef HAVE_MATH_H
|
|
if (strcmp(hydra_options.service, "mysql") == 0)
|
|
service_mysql(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);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "mssql") == 0)
|
|
service_mssql(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);
|
|
#ifdef LIBOPENSSL
|
|
if (strcmp(hydra_options.service, "oracle-listener") == 0)
|
|
service_oracle_listener(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);
|
|
if (strcmp(hydra_options.service, "oracle-sid") == 0)
|
|
service_oracle_sid(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);
|
|
#endif
|
|
#ifdef LIBORACLE
|
|
if (strcmp(hydra_options.service, "oracle") == 0)
|
|
service_oracle(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);
|
|
#endif
|
|
#ifdef LIBPOSTGRES
|
|
if (strcmp(hydra_options.service, "postgres") == 0)
|
|
service_postgres(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);
|
|
#endif
|
|
#ifdef LIBFIREBIRD
|
|
if (strcmp(hydra_options.service, "firebird") == 0)
|
|
service_firebird(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);
|
|
#endif
|
|
#ifdef LIBAFP
|
|
if (strcmp(hydra_options.service, "afp") == 0)
|
|
service_afp(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);
|
|
#endif
|
|
#ifdef LIBNCP
|
|
if (strcmp(hydra_options.service, "ncp") == 0)
|
|
service_ncp(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);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "pcanywhere") == 0)
|
|
service_pcanywhere(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);
|
|
if (strcmp(hydra_options.service, "cvs") == 0)
|
|
service_cvs(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);
|
|
#ifdef LIBSVN
|
|
if (strcmp(hydra_options.service, "svn") == 0)
|
|
service_svn(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);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "snmp") == 0)
|
|
service_snmp(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);
|
|
#ifdef LIBOPENSSL
|
|
if ((strcmp(hydra_options.service, "smb") == 0) || (strcmp(hydra_options.service, "smbnt") == 0))
|
|
service_smb(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);
|
|
#endif
|
|
#ifdef LIBSAPR3
|
|
if (strcmp(hydra_options.service, "sapr3") == 0)
|
|
service_sapr3(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);
|
|
#endif
|
|
#ifdef LIBSSH
|
|
if (strcmp(hydra_options.service, "ssh") == 0)
|
|
service_ssh(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);
|
|
if (strcmp(hydra_options.service, "sshkey") == 0)
|
|
service_sshkey(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);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "smtp") == 0)
|
|
service_smtp(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);
|
|
if (strcmp(hydra_options.service, "smtp-enum") == 0)
|
|
service_smtp_enum(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);
|
|
if (strcmp(hydra_options.service, "teamspeak") == 0)
|
|
service_teamspeak(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);
|
|
#ifdef LIBOPENSSL
|
|
if (strcmp(hydra_options.service, "sip") == 0)
|
|
service_sip(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);
|
|
#endif
|
|
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);
|
|
if (strcmp(hydra_options.service, "irc") == 0)
|
|
service_irc(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);
|
|
#ifdef LIBOPENSSL
|
|
if (strcmp(hydra_options.service, "rdp") == 0)
|
|
service_rdp(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);
|
|
#endif
|
|
if (strcmp(hydra_options.service, "s7-300") == 0)
|
|
service_s7_300(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);
|
|
if (strcmp(hydra_options.service, "rtsp") == 0)
|
|
service_rtsp(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);
|
|
if (strcmp(hydra_options.service, "rpcap") == 0)
|
|
service_rpcap(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);
|
|
// ADD NEW SERVICES HERE
|
|
|
|
|
|
// 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 = 1;
|
|
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 = 0;
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
perror("[ERROR] socketpair creation failed");
|
|
hydra_heads[head_no]->sp[0] = -1;
|
|
hydra_heads[head_no]->active = 0;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int hydra_lookup_port(char *service) {
|
|
int 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},
|
|
{"mssql", PORT_MSSQL, PORT_MSSQL_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},
|
|
{"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},
|
|
// 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(int head_no, int killit, int 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 > 0 || (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 > 0) {
|
|
hydra_heads[head_no]->active = 0;
|
|
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 = -1;
|
|
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 = -1;
|
|
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) wait3(NULL, WNOHANG, NULL);
|
|
}
|
|
|
|
void hydra_increase_fail_count(int target_no, int head_no) {
|
|
int i, k;
|
|
|
|
if (target_no < 0)
|
|
return;
|
|
|
|
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 + (hydra_options.tasks <= 4 && hydra_targets[target_no]->ok ? 6 - hydra_options.tasks : 1) + (hydra_options.tasks - hydra_targets[target_no]->failed < 5
|
|
&& hydra_targets[target_no]->ok ? 6 - (hydra_options.tasks -
|
|
hydra_targets
|
|
[target_no]->failed) : 1)
|
|
+ (hydra_targets[target_no]->ok ? 2 : -2));
|
|
if (hydra_targets[target_no]->fail_count >=
|
|
MAXFAIL + (hydra_options.tasks <= 4 && hydra_targets[target_no]->ok ? 6 - hydra_options.tasks : 1) + (hydra_options.tasks - hydra_targets[target_no]->failed < 5
|
|
&& hydra_targets[target_no]->ok ? 6 - (hydra_options.tasks -
|
|
hydra_targets
|
|
[target_no]->failed) : 1) +
|
|
(hydra_targets[target_no]->ok ? 2 : -2)
|
|
) {
|
|
k = 0;
|
|
for (i = 0; i < hydra_options.max_use; i++)
|
|
if (hydra_heads[i]->active >= 0 && 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 == 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 == 0 && hydra_options.max_use == hydra_targets[target_no]->failed) {
|
|
if (hydra_targets[target_no]->ok == 1)
|
|
hydra_targets[target_no]->done = 2; // mark target as done by errors
|
|
else
|
|
hydra_targets[target_no]->done = 3; // 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
|
|
&& index(hydra_targets[target_no]->target, ':') != NULL ? "[" : "", hydra_targets[target_no]->target, hydra_targets[target_no]->ip[0] == 16
|
|
&& index(hydra_targets[target_no]->target, ':') != NULL ? "]" : "", hydra_targets[target_no]->port);
|
|
}
|
|
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 == 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(int head_no, char *login) {
|
|
int 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;
|
|
}
|
|
|
|
int hydra_send_next_pair(int target_no, int head_no) {
|
|
// variables moved to save stack
|
|
snpdone = 0;
|
|
snp_is_redo = 0;
|
|
snpdont = 0;
|
|
loop_cnt++;
|
|
if (hydra_heads[head_no]->redo && 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 == 0) {
|
|
hydra_targets[target_no]->done = 1;
|
|
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 %lu/%lu, passcnt %lu/%lu, 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 %lu, todo %lu)\n", loop_cnt, hydra_targets[target_no]->sent, hydra_brains.todo);
|
|
return -1;
|
|
}
|
|
|
|
if (hydra_heads[head_no]->redo && 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 - %lu of %lu\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 == 0) {
|
|
hydra_targets[target_no]->done = 1;
|
|
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) {
|
|
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 ((hydra_options.mode & 64) == 64) { // 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 ((hydra_options.mode & 4) == 4)
|
|
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 ((hydra_options.mode & 4) == 4)
|
|
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 ((hydra_options.mode & 4) == 4)
|
|
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 ((hydra_options.mode & 4) == 4) { // bfg mode
|
|
#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 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++;
|
|
}
|
|
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 == 0) {
|
|
hydra_targets[target_no]->done = 1;
|
|
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 ((hydra_options.mode & 64) != 64 && 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\" - %lu of %lu [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(int target_no, char *username) {
|
|
int 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 && (hydra_options.mode & 64) != 64) {
|
|
if (memcmp(username, hydra_targets[target_no]->login_ptr, strlen(username)) == 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
int hydra_check_for_exit_condition() {
|
|
int 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 >= 0)
|
|
k = 1;
|
|
if (k == 0) {
|
|
fprintf(stderr, "[ERROR] all children were disabled due too many connection errors\n");
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int hydra_select_target() {
|
|
int 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 == 0)
|
|
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(int type, char *string) {
|
|
char *type_string = string, *target_string, *port_string, *auth_string = NULL, *device_string = NULL, *sep;
|
|
int 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 = index(target_string, '@')) != NULL) {
|
|
auth_string = target_string;
|
|
*sep = 0;
|
|
target_string = sep + 1;
|
|
if (index(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 = index(target_string, ':')) != NULL) {
|
|
*sep = 0;
|
|
port_string = sep + 1;
|
|
if ((sep = index(port_string, '%')) != NULL) {
|
|
*sep = 0;
|
|
device_string = sep + 1;
|
|
}
|
|
if ((sep = index(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, *cmdtarget = NULL;
|
|
char *outfile_format_tmp;
|
|
FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL, *proxyfp;
|
|
size_t countinfile = 1, sizeinfile = 0;
|
|
unsigned long int math2;
|
|
int i = 0, j = 0, k, error = 0, modusage = 0, ignore_restore = 0;
|
|
int 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;
|
|
char rc, buf[MAXBUF];
|
|
fd_set fdreadheads;
|
|
int max_fd;
|
|
struct addrinfo hints, *res, *p;
|
|
struct sockaddr_in6 *ipv6 = NULL;
|
|
struct sockaddr_in *ipv4 = NULL;
|
|
|
|
printf("%s %s (c) 2017 by %s - Please do not use in military or secret service organizations, or for illegal purposes.\n\n", PROGRAM, VERSION, AUTHOR);
|
|
#ifndef LIBPOSTGRES
|
|
SERVICES = hydra_string_replace(SERVICES, "postgres ", "");
|
|
strcat(unsupported, "postgres ");
|
|
#endif
|
|
#ifndef LIBSAPR3
|
|
SERVICES = hydra_string_replace(SERVICES, "sapr3 ", "");
|
|
strcat(unsupported, "sapr3 ");
|
|
#endif
|
|
#ifndef LIBFIREBIRD
|
|
SERVICES = hydra_string_replace(SERVICES, "firebird ", "");
|
|
strcat(unsupported, "firebird ");
|
|
#endif
|
|
#ifndef LIBAFP
|
|
SERVICES = hydra_string_replace(SERVICES, "afp ", "");
|
|
strcat(unsupported, "afp ");
|
|
#endif
|
|
#ifndef LIBNCP
|
|
SERVICES = hydra_string_replace(SERVICES, "ncp ", "");
|
|
strcat(unsupported, "ncp ");
|
|
#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
|
|
#ifndef LIBORACLE
|
|
SERVICES = hydra_string_replace(SERVICES, "oracle ", "");
|
|
strcat(unsupported, "oracle ");
|
|
#endif
|
|
#ifndef LIBMYSQLCLIENT
|
|
SERVICES = hydra_string_replace(SERVICES, "mysql ", "mysql(v4) ");
|
|
strcat(unsupported, "mysql5 ");
|
|
#endif
|
|
#ifndef LIBOPENSSL
|
|
// for ftps
|
|
SERVICES = hydra_string_replace(SERVICES, " ftps", "");
|
|
// 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 rdp
|
|
SERVICES = hydra_string_replace(SERVICES, " rdp", "");
|
|
// 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.tasks = TASKS;
|
|
hydra_options.max_use = MAXTASKS;
|
|
hydra_options.outfile_format = 0;
|
|
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, "hIq64Rde:vVl:fFg:L:p:OP:o:b:M:C:t:T:m:w:W:s:SUux:y")) >= 0) {
|
|
switch (i) {
|
|
case 'h':
|
|
help(1);
|
|
break;
|
|
case 'q':
|
|
quiet = 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;
|
|
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 | 8;
|
|
break;
|
|
case 'n':
|
|
hydra_options.try_null_password = 1;
|
|
hydra_options.mode = hydra_options.mode | 16;
|
|
break;
|
|
case 's':
|
|
hydra_options.try_password_same_as_login = 1;
|
|
hydra_options.mode = hydra_options.mode | 32;
|
|
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 | 2;
|
|
break;
|
|
case 'p':
|
|
hydra_options.pass = optarg;
|
|
break;
|
|
case 'P':
|
|
hydra_options.passfile = optarg;
|
|
hydra_options.mode = hydra_options.mode | 1;
|
|
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 (0==strcasecmp(outfile_format_tmp,"text"))
|
|
hydra_options.outfile_format = 0;
|
|
else if (0==strcasecmp(outfile_format_tmp,"json")) // latest json formatting.
|
|
hydra_options.outfile_format = 1;
|
|
else if (0==strcasecmp(outfile_format_tmp,"jsonv1"))
|
|
hydra_options.outfile_format = 1;
|
|
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 = 64;
|
|
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 '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 | 4;
|
|
hydra_options.loop_mode = 1;
|
|
break;
|
|
#endif
|
|
case 'y':
|
|
bf_options.disable_symbols = 1;
|
|
break;
|
|
default:
|
|
exit(-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;
|
|
}
|
|
}
|
|
#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] Ouput color flag is %d\n", colored_output);
|
|
|
|
if (hydra_options.restore && argc > 2 + debug + verbose)
|
|
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.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 != 0 && 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 <service-name>://<target>[:<port-number>][/<parameters>] or it's a syntax error
|
|
char *targetdef = strdup(argv[optind]);
|
|
char *service_pos, *target_pos, *port_pos = NULL, *param_pos = NULL;
|
|
cmdtarget = 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 = index(target_pos, ']')) == NULL)
|
|
bail("no closing ']' found in target definition");
|
|
*param_pos++ = 0;
|
|
if (*param_pos == ':')
|
|
port_pos = ++param_pos;
|
|
if ((param_pos = index(param_pos, '/')) != NULL)
|
|
*param_pos++ = 0;
|
|
} else {
|
|
port_pos = index(target_pos, ':');
|
|
param_pos = index(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 && index(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) {
|
|
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, "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, "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 && (index(hydra_options.login, '\\') != NULL || index(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, "rdp") == 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, "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 <port>, 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[1024], *url, *variables, *cond, *optional1;
|
|
|
|
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.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, "%.1000s", 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)) {
|
|
fprintf(stderr, "[ERROR] the variables argument needs at least the strings ^USER^ or ^PASS^: %s\n", 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 currently reported to be unreliable, most likely against new Windows version. Please test, report - and if possible, fix.\n");
|
|
i = 1;
|
|
}
|
|
// 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.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, "gmail.") != NULL || hydra_strcasestr(hydra_options.server, "googlemail.") != NULL))
|
|
fprintf(stderr, "[WARNING] Google Mail has bruteforce detection and sends false positives. You are not doing anything illegal right?!\n");
|
|
|
|
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);
|
|
}
|
|
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 %lu 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 %lu bytes.\n", MAX_BYTES, (unsigned long int) 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);
|
|
}
|
|
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 %lu 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 %lu bytes.\n", MAX_BYTES, (unsigned long int) 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);
|
|
}
|
|
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 %lu 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 %lu bytes.\n", MAX_BYTES / 2, (unsigned long int) 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...", 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, (int) 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, (int) 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 = index(tmpptr, ']')) != NULL) {
|
|
*tmpptr2++ = 0;
|
|
tmpptr = tmpptr2;
|
|
}
|
|
} else
|
|
hydra_targets[i]->target = tmpptr;
|
|
if ((tmpptr2 = index(hydra_targets[i]->target, ':')) != 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;
|
|
while (*tmpptr != 0)
|
|
tmpptr++;
|
|
tmpptr++;
|
|
}
|
|
} else if (index(hydra_options.server, '/') != NULL) {
|
|
if (cmdtarget == 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(cmdtarget, "://") != NULL) {
|
|
tmpptr = index(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;
|
|
sizeservers = strlen(hydra_options.server) + 1;
|
|
} else {
|
|
/* CIDR notation on command line, e.g. 192.168.0.0/24 */
|
|
unsigned int 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 = index(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 = 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;
|
|
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;
|
|
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 %lu\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;
|
|
if (hydra_options.colonfile != NULL)
|
|
printf("[DATA] max %d task%s per %d server%s, overall %d tasks, %lu login tr%s, ~%lu tr%s per task\n", hydra_options.tasks, hydra_options.tasks == 1 ? "" : "s",
|
|
hydra_brains.targets, hydra_brains.targets == 1 ? "" : "s", hydra_options.max_use, hydra_brains.todo, hydra_brains.todo == 1 ? "y" : "ies", math2,
|
|
math2 == 1 ? "y" : "ies");
|
|
else
|
|
printf("[DATA] max %d task%s per %d server%s, overall %d tasks, %lu login tr%s (l:%lu/p:%lu), ~%lu tr%s per task\n", hydra_options.tasks, hydra_options.tasks == 1 ? "" : "s",
|
|
hydra_brains.targets, hydra_brains.targets == 1 ? "" : "s", hydra_options.max_use, hydra_brains.todo, hydra_brains.todo == 1 ? "y" : "ies",
|
|
(unsigned long int) hydra_brains.countlogin, (unsigned long int) hydra_brains.countpass, math2, math2 == 1 ? "y" : "ies");
|
|
|
|
printf("[DATA] attacking 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) {
|
|
if ((hydra_brains.ofp = fopen(hydra_options.outfile_ptr, "a+")) == NULL) {
|
|
perror("[ERROR] Error creating outputfile");
|
|
exit(-1);
|
|
}
|
|
if (hydra_options.outfile_format == 1) { // JSONv1
|
|
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;
|
|
if ((device = index(hydra_targets[i]->target, '%')) != NULL)
|
|
*device++ = 0;
|
|
#endif
|
|
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 = 3;
|
|
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 = 3;
|
|
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 = 3;
|
|
hydra_brains.finished++;
|
|
}
|
|
freeaddrinfo(res);
|
|
}
|
|
}
|
|
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 > 0) {
|
|
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 != -1)
|
|
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 -1:
|
|
// disabled head, ignored
|
|
break;
|
|
case 0:
|
|
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 1:
|
|
if (FD_ISSET(hydra_heads[head_no]->sp[0], &fdreadheads)) {
|
|
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 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);
|
|
}
|
|
if (hydra_options.outfile_format == 1 /* 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 == 0) {
|
|
hydra_targets[hydra_heads[head_no]->target_no]->done = 1; // 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 == 0) {
|
|
hydra_targets[j]->done = 1;
|
|
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;
|
|
|
|
// 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 - %lu of %lu\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);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
} 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) wait3(NULL, WNOHANG, NULL);
|
|
// 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 >= 0)
|
|
k++;
|
|
/* I think we don't need this anymore
|
|
if ((hydra_brains.todo_all + total_redo_count) < hydra_brains.sent) { //in case of overflow of unsigned "-1"
|
|
for (i = 0; i < hydra_options.max_use; i++)
|
|
if (hydra_heads[i]->active > 0 && hydra_heads[i]->pid > 0)
|
|
hydra_kill_head(i, 1, 3);
|
|
printf("[BUG] %lu + %d < %lu\n", hydra_brains.todo_all, total_redo_count, hydra_brains.sent);
|
|
bail("[BUG] Weird bug detected where more tests were performed than possible. Please rerun with -d command line switch and post all output plus command line here: https://github.com/vanhauser-thc/thc-hydra/issues/113 or send it in an email to vh@thc.org");
|
|
}
|
|
*/
|
|
printf("[STATUS] %.2f tries/min, %lu tries in %02lu:%02luh, %lu to do in %02lu:%02luh, %d active\n", (1.0 * hydra_brains.sent) / (((elapsed_status - starttime) * 1.0) / 60), // tries/min
|
|
hydra_brains.sent, // tries
|
|
(long unsigned int) ((elapsed_status - starttime) / 3600), // hours
|
|
(long unsigned int) (((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
|
|
(long unsigned int) (((double) (hydra_brains.todo_all + total_redo_count) - hydra_brains.sent) / ((double) hydra_brains.sent / (elapsed_status - starttime))
|
|
) / 3600, // hours
|
|
(((long unsigned int) (((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 3:
|
|
k++;
|
|
break;
|
|
case 2:
|
|
if (hydra_targets[i]->ok == 0)
|
|
k++;
|
|
else
|
|
error++;
|
|
break;
|
|
case 1:
|
|
break;
|
|
case 0:
|
|
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);
|
|
}
|
|
|
|
if (debug)
|
|
printf("[DEBUG] killing all remaining childs now that might be stuck\n");
|
|
for (i = 0; i < hydra_options.max_use; i++)
|
|
if (hydra_heads[i]->active > 0 && hydra_heads[i]->pid > 0)
|
|
hydra_kill_head(i, 1, 3);
|
|
(void) wait3(NULL, WNOHANG, NULL);
|
|
|
|
printf("%d of %d target%s%scompleted, %lu valid password%s found\n", hydra_brains.targets - j - k - error, hydra_brains.targets, hydra_brains.targets == 1 ? " " : "s ",
|
|
hydra_brains.found > 0 ? "successfully " : "", hydra_brains.found, hydra_brains.found == 1 ? "" : "s");
|
|
if (error == 0 && j == 0) {
|
|
process_restore = 0;
|
|
unlink(RESTOREFILE);
|
|
} else {
|
|
if (hydra_options.cidr == 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);
|
|
}
|
|
}
|
|
#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 (*json_error) {
|
|
strncat(json_error,", ", STRMAX);
|
|
}
|
|
error = 1;
|
|
}
|
|
if (j) {
|
|
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;
|
|
}
|
|
// 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 == 1 /* JSONv1 */ ) {
|
|
fprintf(hydra_brains.ofp, "\n\t],\n\"success\": %s,\n\"errormessages\": [ %s ],\n\"quantityfound\": %lu }\n",
|
|
(error ? "false" : "true"), json_error, hydra_brains.found);
|
|
}
|
|
fclose(hydra_brains.ofp);
|
|
}
|
|
|
|
fflush(NULL);
|
|
if (error || j || exit_condition < 0)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|