#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <platon/hash/md5.h>
#include <platon/str/strplus.h>
#include <platon/str/strctype.h>
/* Compilation agains libplaton library:
gcc -pedantic -L ../../platon/ -I ../../ -o md5scan md5scan.c -lplaton
*/
#define BUFSIZE 1000
#define MAX_PASSWORDS 200
#define compute_and_check(__buf) \
compute_md5(md5str, __buf); \
check_passwords(md5str, __buf);
#define compute_md5(__md5, __buf) \
MD5Init(&context); \
MD5Update(&context, __buf, pw_len); \
MD5Final(__md5, &context);
#define check_passwords(__md5, __plain) \
for (j = 0; j < pw_cnt; j++) { \
if (! memcmp(passwords[j], __md5, 16)) { \
printf("Found: MD5('%s') = '", __plain); \
for (k = 0; k < 16; k++) { \
printf("%02x", (unsigned char ) md5str[k]); \
} \
printf("', username: %s\n", usernames[j]); \
} \
}
int main(int argc, char **argv) /* {{{ */
{
MD5_CTX context;
char usernames[MAX_PASSWORDS][32];
char passwords[MAX_PASSWORDS][16];
char buf[BUFSIZE], buf2[BUFSIZE];
char *ptr, md5str[16];
FILE *f;
int pw_len, buf_base;
register int i, j, k, pw_cnt, line, feature;
long int cnt;
int feature_have_some_uppercase;
if (argc <= 2) {
printf("Usage: %s <password_file> <word-list-file_1> ... <word-list-file_N>\n", argv[0]);
return 1;
}
if ((f = fopen(argv[1], "r")) == NULL) {
printf("Cannot open password file '%s'.\n", argv[i]);
return 2;
}
printf("[%02d/%02d] Loading passwords from '%s'...\n", 1, argc - 1, argv[1]);
for (line = 0, pw_cnt = 0; fgets(buf, BUFSIZE - 1, f) != NULL; line++) {
buf[BUFSIZE-1] = '\0';
str_trim(buf);
if (strlen(buf) <= 0) {
printf(" Skipping empty line %d, continuing on next...\n", line + 1);
continue;
}
for (ptr = buf; ptr - buf != 32; ptr += 2) {
if (! isxdigit(ptr[0]) || !isxdigit(ptr[1])) {
printf("Bad input on line %d: %s\n", line + 1, buf);
return 4;
}
sscanf(ptr, "%2x", md5str + (ptr - buf) / 2);
}
if (i >= MAX_PASSWORDS) {
printf("Sorry MAX_PASSWORDS reached, cannot continue. Recompilation required.\n");
return 8;
}
str_trim(ptr);
memcpy(passwords[pw_cnt], md5str, 16);
memcpy(usernames[pw_cnt], ptr, 31);
usernames[pw_cnt][31] = '\0';
pw_cnt++;
}
printf(" Loading passwords finished, %d passwords loaded from %d lines.\n", pw_cnt, line);
if (pw_cnt == 0) {
printf("No passwords in password file.");
return 16;
}
for (i = 2; i < argc; i++) {
printf("[%02d/%02d] Processing word list '%s'...\n", i, argc - 1, argv[i]);
if ((f = fopen(argv[i], "r")) == NULL) {
printf("Cannot open word list file '%s'. File skipped.\n", argv[i]);
continue;
}
for (cnt = 0; fgets(buf, BUFSIZE - 1, f) != NULL; ) {
pw_len = strlen(buf);
if (pw_len >= BUFSIZE) {
printf("WARNING: too long password on the input (%d)\n", pw_len);
continue;
}
str_trim(buf);
pw_len = strlen(buf);
if (! pw_len) {
continue;
}
cnt++;
/* Features:
* - plain
* - reverse string
* - lowercase
* - lowercase capitalize first
* - capitalize first
* - append 1 digit
* - append 1 digits
*/
for (feature_have_some_uppercase = 0, j = 0; j < pw_len; j++) {
if (isupper(buf[j])) {
feature_have_some_uppercase = 1;
break;
}
}
/* Feature: plain */
compute_and_check(buf);
if (islower(buf[0])) { /* Feature: ucfirst */
k = buf[0];
buf[0] = toupper(buf[0]);
compute_and_check(buf);
buf[0] = k;
}
if (feature_have_some_uppercase) { /* Feature: lowercase */
strncpy(buf2, buf, BUFSIZE);
strtolower(buf2);
compute_and_check(buf2);
if (islower(buf2[0])) { /* Feature: lowercase & ucfirst */
buf2[0] = toupper(buf2[0]);
compute_and_check(buf2);
}
}
/* Feature: reverse */
strncpy(buf2, buf, BUFSIZE);
strrev(buf2);
compute_and_check(buf2);
if (islower(buf2[0])) { /* Feature: reverse & ucfirst */
k = buf2[0];
buf2[0] = toupper(buf2[0]);
compute_and_check(buf2);
buf2[0] = k;
}
if (feature_have_some_uppercase) { /* Feature: reverse & lowercase */
strtolower(buf2);
compute_and_check(buf2);
if (islower(buf2[0])) { /* Feature: reverse & lowercase & ucfirst */
buf2[0] = toupper(buf2[0]);
compute_and_check(buf2);
}
}
}
printf(" %ld passwords checked.\n", cnt);
fclose(f);
}
return 0;
} /* }}} */
/* Modeline for ViM {{{
* vim: set ts=4:
* vim600: fdm=marker fdl=0 fdc=3:
* }}} */
Platon Group <platon@platon.sk> http://platon.sk/
|