/* The decryption_func thread function tests all the passwords of the form: * prefix + x + combination + suffix * where x is a character in the range charset[arg[0]] -> charset[arg[1]]. */ void * decryption_func(void *arg) { unsigned char *password, *key, *iv, *out; unsigned int password_len, index_start, index_end, len, out_len1, out_len2, i, j, k; int ret, found; unsigned int *tab; EVP_CIPHER_CTX ctx; index_start = ((unsigned int *) arg)[0]; index_end = ((unsigned int *) arg)[1]; key = (unsigned char *) malloc(EVP_CIPHER_key_length(cipher)); iv = (unsigned char *) malloc(EVP_CIPHER_iv_length(cipher)); out = (unsigned char *) malloc(data_len + EVP_CIPHER_block_size(cipher)); if((key == NULL) || (iv == NULL) || (out == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } /* For every possible length */ for(len = min_len - prefix_len - 1 - suffix_len; len + 1 <= max_len - prefix_len - suffix_len; len++) { /* For every first character in the range we were given */ for(k = index_start; k <= index_end; k++) { password_len = prefix_len + 1 + len + suffix_len; password = (unsigned char *) malloc(password_len + 1); tab = (unsigned int *) malloc((len + 1) * sizeof(unsigned int)); if((password == NULL) || (tab == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } strncpy(password, prefix, prefix_len); password[prefix_len] = charset[k]; strncpy(password + prefix_len + 1 + len, suffix, suffix_len); password[password_len] = '\0'; for(i = 0; i <= len; i++) tab[i] = 0; /* Test all the combinations */ while((tab[len] == 0) && (stop == 0)) { for(i = 0; i < len; i++) password[prefix_len + 1 + i] = charset[tab[len - 1 - i]]; /* Decrypt data with password */ EVP_BytesToKey(cipher, digest, salt, password, password_len, 1, key, iv); EVP_DecryptInit(&ctx, cipher, key, iv); EVP_DecryptUpdate(&ctx, out, &out_len1, data, data_len); ret = EVP_DecryptFinal(&ctx, out + out_len1, &out_len2); if(no_error || (ret == 1)) { if(magic == NULL) found = valid_data(out, out_len1 + out_len2); else found = !strncmp(out, magic, strlen(magic)); } else found = 0; if(found) { /* We have a positive result */ pthread_mutex_lock(&found_password_lock); if(binary == NULL) printf("Password candidate: %s\n", password); else { int fd; char outfile[128]; sprintf(outfile, "%s-%d", binary, solution++); fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if(fd == -1) perror("open file"); else { printf("Password candidate saved to file: %s \n", outfile); ret = write(fd, password, password_len); close(fd); } } if(only_one_password) stop = 1; pthread_mutex_unlock(&found_password_lock); } EVP_CIPHER_CTX_cleanup(&ctx); if(limit) { pthread_mutex_lock(&found_password_lock); if(limit <= count++) { if(only_one_password) { printf("Maximum number of passphrases tested, aborting.\n"); stop = 1; } else { overall = overall + count - 1; if(binary == NULL) printf("Just tested solution %lu: %s\n", overall, password); else printf("Just tested solution %lu\n", overall); count -= limit; } } pthread_mutex_unlock(&found_password_lock); } if(len == 0) break; tab[0]++; if(tab[0] == charset_len) tab[0] = 0; j = 0; while(tab[j] == 0) { j++; tab[j]++; if((j < len) && (tab[j] == charset_len)) tab[j] = 0; } } free(tab); free(password); } } free(out); free(iv); free(key); pthread_exit(NULL); }
void * decryption_func(void *arg) { struct decryption_func_locals *dfargs; unsigned char *pwd, *key, *iv, *out; unsigned int pwd_len, len, out_len1, out_len2; int ret, found; EVP_CIPHER_CTX *ctx; dfargs = (struct decryption_func_locals *) arg; key = (unsigned char *) malloc(EVP_CIPHER_key_length(cipher)); iv = (unsigned char *) malloc(EVP_CIPHER_iv_length(cipher)); out = (unsigned char *) malloc(data_len + EVP_CIPHER_block_size(cipher)); ctx = EVP_CIPHER_CTX_new(); if((key == NULL) || (iv == NULL) || (out == NULL) || (ctx == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } do { if(dictionary == NULL) { if(binary) ret = generate_next_binary_password(&pwd, &pwd_len); else ret = generate_next_password(&pwd, &pwd_len); } else ret = read_dictionary_line(&pwd, &pwd_len); if(ret == 0) break; /* Decrypt data with password */ if(no_salt) EVP_BytesToKey(cipher, digest, NULL, pwd, pwd_len, 1, key, iv); else EVP_BytesToKey(cipher, digest, salt, pwd, pwd_len, 1, key, iv); EVP_DecryptInit(ctx, cipher, key, iv); EVP_DecryptUpdate(ctx, out, &out_len1, data, data_len); ret = EVP_DecryptFinal(ctx, out + out_len1, &out_len2); if(no_error || (ret == 1)) { if(magic == NULL) found = valid_data(out, out_len1 + out_len2); else found = !strncmp(out, magic, strlen(magic)); } else found = 0; if(found) { /* We have a positive result */ handle_signal(SIGUSR1); /* Print some stats */ pthread_mutex_lock(&found_password_lock); found_password++; printf("Password candidate: %s\n", pwd); if(only_one_password) stop = 1; pthread_mutex_unlock(&found_password_lock); } dfargs->counter++; EVP_CIPHER_CTX_cleanup(ctx); if(limit > 0) { pthread_mutex_lock(&found_password_lock); count_limit++; if(count_limit >= limit) { fprintf(stderr, "Maximum number of passphrases tested, aborting.\n"); stop = 1; } pthread_mutex_unlock(&found_password_lock); } free(pwd); } while(stop == 0); EVP_CIPHER_CTX_free(ctx); free(out); free(iv); free(key); pthread_exit(NULL); }