Crack Password with John the Ripper on Ubuntu 9.10

This section describes how to probe weak user passwords on your system. If the passwords are weak, hackers may guess user names and password and login to your system "legally". Even worse, in many cases user account names are publicly available, such as through email addresses.

An interesting article can be found here: "Hacking Into Your Account is as Easy as 123456"

As a system administrator, you can test your users password strength with a password cracker. John the Ripper is one of the password crackers. In the process, the program "john" guesses passwords with certain algorithm and tests if the "login" attempts are successful by comparing it with the password file.

John the Ripper (JtR) is available from Ubuntu repository, as well as open wall website: http://www.openwall.com/john/. However, none of them works on Ubuntu 9.04 and above due to the lack of support to sha-512 encryption. They give error "No password hashes loaded".

You can use Ubuntu 9.10 "john" to crack supported password encryption copied from other system, but we will download the source, patch the code, and compile the program, based on the suggestion of original JtR author (http://www.openwall.com/lists/john-users/2009/09/02/3), to crack passwords of Ubuntu 9.04 and above. This guide describes the later.

  1. Precaution:
    This program is a password cracker downloaded from Internet. You know the risks. Therefore, a cautious approach is to separate the machine information with account information, that is, never to crack passwords on a machine which accounts belong to.
     
  2. Download John the Ripper

    wget http://www.openwall.com/john/g/john-1.7.3.4.tar.gz
    wget http://www.openwall.com/john/g/john-1.7.3.4.tar.gz.sign
    wget http://www.openwall.com/signatures/openwall-signatures.asc
    

    The above 3 links are for current JtR stable version, you can goto http://www.openwall.com/john/ for the latest version and http://www.openwall.com/signatures/ for the up-to-date public key.
     

  3. Confirm the signature
    Again, more safety measure as we are dealing dangerous thing.
    Install the public key:

    pgp -ka openwall-signatures.asc

    Check the signature:

    $ pgp john-1.7.4.2.tar.gz.sign john-1.7.4.2.tar.gz
    gpg: Signature made Tue 19 Jan 2010 04:10:08 AM EST using RSA key ID 295029F1
    gpg: Good signature from "Openwall Project <signatures@openwall.com>"
    gpg: WARNING: This key is not certified with a trusted signature!
    gpg:          There is no indication that the signature belongs to the owner.
    Primary key fingerprint: 0C 29 43 AE 1E CD 24 EA  6E 0C B6 EE F5 84 25 69
    

    You will see the message similar to the above. Ignore the warning as long as it says Good signature from ...
    The warning is normal, see http://www.kernel.org/signature.html for more details.
     

  4. Unzip, patch and compile the program

    tar -zxvf john-1.7.4.2.tar.gz
    cd john-1.7.4.2/src
    

    The patch lets "john" call crypt(3) to encode passwords when it sees unsupported encryption. There are 3 files we need to change/create: Makefile, crypt_fmt.c and john.c.

    Append "-lcrypt" to line "LDFLAGS = -s", making the line reads as:

    LDFLAGS = -s -lcrypt


    Create file crypt_fmt.c:

    /* public domain proof-of-concept code by Solar Designer */
    
    #define _XOPEN_SOURCE /* for crypt(3) */
    #include <string.h>
    #include <unistd.h>
    
    #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
    	}
    };
    


    Finally add two lines (Red) to 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_DES);
            john_register_one(&fmt_BSDI);
            john_register_one(&fmt_MD5);
            john_register_one(&fmt_BF);
            john_register_one(&fmt_AFS);
            john_register_one(&fmt_LM);
           john_register_one(&fmt_crypt);
    


    On my 32 bit Ubuntu 9.10, I ran

    make linux-x86-sse2
    

    Or

    make linux-x86-64

    for 64 bit Ubuntu.

    You should have "john" in ../run directory.
     

  5. Run the cracker
    On Ubuntu, the actual password is /etc/shadow rather than /etc/passwd. This file is not readable to normal users. So you have to copy it and change the read permission. Remember, don't crack a password file on its own machine. If someone else stole your password file, or compromised JtR sent out your password file, you still have a layer of protection because others don't know which computer these passwords are for.

    On a system to be cracked:

    sudo unshadow /etc/passwd /etc/shadow> shadowfile

    Or copy /etc/shadow as shadowfile and change the file to readable.

    Then copy this file to the run directory of a computer (Ubuntu 9.10) with JtR we just compiled and run:

    ./john shadowfile


    Or

    sudo unshadow /etc/passwd /etc/shadow> shadowfile
    



    Press any key for progress, ^C for interruption.

    To resume cracking from interruption, under run directory

    ./john --restore
    


    To show the cracked password(s)

    ./john --show


     

 

 Its worked on latest ubuntu

 Its worked on latest ubuntu too. Thanks

mini fazenda

this is what i need, great

this is what i need, great script. many thanks for the code

Top News.

cool patch!!

 thanx man..thats some cool stuff posted up ther..
and its got me some passwords..!!!

Thanks

Fantastic work.

Your patch is now running on our 64 bit Ubuntu 9.04 system.

I have scripted the instructions above into a Python script that ultimately puts the executable into /usr/local/bin

For those interested, the script is available at

http://www.aifdr.org/projects/system_administration/browser/security

 

Ole

 

Great Article

I have to say, this was great help for me! Before finding this article, I kept on getting Segmentation fault with John the Ripper. Now, it actually works! Thanks alot!

As for me I think the article

As for me I think the article "Hacking Into Your Account is as Easy as 123456" will help users with account usage. Great article indeed, some topic idea came up into my mind for essay writing in college. I think my essay on Hacking will be very interesting for my teacher!

Regards, Mike

Fantastic article

Fantastic article, thank you!

I did have one little problem compiling. I had to add this line to the Makefile to get it to work, and I thought it might help somebody else:

 JOHN_OBJS_MINIMAL = \
    DES_fmt.o DES_std.o DES_bs.o \
    BSDI_fmt.o \
    MD5_fmt.o MD5_std.o \
    BF_fmt.o BF_std.o \
    AFS_fmt.o \
    LM_fmt.o \
    batch.o bench.o charset.o common.o compiler.o config.o cracker.o \
    crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \
    loader.o logger.o math.o memory.o misc.o options.o params.o path.o \
    recovery.o rpp.o rules.o signals.o single.o status.o tty.o wordlist.o \
    unshadow.o \
    unafs.o \
    unique.o \
   
crypt_fmt.o

Thanks

Yes, crypt_fmt.o has to be put in Makefile.I forgot that when writing up the post.

Thanks for pointing it out.