From 79f7d52ba2f2beadfbf504087500ca8c64fa8def Mon Sep 17 00:00:00 2001 From: xh4vm Date: Wed, 12 Mar 2025 13:07:12 +0500 Subject: [PATCH 1/5] feat: added paths for brute force and additional settings for all targets from the file --- hydra.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/hydra.c b/hydra.c index 30a8ece..d8ede22 100644 --- a/hydra.c +++ b/hydra.c @@ -267,6 +267,7 @@ typedef struct { typedef struct { char *target; + char *miscptr; char ip[36]; char *login_ptr; char *pass_ptr; @@ -1174,13 +1175,12 @@ void hydra_service_init(int32_t target_no) { int32_t x = 99; int32_t i; hydra_target *t = hydra_targets[target_no]; - char *miscptr = hydra_options.miscptr; FILE *ofp = hydra_brains.ofp; for (i = 0; x == 99 && i < sizeof(services) / sizeof(services[0]); i++) { if (strcmp(hydra_options.service, services[i].name) == 0) { if (services[i].init) { - x = services[i].init(t->ip, -1, options, miscptr, ofp, t->port, t->target); + x = services[i].init(t->ip, -1, options, t->miscptr, ofp, t->port, t->target); break; } } @@ -1264,13 +1264,13 @@ int32_t hydra_spawn_head(int32_t head_no, int32_t target_no) { hydra_target *t = hydra_targets[target_no]; int32_t sp = hydra_heads[head_no]->sp[1]; - char *miscptr = hydra_options.miscptr; + // char *miscptr = hydra_options.miscptr; FILE *ofp = hydra_brains.ofp; hydra_target *head_target = hydra_targets[hydra_heads[head_no]->target_no]; for (i = 0; i < sizeof(services) / sizeof(services[0]); i++) { if (strcmp(hydra_options.service, services[i].name) == 0) { if (services[i].exec) { - services[i].exec(t->ip, sp, options, miscptr, ofp, t->port, head_target->target); + services[i].exec(t->ip, sp, options, t->miscptr, ofp, t->port, head_target->target); // just in case a module returns (which it shouldnt) we let it exit // here exit(-1); @@ -2177,7 +2177,7 @@ int main(int argc, char *argv[]) { int32_t i = 0, j = 0, k, error = 0, modusage = 0, ignore_restore = 0, do_switch; int32_t head_no = 0, target_no = 0, exit_condition = 0, readres; time_t starttime, elapsed_status, elapsed_restore, status_print = 59, tmp_time; - char *tmpptr, *tmpptr2; + char *tmpptr, *tmpptr2, *tmpptr3; char rc, buf[MAXBUF]; time_t last_attempt = 0; fd_set fdreadheads; @@ -3543,7 +3543,7 @@ int main(int argc, char *argv[]) { fclose(rfp); } - if (hydra_options.infile_ptr != NULL) { + 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); @@ -3591,6 +3591,7 @@ int main(int argc, char *argv[]) { } } else hydra_targets[i]->target = tmpptr; + if ((tmpptr2 = strchr(tmpptr, ':')) != NULL) { *tmpptr2++ = 0; tmpptr = tmpptr2; @@ -3600,6 +3601,13 @@ int main(int argc, char *argv[]) { } if (hydra_targets[i]->port == 0) hydra_targets[i]->port = hydra_options.port; + + if ((tmpptr3 = strchr(tmpptr, '/')) != NULL) { + hydra_targets[i]->miscptr = tmpptr3; + } + else + hydra_targets[i]->miscptr = "/"; + while (*tmpptr != 0) tmpptr++; tmpptr++; @@ -3622,6 +3630,7 @@ int main(int argc, char *argv[]) { memset(hydra_targets[0], 0, sizeof(hydra_target)); hydra_targets[0]->target = servers_ptr = hydra_options.server; hydra_targets[0]->port = hydra_options.port; + hydra_targets[0]->miscptr = hydra_options.miscptr; sizeservers = strlen(hydra_options.server) + 1; } else { /* CIDR notation on command line, e.g. 192.168.0.0/24 */ @@ -3666,6 +3675,7 @@ int main(int argc, char *argv[]) { memcpy(&target.sin_addr.s_addr, (char *)&addr_cur2, 4); hydra_targets[i]->target = strdup(inet_ntoa((struct in_addr)target.sin_addr)); hydra_targets[i]->port = hydra_options.port; + hydra_targets[i]->miscptr = hydra_options.miscptr; addr_cur++; i++; } @@ -3681,6 +3691,7 @@ int main(int argc, char *argv[]) { memset(hydra_targets[0], 0, sizeof(hydra_target)); hydra_targets[0]->target = servers_ptr = hydra_options.server; hydra_targets[0]->port = hydra_options.port; + hydra_targets[0]->miscptr = hydra_options.miscptr; sizeservers = strlen(hydra_options.server) + 1; } for (i = 0; i < hydra_brains.targets; i++) { @@ -4113,7 +4124,7 @@ int main(int argc, char *argv[]) { } 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); + printf("[%d][%s] host: %s misc: %s login: %s password: %s\n", hydra_targets[hydra_heads[head_no]->target_no]->port, hydra_options.service, hydra_targets[hydra_heads[head_no]->target_no]->target, hydra_targets[hydra_heads[head_no]->target_no]->miscptr, hydra_heads[head_no]->current_login_ptr, hydra_heads[head_no]->current_pass_ptr); } if (hydra_options.outfile_format == FORMAT_JSONV1 && hydra_options.outfile_ptr != NULL && hydra_brains.ofp != NULL) { fprintf(hydra_brains.ofp, From ad286790ca3ca7e61a3341ee784b95864d9349d7 Mon Sep 17 00:00:00 2001 From: xh4vm Date: Thu, 13 Mar 2025 12:26:57 +0500 Subject: [PATCH 2/5] feat: integration with http[s]-* --- hydra.c | 132 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 67 insertions(+), 65 deletions(-) diff --git a/hydra.c b/hydra.c index d8ede22..492089c 100644 --- a/hydra.c +++ b/hydra.c @@ -3201,77 +3201,79 @@ int main(int argc, char *argv[]) { 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, "%.6000s", hydra_options.miscptr); - url = strtok(bufferurl, ":"); - variables = strtok(NULL, ":"); - cond = strtok(NULL, ":"); - optional1 = strtok(NULL, "\n"); - if ((variables == NULL) || (strstr(variables, "^USER^") == NULL && strstr(variables, "^PASS^") == NULL && strstr(variables, "^USER64^") == NULL && strstr(variables, "^PASS64^") == NULL)) { - fprintf(stderr, - "[ERROR] the variables argument needs at least the strings " - "^USER^, ^PASS^, ^USER64^ or ^PASS64^: %s\n", - STR_NULL(variables)); - exit(-1); + if (hydra_options.infile_ptr == NULL) { + if (hydra_options.miscptr == NULL) { + fprintf(stderr, "[WARNING] You must supply the web page as an " + "additional option or via -m, default path set to /\n"); + hydra_options.miscptr = malloc(2); + hydra_options.miscptr = "/"; } - if ((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); + // 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; } - while ((optional1 = strtok(NULL, ":")) != NULL) { - if (optional1[1] != '=' && optional1[1] != ':' && optional1[1] != 0) { - fprintf(stderr, "[ERROR] Wrong syntax of optional argument: %s\n", optional1); + if (strstr(hydra_options.miscptr, "\\:") != NULL) { + fprintf(stderr, "[INFORMATION] escape sequence \\: detected in module " + "option, no parameter verification is performed.\n"); + } else { + sprintf(bufferurl, "%.6000s", hydra_options.miscptr); + url = strtok(bufferurl, ":"); + variables = strtok(NULL, ":"); + cond = strtok(NULL, ":"); + optional1 = strtok(NULL, "\n"); + if ((variables == NULL) || (strstr(variables, "^USER^") == NULL && strstr(variables, "^PASS^") == NULL && strstr(variables, "^USER64^") == NULL && strstr(variables, "^PASS64^") == NULL)) { + fprintf(stderr, + "[ERROR] the variables argument needs at least the strings " + "^USER^, ^PASS^, ^USER64^ or ^PASS64^: %s\n", + STR_NULL(variables)); exit(-1); } + if ((url == NULL) || (cond == NULL)) { + fprintf(stderr, + "[ERROR] Wrong syntax, requires three arguments separated by " + "a colon which may not be null: %s\n", + bufferurl); + exit(-1); + } + while ((optional1 = strtok(NULL, ":")) != NULL) { + if (optional1[1] != '=' && optional1[1] != ':' && optional1[1] != 0) { + fprintf(stderr, "[ERROR] Wrong syntax of optional argument: %s\n", optional1); + exit(-1); + } - switch (optional1[0]) { - case 'C': // fall through - case 'c': - if (optional1[1] != '=' || optional1[2] != '/') { - fprintf(stderr, - "[ERROR] Wrong syntax of parameter C, must look like " - "'C=/url/of/page', not http:// etc.: %s\n", - optional1); - exit(-1); + 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); } - 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); } } } From ba45db1496584f3a2cd439cb794d54c7fc82b202 Mon Sep 17 00:00:00 2001 From: xh4vm Date: Fri, 14 Mar 2025 19:28:04 +0500 Subject: [PATCH 3/5] feat: added documentation --- hydra-http-form.c | 5 +++++ hydra-http.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/hydra-http-form.c b/hydra-http-form.c index 4c6919b..7f56091 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -1613,6 +1613,11 @@ void usage_http_form(const char *service) { "You can specify a header without escaping the colons, but that way you will not\n" "be able to put colons in the header value itself, as they will be interpreted by\n" "hydra as option separators.\n" + "Note: to attack multiple targets, you only need to pass the path to the file containing the targets with parameters,\n" + "for example, a file with targets:\n\n" + " localhost:8443/login:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=401\n" + " localhost:9443/login2:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=302\n" + " ...\n\n" "\nExamples:\n" " \"/login.php:user=^USER^&pass=^PASS^:incorrect\"\n" " \"/" diff --git a/hydra-http.c b/hydra-http.c index ba9a676..c083e8c 100644 --- a/hydra-http.c +++ b/hydra-http.c @@ -473,6 +473,11 @@ void usage_http(const char *service) { "present the\n" " combination is invalid. Note: this must be the last option " "supplied.\n" + "Note: to attack multiple targets, you only need to pass the path to the file containing the targets with parameters,\n" + "for example, a file with targets:\n\n" + " localhost:5000/protected:A=BASIC\n" + " localhost:5002/protected:A=NTLM\n" + " ...\n\n" "For example: \"/secret\" or \"http://bla.com/foo/bar:H=Cookie\\: " "sessid=aaaa\" or \"https://test.com:8080/members:A=NTLM\"\n\n", service); From aae8baae838ef02eb529f8e63b30747cae3ab4a4 Mon Sep 17 00:00:00 2001 From: xh4vm Date: Tue, 18 Mar 2025 17:32:56 +0500 Subject: [PATCH 4/5] fix: hydra-http documentation --- hydra-http.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) mode change 100644 => 100755 hydra-http.c diff --git a/hydra-http.c b/hydra-http.c old mode 100644 new mode 100755 index c083e8c..e78f865 --- a/hydra-http.c +++ b/hydra-http.c @@ -473,12 +473,13 @@ void usage_http(const char *service) { "present the\n" " combination is invalid. Note: this must be the last option " "supplied.\n" - "Note: to attack multiple targets, you only need to pass the path to the file containing the targets with parameters,\n" - "for example, a file with targets:\n\n" - " localhost:5000/protected:A=BASIC\n" - " localhost:5002/protected:A=NTLM\n" - " ...\n\n" "For example: \"/secret\" or \"http://bla.com/foo/bar:H=Cookie\\: " - "sessid=aaaa\" or \"https://test.com:8080/members:A=NTLM\"\n\n", + "sessid=aaaa\" or \"https://test.com:8080/members:A=NTLM\"\n" + "To attack multiple targets, you can use the -M option with a file " + "containing the targets and their parameters.\n" + "Example file content:\n" + " localhost:5000/protected:A=BASIC\n" + " localhost:5002/protected_path:A=NTLM\n" + " ...\n\n", service); } From b81105f6af5b7e1ba43be3863a764bbd2b11c078 Mon Sep 17 00:00:00 2001 From: xh4vm Date: Tue, 18 Mar 2025 17:35:41 +0500 Subject: [PATCH 5/5] fix: hydra-http-form documentation --- hydra-http-form.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) mode change 100644 => 100755 hydra-http-form.c diff --git a/hydra-http-form.c b/hydra-http-form.c old mode 100644 new mode 100755 index 7f56091..af2f457 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -1613,11 +1613,6 @@ void usage_http_form(const char *service) { "You can specify a header without escaping the colons, but that way you will not\n" "be able to put colons in the header value itself, as they will be interpreted by\n" "hydra as option separators.\n" - "Note: to attack multiple targets, you only need to pass the path to the file containing the targets with parameters,\n" - "for example, a file with targets:\n\n" - " localhost:8443/login:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=401\n" - " localhost:9443/login2:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=302\n" - " ...\n\n" "\nExamples:\n" " \"/login.php:user=^USER^&pass=^PASS^:incorrect\"\n" " \"/" @@ -1629,6 +1624,12 @@ void usage_http_form(const char *service) { " \"/exchweb/bin/auth/:F=failed" "owaauth.dll:destination=http%%3A%%2F%%2F%%2Fexchange&flags=0&" "username=%%5C^USER^&password=^PASS^&SubmitCreds=x&trusted=0:" - "C=/exchweb\":reason=\n", + "C=/exchweb\":reason=\n" + "To attack multiple targets, you can use the -M option with a file " + "containing the targets and their parameters.\n" + "Example file content:\n" + " localhost:8443/login:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=401\n" + " localhost:9443/login2:type=login&login=^USER^&password=^PASS^:h=test\\: header:F=302\n" + " ...\n\n", service); }