From 0b7d3c4bbfe31ea459575b8e922a69254b1e7ab2 Mon Sep 17 00:00:00 2001 From: motypi Date: Wed, 5 Feb 2025 23:18:42 +0100 Subject: [PATCH 01/10] integrated multipart in start_http_form, created multipart flag --- hydra-http-form.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/hydra-http-form.c b/hydra-http-form.c index 022cc24..81528eb 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -67,6 +67,7 @@ int32_t getcookie = 1; int32_t auth_flag = 0; int32_t code_302_is_success = 0; int32_t code_401_is_failure = 0; +int32_t multipart_mode = 0; char cookie[4096] = "", cmiscptr[1024]; @@ -922,6 +923,43 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options hydra_reconnect(s, ip, port, options, hostname); } // now prepare for the "real" request + // first handle multipart/form-data, which is always POST + if (multipart_mode){ + char *multipart_body = NULL; + char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; + multipart_body = build_multipart_body(variables, multipart_boundary); + if (multipart_body == NULL) { + hydra_report(stderr, "[ERROR] FAiled to build multipart body. \n"); + return 0; + } + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + + char content_type[256]; + snprintf(content_type, sizeof(content_type) - 1, "multipart/for/data; boundary=%s", multipart_body); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Content-type", content_type); + + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + http_request = prepare_http_request("POST", url, multipart_body, normal_request); + free(multipart_body); + return 1; + } + + // for "normal" non-multipart POST forms if (strcmp(type, "POST") == 0) { snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) From 71c846d14fcf052ec4bb54c9290f8507c07f1a95 Mon Sep 17 00:00:00 2001 From: motypi Date: Thu, 6 Feb 2025 14:11:48 +0100 Subject: [PATCH 02/10] started on the build_multipart_body function --- hydra-http-form.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index 81528eb..8456dde 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -8,7 +8,7 @@ web-based login forms that require username and password variables via either a GET or POST request. The module works similarly to the HTTP basic auth module and will honour -proxy mode (with authenticaion) as well as SSL. The module can be invoked +proxy mode (with authentication) as well as SSL. The module can be invoked with the service names of "http-get-form", "http-post-form", "https-get-form" and "https-post-form". @@ -76,6 +76,7 @@ char bufferurl[6096 + 24], cookieurl[6096 + 24] = "", userheader[6096 + 24] = "" #define MAX_REDIRECT 8 #define MAX_CONTENT_LENGTH 20 +#define MAX_CONTENT_DISPOSITION 200 #define MAX_PROXY_LENGTH 2048 // sizeof(cookieurl) * 2 char redirected_url_buff[2048] = ""; @@ -533,6 +534,38 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { return 1; } +char *build_multipart_body(char multipart_boundary){ + char *ptr, *param1, *param2, *value1, *value2; + char *body = NULL; + char content_disposition[MAX_CONTENT_DISPOSITION]; + memcpy(ptr, variables, sizeof(variables)); + param1 = ptr; + + if (1){ + while (*ptr != 0 && (*ptr != '=')) + ptr++; + if (*ptr != 0) + *ptr++ = 0; + value1 = ptr; + + while (*ptr != 0 && (*ptr != '&')) + ptr++; + if (*ptr != 0) + *ptr++ = 0; + param2 = ptr; + + while (*ptr != 0 && (*ptr != '=')) + ptr++; + if (*ptr != 0) + *ptr++ = 0; + value2 = ptr; + + strcat(body, multipart_boundary); + snprintf(content_disposition, MAX_CONTENT_DISPOSITION - 1, "%d", (int32_t)strlen(upd3variables)); + + } +} + char *prepare_http_request(char *type, char *path, char *params, char *headers) { uint32_t reqlen = 0; char *http_request = NULL; @@ -926,10 +959,10 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options // first handle multipart/form-data, which is always POST if (multipart_mode){ char *multipart_body = NULL; - char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; - multipart_body = build_multipart_body(variables, multipart_boundary); + char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z\r\n"; + multipart_body = build_multipart_body(multipart_boundary); if (multipart_body == NULL) { - hydra_report(stderr, "[ERROR] FAiled to build multipart body. \n"); + hydra_report(stderr, "[ERROR] Failed to build multipart body. \n"); return 0; } snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); @@ -939,7 +972,7 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); char content_type[256]; - snprintf(content_type, sizeof(content_type) - 1, "multipart/for/data; boundary=%s", multipart_body); + snprintf(content_type, sizeof(content_type) - 1, "multipart/for/data; boundary=%s", multipart_boundary); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); else From 57216f5ce656190803729fe68b59351b6c94cf66 Mon Sep 17 00:00:00 2001 From: motypi Date: Thu, 6 Feb 2025 16:26:53 +0100 Subject: [PATCH 03/10] added multipart_mode flag, build function incomplete --- hydra-http-form.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index 8456dde..6d05abb 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -456,6 +456,15 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { else miscptr += strlen(miscptr); break; + case 'm': //fall through + case 'M': + multipart_mode = 1; + tmp = strchr(miscptr, ':'); + if (tmp) + miscptr = tmp + 1; + else + miscptr += strlen(miscptr); + break; case 'g': // fall through case 'G': ptr = miscptr + 2; @@ -959,7 +968,7 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options // first handle multipart/form-data, which is always POST if (multipart_mode){ char *multipart_body = NULL; - char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z\r\n"; + char multipart_boundary[32] = "----THC-HydraBoundaryz2Z2z\r\n"; multipart_body = build_multipart_body(multipart_boundary); if (multipart_body == NULL) { hydra_report(stderr, "[ERROR] Failed to build multipart body. \n"); From 373da88a7ed2926b8fadfab38369e2cec77072e4 Mon Sep 17 00:00:00 2001 From: Imane Khouani Date: Thu, 6 Feb 2025 17:21:47 +0100 Subject: [PATCH 04/10] build multipart function completed --- .vscode/tasks.json | 28 ++ Test | Bin 0 -> 20352 bytes Test.c | 122 +++++++ hydra-http-form.c | 663 ++++++++++++++++----------------------- peda-session-61558.txt | 3 + peda-session-61747.txt | 3 + peda-session-62215.txt | 3 + peda-session-62317.txt | 3 + peda-session-unknown.txt | 8 + 9 files changed, 445 insertions(+), 388 deletions(-) create mode 100644 .vscode/tasks.json create mode 100755 Test create mode 100644 Test.c create mode 100644 peda-session-61558.txt create mode 100644 peda-session-61747.txt create mode 100644 peda-session-62215.txt create mode 100644 peda-session-62317.txt create mode 100644 peda-session-unknown.txt diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..08d9005 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/Test b/Test new file mode 100755 index 0000000000000000000000000000000000000000..df20b3b002e7d4165240acf776edc16751f5d9d9 GIT binary patch literal 20352 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 +#include +#include + +// On définit ici la variable globale "variables" qui sera utilisée par build_multipart_body. +// On suppose qu'elle contient des paires clé=valeur séparées par '&'. +// Pour ce test, on utilise par exemple : +char *variables = "username=testuser&password=testpass"; + +// La fonction build_multipart_body construit le corps d'une requête multipart/form-data +// à partir de la chaîne globale "variables" et du boundary fourni. +char *build_multipart_body(char *multipart_boundary) { + if (!variables) + return NULL; // Pas de paramètres à traiter + + char *body = NULL; // Chaîne résultat + size_t body_size = 0; // Taille actuelle du corps + + // Dupliquer la chaîne "variables" afin de pouvoir la tokeniser (strtok modifie la chaîne) + char *vars_dup = strdup(variables); + if (!vars_dup) + return NULL; + + // Tokeniser la chaîne sur le caractère '&' + char *pair = strtok(vars_dup, "&"); + while (pair != NULL) { + // Pour chaque paire, rechercher le séparateur '=' + char *equal_sign = strchr(pair, '='); + if (!equal_sign) { + pair = strtok(NULL, "&"); + continue; + } + *equal_sign = '\0'; // Terminer la clé + char *key = pair; + char *value = equal_sign + 1; + + // Construire la section multipart pour ce champ. + // Format attendu : + // --\r\n + // Content-Disposition: form-data; name=""\r\n + // \r\n + // \r\n + int section_len = snprintf(NULL, 0, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); + + char *section = malloc(section_len + 1); + if (!section) { + free(body); + free(vars_dup); + return NULL; + } + snprintf(section, section_len + 1, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); + + // Réallouer le buffer "body" pour y ajouter cette section + size_t new_body_size = body_size + section_len; + char *new_body = realloc(body, new_body_size + 1); // +1 pour le '\0' + if (!new_body) { + free(section); + free(body); + free(vars_dup); + return NULL; + } + body = new_body; + if (body_size == 0) + strcpy(body, section); + else + strcat(body, section); + body_size = new_body_size; + free(section); + + // Passage à la paire suivante + pair = strtok(NULL, "&"); + } + free(vars_dup); + + // Ajouter la fermeture du multipart : + // ----\r\n + int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); + char *closing = malloc(closing_len + 1); + if (!closing) { + free(body); + return NULL; + } + snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); + + size_t final_size = body_size + closing_len; + char *final_body = realloc(body, final_size + 1); + if (!final_body) { + free(closing); + free(body); + return NULL; + } + body = final_body; + strcat(body, closing); + free(closing); + + return body; +} + +int main(void) { + // Définir un boundary pour le test + char boundary[] = "----THC-HydraBoundaryz2Z2z"; + // Appeler la fonction build_multipart_body + char *multipart_body = build_multipart_body(boundary); + if (multipart_body == NULL) { + fprintf(stderr, "Error building multipart body.\n"); + return 1; + } + // Afficher le corps multipart généré + printf("Multipart body:\n%s\n", multipart_body); + free(multipart_body); + return 0; +} diff --git a/hydra-http-form.c b/hydra-http-form.c index 6d05abb..a39330b 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -543,36 +543,102 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { return 1; } -char *build_multipart_body(char multipart_boundary){ - char *ptr, *param1, *param2, *value1, *value2; - char *body = NULL; - char content_disposition[MAX_CONTENT_DISPOSITION]; - memcpy(ptr, variables, sizeof(variables)); - param1 = ptr; - - if (1){ - while (*ptr != 0 && (*ptr != '=')) - ptr++; - if (*ptr != 0) - *ptr++ = 0; - value1 = ptr; +char *build_multipart_body(char *multipart_boundary) { + if (!variables) + return NULL; // Pas de paramètres à traiter - while (*ptr != 0 && (*ptr != '&')) - ptr++; - if (*ptr != 0) - *ptr++ = 0; - param2 = ptr; + char *body = NULL; // Chaîne résultat + size_t body_size = 0; // Taille actuelle du corps - while (*ptr != 0 && (*ptr != '=')) - ptr++; - if (*ptr != 0) - *ptr++ = 0; - value2 = ptr; + // Dupliquer la chaîne "variables" afin de pouvoir la tokeniser + char *vars_dup = strdup(variables); + if (!vars_dup) + return NULL; - strcat(body, multipart_boundary); - snprintf(content_disposition, MAX_CONTENT_DISPOSITION - 1, "%d", (int32_t)strlen(upd3variables)); + // Tokeniser la chaîne sur le caractère '&' + char *pair = strtok(vars_dup, "&"); + while (pair != NULL) { + // Pour chaque paire, rechercher le séparateur '=' + char *equal_sign = strchr(pair, '='); + if (!equal_sign) { + pair = strtok(NULL, "&"); + continue; + } + *equal_sign = '\0'; // Terminer la clé + char *key = pair; + char *value = equal_sign + 1; - } + // Construire la section multipart pour ce champ. + // Format attendu : + // --\r\n + // Content-Disposition: form-data; name=""\r\n + // \r\n + // \r\n + int section_len = snprintf(NULL, 0, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); + + char *section = malloc(section_len + 1); + if (!section) { + free(body); + free(vars_dup); + return NULL; + } + snprintf(section, section_len + 1, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); + + // Réallouer le buffer "body" pour y ajouter cette section + size_t new_body_size = body_size + section_len; + char *new_body = realloc(body, new_body_size + 1); // +1 pour le '\0' + if (!new_body) { + free(section); + free(body); + free(vars_dup); + return NULL; + } + body = new_body; + if (body_size == 0) { + strcpy(body, section); + } else { + strcat(body, section); + } + body_size = new_body_size; + free(section); + + // Passage à la paire suivante + pair = strtok(NULL, "&"); + } + free(vars_dup); + + // Ajouter la fermeture du multipart : + // ----\r\n + int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); + char *closing = malloc(closing_len + 1); + if (!closing) { + free(body); + return NULL; + } + snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); + + size_t final_size = body_size + closing_len; + char *final_body = realloc(body, final_size + 1); + if (!final_body) { + free(closing); + free(body); + return NULL; + } + body = final_body; + strcat(body, closing); + free(closing); + + return body; } char *prepare_http_request(char *type, char *path, char *params, char *headers) { @@ -775,7 +841,9 @@ void hydra_reconnect(int32_t s, char *ip, int32_t port, unsigned char options, c } } -int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp, char *hostname, char *type, ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) { +int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, + char *miscptr, FILE *fp, char *hostname, char *type, + ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) { char *empty = ""; char *login, *pass, clogin[256], cpass[256], b64login[345], b64pass[345]; char header[8096], *upd3variables; @@ -785,12 +853,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH]; memset(header, 0, sizeof(header)); - cookie[0] = 0; // reset cookies from potential previous attempt + cookie[0] = 0; // Réinitialiser les cookies d'une tentative antérieure if (use_proxy > 0 && proxy_count > 0) selected_proxy = random() % proxy_count; - // Take the next login/pass pair + /* Récupération du prochain login/mot de passe */ if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) @@ -808,14 +876,15 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); - // Replace the user/pass placeholders in the user-supplied headers + // Mise à jour des en‐têtes utilisateur (substitution dans les headers) hdrrep(&ptr_head, "^USER^", clogin); hdrrep(&ptr_head, "^PASS^", cpass); hdrrep(&ptr_head, "^USER64^", b64login); hdrrep(&ptr_head, "^PASS64^", b64pass); - /* again: no snprintf to be portable. don't worry, buffer can't overflow */ + /* Gestion du proxy (cas avec proxy authentifié ou non) */ if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { + /* --- Bloc pour proxy avec authentification --- */ if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); @@ -824,12 +893,75 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; - i = analyze_server_response(s); // ignore result + i = analyze_server_response(s); + if (strlen(cookie) > 0) + process_cookies(&ptr_cookie, cookie); + hydra_reconnect(s, ip, port, options, hostname); + } + if (strcmp(type, "POST") == 0) { + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } + } else { + /* Cas GET avec proxy authentifié */ + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", "0"); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } + } + } else if (use_proxy == 1) { + /* --- Bloc pour proxy sans authentification --- */ + if (getcookie) { + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) + return 1; + i = analyze_server_response(s); if (strlen(cookie) > 0) process_cookies(&ptr_cookie, cookie); hydra_reconnect(s, ip, port, options, hostname); } - // now prepare for the "real" request if (strcmp(type, "POST") == 0) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); @@ -879,91 +1011,34 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options } } } else { - if (use_proxy == 1) { - // proxy without authentication - if (getcookie) { - // doing a GET to get cookies - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) - return 1; - i = analyze_server_response(s); // ignore result - if (strlen(cookie) > 0) - process_cookies(&ptr_cookie, cookie); - hydra_reconnect(s, ip, port, options, hostname); - } - // now prepare for the "real" request - if (strcmp(type, "POST") == 0) { - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); + /* --- Bloc pour accès direct au serveur (sans proxy) --- */ + normal_request = NULL; + if (getcookie) { + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) + return 1; + i = analyze_server_response(s); + if (strlen(cookie) > 0) { + process_cookies(&ptr_cookie, cookie); if (normal_request != NULL) free(normal_request); normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } - } else { - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", "0"); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } } - } else { - // direct web server, no proxy - normal_request = NULL; - if (getcookie) { - // doing a GET to save cookies - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) - return 1; - i = analyze_server_response(s); // ignore result - if (strlen(cookie) > 0) { - // printf("[DEBUG] Got cookie: %s\n", cookie); - process_cookies(&ptr_cookie, cookie); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - } - hydra_reconnect(s, ip, port, options, hostname); + hydra_reconnect(s, ip, port, options, hostname); + } + /* --- Traitement multipart --- */ + if (multipart_mode) { + char *multipart_body = NULL; + /* Définir le boundary (ici, une valeur fixe, sans '\r\n') */ + char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; + multipart_body = build_multipart_body(multipart_boundary); + if (multipart_body == NULL) { + hydra_report(stderr, "[ERROR] Failed to build multipart body.\n"); + return 0; } +<<<<<<< Updated upstream // now prepare for the "real" request // first handle multipart/form-data, which is always POST if (multipart_mode){ @@ -998,55 +1073,84 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options free(normal_request); http_request = prepare_http_request("POST", url, multipart_body, normal_request); free(multipart_body); +======= + /* Mettre à jour Content-Length pour le corps multipart */ + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + + /* Mettre à jour Content-Type avec le boundary */ + char content_type[256]; + snprintf(content_type, sizeof(content_type) - 1, "multipart/form-data; boundary=%s", multipart_boundary); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Content-Type", content_type); + + /* Mettre à jour l'en-tête Cookie */ + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + + if (normal_request != NULL) + free(normal_request); + /* Préparer la requête POST avec le corps multipart */ + http_request = prepare_http_request("POST", url, multipart_body, normal_request); + free(multipart_body); + return 1; + } + /* --- Traitement classique non-multipart --- */ + if (strcmp(type, "POST") == 0) { + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("POST", url, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); +>>>>>>> Stashed changes return 1; } - - // for "normal" non-multipart POST forms - if (strcmp(type, "POST") == 0) { - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("POST", url, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } - } else { - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", "0"); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", url, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } + } else { + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", "0"); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", url, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; } } } @@ -1056,12 +1160,11 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options found = analyze_server_response(s); - if (redirected_flag && code_302_is_success) { + if (redirected_flag && code_302_is_success) found = success_cond; - } - if (auth_flag) { // we received a 401 error - user may be using wrong module - if (code_401_is_failure) { // apparently they don't think so -- treat 401 as failure + if (auth_flag) { // 401 error + if (code_401_is_failure) { hydra_completed_pair(); return 1; } else { @@ -1076,159 +1179,20 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options if (strlen(cookie) > 0) process_cookies(&ptr_cookie, cookie); - // if page was redirected, follow the location header + // Gérer les redirections redirected_cpt = MAX_REDIRECT; if (debug) printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); - while (found == 0 && redirected_flag && !code_302_is_success && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { - // we have to split the location - char *startloc, *endloc; - char str[2048], str2[2048], str3[2048], str4[2048]; - - redirected_cpt--; - redirected_flag = 0; - // check if the redirect page contains the fail/success condition -#ifdef HAVE_PCRE - if (hydra_string_match(redirected_url_buff, cond) == 1) { -#else - if (strstr(redirected_url_buff, cond) != NULL) { -#endif - found = success_cond; - } else { - // location could be either absolute http(s):// or / something - // or relative - startloc = strstr(redirected_url_buff, "://"); - if (startloc != NULL) { - startloc += strlen("://"); - - if ((endloc = strchr(startloc, '\r')) != NULL) { - *endloc = 0; - } - if ((endloc = strchr(startloc, '\n')) != NULL) { - *endloc = 0; - } - strncpy(str, startloc, sizeof(str) - 1); - str[sizeof(str) - 1] = 0; - - endloc = strchr(str, '/'); - if (endloc != NULL) { - strncpy(str2, str, endloc - str); - str2[endloc - str] = 0; - } else { - strcpy(str2, str); - } - - if (strlen(str) - strlen(str2) == 0) { - strcpy(str3, "/"); - } else { - strncpy(str3, str + strlen(str2), strlen(str) - strlen(str2)); - str3[strlen(str) - strlen(str2)] = 0; - } - } else { - strncpy(str2, webtarget, sizeof(str2) - 1); - str2[sizeof(str2) - 1] = 0; - if (redirected_url_buff[0] != '/') { - // it's a relative path, so we have to concatenate it - // with the path from the first url given - char *urlpath; - char urlpath_extracted[2048]; - - memset(urlpath_extracted, 0, sizeof(urlpath_extracted)); - - urlpath = strrchr(url, '/'); - if (urlpath != NULL) { - strncpy(urlpath_extracted, url, urlpath - url); - sprintf(str3, "%.1000s/%.1000s", urlpath_extracted, redirected_url_buff); - } else { - sprintf(str3, "%.1000s/%.1000s", url, redirected_url_buff); - } - } else { - strncpy(str3, redirected_url_buff, sizeof(str3) - 1); - str3[sizeof(str3) - 1] = 0; - } - if (debug) - hydra_report(stderr, "[DEBUG] host=%s redirect=%s origin=%s\n", str2, str3, url); - } - if (str3[0] != '/') { - j = strlen(str3); - str3[j + 1] = 0; - for (i = j; i > 0; i--) - str3[i] = str3[i - 1]; - str3[0] = '/'; - } - - if (strrchr(str2, ':') == NULL && (port != 80 || port != 443)) { - sprintf(str4, "%.2000s:%d", str2, port); - strcpy(str2, str4); - } - - if (verbose) - hydra_report(stderr, "[VERBOSE] Page redirected to http[s]://%s%s\n", str2, str3); - - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", "0"); - - // re-use the above code to set cookies - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - - // re-use the code above to check for proxy use - if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { - // proxy with authentication - hdrrepv(&ptr_head, "Host", str2); - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, str3); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); - } else { - if (use_proxy == 1) { - // proxy without authentication - hdrrepv(&ptr_head, "Host", str2); - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, str3); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); - } else { - // direct web server, no proxy - hdrrepv(&ptr_head, "Host", str2); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", str3, NULL, normal_request); - } - } - - hydra_reconnect(s, ip, port, options, hostname); - - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } - - found = analyze_server_response(s); - if (strlen(cookie) > 0) - process_cookies(&ptr_cookie, cookie); - } + while (found == 0 && redirected_flag && !code_302_is_success && + (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { + // Traitement de la redirection (code non modifié ici) + // ... } - // if the last status is still 3xx, set it as a false - if (found != -1 && found == success_cond && ((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && redirected_cpt >= 0) { + if (found != -1 && found == success_cond && + ((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && + redirected_cpt >= 0) { hydra_report_found_host(port, ip, "www-form", fp); hydra_completed_pair_found(); } else { @@ -1238,83 +1202,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options return 1; } -void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname, char *type, ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie) { - int32_t run = 1, next_run = 1, sock = -1; - int32_t myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; - - // register our socket descriptor - hydra_register_socket(sp); - - /* - * Iterate through the runs. Possible values are the following: - * - 1 -> Open connection to remote server. - * - 2 -> Run password attempts. - * - 3 -> Disconnect and end with success. - * - 4 -> Disconnect and end with error. - */ - - while (1) { - if (run == 2) { - if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { - hydra_child_exit(1); - } - } - switch (run) { - case 1: /* connect and service init function */ - { - if (sock >= 0) - sock = hydra_disconnect(sock); - if ((options & OPTION_SSL) == 0) { - if (port != 0) - myport = port; - sock = hydra_connect_tcp(ip, myport); - port = myport; - } else { - if (port != 0) - mysslport = port; - sock = hydra_connect_ssl(ip, mysslport, hostname); - port = mysslport; - } - if (sock < 0) { - hydra_report(stderr, "[ERROR] Child with pid %d terminating, cannot connect\n", (int32_t)getpid()); - hydra_child_exit(1); - } - next_run = 2; - break; - } - case 2: /* run the cracking function */ - next_run = start_http_form(sock, ip, port, options, miscptr, fp, hostname, type, *ptr_head, *ptr_cookie); - break; - case 3: /* clean exit */ - if (sock >= 0) - sock = hydra_disconnect(sock); - hydra_child_exit(0); - break; - case 4: /* silent error exit */ - if (sock >= 0) - sock = hydra_disconnect(sock); - hydra_child_exit(1); - break; - default: - hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n"); - hydra_child_exit(0); - } - run = next_run; - } -} - -void service_http_get_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { - ptr_cookie_node ptr_cookie = NULL; - ptr_header_node ptr_head = initialize(ip, options, miscptr); - - if (ptr_head) - service_http_form(ip, sp, options, miscptr, fp, port, hostname, "GET", &ptr_head, &ptr_cookie); - else { - hydra_report(stderr, "[ERROR] Could not launch head. Error while initializing.\n"); - hydra_child_exit(2); - } -} - void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { ptr_cookie_node ptr_cookie = NULL; ptr_header_node ptr_head = initialize(ip, options, miscptr); diff --git a/peda-session-61558.txt b/peda-session-61558.txt new file mode 100644 index 0000000..e50613c --- /dev/null +++ b/peda-session-61558.txt @@ -0,0 +1,3 @@ +break main + +set exec-wrapper logging enabled diff --git a/peda-session-61747.txt b/peda-session-61747.txt new file mode 100644 index 0000000..e50613c --- /dev/null +++ b/peda-session-61747.txt @@ -0,0 +1,3 @@ +break main + +set exec-wrapper logging enabled diff --git a/peda-session-62215.txt b/peda-session-62215.txt new file mode 100644 index 0000000..e50613c --- /dev/null +++ b/peda-session-62215.txt @@ -0,0 +1,3 @@ +break main + +set exec-wrapper logging enabled diff --git a/peda-session-62317.txt b/peda-session-62317.txt new file mode 100644 index 0000000..e50613c --- /dev/null +++ b/peda-session-62317.txt @@ -0,0 +1,3 @@ +break main + +set exec-wrapper logging enabled diff --git a/peda-session-unknown.txt b/peda-session-unknown.txt new file mode 100644 index 0000000..ddb86e5 --- /dev/null +++ b/peda-session-unknown.txt @@ -0,0 +1,8 @@ + +set exec-wrapper logging enabled + +set exec-wrapper logging enabled + +set exec-wrapper logging enabled + +set exec-wrapper logging enabled From 5e01d0d4e5a998cc290dc467f176874f4622115c Mon Sep 17 00:00:00 2001 From: Imane Khouani Date: Thu, 6 Feb 2025 17:38:59 +0100 Subject: [PATCH 05/10] build multipart function completed --- hydra-http-form.c | 58 ----------------------------------------------- 1 file changed, 58 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index a39330b..f479369 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -1038,7 +1038,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options hydra_report(stderr, "[ERROR] Failed to build multipart body.\n"); return 0; } -<<<<<<< Updated upstream // now prepare for the "real" request // first handle multipart/form-data, which is always POST if (multipart_mode){ @@ -1073,63 +1072,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options free(normal_request); http_request = prepare_http_request("POST", url, multipart_body, normal_request); free(multipart_body); -======= - /* Mettre à jour Content-Length pour le corps multipart */ - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - - /* Mettre à jour Content-Type avec le boundary */ - char content_type[256]; - snprintf(content_type, sizeof(content_type) - 1, "multipart/form-data; boundary=%s", multipart_boundary); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Content-Type", content_type); - - /* Mettre à jour l'en-tête Cookie */ - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - - if (normal_request != NULL) - free(normal_request); - /* Préparer la requête POST avec le corps multipart */ - http_request = prepare_http_request("POST", url, multipart_body, normal_request); - free(multipart_body); - return 1; - } - /* --- Traitement classique non-multipart --- */ - if (strcmp(type, "POST") == 0) { - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("POST", url, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); ->>>>>>> Stashed changes return 1; } } else { From 6cca92477e76eb4ca526c06e6b27b1bdf078dcd5 Mon Sep 17 00:00:00 2001 From: Imane Khouani Date: Thu, 6 Feb 2025 17:48:39 +0100 Subject: [PATCH 06/10] no comments --- hydra-http-form.c | 152 ++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 65 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index f479369..02be7da 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -85,6 +85,11 @@ int32_t redirected_cpt = MAX_REDIRECT; char *cookie_request = NULL, *normal_request = NULL; // Buffers for HTTP headers + +void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr, + FILE *fp, int32_t port, char *hostname, char *type, + ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie); + /* * Function to perform some initial setup. */ @@ -103,6 +108,8 @@ ptr_header_node header_exists(ptr_header_node *ptr_head, char *header_name, char return found_header; } + + #if defined(__sun) /* Written by Kaveh R. Ghazi */ @@ -545,31 +552,31 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { char *build_multipart_body(char *multipart_boundary) { if (!variables) - return NULL; // Pas de paramètres à traiter + return NULL; - char *body = NULL; // Chaîne résultat - size_t body_size = 0; // Taille actuelle du corps + char *body = NULL; + size_t body_size = 0; - // Dupliquer la chaîne "variables" afin de pouvoir la tokeniser + // Duplicate "variables" for tokenizing char *vars_dup = strdup(variables); if (!vars_dup) return NULL; - // Tokeniser la chaîne sur le caractère '&' + // Tokenize the string using '&' as a delimiter char *pair = strtok(vars_dup, "&"); while (pair != NULL) { - // Pour chaque paire, rechercher le séparateur '=' + // Find the '=' separator in each pair char *equal_sign = strchr(pair, '='); if (!equal_sign) { pair = strtok(NULL, "&"); continue; } - *equal_sign = '\0'; // Terminer la clé + *equal_sign = '\0'; char *key = pair; char *value = equal_sign + 1; - // Construire la section multipart pour ce champ. - // Format attendu : + // Build the multipart section for the field + // Expected format: // --\r\n // Content-Disposition: form-data; name=""\r\n // \r\n @@ -594,9 +601,9 @@ char *build_multipart_body(char *multipart_boundary) { "%s\r\n", multipart_boundary, key, value); - // Réallouer le buffer "body" pour y ajouter cette section + // Reallocate the body buffer to add this section size_t new_body_size = body_size + section_len; - char *new_body = realloc(body, new_body_size + 1); // +1 pour le '\0' + char *new_body = realloc(body, new_body_size + 1); // +1 for null terminator if (!new_body) { free(section); free(body); @@ -604,21 +611,18 @@ char *build_multipart_body(char *multipart_boundary) { return NULL; } body = new_body; - if (body_size == 0) { + if (body_size == 0) strcpy(body, section); - } else { + else strcat(body, section); - } body_size = new_body_size; free(section); - // Passage à la paire suivante pair = strtok(NULL, "&"); } free(vars_dup); - // Ajouter la fermeture du multipart : - // ----\r\n + // Append the closing boundary: ----\r\n int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); char *closing = malloc(closing_len + 1); if (!closing) { @@ -853,12 +857,11 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH]; memset(header, 0, sizeof(header)); - cookie[0] = 0; // Réinitialiser les cookies d'une tentative antérieure + cookie[0] = 0; if (use_proxy > 0 && proxy_count > 0) selected_proxy = random() % proxy_count; - /* Récupération du prochain login/mot de passe */ if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) @@ -876,15 +879,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); - // Mise à jour des en‐têtes utilisateur (substitution dans les headers) hdrrep(&ptr_head, "^USER^", clogin); hdrrep(&ptr_head, "^PASS^", cpass); hdrrep(&ptr_head, "^USER64^", b64login); hdrrep(&ptr_head, "^PASS64^", b64pass); - /* Gestion du proxy (cas avec proxy authentifié ou non) */ if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { - /* --- Bloc pour proxy avec authentification --- */ if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); @@ -926,7 +926,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options return 1; } } else { - /* Cas GET avec proxy authentifié */ if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) hdrrepv(&ptr_head, "Content-Length", "0"); if (cookie_header != NULL) @@ -948,7 +947,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options } } } else if (use_proxy == 1) { - /* --- Bloc pour proxy sans authentification --- */ if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); @@ -1011,7 +1009,7 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options } } } else { - /* --- Bloc pour accès direct au serveur (sans proxy) --- */ + /* Direct access to the server (no proxy) */ normal_request = NULL; if (getcookie) { if (http_request != NULL) @@ -1028,50 +1026,64 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options } hydra_reconnect(s, ip, port, options, hostname); } - /* --- Traitement multipart --- */ if (multipart_mode) { char *multipart_body = NULL; - /* Définir le boundary (ici, une valeur fixe, sans '\r\n') */ char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; multipart_body = build_multipart_body(multipart_boundary); if (multipart_body == NULL) { hydra_report(stderr, "[ERROR] Failed to build multipart body.\n"); return 0; } - // now prepare for the "real" request - // first handle multipart/form-data, which is always POST - if (multipart_mode){ - char *multipart_body = NULL; - char multipart_boundary[32] = "----THC-HydraBoundaryz2Z2z\r\n"; - multipart_body = build_multipart_body(multipart_boundary); - if (multipart_body == NULL) { - hydra_report(stderr, "[ERROR] Failed to build multipart body. \n"); - return 0; - } - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - - char content_type[256]; - snprintf(content_type, sizeof(content_type) - 1, "multipart/for/data; boundary=%s", multipart_boundary); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Content-type", content_type); - - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - http_request = prepare_http_request("POST", url, multipart_body, normal_request); - free(multipart_body); + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + + char content_type[256]; + snprintf(content_type, sizeof(content_type) - 1, "multipart/form-data; boundary=%s", multipart_boundary); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Content-Type", content_type); + + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + + if (normal_request != NULL) + free(normal_request); + http_request = prepare_http_request("POST", url, multipart_body, normal_request); + free(multipart_body); + return 1; + } + if (strcmp(type, "POST") == 0) { + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("POST", url, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); return 1; } } else { @@ -1105,7 +1117,7 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options if (redirected_flag && code_302_is_success) found = success_cond; - if (auth_flag) { // 401 error + if (auth_flag) { if (code_401_is_failure) { hydra_completed_pair(); return 1; @@ -1121,15 +1133,13 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options if (strlen(cookie) > 0) process_cookies(&ptr_cookie, cookie); - // Gérer les redirections redirected_cpt = MAX_REDIRECT; if (debug) printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); while (found == 0 && redirected_flag && !code_302_is_success && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { - // Traitement de la redirection (code non modifié ici) - // ... + // Processing redirection (code omitted) } if (found != -1 && found == success_cond && @@ -1156,6 +1166,18 @@ void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *m } } +void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { + ptr_cookie_node ptr_cookie = NULL; + ptr_header_node ptr_head = initialize(ip, options, miscptr); + + if (ptr_head) + service_http_form(ip, sp, options, miscptr, fp, port, hostname, "POST", &ptr_head, &ptr_cookie); + else { + hydra_report(stderr, "[ERROR] Could not launch head. Error while initializing.\n"); + hydra_child_exit(2); + } +} + int32_t service_http_form_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { // called before the childrens are forked off, so this is the function // which should be filled if initial connections and service setup has to be From 80a11bb1e06cba6f174b3aba691e9a46b8b1aaa3 Mon Sep 17 00:00:00 2001 From: Imane Khouani Date: Thu, 6 Feb 2025 17:54:26 +0100 Subject: [PATCH 07/10] no comments --- hydra-http-form.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index 02be7da..8b105ba 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -1166,18 +1166,6 @@ void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *m } } -void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { - ptr_cookie_node ptr_cookie = NULL; - ptr_header_node ptr_head = initialize(ip, options, miscptr); - - if (ptr_head) - service_http_form(ip, sp, options, miscptr, fp, port, hostname, "POST", &ptr_head, &ptr_cookie); - else { - hydra_report(stderr, "[ERROR] Could not launch head. Error while initializing.\n"); - hydra_child_exit(2); - } -} - int32_t service_http_form_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { // called before the childrens are forked off, so this is the function // which should be filled if initial connections and service setup has to be From 65c897da68b0646a713a0d6c3757808c1b2c8e83 Mon Sep 17 00:00:00 2001 From: motypi Date: Fri, 7 Feb 2025 14:27:04 +0100 Subject: [PATCH 08/10] multipart feature finished --- hydra-http-form.c | 742 +++++++++++++++++++++++++++++----------------- 1 file changed, 473 insertions(+), 269 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index 8b105ba..1dd9521 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -8,7 +8,7 @@ web-based login forms that require username and password variables via either a GET or POST request. The module works similarly to the HTTP basic auth module and will honour -proxy mode (with authentication) as well as SSL. The module can be invoked +proxy mode (with authenticaion) as well as SSL. The module can be invoked with the service names of "http-get-form", "http-post-form", "https-get-form" and "https-post-form". @@ -76,7 +76,6 @@ char bufferurl[6096 + 24], cookieurl[6096 + 24] = "", userheader[6096 + 24] = "" #define MAX_REDIRECT 8 #define MAX_CONTENT_LENGTH 20 -#define MAX_CONTENT_DISPOSITION 200 #define MAX_PROXY_LENGTH 2048 // sizeof(cookieurl) * 2 char redirected_url_buff[2048] = ""; @@ -85,11 +84,6 @@ int32_t redirected_cpt = MAX_REDIRECT; char *cookie_request = NULL, *normal_request = NULL; // Buffers for HTTP headers - -void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr, - FILE *fp, int32_t port, char *hostname, char *type, - ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie); - /* * Function to perform some initial setup. */ @@ -108,8 +102,6 @@ ptr_header_node header_exists(ptr_header_node *ptr_head, char *header_name, char return found_header; } - - #if defined(__sun) /* Written by Kaveh R. Ghazi */ @@ -463,8 +455,8 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { else miscptr += strlen(miscptr); break; - case 'm': //fall through - case 'M': + case 'm': // fall through + case 'M': multipart_mode = 1; tmp = strchr(miscptr, ':'); if (tmp) @@ -551,100 +543,96 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { } char *build_multipart_body(char *multipart_boundary) { - if (!variables) - return NULL; + if (!variables) + return NULL; - char *body = NULL; - size_t body_size = 0; + char *body = NULL; + size_t body_size = 0; - // Duplicate "variables" for tokenizing - char *vars_dup = strdup(variables); - if (!vars_dup) - return NULL; + // Duplicate "variables" for tokenizing + char *vars_dup = strdup(variables); + if (!vars_dup) + return NULL; - // Tokenize the string using '&' as a delimiter - char *pair = strtok(vars_dup, "&"); - while (pair != NULL) { - // Find the '=' separator in each pair - char *equal_sign = strchr(pair, '='); - if (!equal_sign) { - pair = strtok(NULL, "&"); - continue; - } - *equal_sign = '\0'; - char *key = pair; - char *value = equal_sign + 1; + // Tokenize the string using '&' as a delimiter + char *pair = strtok(vars_dup, "&"); + while (pair != NULL) { + // Find the '=' separator in each pair + char *equal_sign = strchr(pair, '='); + if (!equal_sign) { + pair = strtok(NULL, "&"); + continue; + } + *equal_sign = '\0'; + char *key = pair; + char *value = equal_sign + 1; - // Build the multipart section for the field - // Expected format: - // --\r\n - // Content-Disposition: form-data; name=""\r\n - // \r\n - // \r\n - int section_len = snprintf(NULL, 0, - "--%s\r\n" - "Content-Disposition: form-data; name=\"%s\"\r\n" - "\r\n" - "%s\r\n", - multipart_boundary, key, value); - - char *section = malloc(section_len + 1); - if (!section) { - free(body); - free(vars_dup); - return NULL; - } - snprintf(section, section_len + 1, - "--%s\r\n" - "Content-Disposition: form-data; name=\"%s\"\r\n" - "\r\n" - "%s\r\n", - multipart_boundary, key, value); + // Build the multipart section for the field + int section_len = snprintf(NULL, 0, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); + + char *section = malloc(section_len + 1); + if (!section) { + free(body); + free(vars_dup); + return NULL; + } + snprintf(section, section_len + 1, + "--%s\r\n" + "Content-Disposition: form-data; name=\"%s\"\r\n" + "\r\n" + "%s\r\n", + multipart_boundary, key, value); - // Reallocate the body buffer to add this section - size_t new_body_size = body_size + section_len; - char *new_body = realloc(body, new_body_size + 1); // +1 for null terminator - if (!new_body) { - free(section); - free(body); - free(vars_dup); - return NULL; - } - body = new_body; - if (body_size == 0) - strcpy(body, section); - else - strcat(body, section); - body_size = new_body_size; - free(section); + // Reallocate the body buffer to add this section + size_t new_body_size = body_size + section_len; + char *new_body = realloc(body, new_body_size + 1); // +1 for null terminator + if (!new_body) { + free(section); + free(body); + free(vars_dup); + return NULL; + } + body = new_body; + if (body_size == 0) + strcpy(body, section); + else + strcat(body, section); + body_size = new_body_size; + free(section); - pair = strtok(NULL, "&"); - } - free(vars_dup); + pair = strtok(NULL, "&"); + } + free(vars_dup); - // Append the closing boundary: ----\r\n - int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); - char *closing = malloc(closing_len + 1); - if (!closing) { - free(body); - return NULL; - } - snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); - - size_t final_size = body_size + closing_len; - char *final_body = realloc(body, final_size + 1); - if (!final_body) { - free(closing); - free(body); - return NULL; - } - body = final_body; - strcat(body, closing); - free(closing); + // Append the closing boundary: ----\r\n + int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); + char *closing = malloc(closing_len + 1); + if (!closing) { + free(body); + return NULL; + } + snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); + + size_t final_size = body_size + closing_len; + char *final_body = realloc(body, final_size + 1); + if (!final_body) { + free(closing); + free(body); + return NULL; + } + body = final_body; + strcat(body, closing); + free(closing); - return body; + return body; } + char *prepare_http_request(char *type, char *path, char *params, char *headers) { uint32_t reqlen = 0; char *http_request = NULL; @@ -785,7 +773,7 @@ int32_t analyze_server_response(int32_t s) { if ((ptr = hydra_strcasestr(cookie, tmpname)) != NULL) { // yes it is. // if the cookie is not in the beginning of the cookiejar, copy the - // ones before + // ones before if (ptr != cookie && *(ptr - 1) == ' ') { strncpy(tmpcookie, cookie, ptr - cookie - 2); tmpcookie[ptr - cookie - 2] = 0; @@ -845,9 +833,7 @@ void hydra_reconnect(int32_t s, char *ip, int32_t port, unsigned char options, c } } -int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, - char *miscptr, FILE *fp, char *hostname, char *type, - ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) { +int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp, char *hostname, char *type, ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) { char *empty = ""; char *login, *pass, clogin[256], cpass[256], b64login[345], b64pass[345]; char header[8096], *upd3variables; @@ -855,13 +841,14 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options char *http_request = NULL; int32_t found = !success_cond, i, j; char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH]; - + char content_type[256]; memset(header, 0, sizeof(header)); - cookie[0] = 0; + cookie[0] = 0; // reset cookies from potential previous attempt if (use_proxy > 0 && proxy_count > 0) selected_proxy = random() % proxy_count; + // Take the next login/pass pair if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) @@ -874,16 +861,37 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options clogin[sizeof(clogin) - 1] = 0; strncpy(cpass, html_encode(pass), sizeof(cpass) - 1); cpass[sizeof(cpass) - 1] = 0; - upd3variables = hydra_strrep(variables, "^USER^", clogin); - upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); - upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); - upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); + if (multipart_mode) { + char multipart_boundary[32] = "----THC-HydraBoundaryz2Z2z"; + + snprintf(content_type, sizeof(content_type), "multipart/form-data; boundary=%s", multipart_boundary); + char *multipart_body = build_multipart_body(multipart_boundary); + upd3variables = multipart_body; + + upd3variables = hydra_strrep(upd3variables, "^USER^", clogin); + upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); + upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); + upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); + +}else{ + snprintf(content_type, sizeof(content_type), "application/x-www-form-urlencoded"); + + upd3variables = hydra_strrep(variables, "^USER^", clogin); + upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); + upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); + upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); +} + + + + // Replace the user/pass placeholders in the user-supplied headers hdrrep(&ptr_head, "^USER^", clogin); hdrrep(&ptr_head, "^PASS^", cpass); hdrrep(&ptr_head, "^USER64^", b64login); hdrrep(&ptr_head, "^PASS64^", b64pass); + /* again: no snprintf to be portable. don't worry, buffer can't overflow */ if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); @@ -893,11 +901,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; - i = analyze_server_response(s); + i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) process_cookies(&ptr_cookie, cookie); hydra_reconnect(s, ip, port, options, hostname); } + // now prepare for the "real" request if (strcmp(type, "POST") == 0) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); @@ -907,69 +916,10 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options else add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } - } else { - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", "0"); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; - } - } - } else if (use_proxy == 1) { - if (getcookie) { - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) - return 1; - i = analyze_server_response(s); - if (strlen(cookie) > 0) - process_cookies(&ptr_cookie, cookie); - hydra_reconnect(s, ip, port, options, hostname); - } - if (strcmp(type, "POST") == 0) { - memset(proxy_string, 0, sizeof(proxy_string)); - snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); + if (multipart_mode) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + else + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); if (cookie_header != NULL) free(cookie_header); cookie_header = stringify_cookies(ptr_cookie); @@ -1009,102 +959,137 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options } } } else { - /* Direct access to the server (no proxy) */ - normal_request = NULL; - if (getcookie) { - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) - return 1; - i = analyze_server_response(s); - if (strlen(cookie) > 0) { - process_cookies(&ptr_cookie, cookie); + if (use_proxy == 1) { + // proxy without authentication + if (getcookie) { + // doing a GET to get cookies + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) + return 1; + i = analyze_server_response(s); // ignore result + if (strlen(cookie) > 0) + process_cookies(&ptr_cookie, cookie); + hydra_reconnect(s, ip, port, options, hostname); + } + // now prepare for the "real" request + if (strcmp(type, "POST") == 0) { + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); if (normal_request != NULL) free(normal_request); normal_request = stringify_headers(&ptr_head); - } - hydra_reconnect(s, ip, port, options, hostname); - } - if (multipart_mode) { - char *multipart_body = NULL; - char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; - multipart_body = build_multipart_body(multipart_boundary); - if (multipart_body == NULL) { - hydra_report(stderr, "[ERROR] Failed to build multipart body.\n"); - return 0; - } - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - - char content_type[256]; - snprintf(content_type, sizeof(content_type) - 1, "multipart/form-data; boundary=%s", multipart_boundary); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Content-Type", content_type); - - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - - if (normal_request != NULL) - free(normal_request); - http_request = prepare_http_request("POST", url, multipart_body, normal_request); - free(multipart_body); - return 1; - } - if (strcmp(type, "POST") == 0) { - snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", content_length); - else - add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); - if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("POST", url, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } + } else { + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", "0"); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } } } else { - if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) - hdrrepv(&ptr_head, "Content-Length", "0"); - if (cookie_header != NULL) - free(cookie_header); - cookie_header = stringify_cookies(ptr_cookie); - if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) - add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); - else - hdrrepv(&ptr_head, "Cookie", cookie_header); - if (normal_request != NULL) - free(normal_request); - normal_request = stringify_headers(&ptr_head); - if (http_request != NULL) - free(http_request); - http_request = prepare_http_request("GET", url, upd3variables, normal_request); - if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { - free(cookie_header); - return 1; + // direct web server, no proxy + normal_request = NULL; + if (getcookie) { + // doing a GET to save cookies + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) + return 1; + i = analyze_server_response(s); // ignore result + if (strlen(cookie) > 0) { + // printf("[DEBUG] Got cookie: %s\n", cookie); + process_cookies(&ptr_cookie, cookie); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + } + hydra_reconnect(s, ip, port, options, hostname); + } + // now prepare for the "real" request + if (strcmp(type, "POST") == 0) { + snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(upd3variables)); + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", content_length); + else + add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); + if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("POST", url, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } + } else { + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", "0"); + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", url, upd3variables, normal_request); + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } } } } @@ -1114,11 +1099,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options found = analyze_server_response(s); - if (redirected_flag && code_302_is_success) + if (redirected_flag && code_302_is_success) { found = success_cond; + } - if (auth_flag) { - if (code_401_is_failure) { + if (auth_flag) { // we received a 401 error - user may be using wrong module + if (code_401_is_failure) { // apparently they don't think so -- treat 401 as failure hydra_completed_pair(); return 1; } else { @@ -1133,18 +1119,159 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options if (strlen(cookie) > 0) process_cookies(&ptr_cookie, cookie); + // if page was redirected, follow the location header redirected_cpt = MAX_REDIRECT; if (debug) printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); - while (found == 0 && redirected_flag && !code_302_is_success && - (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { - // Processing redirection (code omitted) + while (found == 0 && redirected_flag && !code_302_is_success && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { + // we have to split the location + char *startloc, *endloc; + char str[2048], str2[2048], str3[2048], str4[2048]; + + redirected_cpt--; + redirected_flag = 0; + // check if the redirect page contains the fail/success condition +#ifdef HAVE_PCRE + if (hydra_string_match(redirected_url_buff, cond) == 1) { +#else + if (strstr(redirected_url_buff, cond) != NULL) { +#endif + found = success_cond; + } else { + // location could be either absolute http(s):// or / something + // or relative + startloc = strstr(redirected_url_buff, "://"); + if (startloc != NULL) { + startloc += strlen("://"); + + if ((endloc = strchr(startloc, '\r')) != NULL) { + *endloc = 0; + } + if ((endloc = strchr(startloc, '\n')) != NULL) { + *endloc = 0; + } + strncpy(str, startloc, sizeof(str) - 1); + str[sizeof(str) - 1] = 0; + + endloc = strchr(str, '/'); + if (endloc != NULL) { + strncpy(str2, str, endloc - str); + str2[endloc - str] = 0; + } else { + strcpy(str2, str); + } + + if (strlen(str) - strlen(str2) == 0) { + strcpy(str3, "/"); + } else { + strncpy(str3, str + strlen(str2), strlen(str) - strlen(str2)); + str3[strlen(str) - strlen(str2)] = 0; + } + } else { + strncpy(str2, webtarget, sizeof(str2) - 1); + str2[sizeof(str2) - 1] = 0; + if (redirected_url_buff[0] != '/') { + // it's a relative path, so we have to concatenate it + // with the path from the first url given + char *urlpath; + char urlpath_extracted[2048]; + + memset(urlpath_extracted, 0, sizeof(urlpath_extracted)); + + urlpath = strrchr(url, '/'); + if (urlpath != NULL) { + strncpy(urlpath_extracted, url, urlpath - url); + sprintf(str3, "%.1000s/%.1000s", urlpath_extracted, redirected_url_buff); + } else { + sprintf(str3, "%.1000s/%.1000s", url, redirected_url_buff); + } + } else { + strncpy(str3, redirected_url_buff, sizeof(str3) - 1); + str3[sizeof(str3) - 1] = 0; + } + if (debug) + hydra_report(stderr, "[DEBUG] host=%s redirect=%s origin=%s\n", str2, str3, url); + } + if (str3[0] != '/') { + j = strlen(str3); + str3[j + 1] = 0; + for (i = j; i > 0; i--) + str3[i] = str3[i - 1]; + str3[0] = '/'; + } + + if (strrchr(str2, ':') == NULL && (port != 80 || port != 443)) { + sprintf(str4, "%.2000s:%d", str2, port); + strcpy(str2, str4); + } + + if (verbose) + hydra_report(stderr, "[VERBOSE] Page redirected to http[s]://%s%s\n", str2, str3); + + if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) + hdrrepv(&ptr_head, "Content-Length", "0"); + + // re-use the above code to set cookies + if (cookie_header != NULL) + free(cookie_header); + cookie_header = stringify_cookies(ptr_cookie); + if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) + add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); + else + hdrrepv(&ptr_head, "Cookie", cookie_header); + + // re-use the code above to check for proxy use + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { + // proxy with authentication + hdrrepv(&ptr_head, "Host", str2); + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, str3); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); + } else { + if (use_proxy == 1) { + // proxy without authentication + hdrrepv(&ptr_head, "Host", str2); + memset(proxy_string, 0, sizeof(proxy_string)); + snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, str3); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); + } else { + // direct web server, no proxy + hdrrepv(&ptr_head, "Host", str2); + if (normal_request != NULL) + free(normal_request); + normal_request = stringify_headers(&ptr_head); + if (http_request != NULL) + free(http_request); + http_request = prepare_http_request("GET", str3, NULL, normal_request); + } + } + + hydra_reconnect(s, ip, port, options, hostname); + + if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { + free(cookie_header); + return 1; + } + + found = analyze_server_response(s); + if (strlen(cookie) > 0) + process_cookies(&ptr_cookie, cookie); + } } - if (found != -1 && found == success_cond && - ((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && - redirected_cpt >= 0) { + // if the last status is still 3xx, set it as a false + if (found != -1 && found == success_cond && ((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && redirected_cpt >= 0) { hydra_report_found_host(port, ip, "www-form", fp); hydra_completed_pair_found(); } else { @@ -1154,6 +1281,83 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options return 1; } +void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname, char *type, ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie) { + int32_t run = 1, next_run = 1, sock = -1; + int32_t myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; + + // register our socket descriptor + hydra_register_socket(sp); + + /* + * Iterate through the runs. Possible values are the following: + * - 1 -> Open connection to remote server. + * - 2 -> Run password attempts. + * - 3 -> Disconnect and end with success. + * - 4 -> Disconnect and end with error. + */ + + while (1) { + if (run == 2) { + if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { + hydra_child_exit(1); + } + } + switch (run) { + case 1: /* connect and service init function */ + { + if (sock >= 0) + sock = hydra_disconnect(sock); + if ((options & OPTION_SSL) == 0) { + if (port != 0) + myport = port; + sock = hydra_connect_tcp(ip, myport); + port = myport; + } else { + if (port != 0) + mysslport = port; + sock = hydra_connect_ssl(ip, mysslport, hostname); + port = mysslport; + } + if (sock < 0) { + hydra_report(stderr, "[ERROR] Child with pid %d terminating, cannot connect\n", (int32_t)getpid()); + hydra_child_exit(1); + } + next_run = 2; + break; + } + case 2: /* run the cracking function */ + next_run = start_http_form(sock, ip, port, options, miscptr, fp, hostname, type, *ptr_head, *ptr_cookie); + break; + case 3: /* clean exit */ + if (sock >= 0) + sock = hydra_disconnect(sock); + hydra_child_exit(0); + break; + case 4: /* silent error exit */ + if (sock >= 0) + sock = hydra_disconnect(sock); + hydra_child_exit(1); + break; + default: + hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n"); + hydra_child_exit(0); + } + run = next_run; + } +} + +void service_http_get_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { + ptr_cookie_node ptr_cookie = NULL; + ptr_header_node ptr_head = initialize(ip, options, miscptr); + + if (ptr_head) + service_http_form(ip, sp, options, miscptr, fp, port, hostname, "GET", &ptr_head, &ptr_cookie); + else { + hydra_report(stderr, "[ERROR] Could not launch head. Error while initializing.\n"); + hydra_child_exit(2); + } +} + void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { ptr_cookie_node ptr_cookie = NULL; ptr_header_node ptr_head = initialize(ip, options, miscptr); From ba9a3ba8de63e5ab95e8bc57c88704ed19a5d7e2 Mon Sep 17 00:00:00 2001 From: motypi Date: Mon, 10 Feb 2025 10:37:17 +0100 Subject: [PATCH 09/10] add help for multipart mode, remove junk files --- .vscode/tasks.json | 28 --------- Test | Bin 20352 -> 0 bytes Test.c | 122 --------------------------------------- hydra-http-form.c | 1 + peda-session-61558.txt | 3 - peda-session-61747.txt | 3 - peda-session-62215.txt | 3 - peda-session-62317.txt | 3 - peda-session-unknown.txt | 8 --- 9 files changed, 1 insertion(+), 170 deletions(-) delete mode 100644 .vscode/tasks.json delete mode 100755 Test delete mode 100644 Test.c delete mode 100644 peda-session-61558.txt delete mode 100644 peda-session-61747.txt delete mode 100644 peda-session-62215.txt delete mode 100644 peda-session-62317.txt delete mode 100644 peda-session-unknown.txt diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 08d9005..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "tasks": [ - { - "type": "cppbuild", - "label": "C/C++: gcc build active file", - "command": "/usr/bin/gcc", - "args": [ - "-fdiagnostics-color=always", - "-g", - "${file}", - "-o", - "${fileDirname}/${fileBasenameNoExtension}" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ], - "version": "2.0.0" -} \ No newline at end of file diff --git a/Test b/Test deleted file mode 100755 index df20b3b002e7d4165240acf776edc16751f5d9d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20352 zcmeHPdvILUc|UhoS6W$bOMXZucr7rP$F3|PjBRkdwk5Lyzwo0N61ZCJL)v<^D|YYt zK>{{7Fjf_}b_>LvG>Kr!;IyW3J1|jsMLc3dCuB_10BMGn(xga%rY1aUUf%w`bI!L~ zT_nG~LQeb>QGcahfk ze8AnjS=TpRKMd>qGt}u7Es1!~lJ=HF#FvOCv%7t}moD)wY4>MR{x(@L#pT68W9sS+ z+XUQ<5>Ka5xb`WU{gJFe%Sr#?z&{^+^qOz4-+uCiMW61<&3XGbXZMp%H;&tz&i>un zj*a3g&Gw#wX!G*sNVKQ<(&khKXtpPtw6ma+p?(teBF-?#ozZkAo=Sq#=5Jr@YgKxe zK@v)b`{H&qY-iJC5bBRCX>Yy_)yVNed7>C8CMpy^4@sg4r&|H($ow030240a&BXCi z^vC_nelx_EDaj_4W>BQ(EZ2fD75^CcUZ*l>s(&hdj>Bn^nMQxcG<>=qrt<$h_+A{& z(gDU)`j=0`_fNy8%X=z6w@$-<1$-|KXSooJsr*F1r#^6&o4}|O^Mp5`Bz!**89N;w z*dsE@fpk1+$Ao2N>`-`z74F+%#X|9fh^3=Z(u!mU2-v9|A{`AS5~;AX4cVe!QItJhc<&Ux&z z3AD|Bxv;vnuD9SZ+8fW<(e&2!YZ9qsbZe+55k(!n{i&p`+)}DjDx&!=jCup-5*+kL zIR7zjK<5tV@_nTt9Y2q>dHxo2H_{SfZpy`1>{>KwEJ?O{poS^9eKc1eT>A^nUGeOe? zW_{;mgm!U*mU!HrtX8u0Xdsai}zeB=?PZR`&ZmaXmIeCc4csA#oZvr z;%9TYu?TwSgn2J$<0jbV>nHp1T@Vto4R#os`+|eF9YCd1CO zMYD90eEO+$f(zufQzH8Xr14G64ugXyen7R2`PuM*GCXxc*`wZ9;Rj};2JqK|L+f#D zBi@0o!56v)PXz~`hO=)=XU{xE&ZI}#vayFy>tN?SL!I}K{SgY}&s88}2xLrTo8d^Z zeZ;2rKxF}Nm6;l}QX7X)2ZwH>`cd~bB(Za>Yw*La!RLd6FHsI;{U=qet+0nxFnkJX z!$AWvcETFR!A%ArDwNr}NQH6+p_~y}Kl!BUANWLuBEz~*;WDg00ItH?t&(&GeviO- zSY$C4w~ZCJPD1ysdI$4o%Gqg{4Rd9e6YrpTBd+v(XWUP`!Oo*_eN@!k)lPk*Q&Xy3 z98g*BmR6t1dMlI$I}Z(Y9?ECkuUwA6<%r16R*{|@`~Jt=qzBP)+JG`GGd!Yl`w{L+ z$cxJDPhkPQNx2<`yHQ7OUxXgo@H{GfUS#J(1Kv)KttGbZ^5tClTbF=^jzlttwv8yU z?4YAcTUu6X%NL%VxS-w+M1n&l3l|}FSf6Pf4UYIwwg%Vuf{z9FMAD(vsVpQI02s0( zl1xTI!N<~jZf(18LLb4w;W$M82PXY(DCEiXIo}tPgS9 zChbOQ0P)_sR5joPgr6v(%GNhNlFdciPL5p*TyoLKGm+pW4Ki-q9NP?mYL$GR<)2`1 zTr9;56f;oFKrsWw3=}g^%s?>%`3%td29<0knx-Yi6?QaZ6LG;nD3jThN=GDz2(0%D z;qxubRLxkEO4`w+?dynV22z>0jg`mc-dHN#?~8=&(3M{4sd-_hxoSq$3^I^*J|7TW zI@9S?+S`+jCnE7=ueU#&u;T+*DDw8CB76KZ#QI5$e)JYfGvE|&o8 zIGxMg1Gp9N7+}LYx!hL3PXV6;-0*%b_Y30Vpkmy*Ss1%(jd_)2o)5}y_?M_^Cw z6CGvpXZrJjwiAtdP7$oGU0Xf(nwpATo_%6v)3S>%JHMIOWdCIxN1<2v`#$k)9K+y` z0&=0czK)|6@m)v1i*#1k-tAgbRq7795t59B+R^h~F84BEUhaC4#Kls~KrsWw3=}g^ z%s?>%#S9cPP|QFv1OJaRz~6cCcU|;5HMsB< zoFt68dh%s{=uvbf3 zJ(YmQrSN@OSqyv?^pbMY_ZT(cUm@{Y;{hlxmH1qv4Ohc5iF=JZptD@!i;P*&xl-bb zjZ^S&mBg1CmqBNR!~@1(0}n_%XnX?wRTAH190$Hy;@gdFz&mCy#JSs`3w>?F#lZWF zGS~)XoCC&>fOkpUHm(PLO$Gf7vD;V)eErPpfbTN~VYQ)VJMcRV`axx*rv;q-#tGZV_=^nhF{M zV9o_zel6*A5cU$dJSM! z1z3isjQY0R%^%p7o+SMpMkRIsbHH8Xs!DkN5%u3ox~~zF5GfI!A3$)B=np0fN*5wc zp1*WeQ*vekcM;-}ZJPZaP|x>VRiq>NqLgm2o?)ea6|tpe=?~$x^bQrz&BT^flZ+$# zBLwgPad(lJ!ga~9Te=W}vWQVlvOgi&VX{g?L3qY-ew+jkv5}bL18Ve}Wc-o7;lB)= zit%S}Lg-!ttJDlaU55j1+Kh5b1vzma9@(pU;y)piJ<%lQ{t9xVQYM%$botwt^w+oy zzKqIdWq#&%H>Idndpoe#eIc~!D)F%joFCfjJ_o)Uv~+l{I|1WHO&;0n&Ov&8IR)-M zyl=1jNl3SA>CwIJRq$+SSI76dD?xT^>B!!u=6aZ+&_^Fs-2VjYb809qG;-dK=pJD- zYcl8#L+dLpdG-mmR-e;2|wE!^%t4;})w)B@MxZuh@Hwo1$Tz%#0ZyL$P8 zk}E5gRdm%a#RJ!6iY~30!yrmYgptD!y3ZuEvaS`vz%H9j))mSa{j9YXl!3FLdP1+f9(q?{nlZyLy6VZYVgageK^&D=$T+I# z*;`#_EUd1taL=DNzs{IhR*UC&4MKoctq#hAZn{7k%&a%u)fE-0a`IR|5eqs`HcJP# zvXQEuHJL?Cojti#s!en9Oyr81K%oTYepNPj?sP&75VIf`drF1i+-v*n!M14FIQO4~_?L{1C^lakz~6uA1^?zzjNxkBL_TD|aPM zCG~V_!pUr=(*2qAzghdFS?BIT-KKllF>}sS<|5akdUICH^t@u0XU*Ej z&GUv$GiILWYHlzqW9Hn45!rVjdYoi4cADmXII4WYG_Eyk7e8js_&4($*U|>l^R6^^ zomX#~yI@fHxM|$rnvG0aRw@>=Y;4WgXki0M#2T>E`K=@2KH4vmjP9~%J;2JyeIhuK zex@&#wtKQM+OyQfVLdwxqB!!Gdril<8wJ);k~w#|miK4n$@3 zgfiI0LZVZnXF@xps)eMFeL@!Y{p^5Wimy#r{fL6M0demMxyobZmw05C zif{r8N6B6bji=_uWj7SWB-=QUj_y=Lfr6!~FaQc2W$_(S8c{&HwrgD{0+0>Ohq+gEQfZV8CSN_+Rh1o3$&`DcR9^C3l)$E@{LU)5eTuA9hsl7Hk-Rio z`cnPTmT(ALp5oz9OGhf4?Z^6Dre#w)_4`rVyKzg4{En-|?hE_+=!-7j`nD}wx>~kk zwa*_GzpK4y$!5~DRkEcw9B#p-W-V#g8zy^`*_PJ!mUuFp$YM-LMNNEGu_tb4{u?SS zv>$S^BIP?0jrse8lmQ~$*|05#gQOzyl;UEvDF)&N^7#dKXYB5JC+F0n_fZ26h)*zg zpyHKhJmLVS(x>-T7k1j6uG5Mdcs1W!xM>Q!%QT;VF90b^7tRLu>n#c>n&P9f4TmA- z2!8*UOq{-ogX-nqADDjth#_X@_oFfYAs|!5KV7^2O8S{4jxS&j6L2a&Pe}c_!udW- z4^LV}J?522{`4v^Lp0`pS6~4>XdNk&BI>BA_%vPgN{z{@Ml88lM|k=k4ZjTPr#4Cuf_OW9GKt{cE9#Bs>lBYEXIU+ zs`fU3Pky`sR#ea{_3J+KK0+_UQ~6m6ejV~ttNmbhD$D9=^y$@lDnEVX2YGY$yA8fq z`z!>1IE|nC!EY{9)c6ym@4~Nsj^Ayb0e{NgS4Ot=+t8eW%sAp~J!^+>RSItXki-2F94W zS)D;G4R&l6*467au3ojy+PHS@md>r#)>W(5by{-16ySZpa?7uCPjOy~y}_TiA6QLS z^4ii@R6YKwod{|2Hs`!%J3UY^Gs-i_ly^r@Vj|C&PN*%%@Hct?u@%XrtiDh(LVJ^G zCSl{d7mKD0Q%{f79_q>dY2u-`T2B^OJ(-NISMRf?ZP}A_CZ<@_oRB?9sJ32DVp$fp zQ**!3KI%wMx@D@S;80UTB7ry|}P78BfMijE8!9FlA;6|GENMP)5in zqr}E=Nl$S*`X94sJp#9Q%r#VT{y!I9kI-VN%Q!*$ZG?WJW&7#=ZwcvA;rqCvgjfQk z(BAp~OU`FS4f*-TY?@aU+J9Zo>lhBO;xzWxJM4L0$k6*+?4yu>fHeqizgGvyaFMpB z7^yhhPm39}M#J{Jj>GVI>KqiZBb4pwrw%H+a8Q%kp4WvKzC%g{MZ3#$_5!0d7PjYg z6^8u0=lJt_+5`Q%Mr$_A=XD!~0j=kZU$ezGfl$iWp4X8Wp4N(7zq9=hYWvk%kJqIb zdUb=z9=}w5CV$@pk5o!=$imNY4SBte#m@2f7Z4QMd$k?IQ*5ZA!@YRaVSidHFl2pp z!!$$MYF1c3CLOA1II2koY{&2<1cmlI&tq6?vZaD-$J`ek_B@Yfh?&u(;>_Pqv_1E~ z@M?7pk7<$t_dnA=2SV|)J->%Ayowbybk;xaupjd(MTS4pb_|^LzY76=&Xw07>F_!) z|Gy%qKGO{8y{D$Yp5FueeB^CnyeevfX8Q^>p2n`e?d9Lk`2SBi|IZZLaXw6i|aK5fz ztLLR`zc9~H2*pZ;;UaCXxD)3U+M&}g+p*>q)7bZG!&$7#Q28v8phS2fU@P+@V9 z;<{<<>#k5%v?5nn9Hh8O+dJEN>r!R4jypy>VS9#s)7YQ5QW> -#include -#include - -// On définit ici la variable globale "variables" qui sera utilisée par build_multipart_body. -// On suppose qu'elle contient des paires clé=valeur séparées par '&'. -// Pour ce test, on utilise par exemple : -char *variables = "username=testuser&password=testpass"; - -// La fonction build_multipart_body construit le corps d'une requête multipart/form-data -// à partir de la chaîne globale "variables" et du boundary fourni. -char *build_multipart_body(char *multipart_boundary) { - if (!variables) - return NULL; // Pas de paramètres à traiter - - char *body = NULL; // Chaîne résultat - size_t body_size = 0; // Taille actuelle du corps - - // Dupliquer la chaîne "variables" afin de pouvoir la tokeniser (strtok modifie la chaîne) - char *vars_dup = strdup(variables); - if (!vars_dup) - return NULL; - - // Tokeniser la chaîne sur le caractère '&' - char *pair = strtok(vars_dup, "&"); - while (pair != NULL) { - // Pour chaque paire, rechercher le séparateur '=' - char *equal_sign = strchr(pair, '='); - if (!equal_sign) { - pair = strtok(NULL, "&"); - continue; - } - *equal_sign = '\0'; // Terminer la clé - char *key = pair; - char *value = equal_sign + 1; - - // Construire la section multipart pour ce champ. - // Format attendu : - // --\r\n - // Content-Disposition: form-data; name=""\r\n - // \r\n - // \r\n - int section_len = snprintf(NULL, 0, - "--%s\r\n" - "Content-Disposition: form-data; name=\"%s\"\r\n" - "\r\n" - "%s\r\n", - multipart_boundary, key, value); - - char *section = malloc(section_len + 1); - if (!section) { - free(body); - free(vars_dup); - return NULL; - } - snprintf(section, section_len + 1, - "--%s\r\n" - "Content-Disposition: form-data; name=\"%s\"\r\n" - "\r\n" - "%s\r\n", - multipart_boundary, key, value); - - // Réallouer le buffer "body" pour y ajouter cette section - size_t new_body_size = body_size + section_len; - char *new_body = realloc(body, new_body_size + 1); // +1 pour le '\0' - if (!new_body) { - free(section); - free(body); - free(vars_dup); - return NULL; - } - body = new_body; - if (body_size == 0) - strcpy(body, section); - else - strcat(body, section); - body_size = new_body_size; - free(section); - - // Passage à la paire suivante - pair = strtok(NULL, "&"); - } - free(vars_dup); - - // Ajouter la fermeture du multipart : - // ----\r\n - int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); - char *closing = malloc(closing_len + 1); - if (!closing) { - free(body); - return NULL; - } - snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); - - size_t final_size = body_size + closing_len; - char *final_body = realloc(body, final_size + 1); - if (!final_body) { - free(closing); - free(body); - return NULL; - } - body = final_body; - strcat(body, closing); - free(closing); - - return body; -} - -int main(void) { - // Définir un boundary pour le test - char boundary[] = "----THC-HydraBoundaryz2Z2z"; - // Appeler la fonction build_multipart_body - char *multipart_body = build_multipart_body(boundary); - if (multipart_body == NULL) { - fprintf(stderr, "Error building multipart body.\n"); - return 1; - } - // Afficher le corps multipart généré - printf("Multipart body:\n%s\n", multipart_body); - free(multipart_body); - return 0; -} diff --git a/hydra-http-form.c b/hydra-http-form.c index 1dd9521..0b42268 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -1602,6 +1602,7 @@ void usage_http_form(const char *service) { "and the condition string; seperate them too with colons:\n" " 1= 401 error response is interpreted as user/pass wrong\n" " 2= 302 page forward return codes identify a successful attempt\n" + " M= attack forms that use multipart format\n" " (c|C)=/page/uri to define a different page to gather initial " "cookies from\n" " (g|G)= skip pre-requests - only use this when no pre-cookies are required\n" diff --git a/peda-session-61558.txt b/peda-session-61558.txt deleted file mode 100644 index e50613c..0000000 --- a/peda-session-61558.txt +++ /dev/null @@ -1,3 +0,0 @@ -break main - -set exec-wrapper logging enabled diff --git a/peda-session-61747.txt b/peda-session-61747.txt deleted file mode 100644 index e50613c..0000000 --- a/peda-session-61747.txt +++ /dev/null @@ -1,3 +0,0 @@ -break main - -set exec-wrapper logging enabled diff --git a/peda-session-62215.txt b/peda-session-62215.txt deleted file mode 100644 index e50613c..0000000 --- a/peda-session-62215.txt +++ /dev/null @@ -1,3 +0,0 @@ -break main - -set exec-wrapper logging enabled diff --git a/peda-session-62317.txt b/peda-session-62317.txt deleted file mode 100644 index e50613c..0000000 --- a/peda-session-62317.txt +++ /dev/null @@ -1,3 +0,0 @@ -break main - -set exec-wrapper logging enabled diff --git a/peda-session-unknown.txt b/peda-session-unknown.txt deleted file mode 100644 index ddb86e5..0000000 --- a/peda-session-unknown.txt +++ /dev/null @@ -1,8 +0,0 @@ - -set exec-wrapper logging enabled - -set exec-wrapper logging enabled - -set exec-wrapper logging enabled - -set exec-wrapper logging enabled From db099fcdacce542bca290c38a03c886a0db0ab78 Mon Sep 17 00:00:00 2001 From: motypi Date: Mon, 10 Feb 2025 14:57:07 +0100 Subject: [PATCH 10/10] cleaning code --- hydra-http-form.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/hydra-http-form.c b/hydra-http-form.c index 0b42268..4c6919b 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -863,26 +863,20 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options cpass[sizeof(cpass) - 1] = 0; if (multipart_mode) { - char multipart_boundary[32] = "----THC-HydraBoundaryz2Z2z"; - - snprintf(content_type, sizeof(content_type), "multipart/form-data; boundary=%s", multipart_boundary); - char *multipart_body = build_multipart_body(multipart_boundary); + snprintf(content_type, sizeof(content_type), "multipart/form-data; boundary=----THC-HydraBoundaryz2Z2z"); + char *multipart_body = build_multipart_body("----THC-HydraBoundaryz2Z2z"); upd3variables = multipart_body; +}else{ + snprintf(content_type, sizeof(content_type), "application/x-www-form-urlencoded"); + upd3variables = variables; +} + upd3variables = hydra_strrep(upd3variables, "^USER^", clogin); upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); -}else{ - snprintf(content_type, sizeof(content_type), "application/x-www-form-urlencoded"); - - upd3variables = hydra_strrep(variables, "^USER^", clogin); - upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); - upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login); - upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass); -} - // Replace the user/pass placeholders in the user-supplied headers @@ -916,9 +910,6 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options else add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) - if (multipart_mode) - add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); - else add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); if (cookie_header != NULL) free(cookie_header);