forked from pmittaldev/john-the-ripper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEPI_fmt_plug.c
207 lines (173 loc) · 5.01 KB
/
EPI_fmt_plug.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
* EPiServer module for john 1.7.2 (and possibly later)
* Uses hashes/salts found in the tblSID of an EPiServer database installation
*
* Created by Johannes Gumbel (johannes [at] iforge.cc)
*
* If you have any questions as to how a function incorporates with john, please refer to formats.h of john
*
* version 0.1 released on 10 jan 2007
*
* See doc/EPi.patch.README or http://iforge.cc/files/EPi.patch.README
* for information on the input file format.
*/
#include <string.h>
#include "arch.h"
#include "misc.h"
#include "common.h"
#include "formats.h"
#include "sha.h"
#define PLAINTEXT_LENGTH 0x80-4
#define BINARY_LENGTH 20
#define SALT_LENGTH 30
static ARCH_WORD global_crypt[BINARY_LENGTH / ARCH_SIZE + 1];
static char global_key[PLAINTEXT_LENGTH]; // set by set_key and used by get_get
static char global_salt[SALT_LENGTH + PLAINTEXT_LENGTH]; // set by set_salt and used by crypt_all
// the extra plaintext_length is needed because the
// current key is copied there before hashing
int valid(char *ciphertext, struct fmt_main *self);
void* binary(char *ciphertext);
void* salt(char *ciphertext);
void set_salt(void *salt);
void set_key(char *key, int index);
char* get_key(int index);
void crypt_all(int count);
int cmp_all(void *binary, int count);
int cmp_one(void *binary, int index);
int cmp_exact(char *source, int index);
struct fmt_tests global_tests[] =
{
{"0x5F1D84A6DE97E2BEFB637A3CB5318AFEF0750B856CF1836BD1D4470175BE 0x4D5EFDFA143EDF74193076F174AC47CEBF2F417F", "Abc.!23"},
// new tests from pass_gen.pl
{"0x4F5233704337716F63526A7066344B52784F7A6363316750516A72335668 0x7346DA02479E55973E052FC9A173A3FEA4644FF8","test1"},
{"0x76706335715834565A55784662304F3367756350684F634447777A313642 0xDBD3D2764A376673164962E3EE2AE95AB6ED2759","thatsworking"},
{"0x6F724166466172354A7431316A4842746878434B6632744945574A37524A 0xE1ADE625160BB27C16184795715F1C9EF30C45B0","test3"},
{NULL}
};
// Define john integration
struct fmt_main fmt_EPI =
{
{ // fmt_params
"epi",
"EPiServer SID salted SHA-1",
"32/" ARCH_BITS_STR,
"", // benchmark comment
0, // benchmark length
PLAINTEXT_LENGTH,
BINARY_LENGTH,
SALT_LENGTH,
1,
1,
FMT_CASE | FMT_8_BIT, // flags XXX, these are just guesses
global_tests
},
{ // fmt_methods
fmt_default_init,
fmt_default_prepare,
valid,
fmt_default_split,
binary,
salt,
{ // binary_hash[3]
fmt_default_binary_hash,
fmt_default_binary_hash,
fmt_default_binary_hash,
fmt_default_binary_hash,
fmt_default_binary_hash
},
fmt_default_salt_hash,
set_salt,
set_key,
get_key,
fmt_default_clear_keys,
crypt_all,
{ // get_hash[3]
fmt_default_get_hash,
fmt_default_get_hash,
fmt_default_get_hash,
fmt_default_get_hash,
fmt_default_get_hash
},
cmp_all,
cmp_one,
cmp_exact
}
};
/*
* Expects ciphertext of format: 0xHEX*60 0xHEX*40
*/
int valid(char *ciphertext, struct fmt_main *self)
{
unsigned int len, n;
if(!ciphertext) return 0;
len = strlen(ciphertext);
if(len != 105)
return 0;
// check fixed positions
if(ciphertext[0] != '0' || ciphertext[1] != 'x' ||
ciphertext[62] != ' ' ||
ciphertext[63] != '0' || ciphertext[64] != 'x')
return 0;
for(n = 2; n < 62 && atoi16[ARCH_INDEX(ciphertext[n])] != 0x7F; ++n);
for(n = 65; n < 105 && atoi16[ARCH_INDEX(ciphertext[n])] != 0x7F; ++n);
return n == len;
}
void _tobin(char* dst, char *src, unsigned int len)
{
unsigned int n;
if(src[0] == '0' && src[1] == 'x')
src += sizeof(char)*2;
for(n = 0; n < len; ++n)
dst[n] = atoi16[ARCH_INDEX(src[n*2])]<<4 |
atoi16[ARCH_INDEX(src[n*2+1])];
}
void* binary(char *ciphertext)
{
static char bin[BINARY_LENGTH];
_tobin(bin, (char*)(ciphertext+65), sizeof(bin));
return bin;
}
void* salt(char *ciphertext)
{
static char salt[SALT_LENGTH];
_tobin(salt, (char*)(ciphertext+2), sizeof(salt));
return salt;
}
void set_salt(void *salt)
{
memcpy(global_salt, salt, SALT_LENGTH);
}
void set_key(char *key, int index)
{
if(!key) return;
strnzcpy(global_key, key, PLAINTEXT_LENGTH);
}
char* get_key(int index)
{
return global_key;
}
void crypt_all(int count)
{
static SHA_CTX ctx;
// Yes, I'm overwriting the last byte of the salt, perhaps the coder at ElektoPost whom wrote the EPiServer password checking function used to be a C coder (their code is written in .NET)
strnzcpy(global_salt+SALT_LENGTH-1, global_key, PLAINTEXT_LENGTH);
SHA1_Init(&ctx);
SHA1_Update(&ctx, (unsigned char*)global_salt, SALT_LENGTH+strlen(global_key));
SHA1_Final((unsigned char*)global_crypt, &ctx);
}
int cmp_all(void *binary, int count)
{
if (((ARCH_WORD *)binary)[0] != global_crypt[0])
return 0;
return !memcmp(&((ARCH_WORD *)binary)[1], &global_crypt[1],
BINARY_LENGTH - ARCH_SIZE);
}
int cmp_one(void *binary, int index)
{
return cmp_all(binary, 0);
}
// This functions job is done in cmp_all instead
int cmp_exact(char *source, int index)
{
return 1;
}