From 0d6efda1d2e48bac7df2aac9b0668528ad7e3d4f Mon Sep 17 00:00:00 2001 From: Diadlo Date: Thu, 1 Jun 2017 23:56:06 +0300 Subject: [PATCH 1/7] Add swap function --- hydra.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hydra.c b/hydra.c index f54554b..51e5b95 100644 --- a/hydra.c +++ b/hydra.c @@ -1771,6 +1771,14 @@ void hydra_increase_fail_count(int target_no, int head_no) { } } +void swap_chars(char* a, char* b) +{ + unsigned char keep; + keep = *a; + *a = *b; + *b = keep; +} + char *hydra_reverse_login(int head_no, char *login) { int i, j; char *start, *pos; @@ -1793,25 +1801,17 @@ char *hydra_reverse_login(int head_no, char *login) { 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; + swap(pos, pos - 3); + swap(pos - 1, pos - 2); pos -= 3; break; case 0xE: /* U+000800-U+00FFFF: three bytes. */ - keep = *pos; - *pos = *(pos-2); - *(pos-2) = keep; + swap(pos, pos - 2); pos -= 2; break; case 0xC: /* fall-through */ case 0xD: /* U+000080-U+0007FF: two bytes. */ - keep = *pos; - *pos = *(pos-1); - *(pos-1) = keep; + swap(pos, pos - 1); pos--; break; } From 07d55e94afa8c4c54a002f04de07c0b8f5af70c6 Mon Sep 17 00:00:00 2001 From: Diadlo Date: Fri, 2 Jun 2017 00:13:46 +0300 Subject: [PATCH 2/7] Add target_state_t enum --- hydra.c | 63 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/hydra.c b/hydra.c index f54554b..6fbca31 100644 --- a/hydra.c +++ b/hydra.c @@ -200,6 +200,13 @@ typedef struct { time_t last_seen; } hydra_head; +typedef enum { + STATE_ACTIVE = 0, + STATE_FINISHED = 1, + STATE_ERROR = 2, + STATE_UNRESOLVED = 3 +} target_state_t; + typedef struct { char *target; char ip[36]; @@ -210,7 +217,7 @@ typedef struct { 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 + target_state_t done; int fail_count; int redo_state; int redo; @@ -734,7 +741,7 @@ void hydra_restore_write(int print_msg) { return; for (i = 0; i < hydra_brains.targets; i++) - if (hydra_targets[j]->done != 1 && hydra_targets[j]->done != 3) + if (hydra_targets[j]->done != STATE_FINISHED && hydra_targets[j]->done != STATE_UNRESOLVED) j++; if (j == 0) { process_restore = 0; @@ -776,7 +783,7 @@ void hydra_restore_write(int print_msg) { 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) { + if (hydra_targets[j]->done != STATE_FINISHED) { fck = fwrite(hydra_targets[j], sizeof(hydra_target), 1, f); fprintf(f, "%s\n%d\n%d\n", hydra_targets[j]->target == NULL ? "" : hydra_targets[j]->target, (int) (hydra_targets[j]->login_ptr - login_ptr), (int) (hydra_targets[j]->pass_ptr - pass_ptr)); @@ -1315,7 +1322,7 @@ void hydra_service_init(int target_no) { if (x > 0 && x < 4) hydra_targets[target_no]->done = x; else - hydra_targets[target_no]->done = 2; + hydra_targets[target_no]->done = STATE_ERROR; hydra_brains.finished++; if (hydra_brains.targets == 1) exit(-1); @@ -1705,7 +1712,7 @@ void hydra_increase_fail_count(int target_no, int head_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 + if (hydra_targets[target_no]->done == STATE_ACTIVE && 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))) { @@ -1720,11 +1727,11 @@ void hydra_increase_fail_count(int target_no, int head_no) { 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]->done == STATE_ACTIVE && 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 + hydra_targets[target_no]->done = STATE_ERROR; // mark target as done by errors else - hydra_targets[target_no]->done = 3; // mark target as done by unable to connect + hydra_targets[target_no]->done = STATE_UNRESOLVED; // mark target as done by unable to connect hydra_brains.finished++; fprintf(stderr, "[ERROR] Too many connect errors to target, disabling %s://%s%s%s:%d\n", hydra_options.service, hydra_targets[target_no]->ip[0] == 16 && index(hydra_targets[target_no]->target, ':') != NULL ? "[" : "", hydra_targets[target_no]->target, hydra_targets[target_no]->ip[0] == 16 @@ -1737,7 +1744,7 @@ void hydra_increase_fail_count(int target_no, int head_no) { } // 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 + if (hydra_targets[target_no]->done == STATE_ACTIVE && 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))) { @@ -1832,8 +1839,8 @@ int hydra_send_next_pair(int target_no, int head_no) { 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; + if (hydra_targets[target_no]->done == STATE_ACTIVE) { + hydra_targets[target_no]->done = STATE_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to complete tests)\n", hydra_targets[target_no]->target); @@ -1873,8 +1880,8 @@ int hydra_send_next_pair(int target_no, int head_no) { 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; + if (hydra_targets[target_no]->done == STATE_ACTIVE) { + hydra_targets[target_no]->done = STATE_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to complete tests)\n", hydra_targets[target_no]->target); @@ -1883,7 +1890,7 @@ int hydra_send_next_pair(int target_no, int head_no) { return -1; } } else { // normale state, no redo - if (hydra_targets[target_no]->done) { + if (hydra_targets[target_no]->done != STATE_ACTIVE) { loop_cnt = 0; return -1; // head will be disabled by main while() } @@ -2099,8 +2106,8 @@ int hydra_send_next_pair(int target_no, int head_no) { 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; + if (hydra_targets[target_no]->done == STATE_ACTIVE) { + hydra_targets[target_no]->done = STATE_FINISHED; hydra_brains.finished++; if (verbose) printf("[STATUS] attack finished for %s (waiting for children to complete tests)\n", hydra_targets[target_no]->target); @@ -2250,7 +2257,7 @@ 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 (hydra_targets[i]->use_count < hydra_options.tasks && hydra_targets[i]->done == STATE_ACTIVE) if (j < hydra_options.tasks - hydra_targets[i]->failed - hydra_targets[i]->use_count) { target_no = i; j = hydra_options.tasks - hydra_targets[i]->failed - hydra_targets[i]->use_count; @@ -3840,7 +3847,7 @@ int main(int argc, char *argv[]) { 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_targets[i]->done = STATE_UNRESOLVED; hydra_brains.finished++; } } else { @@ -3862,7 +3869,7 @@ int main(int argc, char *argv[]) { 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_targets[i]->done = STATE_UNRESOLVED; hydra_brains.finished++; } else { hydra_targets[i]->ip[0] = 16; @@ -3887,7 +3894,7 @@ int main(int argc, char *argv[]) { 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_targets[i]->done = STATE_UNRESOLVED; hydra_brains.finished++; } freeaddrinfo(res); @@ -4064,15 +4071,15 @@ int main(int argc, char *argv[]) { 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 + if (hydra_targets[hydra_heads[head_no]->target_no]->done == STATE_ACTIVE) { + hydra_targets[hydra_heads[head_no]->target_no]->done = STATE_FINISHED; // mark target as done hydra_brains.finished++; printf("[STATUS] attack finished for %s (valid pair found)\n", hydra_targets[hydra_heads[head_no]->target_no]->target); } if (hydra_options.exit_found == 2) { for (j = 0; j < hydra_brains.targets; j++) - if (hydra_targets[j]->done == 0) { - hydra_targets[j]->done = 1; + if (hydra_targets[j]->done == STATE_ACTIVE) { + hydra_targets[j]->done = STATE_FINISHED; hydra_brains.finished++; } } @@ -4210,18 +4217,18 @@ int main(int argc, char *argv[]) { j = k = error = 0; for (i = 0; i < hydra_brains.targets; i++) switch (hydra_targets[i]->done) { - case 3: + case STATE_UNRESOLVED: k++; break; - case 2: + case STATE_ERROR: if (hydra_targets[i]->ok == 0) k++; else error++; break; - case 1: + case STATE_FINISHED: break; - case 0: + case STATE_ACTIVE: if (hydra_targets[i]->ok == 0) k++; else From cdb9123e2869fed896a5fdfad99da604f764bf0b Mon Sep 17 00:00:00 2001 From: Diadlo Date: Fri, 2 Jun 2017 09:50:42 +0300 Subject: [PATCH 3/7] Add hydra_mode_t enum --- hydra.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/hydra.c b/hydra.c index 6fbca31..bb84f2d 100644 --- a/hydra.c +++ b/hydra.c @@ -247,8 +247,18 @@ typedef struct { FILE *ofp; } hydra_brain; +typedef enum { + MODE_PASSWORD_LIST = 1, + MODE_LOGIN_LIST = 2, + MODE_PASSWORD_BRUTE = 4, + MODE_PASSWORD_REVERSE = 8, + MODE_PASSWORD_NULL = 16, + MODE_PASSWORD_SAME = 32, + MODE_COLON_FILE = 64 +} hydra_mode_t; + 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 + hydra_mode_t mode; int loop_mode; // valid modes: 0 = password, 1 = user int ssl; int restore; @@ -330,6 +340,10 @@ int snpdone, snp_is_redo, snpbuflen, snpi, snpj, snpdont; #include "performance.h" +int inline check_flag(int value, int flag) { + return (value & flag) == flag; +} + 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 @@ -934,7 +948,7 @@ void hydra_restore_read() { 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 + if (!check_flag(hydra_options.mode, MODE_COLON_FILE)) { // NOT colonfile mode pass_ptr = malloc(hydra_brains.sizepass); fck = (int) fread(pass_ptr, hydra_brains.sizepass, 1, f); } else { // colonfile mode @@ -1939,7 +1953,7 @@ int hydra_send_next_pair(int target_no, int head_no) { } // 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 + if (check_flag(hydra_options.mode, MODE_COLON_FILE)) { // colon mode hydra_heads[head_no]->current_login_ptr = hydra_targets[target_no]->login_ptr; hydra_heads[head_no]->current_pass_ptr = hydra_targets[target_no]->pass_ptr; hydra_targets[target_no]->login_no++; @@ -2008,17 +2022,17 @@ int hydra_send_next_pair(int target_no, int head_no) { 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) + if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(hydra_heads[head_no]->current_login_ptr); else hydra_heads[head_no]->current_pass_ptr = hydra_heads[head_no]->current_login_ptr; } else if (hydra_targets[target_no]->pass_state == 1) { - if ((hydra_options.mode & 4) == 4) + if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(empty_login); else hydra_heads[head_no]->current_pass_ptr = empty_login; } else if (hydra_targets[target_no]->pass_state == 2) { - if ((hydra_options.mode & 4) == 4) + if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) hydra_heads[head_no]->current_pass_ptr = strdup(hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr)); else hydra_heads[head_no]->current_pass_ptr = hydra_reverse_login(head_no, hydra_heads[head_no]->current_login_ptr); @@ -2048,7 +2062,7 @@ int hydra_send_next_pair(int target_no, int head_no) { if (snpdont) { hydra_targets[target_no]->pass_ptr = pass_ptr; } else { - if ((hydra_options.mode & 4) == 4) { // bfg mode + if (check_flag(hydra_options.mode, MODE_PASSWORD_BRUTE)) { #ifndef HAVE_MATH_H sleep(1); #else @@ -2129,7 +2143,7 @@ int hydra_send_next_pair(int target_no, int head_no) { 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) + if (!check_flag(hydra_options.mode, MODE_COLON_FILE) && hydra_options.loop_mode == 0 && hydra_targets[target_no]->pass_no > 0) { // -l -P (not! -u) // increase login_ptr to next hydra_targets[target_no]->login_no++; if (hydra_targets[target_no]->login_no < hydra_brains.countlogin) { @@ -2204,7 +2218,7 @@ void hydra_skip_user(int target_no, char *username) { 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 (hydra_options.loop_mode == 0 && !check_flag(hydra_options.mode, MODE_COLON_FILE)) { if (memcmp(username, hydra_targets[target_no]->login_ptr, strlen(username)) == 0) { if (debug) printf("[DEBUG] skipping username %s\n", username); @@ -2554,15 +2568,15 @@ int main(int argc, char *argv[]) { switch (optarg[i]) { case 'r': hydra_options.try_password_reverse_login = 1; - hydra_options.mode = hydra_options.mode | 8; + hydra_options.mode = hydra_options.mode | MODE_PASSWORD_REVERSE; break; case 'n': hydra_options.try_null_password = 1; - hydra_options.mode = hydra_options.mode | 16; + hydra_options.mode = hydra_options.mode | MODE_PASSWORD_NULL; break; case 's': hydra_options.try_password_same_as_login = 1; - hydra_options.mode = hydra_options.mode | 32; + hydra_options.mode = hydra_options.mode | MODE_PASSWORD_SAME; break; default: fprintf(stderr, "[ERROR] unknown mode %c for option -e, only supporting \"n\", \"s\" and \"r\"\n", optarg[i]); @@ -2582,14 +2596,14 @@ int main(int argc, char *argv[]) { break; case 'L': hydra_options.loginfile = optarg; - hydra_options.mode = hydra_options.mode | 2; + hydra_options.mode = hydra_options.mode | MODE_LOGIN_LIST; break; case 'p': hydra_options.pass = optarg; break; case 'P': hydra_options.passfile = optarg; - hydra_options.mode = hydra_options.mode | 1; + hydra_options.mode = hydra_options.mode | MODE_PASSWORD_LIST; break; case 'f': hydra_options.exit_found = 1; @@ -2620,7 +2634,7 @@ int main(int argc, char *argv[]) { break; case 'C': hydra_options.colonfile = optarg; - hydra_options.mode = 64; + hydra_options.mode = MODE_COLON_FILE; break; case 'm': hydra_options.miscptr = optarg; @@ -2666,7 +2680,7 @@ int main(int argc, char *argv[]) { help_bfg(); bf_options.arg = optarg; hydra_options.bfg = 1; - hydra_options.mode = hydra_options.mode | 4; + hydra_options.mode = hydra_options.mode | MODE_PASSWORD_BRUTE; hydra_options.loop_mode = 1; break; #endif From 985f9c43b0991760a69990f01796fcfa3c80135a Mon Sep 17 00:00:00 2001 From: Diadlo Date: Fri, 2 Jun 2017 10:21:15 +0300 Subject: [PATCH 4/7] Add output_format_t enum --- hydra.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hydra.c b/hydra.c index bb84f2d..e1b5d07 100644 --- a/hydra.c +++ b/hydra.c @@ -257,6 +257,13 @@ typedef enum { MODE_COLON_FILE = 64 } hydra_mode_t; +typedef enum { + FORMAT_PLAIN_TEXT, + FORMAT_JSONV1, + FORMAT_JSONV2, + FORMAT_XMLV1 +} output_format_t; + typedef struct { hydra_mode_t mode; int loop_mode; // valid modes: 0 = password, 1 = user @@ -272,7 +279,7 @@ typedef struct { int exit_found; int max_use; int cidr; - int outfile_format; // 0 = plain text, 1 = JSONv1, [future --> ] 2 = JSONv2, 3=XMLv1, 4=... + output_format_t outfile_format; char *login; char *loginfile; char *pass; @@ -2521,7 +2528,7 @@ int main(int argc, char *argv[]) { hydra_options.passfile = NULL; hydra_options.tasks = TASKS; hydra_options.max_use = MAXTASKS; - hydra_options.outfile_format = 0; + hydra_options.outfile_format = FORMAT_PLAIN_TEXT; hydra_brains.ofp = stdout; hydra_brains.targets = 1; hydra_options.waittime = waittime = WAITTIME; @@ -2618,11 +2625,11 @@ int main(int argc, char *argv[]) { case 'b': outfile_format_tmp = optarg; if (0==strcasecmp(outfile_format_tmp,"text")) - hydra_options.outfile_format = 0; + hydra_options.outfile_format = FORMAT_PLAIN_TEXT; else if (0==strcasecmp(outfile_format_tmp,"json")) // latest json formatting. - hydra_options.outfile_format = 1; + hydra_options.outfile_format = FORMAT_JSONV1; else if (0==strcasecmp(outfile_format_tmp,"jsonv1")) - hydra_options.outfile_format = 1; + hydra_options.outfile_format = FORMAT_JSONV1; else { fprintf(stderr, "[ERROR] Output file format must be (text, json, jsonv1)\n"); exit(-1); @@ -2726,7 +2733,7 @@ int main(int argc, char *argv[]) { 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) + if (hydra_options.outfile_format != FORMAT_PLAIN_TEXT && hydra_options.outfile_ptr == NULL) fprintf(stderr, "[WARNING] output file format specified (-b) - but no output file (-o)\n"); if (hydra_options.restore) { @@ -3805,7 +3812,7 @@ int main(int argc, char *argv[]) { perror("[ERROR] Error creating outputfile"); exit(-1); } - if (hydra_options.outfile_format == 1) { // JSONv1 + if (hydra_options.outfile_format == FORMAT_JSONV1) { fprintf(hydra_brains.ofp, "{ \"generator\": {\n" "\t\"software\": \"%s\", \"version\": \"%s\", \"built\": \"%s\",\n" "\t\"server\": \"%s\", \"service\": \"%s\", \"jsonoutputversion\": \"1.00\",\n" @@ -4058,7 +4065,7 @@ int main(int argc, char *argv[]) { 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) { + if (hydra_options.outfile_format == FORMAT_JSONV1 && hydra_options.outfile_ptr != NULL && hydra_brains.ofp != NULL) { fprintf(hydra_brains.ofp, "%s\n\t{\"port\": %d, \"service\": \"%s\", \"host\": \"%s\", \"login\": \"%s\", \"password\": \"%s\"}", hydra_brains.found == 1 ? "" : ",", // prefix a comma if not first finding hydra_targets[hydra_heads[head_no]->target_no]->port, @@ -4312,7 +4319,7 @@ int main(int argc, char *argv[]) { // 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 */ ) { + if (hydra_options.outfile_format == FORMAT_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); } From 0519661f9514c3b711cfe3087430cb94fb3a9066 Mon Sep 17 00:00:00 2001 From: Diadlo Date: Fri, 2 Jun 2017 10:58:10 +0300 Subject: [PATCH 5/7] Add using macros to align help text --- hydra.c | 149 ++++++++++++++++++++++++++------------------------------ 1 file changed, 70 insertions(+), 79 deletions(-) diff --git a/hydra.c b/hydra.c index f54554b..a4cee40 100644 --- a/hydra.c +++ b/hydra.c @@ -323,88 +323,78 @@ 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"); +#define PRINT_NORMAL(ext, text, ...) printf(text, ##__VA_ARGS__) +#define PRINT_EXTEND(ext, text, ...) do { \ + if (ext) \ + printf(text, ##__VA_ARGS__); \ + } while(0) + +void help(int ext) { + PRINT_NORMAL(ext, "Syntax: hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e nsr]" + " [-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-W TIME] [-f] [-s PORT]" +#ifdef HAVE_MATH_H + " [-x MIN:MAX:CHARSET]" +#endif + " [-ISOuvVd46] " + //"[server service [OPT]]|" + "[service://server[:PORT][/OPT]]\n"); + PRINT_NORMAL(ext, "\nOptions:\n"); + PRINT_EXTEND(ext, " -R restore a previous aborted/crashed session\n" + " -I ignore an existing restore file (dont wait 10 seconds)\n" +#ifdef LIBOPENSSL + " -S perform an SSL connect\n" +#endif + " -s PORT if the service is on a different default port, define it here\n"); + PRINT_NORMAL(ext, " -l LOGIN or -L FILE login with LOGIN name, or load several logins from FILE\n" + " -p PASS or -P FILE try password PASS, or load several passwords from FILE\n"); + PRINT_EXTEND(ext, +#ifdef HAVE_MATH_H + " -x MIN:MAX:CHARSET password bruteforce generation, type \"-x -h\" to get help\n" + " -y disable use of symbols in bruteforce, see above\n" +#endif + " -e nsr try \"n\" null password, \"s\" login as pass and/or \"r\" reversed login\n" + " -u loop around users, not passwords (effective! implied with -x)\n"); + PRINT_NORMAL(ext, " -C FILE colon separated \"login:pass\" format, instead of -L/-P options\n" + " -M FILE list of servers to attack, one entry per line, ':' to specify port\n"); + PRINT_EXTEND(ext, " -o FILE write found login/password pairs to FILE instead of stdout\n" + " -b FORMAT specify the format for the -o FILE: text(default), json, jsonv1\n" + " -f / -F exit when a login/pass pair is found (-M: -f per host, -F global)\n"); + PRINT_NORMAL(ext, " -t TASKS run TASKS number of connects in parallel per target (default: %d)\n", TASKS); + PRINT_EXTEND(ext, " -T TASKS run TASKS connects in parallel overall (for -M, default: %d)\n" + " -w / -W TIME waittime for responses (%d) / between connects per thread (%d)\n" + " -4 / -6 use IPv4 (default) / IPv6 addresses (put always in [] also in -M)\n" + " -v / -V / -d verbose mode / show login+pass for each attempt / debug mode \n" + " -O use old SSL v2 and v3\n" + " -q do not print messages about connection errors\n", + MAXTASKS, WAITTIME, conwait + ); + PRINT_NORMAL(ext, " -U service module usage details\n" + " -h more command line options (COMPLETE HELP)\n" + " server the target: DNS, IP or 192.168.0.0/24 (this OR the -M option)\n" + " service the service to crack (see below for supported protocols)\n" + " OPT some service modules support additional input (-U for module help)\n"); + PRINT_NORMAL(ext, "\nSupported services: %s\n" + "\n%s is a tool to guess/crack valid login/password pairs. Licensed under AGPL\n" + "v3.0. The newest version is always available at %s\n" + "Don't use in military or secret service organizations, or for illegal purposes.\n", + SERVICES, PROGRAM, RESOURCE + ); - 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"); - } + PRINT_EXTEND(ext, "\nUse HYDRA_PROXY_HTTP or HYDRA_PROXY environment variables for a proxy setup.\n" + "E.g. %% export HYDRA_PROXY=socks5://l:p@127.0.0.1:9150 (or: socks4:// connect://)\n" + " %% export HYDRA_PROXY=connect_and_socks_proxylist.txt (up to 64 entries)\n" + " %% export HYDRA_PROXY_HTTP=http://login:pass@proxy:8080\n" + " %% export HYDRA_PROXY_HTTP=proxylist.txt (up to 64 entries)\n"); + PRINT_NORMAL(ext, "\nExample%s:%s hydra -l user -P passlist.txt ftp://192.168.0.1\n", ext == 0 ? "" : "s", ext == 0 ? "" : "\n"); + PRINT_EXTEND(ext, " hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN\n" + " hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5\n" + " hydra -l admin -p password ftp://[192.168.0.0/24]/\n" + " hydra -L logins.txt -P pws.txt -M targets.txt ssh\n"); exit(-1); } @@ -421,9 +411,10 @@ void help_bfg() { "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"); + " -x 1:3:/ generate passwords from length 1 to 3 containing only slashes\n" + " -x 5:5:/%%,.- generate passwords with length 5 which consists only of /%%,.-\n" + " -x 3:5:aA1 -y generate passwords from length 3 to 5 with a, A and 1 only\n" + "\nThe bruteforce mode was made by Jan Dlabal, http://houbysoft.com/bfg/\n"); exit(-1); } From f7b122f6edfae76491054a89a51e864bd1852394 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 6 Jun 2017 15:22:37 +0200 Subject: [PATCH 6/7] cleanup --- hydra.c | 59 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/hydra.c b/hydra.c index 10c069f..d68f872 100644 --- a/hydra.c +++ b/hydra.c @@ -187,6 +187,31 @@ extern int old_ssl; void hydra_kill_head(int head_no, int killit, int fail); +// some enum definitions +typedef enum { + STATE_ACTIVE = 0, + STATE_FINISHED = 1, + STATE_ERROR = 2, + STATE_UNRESOLVED = 3 +} target_state_t; + +typedef enum { + MODE_PASSWORD_LIST = 1, + MODE_LOGIN_LIST = 2, + MODE_PASSWORD_BRUTE = 4, + MODE_PASSWORD_REVERSE = 8, + MODE_PASSWORD_NULL = 16, + MODE_PASSWORD_SAME = 32, + MODE_COLON_FILE = 64 +} hydra_mode_t; + +typedef enum { + FORMAT_PLAIN_TEXT, + FORMAT_JSONV1, + FORMAT_JSONV2, + FORMAT_XMLV1 +} output_format_t; + // some structure definitions typedef struct { pid_t pid; @@ -200,13 +225,6 @@ typedef struct { time_t last_seen; } hydra_head; -typedef enum { - STATE_ACTIVE = 0, - STATE_FINISHED = 1, - STATE_ERROR = 2, - STATE_UNRESOLVED = 3 -} target_state_t; - typedef struct { char *target; char ip[36]; @@ -247,23 +265,6 @@ typedef struct { FILE *ofp; } hydra_brain; -typedef enum { - MODE_PASSWORD_LIST = 1, - MODE_LOGIN_LIST = 2, - MODE_PASSWORD_BRUTE = 4, - MODE_PASSWORD_REVERSE = 8, - MODE_PASSWORD_NULL = 16, - MODE_PASSWORD_SAME = 32, - MODE_COLON_FILE = 64 -} hydra_mode_t; - -typedef enum { - FORMAT_PLAIN_TEXT, - FORMAT_JSONV1, - FORMAT_JSONV2, - FORMAT_XMLV1 -} output_format_t; - typedef struct { hydra_mode_t mode; int loop_mode; // valid modes: 0 = password, 1 = user @@ -304,7 +305,6 @@ typedef struct { // external vars extern char HYDRA_EXIT[5]; - #if !defined(ANDROID) && !defined(__BIONIC__) extern int errno; #endif @@ -347,16 +347,17 @@ int snpdone, snp_is_redo, snpbuflen, snpi, snpj, snpdont; #include "performance.h" -int inline check_flag(int value, int flag) { - return (value & flag) == flag; -} - #define PRINT_NORMAL(ext, text, ...) printf(text, ##__VA_ARGS__) #define PRINT_EXTEND(ext, text, ...) do { \ if (ext) \ printf(text, ##__VA_ARGS__); \ } while(0) + +int inline check_flag(int value, int flag) { + return (value & flag) == flag; +} + void help(int ext) { PRINT_NORMAL(ext, "Syntax: hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e nsr]" " [-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-W TIME] [-f] [-s PORT]" From 5033c262dfca80727ecf76365428d2f9f0aa120a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 6 Jun 2017 15:23:43 +0200 Subject: [PATCH 7/7] changelog update --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index fb9ebcd..3a851c2 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Changelog for hydra Release 8.6-dev * http-form module now supports URLs up to 6000 bytes (thanks to petrock6@github for the patch) +* merged several patches by Diadlo@github to make the code easier readable. thanks for that! Release 8.5