638 lines
23 KiB
C
638 lines
23 KiB
C
/*
|
|
* The IKE Scanner (ike-scan) is Copyright (C) 2003-2007 Roy Hills,
|
|
* NTA Monitor Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* In addition, as a special exception, the copyright holders give
|
|
* permission to link the code of portions of this program with the
|
|
* OpenSSL library, and distribute linked combinations including the two.
|
|
*
|
|
* You must obey the GNU General Public License in all respects
|
|
* for all of the code used other than OpenSSL. If you modify
|
|
* file(s) with this exception, you may extend this exception to your
|
|
* version of the file(s), but you are not obligated to do so. If you
|
|
* do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*
|
|
* If this license is unacceptable to you, I may be willing to negotiate
|
|
* alternative licenses (contact ike-scan@nta-monitor.com).
|
|
*
|
|
* You are encouraged to send comments, improvements or suggestions to
|
|
* me at ike-scan@nta-monitor.com.
|
|
*
|
|
* $Id: psk-crack.c 9919 2007-01-22 22:52:36Z rsh $
|
|
*
|
|
* psk-crack.c -- IKE Aggressive Mode Pre-Shared Key cracker for ike-scan
|
|
*
|
|
* Author: Roy Hills
|
|
* Date: 8 July 2004
|
|
*
|
|
* Usage:
|
|
* psk-crack [options] <psk-parameters-file>
|
|
*
|
|
*/
|
|
#include "psk-crack.h"
|
|
#include "hash_functions.h"
|
|
|
|
static const char rcsid[] = "$Id: psk-crack.c 9919 2007-01-22 22:52:36Z rsh $"; /* RCS ID for ident(1) */
|
|
|
|
static const char *default_charset =
|
|
"0123456789abcdefghijklmnopqrstuvwxyz"; /* default bruteforce charset */
|
|
|
|
static psk_entry *psk_list; /* List of PSK parameters */
|
|
|
|
int
|
|
main (int argc, char *argv[]) {
|
|
const struct option long_options[] = {
|
|
{"help", no_argument, 0, 'h'},
|
|
{"verbose", no_argument, 0, 'v'},
|
|
{"version", no_argument, 0, 'V'},
|
|
{"bruteforce", required_argument, 0, 'B'},
|
|
{"charset", required_argument, 0, 'c'},
|
|
{"dictionary", required_argument, 0, 'd'},
|
|
{"norteluser", required_argument, 0, 'u'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
const char *short_options = "hvVB:c:d:u:";
|
|
int arg;
|
|
int options_index=0;
|
|
int verbose=0;
|
|
unsigned brute_len=0; /* Bruteforce len. 0=dictionary attack (default) */
|
|
const char *charset = NULL;
|
|
char dict_file_name[MAXLINE]; /* Dictionary file name */
|
|
char *nortel_user = NULL; /* For cracking Nortel Contivity passwords only */
|
|
FILE *dictionary_file=NULL; /* Dictionary file */
|
|
IKE_UINT64 iterations=0;
|
|
struct timeval start_time; /* Program start time */
|
|
struct timeval end_time; /* Program end time */
|
|
struct timeval elapsed_time; /* Elapsed time as timeval */
|
|
double elapsed_seconds; /* Elapsed time in seconds */
|
|
int psk_idx; /* Index into psk list */
|
|
unsigned psk_count; /* Number of PSK entries in the list */
|
|
unsigned psk_uncracked; /* Number of uncracked PSK entries */
|
|
unsigned char *hash_r;
|
|
char line[MAXLINE];
|
|
|
|
dict_file_name[0] = '\0'; /* Initialise to empty string */
|
|
/*
|
|
* Process options and arguments.
|
|
*/
|
|
while ((arg=getopt_long_only(argc, argv, short_options, long_options, &options_index)) != -1) {
|
|
switch (arg) {
|
|
case 'h': /* --help */
|
|
psk_crack_usage(EXIT_SUCCESS);
|
|
break; /* NOTREACHED */
|
|
case 'v': /* --verbose */
|
|
verbose++;
|
|
break;
|
|
case 'V': /* --version */
|
|
fprintf(stderr, "psk-crack (%s)\n\n", PACKAGE_STRING);
|
|
fprintf(stderr, "Copyright (C) 2003-2007 Roy Hills, NTA Monitor Ltd.\n");
|
|
fprintf(stderr, "ike-scan comes with NO WARRANTY to the extent permitted by law.\n");
|
|
fprintf(stderr, "You may redistribute copies of ike-scan under the terms of the GNU\n");
|
|
fprintf(stderr, "General Public License.\n");
|
|
fprintf(stderr, "For more information about these matters, see the file named COPYING.\n");
|
|
fprintf(stderr, "\n");
|
|
/* We use rcsid here to prevent it being optimised away */
|
|
fprintf(stderr, "%s\n", rcsid);
|
|
error_use_rcsid();
|
|
utils_use_rcsid();
|
|
wrappers_use_rcsid();
|
|
exit(EXIT_SUCCESS);
|
|
break; /* NOTREACHED */
|
|
case 'B': /* --bruteforce */
|
|
brute_len=Strtoul(optarg, 10);
|
|
break;
|
|
case 'c': /* --charset */
|
|
charset=make_message("%s", optarg);
|
|
break;
|
|
case 'd': /* --dictionary */
|
|
strncpy(dict_file_name, optarg, MAXLINE);
|
|
brute_len = 0;
|
|
break;
|
|
case 'u': /* --norteluser */
|
|
nortel_user = make_message("%s", optarg);
|
|
break;
|
|
default: /* Unknown option */
|
|
psk_crack_usage(EXIT_FAILURE);
|
|
break; /* NOTREACHED */
|
|
}
|
|
} /* End While */
|
|
|
|
/*
|
|
* Check that we've got exactly one argument.
|
|
*/
|
|
if ((argc - optind) != 1) {
|
|
psk_crack_usage(EXIT_FAILURE);
|
|
}
|
|
/*
|
|
* Display the starting message.
|
|
*/
|
|
printf("Starting psk-crack [%s] (http://www.nta-monitor.com/tools/ike-scan/)\n",
|
|
PACKAGE_STRING);
|
|
/*
|
|
* If the character set has not been specified, use the default one.
|
|
*/
|
|
if (!charset)
|
|
charset = default_charset;
|
|
/*
|
|
* Load the PSK entries from the data file.
|
|
*/
|
|
psk_count = load_psk_params(argv[optind], nortel_user);
|
|
if (verbose)
|
|
printf("Loaded %u PSK entries from %s\n", psk_count, argv[optind]);
|
|
if (psk_count < 1)
|
|
err_msg("ERROR: No pre-shared keys to crack");
|
|
/*
|
|
* Open dictionary file if required.
|
|
*/
|
|
if (!brute_len) /* If not bruteforcing */
|
|
dictionary_file = open_dict_file(dict_file_name);
|
|
/*
|
|
* Get program start time for statistics displayed on completion.
|
|
*/
|
|
if (brute_len) {
|
|
printf("Running in brute-force cracking mode\n");
|
|
} else {
|
|
printf("Running in dictionary cracking mode\n");
|
|
}
|
|
Gettimeofday(&start_time);
|
|
/*
|
|
* Cracking loop.
|
|
*/
|
|
psk_uncracked = psk_count;
|
|
if (brute_len) { /* Brute force cracking */
|
|
IKE_UINT64 max;
|
|
unsigned base;
|
|
unsigned i;
|
|
IKE_UINT64 loop;
|
|
IKE_UINT64 val;
|
|
unsigned digit;
|
|
|
|
base = strlen(charset);
|
|
max = base;
|
|
for (i=1; i<brute_len; i++)
|
|
max *= base; /* max = base^brute_len without using pow() */
|
|
printf("Brute force with %u chars up to length %u will take up to "
|
|
IKE_UINT64_FORMAT " iterations\n", base, brute_len, max);
|
|
|
|
for (loop=0; psk_uncracked && loop<max; loop++) {
|
|
char *line_p;
|
|
|
|
val = loop;
|
|
line_p = line;
|
|
do {
|
|
digit = val % base;
|
|
val /= base;
|
|
*line_p++ = charset[digit];
|
|
} while (val);
|
|
*line_p = '\0';
|
|
if (verbose > 1)
|
|
printf("Trying key \"%s\"\n", line);
|
|
iterations++;
|
|
for (psk_idx=0; psk_idx<psk_count; psk_idx++) {
|
|
if (psk_list[psk_idx].live) {
|
|
hash_r = compute_hash(&psk_list[psk_idx], line);
|
|
if (!memcmp(hash_r, psk_list[psk_idx].hash_r,
|
|
psk_list[psk_idx].hash_r_len)) {
|
|
printf("key \"%s\" matches %s hash %s\n", line,
|
|
psk_list[psk_idx].hash_name,
|
|
psk_list[psk_idx].hash_r_hex);
|
|
psk_uncracked--;
|
|
psk_list[psk_idx].live=0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else { /* Dictionary cracking */
|
|
while (psk_uncracked && fgets(line, MAXLINE, dictionary_file)) {
|
|
char *line_p;
|
|
for (line_p = line; !isspace((unsigned char)*line_p) &&
|
|
*line_p != '\0'; line_p++)
|
|
;
|
|
*line_p = '\0';
|
|
if (verbose > 1)
|
|
printf("Trying key \"%s\"\n", line);
|
|
iterations++;
|
|
for (psk_idx=0; psk_idx<psk_count; psk_idx++) {
|
|
if (psk_list[psk_idx].live) {
|
|
hash_r = compute_hash(&psk_list[psk_idx], line);
|
|
if (!memcmp(hash_r, psk_list[psk_idx].hash_r,
|
|
psk_list[psk_idx].hash_r_len)) {
|
|
printf("key \"%s\" matches %s hash %s\n", line,
|
|
psk_list[psk_idx].hash_name,
|
|
psk_list[psk_idx].hash_r_hex);
|
|
psk_uncracked--;
|
|
psk_list[psk_idx].live=0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* Display any hashes that we've not cracked.
|
|
*/
|
|
for (psk_idx=0; psk_idx<psk_count; psk_idx++) {
|
|
if (psk_list[psk_idx].live)
|
|
printf("no match found for %s hash %s\n",
|
|
psk_list[psk_idx].hash_name,
|
|
psk_list[psk_idx].hash_r_hex);
|
|
}
|
|
/*
|
|
* Get program end time and calculate elapsed time.
|
|
*/
|
|
Gettimeofday(&end_time);
|
|
timeval_diff(&end_time, &start_time, &elapsed_time);
|
|
elapsed_seconds = (elapsed_time.tv_sec*1000 +
|
|
elapsed_time.tv_usec/1000.0) / 1000.0;
|
|
if (elapsed_seconds < 0.000001)
|
|
elapsed_seconds = 0.000001; /* Avoid div by zero */
|
|
printf("Ending psk-crack: " IKE_UINT64_FORMAT
|
|
" iterations in %.3f seconds (%.2f iterations/sec)\n",
|
|
iterations, elapsed_seconds, iterations/elapsed_seconds);
|
|
|
|
if (!brute_len)
|
|
fclose(dictionary_file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* load_psk_params -- Load PSK parameters from data file
|
|
*
|
|
* Inputs:
|
|
*
|
|
* filename The name of the data file
|
|
* nortel_user The username for Nortel PSK cracking, or NULL
|
|
*
|
|
* Returns:
|
|
*
|
|
* The number of PSK parameters successfully loaded into the list.
|
|
*
|
|
* This function loads the pre-shared key parameters from the input
|
|
* data file into the psk parameters list, which is an array of structs.
|
|
*
|
|
* The array is created dynamically with malloc and realloc, as we don't
|
|
* know in advance how many PSK entries there will be in the file.
|
|
*/
|
|
static unsigned
|
|
load_psk_params(const char *filename, const char *nortel_user) {
|
|
FILE *data_file; /* PSK parameters in colon separated format */
|
|
char psk_data[MAXLEN]; /* Line read from data file */
|
|
int n; /* Number of fields read by sscanf() */
|
|
static int num_left=0; /* Number of free entries left */
|
|
unsigned count=0; /* Number of entries in the list */
|
|
psk_entry *pe; /* Pointer to current PSK entry */
|
|
unsigned char *cp;
|
|
unsigned char *skeyid_data; /* Data for SKEYID hash */
|
|
size_t skeyid_data_len; /* Length of skeyid data */
|
|
unsigned char *hash_r_data; /* Data for HASH_R hash */
|
|
size_t hash_r_data_len; /* Length of hash_r */
|
|
char g_xr_hex[MAXLEN]; /* Individual PSK params as hex */
|
|
char g_xi_hex[MAXLEN];
|
|
char cky_r_hex[MAXLEN];
|
|
char cky_i_hex[MAXLEN];
|
|
char sai_b_hex[MAXLEN];
|
|
char idir_b_hex[MAXLEN];
|
|
char ni_b_hex[MAXLEN];
|
|
char nr_b_hex[MAXLEN];
|
|
char hash_r_hex[MAXLEN];
|
|
unsigned char *g_xr; /* Individual PSK params as binary */
|
|
unsigned char *g_xi;
|
|
unsigned char *cky_r;
|
|
unsigned char *cky_i;
|
|
unsigned char *sai_b;
|
|
unsigned char *idir_b;
|
|
unsigned char *ni_b;
|
|
unsigned char *nr_b;
|
|
size_t g_xr_len; /* Lengths of binary PSK params */
|
|
size_t g_xi_len;
|
|
size_t cky_r_len;
|
|
size_t cky_i_len;
|
|
size_t sai_b_len;
|
|
size_t idir_b_len;
|
|
size_t ni_b_len;
|
|
size_t nr_b_len;
|
|
size_t hash_r_hex_len;
|
|
/*
|
|
* Open PSK data file for reading.
|
|
*/
|
|
if ((data_file = fopen(filename, "r")) == NULL)
|
|
err_sys("error opening data file %s", filename);
|
|
/*
|
|
* For each line in the data file, read the PSK data, convert to
|
|
* binary, and store in the PSK list. We ignore blank lines, and
|
|
* any lines beginning with '#'.
|
|
*/
|
|
while ((fgets(psk_data, MAXLEN, data_file)) != NULL) {
|
|
if (psk_data[0] == '#' || psk_data[0] == '\n' || psk_data[0] == '\r')
|
|
continue; /* Skip comments and blank lines */
|
|
n=sscanf(psk_data,
|
|
"%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^:\r\n]",
|
|
g_xr_hex, g_xi_hex, cky_r_hex, cky_i_hex, sai_b_hex,
|
|
idir_b_hex, ni_b_hex, nr_b_hex, hash_r_hex);
|
|
if (n != 9) {
|
|
warn_msg("ERROR: Format error in PSK data file %s, line %u",
|
|
filename, count+1);
|
|
err_msg("ERROR: Expected 9 colon-separated fields, found %d", n);
|
|
}
|
|
/*
|
|
* Create or grow the psk list array if required.
|
|
* We grow the list by PSK_REALLOC_COUNT elements each time.
|
|
*/
|
|
if (!num_left) { /* No entries left, allocate some more */
|
|
if (psk_list)
|
|
psk_list=Realloc(psk_list, (count * sizeof(psk_entry)) +
|
|
PSK_REALLOC_COUNT*sizeof(psk_entry));
|
|
else
|
|
psk_list=Malloc(PSK_REALLOC_COUNT*sizeof(psk_entry));
|
|
num_left = PSK_REALLOC_COUNT;
|
|
}
|
|
|
|
pe = psk_list + count; /* Would array notation be better? */
|
|
count++;
|
|
num_left--;
|
|
/*
|
|
* Convert hex to binary representation, and construct SKEYID
|
|
* and HASH_R data.
|
|
*/
|
|
g_xr = hex2data(g_xr_hex, &g_xr_len);
|
|
g_xi = hex2data(g_xi_hex, &g_xi_len);
|
|
cky_r = hex2data(cky_r_hex, &cky_r_len);
|
|
cky_i = hex2data(cky_i_hex, &cky_i_len);
|
|
sai_b = hex2data(sai_b_hex, &sai_b_len);
|
|
idir_b = hex2data(idir_b_hex, &idir_b_len);
|
|
ni_b = hex2data(ni_b_hex, &ni_b_len);
|
|
nr_b = hex2data(nr_b_hex, &nr_b_len);
|
|
|
|
/* skeyid_data = ni_b | nr_b */
|
|
skeyid_data_len = ni_b_len + nr_b_len;
|
|
skeyid_data = Malloc(skeyid_data_len);
|
|
cp = skeyid_data;
|
|
memcpy(cp, ni_b, ni_b_len);
|
|
cp += ni_b_len;
|
|
memcpy(cp, nr_b, nr_b_len);
|
|
free(ni_b);
|
|
free(nr_b);
|
|
|
|
/* hash_r_data = g_xr | g_xi | cky_r | cky_i | sai_b | idir_b */
|
|
hash_r_data_len = g_xr_len + g_xi_len + cky_r_len + cky_i_len +
|
|
sai_b_len + idir_b_len;
|
|
hash_r_data = Malloc(hash_r_data_len);
|
|
cp = hash_r_data;
|
|
memcpy(cp, g_xr, g_xr_len);
|
|
cp += g_xr_len;
|
|
memcpy(cp, g_xi, g_xi_len);
|
|
cp += g_xi_len;
|
|
memcpy(cp, cky_r, cky_r_len);
|
|
cp += cky_r_len;
|
|
memcpy(cp, cky_i, cky_i_len);
|
|
cp += cky_i_len;
|
|
memcpy(cp, sai_b, sai_b_len);
|
|
cp += sai_b_len;
|
|
memcpy(cp, idir_b, idir_b_len);
|
|
free(g_xr);
|
|
free(g_xi);
|
|
free(cky_r);
|
|
free(cky_i);
|
|
free(sai_b);
|
|
free(idir_b);
|
|
/*
|
|
* Store the PSK parameters in the current psk list entry.
|
|
*/
|
|
pe->skeyid_data = skeyid_data;
|
|
pe->skeyid_data_len = skeyid_data_len;
|
|
pe->hash_r_data = hash_r_data;
|
|
pe->hash_r_data_len = hash_r_data_len;
|
|
pe->hash_r = hex2data(hash_r_hex, &pe->hash_r_len);
|
|
hash_r_hex_len = strlen(hash_r_hex) + 1; /* includes terminating null */
|
|
pe->hash_r_hex = Malloc(hash_r_hex_len);
|
|
strncpy(pe->hash_r_hex, hash_r_hex, hash_r_hex_len);
|
|
pe->nortel_user = nortel_user;
|
|
/*
|
|
* Determine hash type based on the length of the hash, and
|
|
* store this in the current psk list entry.
|
|
*/
|
|
if (pe->hash_r_len == MD5_HASH_LEN) {
|
|
pe->hash_type=HASH_TYPE_MD5;
|
|
pe->hash_name=make_message("MD5");
|
|
} else if (pe->hash_r_len == SHA1_HASH_LEN) {
|
|
pe->hash_type=HASH_TYPE_SHA1;
|
|
pe->hash_name=make_message("SHA1");
|
|
} else {
|
|
err_msg("Cannot determine hash type from %u byte HASH_R",
|
|
pe->hash_r_len);
|
|
}
|
|
pe->live = 1;
|
|
} /* End While fgets() */
|
|
/*
|
|
* Close the data file, and return the number of PSK entries
|
|
* read into the list.
|
|
*/
|
|
fclose(data_file);
|
|
return count;
|
|
}
|
|
|
|
/*
|
|
* compute_hash -- Compute the hash given a candidate password
|
|
*
|
|
* Inputs:
|
|
*
|
|
* psk_params Pointer to PSK params structure
|
|
* password The candidate password
|
|
*
|
|
* Returns:
|
|
*
|
|
* Pointer to the computed hash.
|
|
*
|
|
* This function calculates a hash given the PSK parameters and
|
|
* a candidate password.
|
|
*
|
|
* The standard process used to calculate the hash is detailed in
|
|
* RFC 2409. The hash used by Nortel Contivity systems use a different,
|
|
* proprietary, method.
|
|
*
|
|
* In all cases, the calculation of the hash is a two-stage process:
|
|
*
|
|
* a) Calculate SKEYID using some of the PSK parameters and the password;
|
|
* b) Calculate HASH_R using SKEYID and the other PSK parameters.
|
|
*
|
|
*/
|
|
static inline unsigned char *
|
|
compute_hash (const psk_entry *psk_params, const char *password) {
|
|
size_t password_len = strlen(password);
|
|
unsigned char skeyid[SHA1_HASH_LEN];
|
|
static unsigned char hash_r[SHA1_HASH_LEN];
|
|
/*
|
|
* Calculate SKEYID
|
|
*/
|
|
if (psk_params->nortel_user == NULL) { /* RFC 2409 SKEYID calculation */
|
|
if (psk_params->hash_type == HASH_TYPE_MD5) {
|
|
hmac_md5(psk_params->skeyid_data, psk_params->skeyid_data_len,
|
|
(const unsigned char *) password, password_len, skeyid);
|
|
} else { /* SHA1 */
|
|
hmac_sha1(psk_params->skeyid_data, psk_params->skeyid_data_len,
|
|
(const unsigned char *) password, password_len, skeyid);
|
|
}
|
|
} else { /* Nortel proprietary SKEYID calculation */
|
|
unsigned char nortel_psk[SHA1_HASH_LEN];
|
|
unsigned char nortel_pwd_hash[SHA1_HASH_LEN];
|
|
|
|
SHA1((const unsigned char *) password, password_len, nortel_pwd_hash);
|
|
hmac_sha1((const unsigned char *)psk_params->nortel_user,
|
|
strlen(psk_params->nortel_user), nortel_pwd_hash,
|
|
SHA1_HASH_LEN, nortel_psk);
|
|
if (psk_params->hash_type == HASH_TYPE_MD5) {
|
|
hmac_md5(psk_params->skeyid_data, psk_params->skeyid_data_len,
|
|
nortel_psk, SHA1_HASH_LEN, skeyid);
|
|
} else { /* SHA1 */
|
|
hmac_sha1(psk_params->skeyid_data, psk_params->skeyid_data_len,
|
|
nortel_psk, SHA1_HASH_LEN, skeyid);
|
|
}
|
|
}
|
|
/*
|
|
* Calculate HASH_R
|
|
*/
|
|
if (psk_params->hash_type == HASH_TYPE_MD5) {
|
|
hmac_md5(psk_params->hash_r_data, psk_params->hash_r_data_len, skeyid,
|
|
psk_params->hash_r_len, hash_r);
|
|
} else { /* SHA1 */
|
|
hmac_sha1(psk_params->hash_r_data, psk_params->hash_r_data_len, skeyid,
|
|
psk_params->hash_r_len, hash_r);
|
|
}
|
|
return hash_r;
|
|
}
|
|
|
|
/*
|
|
* open_dict_file -- Open the dictionary file
|
|
*
|
|
* Inputs:
|
|
*
|
|
* dict_file_name The dictionary file name, or NULL for default.
|
|
*
|
|
* Returns:
|
|
*
|
|
* The file descriptor of the dictionary file.
|
|
*/
|
|
static FILE *
|
|
open_dict_file(const char *dict_file_name) {
|
|
char *fn;
|
|
FILE *fp;
|
|
#ifdef __CYGWIN__
|
|
char fnbuf[MAXLINE];
|
|
int fnbuf_siz;
|
|
int i;
|
|
#endif
|
|
|
|
if (dict_file_name[0] == '\0') { /* Dictionary file not specified */
|
|
#ifdef __CYGWIN__
|
|
if ((fnbuf_siz=GetModuleFileName(GetModuleHandle(0),
|
|
fnbuf, MAXLINE)) == 0) {
|
|
err_msg("ERROR: Call to GetModuleFileName failed");
|
|
}
|
|
for (i=fnbuf_siz-1; i>=0 && fnbuf[i] != '/' && fnbuf[i] != '\\'; i--)
|
|
;
|
|
if (i >= 0) {
|
|
fnbuf[i] = '\0';
|
|
}
|
|
fn = make_message("%s\\%s", fnbuf, DICT_FILE);
|
|
#else
|
|
fn = make_message("%s/%s", IKEDATADIR, DICT_FILE);
|
|
#endif
|
|
} else { /* Dictionary filename was specified */
|
|
fn = make_message("%s", dict_file_name);
|
|
}
|
|
|
|
if ((strcmp(fn, "-")) == 0) { /* Filename "-" means stdin */
|
|
fp = stdin;
|
|
} else {
|
|
if ((fp = fopen(fn, "r")) == NULL) {
|
|
err_sys("error opening dictionary file %s", fn);
|
|
}
|
|
}
|
|
free(fn);
|
|
|
|
return fp;
|
|
}
|
|
|
|
/*
|
|
* psk_crack_usage -- display usage message and exit
|
|
*
|
|
* Inputs:
|
|
*
|
|
* status Status value to pass to exit()
|
|
*
|
|
* Returns:
|
|
*
|
|
* None (this function never returns).
|
|
*/
|
|
static void
|
|
psk_crack_usage(int status) {
|
|
fprintf(stderr, "Usage: psk-crack [options] <psk-parameters-file>\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "<psk-parameters-file> is a file containing the parameters for the pre-shared\n");
|
|
fprintf(stderr, "key cracking process in the format generated by ike-scan with the --pskcrack\n");
|
|
fprintf(stderr, "(-P) option. This file can contain one or more entries. For multiple entries,\n");
|
|
fprintf(stderr, "each one must be on a separate line.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Two SKEYID computation methods are supported: the standard method for pre-\n");
|
|
fprintf(stderr, "shared keys as described in RFC 2409, and the proprietary method used by\n");
|
|
fprintf(stderr, "Nortel Contivity / VPN Router systems. The standard method is used by default,\n");
|
|
fprintf(stderr, "and the Nortel method can be selected with the --norteluser option.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "The program can crack either MD5 or SHA1-based hashes. The type of hash is\n");
|
|
fprintf(stderr, "automatically determined from the length of the hash (16 bytes for MD5 or\n");
|
|
fprintf(stderr, "20 bytes for SHA1). Each entry in the <psk-parameters-file> is handled\n");
|
|
fprintf(stderr, "separately, so it is possible to crack a mixture of MD5 and SHA1 hashes.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "By default, psk-crack will perform dictionary cracking using the default\n");
|
|
fprintf(stderr, "dictionary. The dictionary can be changed with the --dictionary (-d) option,\n");
|
|
fprintf(stderr, "or brute-force cracking can be selected with the --bruteforce (-B) option.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Options:\n");
|
|
fprintf(stderr, "\n--help or -h\t\tDisplay this usage message and exit.\n");
|
|
fprintf(stderr, "\n--version or -V\t\tDisplay program version and exit.\n");
|
|
fprintf(stderr, "\n--verbose or -v\t\tDisplay verbose progress messages.\n");
|
|
fprintf(stderr, "\t\t\tUse more than once for increased verbosity.\n");
|
|
fprintf(stderr, "\n--dictionary=<f> or -d <f> Set dictionary file to <f>\n");
|
|
#ifdef __CYGWIN__
|
|
fprintf(stderr, "\t\t\tdefault=%s in psk-crack.exe dir.\n", DICT_FILE);
|
|
#else
|
|
fprintf(stderr, "\t\t\tdefault=%s/%s.\n", IKEDATADIR, DICT_FILE);
|
|
#endif
|
|
fprintf(stderr, "\t\t\tUse \"-\" for standard input.\n");
|
|
fprintf(stderr, "\n--norteluser=<u> or -u <u> Specify username for Nortel Contivity PSK cracking.\n");
|
|
fprintf(stderr, "\t\t\tThis option is required when cracking pre-shared keys\n");
|
|
fprintf(stderr, "\t\t\ton Nortel Contivity / VPN Router systems. These\n");
|
|
fprintf(stderr, "\t\t\tsystems use a proprietary method to calculate the hash\n");
|
|
fprintf(stderr, "\t\t\tthat includes a hash of the username.\n");
|
|
fprintf(stderr, "\t\t\tThis option is only needed when cracking Nortel format\n");
|
|
fprintf(stderr, "\t\t\thashes, and should not be used for standard format\n");
|
|
fprintf(stderr, "\t\t\thashes.\n");
|
|
fprintf(stderr, "\t\t\tWhen this option is used, all the PSK entries in the\n");
|
|
fprintf(stderr, "\t\t\tpsk parameters file are assumed to be in Nortel format\n");
|
|
fprintf(stderr, "\t\t\tusing the supplied username. There is currently no way\n");
|
|
fprintf(stderr, "\t\t\tto crack a mixture of Nortel and standard format PSK\n");
|
|
fprintf(stderr, "\t\t\tentries, or Nortel entries with different usernames in\n");
|
|
fprintf(stderr, "\t\t\ta single psk-crack run.\n");
|
|
fprintf(stderr, "\n--bruteforce=<n> or -B <n> Select bruteforce cracking up to <n> characters.\n");
|
|
fprintf(stderr, "\n--charset=<s> or -c <s>\tSet bruteforce character set to <s>\n");
|
|
fprintf(stderr, "\t\t\tDefault is \"%s\"\n", default_charset);
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Report bugs or send suggestions to %s\n", PACKAGE_BUGREPORT);
|
|
fprintf(stderr, "See the ike-scan homepage at http://www.nta-monitor.com/tools/ike-scan/\n");
|
|
exit(status);
|
|
}
|