Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 25 Aug 2005 10:12:48 +0200
From: Simon Marechal <simon@...quise.net>
To: john-users@...ts.openwall.com
Subject: Oracle password cracker

Here is an oracle password cracker I wrote for JtR. It is not tested and
requires tweaking in loader.c and stuff just like the mscash patch. It
uses DES.

I do not really understand how the bitsliced library works. Is it
possible to use it on the oracle passwords? Is it worth it?

/*
 * Copyright (c) 2004 Simon Marechal
 * simon.marechal@...les-security.com
 */

#include <string.h>

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

#define FORMAT_LABEL			"oracle"
#define FORMAT_NAME			"Oracle"
#define ALGORITHM_NAME			"oracle"

#define BENCHMARK_COMMENT		""
#define BENCHMARK_LENGTH		-1

#define PLAINTEXT_LENGTH		16

#define BINARY_SIZE			8
#define SALT_SIZE			32
#define CIPHERTEXT_LENGTH		(BINARY_SIZE + SALT_SIZE)

#define MIN_KEYS_PER_CRYPT		1
#define MAX_KEYS_PER_CRYPT		1

static struct fmt_tests oracle_tests[] = {
	{"O$SIMON#4F8BC1809CB2AF77", "A"},
	{"O$SIMON#183D72325548EF11", "THALES2" },
	{"O$SIMON#C4EB3152E17F24A4", "TST" },
	{"O$SYSTEM#9EEDFA0AD26C6D52", "THALES" },
	{NULL}
};

#if ARCH_LITTLE_ENDIAN
#define ENDIAN_SHIFT_L  << 8
#define ENDIAN_SHIFT_R  >> 8
#else
#define ENDIAN_SHIFT_L
#define ENDIAN_SHIFT_R
#endif

//stores the ciphertext for value currently being tested
static char crypt_key[BINARY_SIZE+1];

static unsigned char cur_salt[128 + 1]; //current salt
static unsigned char cur_key[128 + 1]; //current salt

static unsigned char deskey[8];
static unsigned char salt_iv[8];
static DES_key_schedule desschedule1;
static DES_key_schedule desschedule2;

static int salt_length;
static int key_length;

static int valid(char *ciphertext)
{
	int i;
	int l;

	/*
	 * 2 cases
	 * 1 - it comes from the disk, and does not have O$ + salt
	 * 2 - it comes from memory, and has got O$ + salt + # + blah
	 */

	if (!memcmp(ciphertext, "O$", 2))
	{
		l = strlen(ciphertext) - PLAINTEXT_LENGTH;
		if(ciphertext[l-1]!='#')
			return 0;
	}
	else
	{
		if(strlen(ciphertext)!=PLAINTEXT_LENGTH)
			return 0;
		l = 0;
	}
	for (i = l; i < l + PLAINTEXT_LENGTH; i++){
		if (!(  (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) ||
			(('a' <= ciphertext[i])&&(ciphertext[i] <= 'f'))  
			|| (('A' <= ciphertext[i])&&(ciphertext[i] <= 'F'))))
			return 0;
	}
	
	return 1;
}

static void oracle_init(void)
{
	deskey[0] = 0x01;
	deskey[1] = 0x23;
	deskey[2] = 0x45;
	deskey[3] = 0x67;
	deskey[4] = 0x89;
	deskey[5] = 0xab;
	deskey[6] = 0xcd;
	deskey[7] = 0xef;

	my_des_set_key(&deskey, &desschedule1);
}

static void oracle_set_salt(void *salt, int count) {
	salt_length = 0;

	memset(salt_iv, 0, 8);
	while ( (((unsigned short *)cur_salt)[salt_length] = ((unsigned char *)salt)[salt_length] ENDIAN_SHIFT_L ))
		salt_length++;
	//this optimization is for Bob the Butcher only
	/*
	if(salt_length > 4)
	{
		salt_offset = (salt_length & (~3))*2;
		my_des_ncbc_encrypt(cur_salt, salt_offset, &desschedule1, salt_iv);
	}*/
}

static void oracle_set_key(char *key, int index) {
	key_length = 0;
	while( (((unsigned short *)cur_key)[key_length] = key[key_length] ENDIAN_SHIFT_L ))
		key_length++;
}

static char *oracle_get_key(int index) {
	static unsigned char out[PLAINTEXT_LENGTH];
	unsigned int i;
	for(i=0;i<key_length;i++)
		out[i] = ((unsigned short *)cur_key)[i] ENDIAN_SHIFT_R;
	out[i] = 0;
	return out;
}

static int oracle_cmp_all(void *binary, int index) { 
	int i=0;
	while(i<(BINARY_SIZE/sizeof(int)))
	{
		if(((int *)binary)[i]!=((int *)crypt_key)[i])
			return 0;
		i++;
	}
	return 1;
}

static void oracle_crypt_all(int count)  
{
	unsigned int l;

	
	l = (salt_length + key_length)*2;
	memcpy(crypt_key, salt_iv, 8);
	memcpy(cur_salt + salt_length*2, cur_key, key_length * 2); //stupid way john works
	my_des_ncbc_encrypt(cur_salt ,l , &desschedule1, crypt_key);
	my_des_set_key(crypt_key, &desschedule2);
	memset(crypt_key, 0, 8);
	my_des_ncbc_encrypt(cur_salt, l , &desschedule2, crypt_key);
}

static void * oracle_binary(char *ciphertext) 
{
	static unsigned char out3[BINARY_SIZE];
	int l;
	int i;
	l = strlen(ciphertext) - PLAINTEXT_LENGTH;
	for(i=0;i<BINARY_SIZE;i++) 
	{
		out3[i] = atoi16[ARCH_INDEX(ciphertext[i*2+l])]*16 
			+ atoi16[ARCH_INDEX(ciphertext[i*2+l+1])];
	}
	return out3;
}

static void * oracle_get_salt(char * ciphertext)
{
	static unsigned char out2[SALT_SIZE];
	int l;

	l = 2;
	while( ciphertext[l] && (ciphertext[l]!='#') )
	{
		out2[l-2] = ciphertext[l];
		l++;
	}
	out2[l-2] = 0;
	return out2;
}

static int oracle_cmp_one(void *binary, int count){
	return (1);
}

static int oracle_cmp_exact(char *source, int count){
	return 1;
}

static int binary_hash1(void * binary) { return (((unsigned int *)binary)[0] & 0xf); }
static int binary_hash2(void * binary) { return (((unsigned int *)binary)[0] & 0xff); }
static int binary_hash3(void * binary) { return (((unsigned int *)binary)[0] & 0xfff); }

static int get_hash1(int index) { return (((unsigned int *)crypt_key)[0] & 0xf); }
static int get_hash2(int index) { return (((unsigned int *)crypt_key)[0] & 0xff); }
static int get_hash3(int index) { return (((unsigned int *)crypt_key)[0] & 0xfff); }

struct fmt_main fmt_oracle = {
	{
		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_8_BIT,
		oracle_tests
	}, {
		oracle_init,
		valid,
		fmt_default_split,
		oracle_binary,
		oracle_get_salt,
		{
			binary_hash1,
			binary_hash2,
			binary_hash3
		},
		fmt_default_salt_hash,
		oracle_set_salt,
		oracle_set_key,
		oracle_get_key,
		fmt_default_clear_keys,
		oracle_crypt_all,
		{
			get_hash1,
			get_hash2,
			get_hash3
		},
		oracle_cmp_all,
		oracle_cmp_one,
		oracle_cmp_exact
	}
};

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ