Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Sun, 28 Oct 2012 16:03:33 +0530
From: Dhiru Kholia <dhiru.kholia@...il.com>
To: john-dev@...ts.openwall.com
Cc: Milen Rangelov <gat3way@...3way.eu>
Subject: ssh_fmt / privkey without using high level OpenSSL functions

Hi,

I tried to re-implement ssh / privkey format without using high level
OpenSSL functions. However I didn't get a speed-up over JtR's existing
ssh format :-(. Code is attached. Feel free to re-use it.

One advantage of my new code over existing JtR code is that it has no
multi-threading issues.

Milen,

So far, I have only seen private keys using one of the following two
encryption algorithms,

    _CIPHER_TABLE = {
        'AES-128-CBC': { 'cipher': AES, 'keysize': 16, 'blocksize':
16, 'mode': AES.MODE_CBC },
        'DES-EDE3-CBC': { 'cipher': DES3, 'keysize': 24, 'blocksize':
8, 'mode': DES3.MODE_CBC },
    }

Let me know if you need corresponding fastssh2john program.

-- 
Cheers,
Dhiru

/* Cracker for SSH RSA key files. Hacked together during September of 2012 by 
 * Dhiru Kholia <dhiru.kholia at gmail.com>.
 *
 * This software is Copyright (c) 2012, Dhiru Kholia <dhiru.kholia at gmail.com>,
 * and it is hereby released to the general public under the following terms:
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted. */

#define _GNU_SOURCE
#include "md5.h"
#include <string.h>
#include <openssl/aes.h>
#include <openssl/des.h>
#include <openssl/asn1.h>
#include <assert.h>
#include <errno.h>
#include "arch.h"
#include "misc.h"
#include "common.h"
#include "formats.h"
#include "params.h"
#include "options.h"
#ifdef _OPENMP
static int omp_t = 1;
#include <omp.h>
#define OMP_SCALE               64
#endif

#define FORMAT_LABEL		"fastssh"
#define FORMAT_NAME		"fast SSH RSA / DSA"
#define ALGORITHM_NAME		"32/" ARCH_BITS_STR
#define BENCHMARK_COMMENT	""
#define BENCHMARK_LENGTH	-1
#define PLAINTEXT_LENGTH	32
#define BINARY_SIZE		16
#define SALT_SIZE		sizeof(struct custom_salt)
#define MIN_KEYS_PER_CRYPT	1
#define MAX_KEYS_PER_CRYPT	1

static struct fmt_tests fastssh_tests[] = {
	{"$fastssh$0$8$DAA422E8A5A8EFB7$608$fa7b2c1c699697dd487261a213a0dd088a86bc03f4e2db8b87ad302e3581bdd8ed17d0a3ced3e7179ef17beea9064ee862017f472de293d655f6b1cd7115e27c328cf5caf1b5896952590cd82d123fcf6c5da3b43f5435c829ebb595300c828e04d57c7ade57efe006305b32fe79afd0d14cadba681b4dc3a69b25a1e71ddbd353465217c311d11721f1cba05d1226ff0e7d261156f0837753bcaaddfec383591f61470a4318cf679046d43490a1eef33014a90865917ccaa16f986724b8ee421d990327a46410362b4992406af41a88e3c5e5bbb7707ba08517e7ac8295ad0b934c38968f05fd372f1ee29e24eddcbbacba5b3e1b7150e51ba4e17b4f54319630e2d5372adc46e4de437f64b3d11670eb25fc94c7e9bd0579806bbf16c6cfe529a4bc0d3918ca4777f8418e789163660d9bbe0aa297857ee4922dffe310e6967fba2ee2e06707d9bbd9c8601bad7ccfdcb8a948074de511be7d588b7b71d4b5f0b1e19020b54efc4d626b2e4d85c0a40682517128b9ecc29f882996f4f6b655bb1986e293cb5271fe98c61d8b2e6e8338fee42f22674fc8b2da475663ba19644e7de76927cd9e333b533ad7617cc7a9f19dc7c00c240ed92c2fb1aaf6495bd16ab9fae4650567ad8b175d02f9e6a9737362168035670017fd9ad87cf4e916f47baa5efe0d04939295fba608f83fa811b946d12afe77836dc6d0d398824a355926ce5848dace776c7a7ab7109be495894bc98a2cf04107368d5d8777a1d0ef19782ebb1527b564ac0f5d4ac91e81f435cc21f5905b9753ee1a79913306957589943da161a6f5dc3082b80930553769ce11d82d9cb12d8a12bb4e56eb3f1200eb", "television"},
	{NULL}
};

static char (*saved_key)[PLAINTEXT_LENGTH + 1];
static int *cracked;

static struct custom_salt {
	char unsigned salt[16];
	char unsigned ct[8192];
	int cipher;
	int ctl;
	int sl;
} *cur_salt;

static void init(struct fmt_main *self)
{
#ifdef _OPENMP
	omp_t = omp_get_max_threads();
	self->params.min_keys_per_crypt *= omp_t;
	omp_t *= OMP_SCALE;
	self->params.max_keys_per_crypt *= omp_t;
#endif
	saved_key = mem_calloc_tiny(sizeof(*saved_key) *
			self->params.max_keys_per_crypt, MEM_ALIGN_NONE);
	cracked = mem_calloc_tiny(sizeof(*cracked) *
			self->params.max_keys_per_crypt, MEM_ALIGN_WORD);
}

static int valid(char *ciphertext, struct fmt_main *self)
{
	return !strncmp(ciphertext, "$fastssh$", 9);
}

#ifdef DEBUG
static void print_hex(unsigned char *str, int len)
{
	int i;
	for (i = 0; i < len; ++i)
		printf("%02x", str[i]);
	printf("\n");
}
#endif

static void *get_salt(char *ciphertext)
{
	char *ctcopy = strdup(ciphertext);
	char *keeptr = ctcopy;
	char *p;
	int i;
	static struct custom_salt cs;
	ctcopy += 9;	/* skip over "$fastssh$" */
	p = strtok(ctcopy, "$");
	cs.cipher = atoi(p);
	p = strtok(NULL, "$");
	cs.sl = atoi(p);
	p = strtok(NULL, "$");
	for (i = 0; i < cs.sl; i++)
		cs.salt[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16
			+ atoi16[ARCH_INDEX(p[i * 2 + 1])];
	p = strtok(NULL, "$");
	cs.ctl = atoi(p);
	p = strtok(NULL, "$");
	for (i = 0; i < cs.ctl; i++)
		cs.ct[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16
			+ atoi16[ARCH_INDEX(p[i * 2 + 1])];
	MEM_FREE(keeptr);
	return (void *)&cs;
}

static void set_salt(void *salt)
{
	cur_salt = (struct custom_salt *)salt;
}

void generate_key_bytes(int nbytes, unsigned char *password, unsigned char *key)
{
	unsigned char digest[16];
	int keyidx = 0;
	int digest_inited = 0;
	int size;
	int i;

	while (nbytes > 0) {
		MD5_CTX ctx;
		MD5_Init(&ctx);
		if (digest_inited) {
			MD5_Update(&ctx, digest, 16);
		}
		MD5_Update(&ctx, password, strlen((const char*)password));
		/* use first 8 bytes of salt */
		MD5_Update(&ctx, cur_salt->salt, 8);
		MD5_Final(digest, &ctx);
		digest_inited = 1;
		if (nbytes > 16)
			size = 16;
		else 
			size = nbytes;
		/* copy part of digest to keydata */
		for(i = 0; i < size; i++)
			key[keyidx++] = digest[i];
		nbytes -= size;
	}
}

int check_padding_3des(unsigned char *out, int length)
{
	int pad;
	int i;
	int n;
	unsigned char output[8192];
	char *res;
	BIO * outfile;

	
	// now check padding
	pad = out[length - 1];
	if(pad > 8)
		// "Bad padding byte. You probably have a wrong password"
		 return -1;
	n = length - pad;
	for(i = n; i < length; i++)
		if(out[i] != pad)
			return -1;
	/* check BER decoding */
	outfile = BIO_new(BIO_s_mem());
	ASN1_parse(outfile, out, cur_salt->ctl, 0);
	BIO_gets(outfile, (char*)output, 8192);
	res = memmem(output, 128, "SEQUENCE", 8);
	if (!res)
		return -1;
	BIO_gets(outfile, (char*)output, 8192);
	res = memmem(output, 128, ":00", 3);
	if (!res)
		return -1;

	return 0;
}


static void crypt_all(int count)
{
	int index = 0;
#ifdef _OPENMP
#pragma omp parallel for
	for (index = 0; index < count; index++)
#endif
	{
		unsigned char key[24] = {0};
		unsigned char out[cur_salt->ctl];
		DES_cblock key1, key2, key3;
		DES_cblock ivec;
		DES_key_schedule ks1, ks2, ks3;
		generate_key_bytes(24, (unsigned char*)saved_key[index], key);
		memset(out, 0, sizeof(out));
		memcpy(key1, key, 8);
		memcpy(key2, key + 8, 8);
		memcpy(key3, key + 16, 8);
		DES_set_key((C_Block *) key1, &ks1);
		DES_set_key((C_Block *) key2, &ks2);
		DES_set_key((C_Block *) key3, &ks3);
		memcpy(ivec, cur_salt->salt, 8);
		DES_ede3_cbc_encrypt(cur_salt->ct, out, cur_salt->ctl, &ks1, &ks2, &ks3, &ivec,  DES_DECRYPT);

		if (check_padding_3des(out, cur_salt->ctl) == 0)
			cracked[index] = 1;
		else
			cracked[index] = 0;
	}
		/* AES_set_decrypt_key(key, 192, &akey);
		AES_cbc_encrypt(cur_salt->ct + 16, pt + 16, 32, &akey, iv, AES_DECRYPT);
		if (!memcmp(pt + 40, "\x08\x08\x08\x08\x08\x08\x08\x08", 8)) {
			cracked[index] = 1;
		}
		else
			cracked[index] = 0; */

}

static int cmp_all(void *binary, int count)
{
	int index;
	for (index = 0; index < count; index++)
		if (cracked[index])
			return 1;
	return 0;
}

static int cmp_one(void *binary, int index)
{
	return cracked[index];
}

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

static void fastssh_set_key(char *key, int index)
{
	int saved_key_length = strlen(key);
	if (saved_key_length > PLAINTEXT_LENGTH)
		saved_key_length = PLAINTEXT_LENGTH;
	memcpy(saved_key[index], key, saved_key_length);
	saved_key[index][saved_key_length] = 0;
}

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

struct fmt_main fastssh_fmt = {
	{
		FORMAT_LABEL,
		FORMAT_NAME,
		ALGORITHM_NAME,
		BENCHMARK_COMMENT,
		BENCHMARK_LENGTH,
		PLAINTEXT_LENGTH,
		BINARY_SIZE,
#if FMT_MAIN_VERSION > 9
		DEFAULT_ALIGN,
#endif
		SALT_SIZE,
#if FMT_MAIN_VERSION > 9
		DEFAULT_ALIGN,
#endif
		MIN_KEYS_PER_CRYPT,
		MAX_KEYS_PER_CRYPT,
		FMT_CASE | FMT_8_BIT | FMT_OMP,
		fastssh_tests
	}, {
		init,
		fmt_default_prepare,
		valid,
		fmt_default_split,
		fmt_default_binary,
		get_salt,
#if FMT_MAIN_VERSION > 9
		fmt_default_source,
#endif
		{
			fmt_default_binary_hash
		},
		fmt_default_salt_hash,
		set_salt,
		fastssh_set_key,
		get_key,
		fmt_default_clear_keys,
		crypt_all,
		{
			fmt_default_get_hash
		},
		cmp_all,
		cmp_one,
		cmp_exact
	}
};

Powered by blists - more mailing lists

Your e-mail address:

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