Merge pull request from motypi/add-distributed-computing

Add distributed computing
This commit is contained in:
van Hauser 2025-03-12 10:52:40 +01:00 committed by GitHub
commit 9bf9f8ba76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 106 additions and 3 deletions

108
hydra.c

@ -343,6 +343,11 @@ int32_t prefer_ipv6 = 0, conwait = 0, loop_cnt = 0, fck = 0, options = 0, killed
int32_t child_head_no = -1, child_socket;
int32_t total_redo_count = 0;
// requred for distributed attack capability
uint32_t num_segments = 0;
uint32_t my_segment = 0;
char junk_file[50];
// moved for restore feature
int32_t process_restore = 0, dont_unlink;
char *login_ptr = NULL, *pass_ptr = "", *csv_ptr = NULL, *servers_ptr = NULL;
@ -519,6 +524,8 @@ void help(int32_t ext) {
"instead of -L/-P options\n"
" -M FILE list of servers to attack, one entry per "
"line, ':' to specify port\n");
PRINT_NORMAL(ext, " -D XofY Divide wordlist into Y segments and use the "
"Xth segment.\n");
PRINT_EXTEND(ext, " -o FILE write found login/password pairs to FILE instead of stdout\n"
" -b FORMAT specify the format for the -o FILE: text(default), json, "
"jsonv1\n"
@ -1591,6 +1598,73 @@ char *hydra_reverse_login(int32_t head_no, char *login) {
return hydra_heads[head_no]->reverse;
}
void delete_junk_files(){
remove(junk_file);
}
FILE *hydra_divide_file(FILE *file, uint32_t my_segment, uint32_t num_segments){
if(my_segment > num_segments){
fprintf(stderr, "[ERROR] in option -D XofY, X must not be greater than Y: %s\n", hydra_options.passfile);
return NULL;
}
FILE *output_file;
char line[500];
char output_file_name[50];
uint32_t line_number = 0;
double total_lines = countlines(file,0);
if(num_segments > total_lines){
fprintf(stderr, "[ERROR] in option -D XofY, Y must not be greater than the total number of lines in the file to be divided: %s\n", hydra_options.passfile);
return NULL;
}
double segment_size_double = total_lines / num_segments;
// round up segment_size_float to integer
uint64_t segment_size = (uint64_t)segment_size_double;
if(segment_size < segment_size_double)
segment_size++;
uint64_t segment_start = segment_size * (my_segment - 1) + 1;
uint64_t segment_end = segment_size * my_segment;
srand(time(NULL));
int filetag = rand();
sprintf(output_file_name, "segment_%d_%d.txt",filetag, my_segment);
output_file = fopen(output_file_name, "w");
if(!output_file){
fprintf(stderr, "[ERROR] Segment file empty: %s\n", hydra_options.passfile);
return NULL;
}
strcpy(junk_file, output_file_name);
atexit(delete_junk_files);
while(fgets(line, sizeof line, file) != NULL && line_number < segment_end){
line_number++;
if(line_number >= segment_start && line_number <= segment_end)
fprintf(output_file, "%s", line);
}
rewind(file);
fclose(output_file);
output_file = fopen(output_file_name, "r");
return output_file;
}
int32_t hydra_send_next_pair(int32_t target_no, int32_t head_no) {
// variables moved to save stack
snpdone = 0;
@ -2171,7 +2245,7 @@ void process_proxy_line(int32_t type, char *string) {
int main(int argc, char *argv[]) {
char *proxy_string = NULL, *device = NULL, *memcheck;
char *outfile_format_tmp;
FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL, *proxyfp;
FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL, *proxyfp, *filecloser=NULL;
size_t countinfile = 1, sizeinfile = 0;
uint64_t math2;
int32_t i = 0, j = 0, k, error = 0, modusage = 0, ignore_restore = 0, do_switch;
@ -2307,6 +2381,7 @@ int main(int argc, char *argv[]) {
hydra_options.loginfile = NULL;
hydra_options.pass = NULL;
hydra_options.passfile = NULL;
hydra_options.distributed = NULL;
hydra_options.tasks = TASKS;
hydra_options.max_use = MAXTASKS;
hydra_options.outfile_format = FORMAT_PLAIN_TEXT;
@ -2320,8 +2395,18 @@ int main(int argc, char *argv[]) {
help(1);
if (argc < 2)
help(0);
while ((i = getopt(argc, argv, "hIq64Rrde:vVl:fFg:L:p:OP:o:b:M:C:t:T:m:w:W:s:SUux:yc:K")) >= 0) {
while ((i = getopt(argc, argv, "hIq64Rrde:vVl:fFg:D:L:p:OP:o:b:M:C:t:T:m:w:W:s:SUux:yc:K")) >= 0) {
switch (i) {
case 'D':
hydra_options.distributed = optarg;
if (sscanf(hydra_options.distributed, "%dof%d", &my_segment, &num_segments) != 2) {
fprintf(stderr, "Invalid format. Expected format -D XofY where X and Y are integers.\n");
exit(EXIT_FAILURE);
}
else{
fprintf(stdout, "Option \'D\': successfully set X to %d and Y to %d\n", my_segment, num_segments);
}
break;
case 'h':
help(1);
break;
@ -3402,6 +3487,13 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "[ERROR] File for logins not found: %s\n", hydra_options.loginfile);
exit(-1);
}
else if (hydra_options.passfile == NULL){
if(my_segment && num_segments){
filecloser = lfp;
lfp = hydra_divide_file(lfp, my_segment, num_segments);
fclose(filecloser);
}
}
hydra_brains.countlogin = countlines(lfp, 0);
hydra_brains.sizelogin = size_of_data;
if (hydra_brains.countlogin == 0) {
@ -3434,6 +3526,11 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "[ERROR] File for passwords not found: %s\n", hydra_options.passfile);
exit(-1);
}
else if(my_segment && num_segments){
filecloser = pfp;
pfp = hydra_divide_file(pfp, my_segment, num_segments);
fclose(filecloser);
}
hydra_brains.countpass = countlines(pfp, 0);
hydra_brains.sizepass = size_of_data;
if (hydra_brains.countpass == 0) {
@ -3488,6 +3585,11 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "[ERROR] File for colon files (login:pass) not found: %s\n", hydra_options.colonfile);
exit(-1);
}
else if(my_segment && num_segments){
filecloser = cfp;
cfp = hydra_divide_file(cfp, my_segment, num_segments);
fclose(filecloser);
}
hydra_brains.countlogin = countlines(cfp, 1);
hydra_brains.sizelogin = size_of_data;
if (hydra_brains.countlogin == 0) {
@ -4408,4 +4510,4 @@ int main(int argc, char *argv[]) {
return -1;
else
return 0;
}
}

@ -194,6 +194,7 @@ typedef struct {
int32_t cidr;
int32_t time_next_attempt;
output_format_t outfile_format;
char *distributed; // Use distributed computing by splitting user files on the fly
char *login;
char *loginfile;
char *pass;