Pages

November 14, 2012

Using John the Ripper to crack Ubuntu passwords

John the Ripper is a password cracker that can be used to uncover weak passwords on systems on your network. Starting with Ubuntu 9.10 John the Ripper fails to crack passwords because it does not support sha-512 encryption. Below are the steps i used to add sha-512 support to John the Ripper so that you can test the password strength of your newer Ubuntu systems.

1. Download the source for John the Ripper from http://www.openwall.com/john/

2. Extract the tar file with the following command:
tar -xzvf john-1.7.9.tar.gz

3. Open the john-1.7.9/src/Makefile and append "-lcrypt" to line "LDFLAGS = -s"

OLD VALUE: LDFLAGS = -s $(OMPFLAGS)
NEW VALUE: LDFLAGS = -s -lcrypt $(OMPFLAGS)

4. Create a new file called "crypt_fmt.c" and paste the following code into it. Save the file in john-1.7.9/src/




/* public domain proof-of-concept code by Solar Designer */

#define _XOPEN_SOURCE /* for crypt(3) */
#include 
#include 

#include "arch.h"
#include "params.h"
#include "formats.h"

#define FORMAT_LABEL   "crypt"
#define FORMAT_NAME   "generic crypt(3)"
#define ALGORITHM_NAME   "?/" ARCH_BITS_STR

#define BENCHMARK_COMMENT  ""
#define BENCHMARK_LENGTH  0

#define PLAINTEXT_LENGTH  72

#define BINARY_SIZE   128
#define SALT_SIZE   BINARY_SIZE

#define MIN_KEYS_PER_CRYPT  1
#define MAX_KEYS_PER_CRYPT  1

static struct fmt_tests tests[] = {
 {"CCNf8Sbh3HDfQ", "U*U*U*U*"},
 {"CCX.K.MFy4Ois", "U*U***U"},
 {"CC4rMpbg9AMZ.", "U*U***U*"},
 {"XXxzOu6maQKqQ", "*U*U*U*U"},
 {"SDbsugeBiC58A", ""},
 {NULL}
};

static char saved_key[PLAINTEXT_LENGTH + 1];
static char saved_salt[SALT_SIZE];
static char *crypt_out;

static int valid(char *ciphertext)
{
#if 1
 int l = strlen(ciphertext);
 return l >= 13 && l < BINARY_SIZE;
#else
/* Poor load time, but more effective at rejecting bad/unsupported hashes */
 char *r = crypt("", ciphertext);
 int l = strlen(r);
 return
     !strncmp(r, ciphertext, 2) &&
     l == strlen(ciphertext) &&
     l >= 13 && l < BINARY_SIZE;
#endif
}

static void *binary(char *ciphertext)
{
 static char out[BINARY_SIZE];
 strncpy(out, ciphertext, sizeof(out)); /* NUL padding is required */
 return out;
}

static void *salt(char *ciphertext)
{
 static char out[SALT_SIZE];
 int cut = sizeof(out);

#if 1
/* This piece is optional, but matching salts are not detected without it */
 switch (strlen(ciphertext)) {
 case 13:
 case 24:
  cut = 2;
  break;

 case 20:
  if (ciphertext[0] == '_') cut = 9;
  break;

 case 34:
  if (!strncmp(ciphertext, "$1$", 3)) {
   char *p = strchr(ciphertext + 3, '$');
   if (p) cut = p - ciphertext;
  }
  break;

 case 59:
  if (!strncmp(ciphertext, "$2$", 3)) cut = 28;
  break;

 case 60:
  if (!strncmp(ciphertext, "$2a$", 4)) cut = 29;
  break;
 }
#endif

 /* NUL padding is required */
 memset(out, 0, sizeof(out));
 memcpy(out, ciphertext, cut);

 return out;
}

static int binary_hash_0(void *binary)
{
 return ((unsigned char *)binary)[12] & 0xF;
}

static int binary_hash_1(void *binary)
{
 return ((unsigned char *)binary)[12] & 0xFF;
}

static int binary_hash_2(void *binary)
{
 return
     (((unsigned char *)binary)[12] & 0xFF) |
     ((int)(((unsigned char *)binary)[11] & 0xF) << 8);
}

static int get_hash_0(int index)
{
 return (unsigned char)crypt_out[12] & 0xF;
}

static int get_hash_1(int index)
{
 return (unsigned char)crypt_out[12] & 0xFF;
}

static int get_hash_2(int index)
{
 return
     ((unsigned char)crypt_out[12] & 0xFF) |
     ((int)((unsigned char)crypt_out[11] & 0xF) << 8);
}

static int salt_hash(void *salt)
{
 int pos = strlen((char *)salt) - 2;

 return
     (((unsigned char *)salt)[pos] & 0xFF) |
     ((int)(((unsigned char *)salt)[pos + 1] & 3) << 8);
}

static void set_salt(void *salt)
{
 strcpy(saved_salt, salt);
}

static void set_key(char *key, int index)
{
 strcpy(saved_key, key);
}

static char *get_key(int index)
{
 return saved_key;
}

static void crypt_all(int count)
{
 crypt_out = crypt(saved_key, saved_salt);
}

static int cmp_all(void *binary, int count)
{
 return !strcmp((char *)binary, crypt_out);
}

static int cmp_exact(char *source, int index)
{
 return 1;
}

struct fmt_main fmt_crypt = {
 {
  FORMAT_LABEL,
  FORMAT_NAME,
  ALGORITHM_NAME,
  BENCHMARK_COMMENT,
  BENCHMARK_LENGTH,
  PLAINTEXT_LENGTH,
  BINARY_SIZE,
  SALT_SIZE,
  MIN_KEYS_PER_CRYPT,
  MAX_KEYS_PER_CRYPT,
  FMT_CASE | FMT_8_BIT,
  tests
 }, {
  fmt_default_init,
  valid,
  fmt_default_split,
  binary,
  salt,
  {
   binary_hash_0,
   binary_hash_1,
   binary_hash_2
  },
  salt_hash,
  set_salt,
  set_key,
  get_key,
  fmt_default_clear_keys,
  crypt_all,
  {
   get_hash_0,
   get_hash_1,
   get_hash_2
  },
  cmp_all,
  cmp_all,
  cmp_exact
 }
};


5. Add the following two lines to john-1.7.9/src/john.c


extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF;
extern struct fmt_main fmt_AFS, fmt_LM;
extern struct fmt_main fmt_crypt;
and
...
john_register_one(&fmt_LM);
john_register_one(&fmt_crypt);


6. In the john-1.7.9/src/ folder run the following command.

Ubuntu 64Bit
make linux-x86-64

Ubuntu 32Bit
make linux-x86-sse2

7. Once that finishes you should now see "john" in the run/ directory.
8. Now you can crack password files.
9. On Ubuntu you must first run the unshadow file to combine the passwd & shadow file.

sudo unshadow /etc/passwd /etc/shaw > /tmp/passwords.db

10. Now run john against the new password file with the following command.

./john /tmp/passwords.db

11. After a short period of time you should receive results of the password cracking process.
      Please refer to John The Ripper's site for more details on using the product.

No comments:

Post a Comment