Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <BAY120-W16CD4A4D4FBF2CED909FE1B0B40@phx.gbl>
Date: Tue, 17 Feb 2009 06:24:09 +0000
From: P PO1434 <p2409@...mail.com>
To: <john-users@...ts.openwall.com>
Subject: RE: 2 known letters + wordlist word --> is new format
 definition best way?


Thanks Alex - all working now. I got rid of the null terminated salt - as you said just not needed.
I also had to update the key with the most recent salt (previouslyit wasn't trying all the hashes
in conjunction with the candidate passwords.)

So...here it is: a basic MD5 crack when you know the first 'x' characters.
I'm sure there a bit of efficiency/tidying up in my code, but it should work as is.

OSC_fmt.c

/*
 * MD5 where first 2 character are known and supplied
 * by Pete. Test version only - handles the test conditions fine
 * NOT HANDLING FILE INPUT AT THIS STAGE!
 *
 * This algorithm is often used in PHP - sort of a fake
 * salt + plaintext which is MD5'd
 *
 * This code is really just a mod of raw_md5 which is
 *
 * Copyright (c) 2004 bartavelle
 * bartavelle at bandecon.com
 *
 * by Justin
 *
 * Minor changes by David Luyer <david at luyer.net> to
 * use a modified (faster) version of Solar Designer's
 * md5 implementation.
 *
 * More improvement by
 * Bal�zs Bucsay - earthquake at rycon.hu - http://www.rycon.hu/
 * (2times faster, but it's only works up to 54characters)
 *
 * Credits to john!
 */

#include <string.h>

#include "arch.h"
#include "misc.h"
#include "common.h"
#include "formats.h"

#if ARCH_LITTLE_ENDIAN
#define MD5_out MD5_out_eq
#else
#define MD5_out MD5_bitswapped_out_eq
#endif


#define FORMAT_LABEL            "osc-md5"
#define FORMAT_NAME            "osc md5"
#define ALGORITHM_NAME            "osc-md5"

#define BENCHMARK_COMMENT        ""
#define BENCHMARK_LENGTH        -1

#define PLAINTEXT_LENGTH        32

#define BINARY_SIZE            16
#define SALT_SIZE            2

#define MIN_KEYS_PER_CRYPT        1
#define MAX_KEYS_PER_CRYPT        64

#define MD5_BINARY_SIZE        16
#define MD5_HEX_SIZE        (MD5_BINARY_SIZE * 2)

#define CIPHERTEXT_LENGTH    (1 + 3 + 1 + 2 + 1 + MD5_HEX_SIZE)


// Our salt is the 2 characters we know that
// prefix the password
static char OSCSalt[SALT_SIZE];

extern ARCH_WORD_32 MD5_out[MAX_KEYS_PER_CRYPT];
extern char MD5_tmp[MAX_KEYS_PER_CRYPT][MD5_HEX_SIZE + 1];

typedef unsigned int MD5_u32plus;
static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1 + 128 /* MD5 scratch space */];
int saved_key_len[MAX_KEYS_PER_CRYPT];

extern void MD5_Go_eq(unsigned char *data, unsigned int len, int index);
extern void MD5_Go2_eq(unsigned char *data, unsigned int len, int index);

// This struct primes up the fmt variable as an extern in john.c line 40
// the password in this case is 03ericsson - 03 provided, ericsson guessed AND
// a2justin - a2 supplied, justin is decode
// {"$OSC$a2$14f194bdf3a1c50d61e3427d0f77544c","justin"},
// {"$OSC$03$066ab82156b450503861270cf0c0aa68", "ericsson"},
// {"$OSC$99$545471039e2daea8d6c337ee6adffcee,william1},

//372788bad6617f2083f9c07695ee2229 :49eiffel
//066ab82156b450503861270cf0c0aa68: 03ericsson
static struct fmt_tests oscmd5_tests[] = {
    {"$OSC$49$372788bad6617f2083f9c07695ee2229","eiffel"},
    {NULL}
};
// No set up goes on here, just a check
static int oscmd5_valid(char *ciphertext)
{
    //  0123456789012345678901234567890123456789
    //  $OSC$03$066ab82156b450503861270cf0c0aa68
    //  printf("%s %s%s","We are in OSC. Ciphertext is:",ciphertext,"\n");
    if (!ciphertext)
        return 0;

        if (strncmp(ciphertext, "$OSC$", 5) != 0) {
            //    printf("%s %s %s","Initial 5 characters of ciphertext line was not $OSC$ but rather\n",ciphertext,"\n");
                //return 0;
        }

    if (strlen(ciphertext) != CIPHERTEXT_LENGTH) {
          //  printf ("%s %u %s %s", "OSC ciphertext length invalid\n",strlen(ciphertext),ciphertext,"\n");
            return 0;
        }

     if (ciphertext[7] != '$') {
          //  printf("%s","Character 7 must be a $ to split the 'salt' and the ciphertext\n");
            return 0;
        }
     if (strspn(ciphertext+5+1+SALT_SIZE, itoa16) != MD5_HEX_SIZE) {
         //   printf("%s %u %s","OSC ciphertext key not valid size: must be",(unsigned int)MD5_HEX_SIZE,"\n");
                return 0;
        }

        int i;
        for (i = 8; i < CIPHERTEXT_LENGTH; i++){
        if (!(  (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) ||
                    (('a' <= ciphertext[i])&&(ciphertext[i] <= 'f'))  )) {
                    printf("%s","OSC non-hex characters found in key\n");
                    return 0;
                }
    }
        // All checks passed...continue
    return 1;
}

// Convert ASCII salt to its internal representation
// Skip first 5 chars = $OSC$
static void *oscmd5_get_salt(char *ciphertext) {
    printf("%s %s %s","Get salt: ",ciphertext+5,"\n");
    return ciphertext+5;
}
/* Sets a salt for the crypt_all() method */
static void oscmd5_set_salt(void *salt) {
    memcpy(OSCSalt,salt,SALT_SIZE);
}

// Set the suggested key up in saved_key by prefixing
// with the 2 known characters
static void oscmd5_set_key(char *key, int index) {
    char x[PLAINTEXT_LENGTH+1];
    memcpy(x,OSCSalt,SALT_SIZE);
    memcpy(x+SALT_SIZE,key,strlen(key)+1);
    strnzcpy(saved_key[index], x, PLAINTEXT_LENGTH+1);
    saved_key_len[index] = strlen(saved_key[index]);
}

// Get the key stored in the saved_key array eg. ericsson from 03ericsson
static char *oscmd5_get_key(int index) {
    saved_key[index][saved_key_len[index]] = '\0';
    // Chop off the salt characters of saved_key to compare with the plaintext.
    return saved_key[index]+SALT_SIZE;
}

static int oscmd5_cmp_one(void *binary, int index)
{

        return (!(*((unsigned int*)binary) - (unsigned int)MD5_out[index]));
}
// Do a binary (number) check of the ciphertext eg. 06 6a b8 ... aa 68.
// Quit as soon as MD5 of password and key don't match
static int oscmd5_cmp_all(void *binary, int count)
{
    unsigned int i;

    for (i = 0; i < count; i++)
    {
        if (!(*((unsigned int*)binary) - *((unsigned int*)&MD5_out[i]))) return 1;
    }
    return 0;
}
// Compare ASCII hex keys
static int oscmd5_cmp_exact(char *source, int index)
{
    // Creates a hash and compares to key
    MD5_Go2_eq((unsigned char *)saved_key[index], saved_key_len[index], index);
    // Do a straight byte for byte memory compare of the ascii hex variable to test, vs the MD5 calced one
    // Move along to get the ciphertext
    source+=5+SALT_SIZE+1;
    return !memcmp(source,MD5_tmp[index], MD5_HEX_SIZE);
}

static void oscmd5_crypt_all(int count)
{
    unsigned int i;

    for (i = 0; i < count; i++)
    {
           // Update the salt with the latest
           memcpy(saved_key[i],OSCSalt,SALT_SIZE);
           MD5_Go_eq((unsigned char *)saved_key[i], saved_key_len[i], i);
        }
}

int oscmd5_binary_hash_0(void *binary)
{
    return *(ARCH_WORD_32 *)binary & 0xF;
}

int oscmd5_binary_hash_1(void *binary)
{
    return *(ARCH_WORD_32 *)binary & 0xFF;
}

int oscmd5_binary_hash_2(void *binary)
{
    return *(ARCH_WORD_32 *)binary & 0xFFF;
}

int oscmd5_get_hash_0(int index)
{
        return MD5_out[index] & 0xF;
}

int oscmd5_get_hash_1(int index)
{
    return MD5_out[index] & 0xFF;
}

int oscmd5_get_hash_2(int index)
{
    return MD5_out[index] & 0xFFF;
}
// Convert the ASCII Hex representation to a real number
static void *oscmd5_binary(char *ciphertext)
{
    static char realcipher[BINARY_SIZE];
    int i;
        // Move along to the actual ciphertext ie. after $OSC$xx$
        ciphertext+= 5+SALT_SIZE+1;
    for(i=0;i<BINARY_SIZE;i++)
    {
        realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+1])];
    }
        // realcipher must be binary value of actual password
    return (void *)realcipher;
}

// Define our format - identifying the 'override' functions we will use
struct fmt_main fmt_OSC =
{
    {
        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,
        oscmd5_tests
    }, {
        fmt_default_init,
        oscmd5_valid,
        fmt_default_split,
        oscmd5_binary,
        oscmd5_get_salt, // Extract salt
        {
            oscmd5_binary_hash_0,
            oscmd5_binary_hash_1,
            oscmd5_binary_hash_2
                },
        fmt_default_salt_hash,
                oscmd5_set_salt, // Put into global variable
                oscmd5_set_key,
        oscmd5_get_key,
        fmt_default_clear_keys,
        oscmd5_crypt_all, // Adds on salt
        {
            oscmd5_get_hash_0,
            oscmd5_get_hash_1,
            oscmd5_get_hash_2
                },
        oscmd5_cmp_all,
        oscmd5_cmp_one,
        oscmd5_cmp_exact
    }
};



_________________________________________________________________
Are you a friend magnet? Play now to win prizes for you and your friends!
http://clk.atdmt.com/GBL/go/106906016/direct/01/?href=http://www.friendmagnet.com.au

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.