This repository has been archived by the owner on May 8, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
370 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
regular: | ||
gcc -fopenmp -O3 -Wall -Wextra RC4-40-brute.c rc4.c -lcrypto -o RC4-40-brute | ||
|
||
debug: | ||
gcc -fsanitize=address -fopenmp -O3 -Wall -Wextra RC4-40-brute.c rc4.c -lcrypto -o RC4-40-brute |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* Program to brute-force RC4 40-bit keyspace by Dhiru Kholia. | ||
* | ||
* common_init is part of John the Ripper password cracker, | ||
* Copyright (c) 1996-99 by Solar Designer */ | ||
|
||
#include <string.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <assert.h> | ||
#include "rc4.h" | ||
#include <openssl/md5.h> | ||
#include <openssl/sha.h> | ||
#include <omp.h> | ||
#include <sys/time.h> | ||
#include <time.h> | ||
|
||
#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) | ||
|
||
char itoa64[64] = | ||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||
char atoi64[0x100]; | ||
|
||
char itoa16[16] = | ||
"0123456789abcdef"; | ||
char itoa16u[16] = | ||
"0123456789ABCDEF"; | ||
char atoi16[0x100]; | ||
|
||
static int initialized = 0; | ||
|
||
void common_init(void) | ||
{ | ||
char *pos; | ||
|
||
if (initialized) return; | ||
|
||
memset(atoi64, 0x7F, sizeof(atoi64)); | ||
for (pos = itoa64; pos <= &itoa64[63]; pos++) | ||
atoi64[ARCH_INDEX(*pos)] = pos - itoa64; | ||
|
||
memset(atoi16, 0x7F, sizeof(atoi16)); | ||
for (pos = itoa16; pos <= &itoa16[15]; pos++) | ||
atoi16[ARCH_INDEX(*pos)] = pos - itoa16; | ||
|
||
atoi16['A'] = atoi16['a']; | ||
atoi16['B'] = atoi16['b']; | ||
atoi16['C'] = atoi16['c']; | ||
atoi16['D'] = atoi16['d']; | ||
atoi16['E'] = atoi16['e']; | ||
atoi16['F'] = atoi16['f']; | ||
|
||
initialized = 1; | ||
} | ||
|
||
int type; | ||
unsigned char salt[16]; | ||
unsigned char verifier[16]; | ||
unsigned char verifierHash[20]; | ||
|
||
static void print_hex(unsigned char *str, int len) | ||
{ | ||
int i; | ||
for (i = 0; i < len; ++i) | ||
printf("%02x", str[i]); | ||
printf("\n"); | ||
} | ||
|
||
static void (*try_key)(unsigned char *hashBuf); | ||
|
||
static inline void try_key_md5(unsigned char *hashBuf) | ||
{ | ||
MD5_CTX ctx; | ||
unsigned char pwdHash[16]; | ||
unsigned char rc4Key[16]; | ||
unsigned char out[32]; | ||
RC4_KEY key; | ||
|
||
MD5_Init(&ctx); | ||
MD5_Update(&ctx, hashBuf, 9); | ||
MD5_Final(pwdHash, &ctx); | ||
memcpy(rc4Key, pwdHash, 16); /* 128-bit key */ | ||
RC4_set_key(&key, 16, rc4Key); | ||
RC4(&key, 16, verifier, out); /* encryptedVerifier */ | ||
RC4(&key, 16, verifierHash, out + 16); /* encryptedVerifierHash */ | ||
/* hash the decrypted verifier */ | ||
MD5_Init(&ctx); | ||
MD5_Update(&ctx, out, 16); | ||
MD5_Final(pwdHash, &ctx); | ||
if(!memcmp(pwdHash, out + 16, 16)) { | ||
printf("Key is : " ); | ||
print_hex(hashBuf, 5); | ||
exit(0); | ||
} | ||
} | ||
|
||
static inline void try_key_sha1(unsigned char *hashBuf) | ||
{ | ||
SHA_CTX ctx; | ||
unsigned char pwdHash[16]; | ||
unsigned char rc4Key[16] = { 0 }; | ||
unsigned char out[36]; | ||
RC4_KEY key; | ||
|
||
memcpy(rc4Key, hashBuf, 5); /* 128-bit key */ | ||
RC4_set_key(&key, 16, rc4Key); | ||
RC4(&key, 16, verifier, out); /* encryptedVerifier to DecryptedVerifier */ | ||
RC4(&key, 16, verifierHash, out + 16); /* encryptedVerifierHash */ | ||
/* hash the decrypted verifier */ | ||
SHA1_Init(&ctx); | ||
SHA1_Update(&ctx, out, 16); | ||
SHA1_Final(pwdHash, &ctx); | ||
if(!memcmp(pwdHash, out + 16, 16)) { | ||
printf("Key is : " ); | ||
print_hex(hashBuf, 5); | ||
exit(0); | ||
} | ||
} | ||
|
||
void keyspace_search() | ||
{ | ||
char buffer[30]; | ||
struct timeval tv; | ||
time_t curtime; | ||
|
||
int i, j, k; | ||
int is = 0x00; | ||
int js = 0x00; | ||
int ks = 0x00; | ||
int ls = 0x00; | ||
int ms = 0x00; | ||
|
||
/* 69a3aea22c is key for test.doc */ | ||
/* int is = 0x69; | ||
int js = 0xa3; | ||
int ks = 0x00; | ||
int ls = 0x00; | ||
int ms = 0x00; */ | ||
|
||
for(i = is; i <= 255; i++) { /* time = 256 * 9 * 256 seconds ~= 6.83 days */ | ||
for(j = js; j <= 255; j++) { | ||
/* takes 8.5 seconds on AMD X3 (using all cores) for one tick */ | ||
/* takes 3 seconds on AMD FX-8120 (using all cores) for one tick */ | ||
gettimeofday(&tv, NULL); | ||
curtime = tv.tv_sec; | ||
printf("%d %d @ ", i, j); | ||
strftime(buffer, 30, "%m-%d-%Y %T.", localtime(&curtime)); | ||
printf("%s%ld\n", buffer, tv.tv_usec); | ||
fflush(stdout); | ||
#pragma omp parallel for | ||
for(k = ks; k <= 255; k++) { | ||
int l, m; | ||
for(l = ls; l <= 255; l++) { | ||
for(m = ms; m <= 255; m++) { | ||
unsigned char hashBuf[9] = { 0 }; | ||
hashBuf[0] = (char)i; | ||
hashBuf[1] = (char)j; | ||
hashBuf[2] = (char)k; | ||
hashBuf[3] = (char)l; | ||
hashBuf[4] = (char)m; | ||
try_key(hashBuf); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int i; | ||
|
||
if(argc < 2) { | ||
fprintf(stderr, "Usage: %s <hash given by office2john.py program>\n\n", argv[0]); | ||
// Password: test, MITM key: 69a3aea22c | ||
fprintf(stderr, "Example: %s \'test.doc:$oldoffice$1*de17a7f3c3ff03a39937ba9666d6e952*2374d5b6ce7449f57c9f252f9f9b53d2*e60e1185f7aecedba262f869c0236f81\'\n", argv[0]); | ||
// Password: 12345, MITM key: d2b6cfbda3 | ||
fprintf(stderr, "Example: %s \'12345.accdb:$oldoffice$3*49b09b9fb5a69798e8f7ca200e26d199*f0e2de067d37538ed04d7c75781a407e*4b5a7e08da5442f898540ab311034f261df0320a\'\n", argv[0]); | ||
exit(-1); | ||
} | ||
|
||
common_init(); | ||
|
||
char *ctcopy = strdup(argv[1]); | ||
char *keeptr = ctcopy; | ||
char *p; | ||
ctcopy = strchr(ctcopy, ':') + 1 + 11; /* skip over filename and "$oldoffice$" */ | ||
p = strtok(ctcopy, "*"); | ||
type = atoi(p); | ||
if (!(type <= 3)) { | ||
fprintf(stderr, "Only documents encrypted using RC4 40-bit are supported!\n"); | ||
exit(-1); | ||
} | ||
|
||
p = strtok(NULL, "*"); | ||
for (i = 0; i < 16; i++) | ||
salt[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 | ||
+ atoi16[ARCH_INDEX(p[i * 2 + 1])]; | ||
p = strtok(NULL, "*"); | ||
for (i = 0; i < 16; i++) | ||
verifier[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 | ||
+ atoi16[ARCH_INDEX(p[i * 2 + 1])]; | ||
p = strtok(NULL, "*"); | ||
if (type < 3) { | ||
for (i = 0; i < 16; i++) | ||
verifierHash[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 | ||
+ atoi16[ARCH_INDEX(p[i * 2 + 1])]; | ||
print_hex(verifierHash, 16); | ||
try_key = &try_key_md5; | ||
} else if (type < 4) { | ||
for (i = 0; i < 20; i++) | ||
verifierHash[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 | ||
+ atoi16[ARCH_INDEX(p[i * 2 + 1])]; | ||
print_hex(verifierHash, 20); | ||
try_key = &try_key_sha1; | ||
} | ||
|
||
free(keeptr); | ||
|
||
keyspace_search(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
RC4-40-brute-office | ||
=================== | ||
### RC4-40-brute-office | ||
|
||
Guaranteed cracking of M$ Office files using RC4 40-bit encryption | ||
Guaranteed cracking of MS Office files using RC4 40-bit encryption. | ||
|
||
Get `office2john.py` from https://github.com/magnumripper/JohnTheRipper/. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Our own RC4 based on the "original" as posted to sci.crypt in 1994 and | ||
* tweaked for performance on x86-64. OpenSSL is probably faster for | ||
* decrypting larger amounts of data but we are more interested in a very | ||
* fast key setup. On Intel and AMD x64, I have seen up to 50% speedups. | ||
* | ||
* The speed improvement (if you see one) is due to OpenSSL's (or your | ||
* distributor's) choice of type for RC4_INT. Some systems perform bad if | ||
* this is defined as char. Others perform bad if it's not. If needed, we | ||
* could move JOHN_RC4_INT to arch.h | ||
* | ||
* Syntax is same as OpenSSL; | ||
* just #include "rc4.h" instead of <openssl/rc4.h> | ||
* | ||
* Put together by magnum in 2011, 2013. No Rights Reserved. | ||
*/ | ||
|
||
#include "rc4.h" | ||
|
||
#define swap_byte(a, b) { RC4_INT tmp = (*a); (*a) = (*b); (*b) = tmp; } | ||
|
||
#define swap_state(n) { \ | ||
index2 = (kp[index1] + state[(n)] + index2) & 255; \ | ||
swap_byte(&state[(n)], &state[index2]); \ | ||
if (++index1 == keylen) index1 = 0; \ | ||
} | ||
|
||
void RC4_set_key(RC4_KEY *ctx, RC4_INT keylen, const unsigned char *kp) | ||
{ | ||
RC4_INT index1; | ||
RC4_INT index2; | ||
RC4_INT *state; | ||
int counter; | ||
|
||
state = &ctx->state[0]; | ||
for (counter = 0; counter < 256; counter++) | ||
state[counter] = counter; | ||
ctx->x = 0; | ||
ctx->y = 0; | ||
index1 = 0; | ||
index2 = 0; | ||
for (counter = 0; counter < 256; counter += 4) { | ||
swap_state(counter); | ||
swap_state(counter + 1); | ||
swap_state(counter + 2); | ||
swap_state(counter + 3); | ||
} | ||
} | ||
|
||
void RC4(RC4_KEY *ctx, RC4_INT len, const unsigned char *in, unsigned char *out) | ||
{ | ||
RC4_INT x; | ||
RC4_INT y; | ||
RC4_INT *state; | ||
RC4_INT counter; | ||
|
||
x = ctx->x; | ||
y = ctx->y; | ||
|
||
state = &ctx->state[0]; | ||
for (counter = 0; counter < len; counter ++) { | ||
x = (x + 1) & 255; | ||
y = (state[x] + y) & 255; | ||
swap_byte(&state[x], &state[y]); | ||
*out++ = *in++ ^ state[(state[x] + state[y]) & 255]; | ||
} | ||
ctx->x = x; | ||
ctx->y = y; | ||
} | ||
|
||
void RC4_single(void *key, unsigned int keylen, const unsigned char *in, int len, unsigned char *out) | ||
{ | ||
unsigned char *kp = (unsigned char*)key; | ||
unsigned int i; | ||
RC4_INT x = 0; | ||
RC4_INT y = 0; | ||
RC4_INT index1 = 0; | ||
RC4_INT index2 = 0; | ||
RC4_INT state[256]; | ||
|
||
for (i = 0; i < 256; i += 4) { | ||
state[i] = i; | ||
state[i + 1] = i + 1; | ||
state[i + 2] = i + 2; | ||
state[i + 3] = i + 3; | ||
} | ||
|
||
for (i = 0; i < 256; i += 4) { | ||
swap_state(i); | ||
swap_state(i + 1); | ||
swap_state(i + 2); | ||
swap_state(i + 3); | ||
} | ||
|
||
while (len--) { | ||
x = (x + 1) & 255; | ||
y = (state[x] + y) & 255; | ||
swap_byte(&state[x], &state[y]); | ||
*out++ = *in++ ^ state[(state[x] + state[y]) & 255]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Our own RC4 based on the "original" as posted to sci.crypt in 1994 and | ||
* tweaked for performance on x86-64. OpenSSL is probably faster for | ||
* decrypting larger amounts of data but we are more interested in a very | ||
* fast key setup. On Intel and AMD x64, I have seen up to 50% speedups. | ||
* | ||
* The speed improvement (if you see one) is due to OpenSSL's (or your | ||
* distributor's) choice of type for RC4_INT. Some systems perform bad if | ||
* this is defined as char. Others perform bad if it's not. If needed, we | ||
* could move JOHN_RC4_INT to arch.h | ||
* | ||
* Syntax is same as OpenSSL; | ||
* just #include "rc4.h" instead of <openssl/rc4.h> | ||
* | ||
* Put together by magnum in 2011. No Rights Reserved. | ||
*/ | ||
|
||
#ifndef HEADER_RC4_H | ||
#define HEADER_RC4_H | ||
|
||
#include <stdint.h> | ||
|
||
#define RC4_INT uint32_t | ||
|
||
typedef struct rc4_key | ||
{ | ||
RC4_INT state[256]; | ||
RC4_INT x; | ||
RC4_INT y; | ||
} RC4_KEY; | ||
|
||
extern void RC4_set_key(RC4_KEY *ctx, RC4_INT len, const unsigned char *data); | ||
extern void RC4(RC4_KEY *ctx, RC4_INT len, const unsigned char *indata, | ||
unsigned char *outdata); | ||
extern void RC4_single(void *key, unsigned int keylen, const unsigned char *in, int len, | ||
unsigned char *out); | ||
|
||
#endif /* HEADER_RC4_H */ |