Skip to content

Commit e2e9d14

Browse files
committed
Reworked hash decryption algorithm
Deleted big-endian support, because of irrelevance
1 parent a9e9d71 commit e2e9d14

3 files changed

Lines changed: 111 additions & 114 deletions

File tree

src/dump_hashes.c

Lines changed: 82 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ int dump_users_keys(FILE* sam_hive, named_key_t** users_keys_array, size_t* user
142142
return 0;
143143
}
144144

145-
// TODO(Complete the function)
146145
int dump_v_value(FILE* sam_hive, named_key_t* user_key_ptr, ntlm_user_t* user_info_ptr)
147146
{
148147
// Validating parameters
@@ -207,10 +206,12 @@ int dump_user_ntlm(ntlm_user_t* user_info_ptr, const uint8_t* hashed_bootkey)
207206
return -1;
208207
}
209208

209+
// Decrypt LM hash
210210
int result = decrypt_ntlm_hash(user_info_ptr, hashed_bootkey, hash_lm);
211211
if (result != 0)
212212
return -2;
213213

214+
// Decrypt NT hash
214215
result = decrypt_ntlm_hash(user_info_ptr, hashed_bootkey, hash_nt);
215216
if (result != 0)
216217
return -3;
@@ -245,74 +246,58 @@ int decrypt_ntlm_hash(ntlm_user_t* user_info_ptr, const uint8_t* hashed_bootkey,
245246
}
246247

247248
// Preparing arrays for encrypted hash and salt
249+
uint8_t salt[16];
248250
uint8_t encrypted_hash[32];
249-
uint8_t encrypted_hash_salt[16];
250-
memset(encrypted_hash, 0, 32);
251-
memset(encrypted_hash_salt, 0, 16);
251+
memcpy(salt, hash_type ? NTPASSWORD : LMPASSWORD, 16);
252+
memcpy(encrypted_hash, ((uint8_t*)user_info_ptr->v_value) + hash_offset + 4, 16);
252253

253254
// Setting proper pointer to hash
254255
uint8_t* hash_pointer = hash_type ? user_info_ptr->nthash : user_info_ptr->lmhash;
255-
switch (revision)
256-
{
257-
case 1:
258-
if (hash_exists != 0x14)
259-
{
260-
//hash_pointer = hash_nt ? EMPTY_NT_HASH : EMPTY_LM_HASH;
261-
memcpy(hash_pointer, hash_type ? EMPTY_NT_HASH : EMPTY_LM_HASH, 16);
262-
return 0;
263-
}
264256

265-
memcpy(encrypted_hash, ((uint8_t*)user_info_ptr->v_value) + hash_offset + 4, 16);
266-
// Decrypt NTLMv1 Hash (without a salt)
267-
if (decrypt_hash(
268-
encrypted_hash,
269-
hashed_bootkey,
270-
hash_type ? NTPASSWORD : LMPASSWORD,
271-
user_info_ptr,
272-
hash_pointer
273-
) != 0)
274-
return -3;
275-
break;
276-
case 2:
277-
if (hash_exists != 0x38)
278-
{
279-
memcpy(hash_pointer, hash_type ? EMPTY_NT_HASH : EMPTY_LM_HASH, 16);
280-
return 0;
281-
}
282-
283-
// Reading salt and encrypted hash (offset +4 if hash type is NT)
284-
memcpy(encrypted_hash_salt, (uint8_t*)user_info_ptr->v_value + hash_offset + 4 + (hash_type * 4), 16);
257+
uint32_t exists_cmp = 0x14;
258+
decrypt_callback_t decrypt_callback = &decrypt_ntlmv1_callback;
259+
if (revision == 2)
260+
{
261+
exists_cmp = 0x38;
262+
decrypt_callback = &decrypt_ntlmv2_callback;
263+
memcpy(salt, (uint8_t*)user_info_ptr->v_value + hash_offset + 4 + (hash_type * 4), 16);
285264
memcpy(encrypted_hash, (uint8_t*)user_info_ptr->v_value + hash_offset + 20 + (hash_type * 4), 32);
265+
}
286266

287-
// Decrypt NTLMv2 Hash (with a salt)
288-
if (decrypt_salted_hash(
289-
encrypted_hash,
290-
hashed_bootkey,
291-
encrypted_hash_salt,
292-
user_info_ptr,
293-
hash_pointer
294-
) != 0)
295-
return -4;
296-
297-
break;
267+
if (hash_exists != exists_cmp)
268+
{
269+
memcpy(hash_pointer, hash_type ? EMPTY_NT_HASH : EMPTY_LM_HASH, 16);
270+
return 0;
271+
}
298272

299-
default:
273+
if (decrypt_ntlm_hash_wrapper(
274+
encrypted_hash,
275+
hashed_bootkey,
276+
salt,
277+
user_info_ptr,
278+
decrypt_callback,
279+
hash_pointer
280+
) != 0)
300281
return -2;
301-
}
302282

303283
return 0;
304284
}
305285

306-
int decrypt_hash(
286+
int decrypt_ntlm_hash_wrapper(
307287
const uint8_t* enc_hash,
308288
const uint8_t* hashed_bootkey,
309-
const uint8_t* ntlmphrase,
289+
const uint8_t* salt,
310290
ntlm_user_t* user_info_ptr,
291+
decrypt_callback_t ntlm_version,
311292
uint8_t* decrypted_hash
312293
)
313294
{
314295
// Validating parameters
315-
if (enc_hash == NULL || hashed_bootkey == NULL || ntlmphrase == NULL || user_info_ptr == NULL || decrypted_hash == NULL)
296+
if (enc_hash == NULL || hashed_bootkey == NULL ||
297+
salt == NULL || user_info_ptr == NULL ||
298+
decrypted_hash == NULL || ntlm_version == NULL ||
299+
user_info_ptr == NULL
300+
)
316301
{
317302
errno = EINVAL;
318303
return -1;
@@ -326,12 +311,51 @@ int decrypt_hash(
326311
des_key1 = BYTE_SWAP64(des_key1);
327312
des_key2 = BYTE_SWAP64(des_key2);
328313

314+
uint8_t* staged_hash = malloc_check(staged_hash, 32, -3);
315+
{
316+
int result = (*ntlm_version)(enc_hash, hashed_bootkey, salt, user_info_ptr, staged_hash);
317+
if (result != 0)
318+
{
319+
errno = EBADF;
320+
free(staged_hash);
321+
return result;
322+
}
323+
}
324+
325+
uint8_t* des_key = &des_key1;
326+
for (size_t i = 0; i < 16; i += sizeof(uint64_t), des_key = &des_key2)
327+
{
328+
if (des_ecb_decrypt(staged_hash + i, sizeof(uint64_t), des_key, decrypted_hash + i) == 0)
329+
{
330+
free(staged_hash);
331+
return -6;
332+
}
333+
}
334+
335+
return 0;
336+
}
337+
338+
int decrypt_ntlmv1_callback(
339+
const uint8_t* encrypted_hash,
340+
const uint8_t* hashed_bootkey,
341+
const uint8_t* salt,
342+
const ntlm_user_t* user_info_ptr,
343+
uint8_t* output
344+
)
345+
{
346+
// Validating parameters
347+
if (encrypted_hash == NULL || hashed_bootkey == NULL || salt == NULL || output == NULL || user_info_ptr == NULL)
348+
{
349+
errno = EINVAL;
350+
return -1;
351+
}
352+
329353
// Constructing full data for RC4 key
330-
size_t ntlmphrase_len = strlen(ntlmphrase) + 1;
354+
size_t ntlmphrase_len = strlen(salt) + 1;
331355
uint8_t* full_data = malloc_check(full_data, 16 + sizeof(uint32_t) + ntlmphrase_len, -3);
332356
memcpy(full_data, hashed_bootkey, 16);
333357
memcpy(full_data + 16, &user_info_ptr->sid, sizeof(uint32_t));
334-
memcpy(full_data + 16 + sizeof(uint32_t), ntlmphrase, ntlmphrase_len);
358+
memcpy(full_data + 16 + sizeof(uint32_t), output, ntlmphrase_len);
335359

336360
// MD5 of the data will be RC4 key
337361
uint8_t* md5_hash = get_md5(full_data, 16 + sizeof(uint32_t) + ntlmphrase_len);
@@ -341,66 +365,33 @@ int decrypt_hash(
341365
return -4;
342366
}
343367

344-
uint8_t pre_des_hash[32];
345-
if (rc4_encrypt(enc_hash, 16, md5_hash, pre_des_hash) == 0)
368+
if (rc4_encrypt(encrypted_hash, 16, md5_hash, output) == 0)
346369
{
347370
cleanup_pointers(2, full_data, md5_hash);
348371
return -5;
349372
}
350373

351-
uint8_t* des_key = &des_key1;
352-
for (size_t i = 0; i < 16; i += sizeof(uint64_t), des_key = &des_key2)
353-
{
354-
if (des_ecb_decrypt(pre_des_hash + i, sizeof(uint64_t), des_key, decrypted_hash + i) == 0)
355-
{
356-
free(pre_des_hash);
357-
return -6;
358-
}
359-
}
360-
361374
return 0;
362375
}
363376

364-
int decrypt_salted_hash(
365-
const uint8_t* enc_hash,
377+
int decrypt_ntlmv2_callback(
378+
const uint8_t* encrypted_hash,
366379
const uint8_t* hashed_bootkey,
367380
const uint8_t* salt,
368-
ntlm_user_t* user_info_ptr,
369-
uint8_t* decrypted_hash
381+
const ntlm_user_t* user_info_ptr,
382+
uint8_t* output
370383
)
371384
{
372385
// Validating parameters
373-
if (enc_hash == NULL || hashed_bootkey == NULL || salt == NULL || user_info_ptr == NULL || decrypted_hash == NULL)
386+
if (encrypted_hash == NULL || hashed_bootkey == NULL || salt == NULL || output == NULL || user_info_ptr == NULL)
374387
{
375388
errno = EINVAL;
376389
return -1;
377390
}
378391

379-
uint64_t des_key1 = 0;
380-
uint64_t des_key2 = 0;
381-
if (sid_to_des_keys(user_info_ptr->sid, &des_key1, &des_key2) != 0)
392+
if (aes_128_cbc_decrypt(encrypted_hash, 32, hashed_bootkey, salt, output) == 0)
382393
return -2;
383394

384-
des_key1 = BYTE_SWAP64(des_key1);
385-
des_key2 = BYTE_SWAP64(des_key2);
386-
387-
uint8_t* pre_des_hash = malloc_check(pre_des_hash, 32, -3);
388-
if (aes_128_cbc_decrypt(enc_hash, 32, hashed_bootkey, salt, pre_des_hash) == 0)
389-
{
390-
free(pre_des_hash);
391-
return -4;
392-
}
393-
394-
uint8_t* des_key = &des_key1;
395-
for (size_t i = 0; i < 16; i += sizeof(uint64_t), des_key = &des_key2)
396-
{
397-
if (des_ecb_decrypt(pre_des_hash + i, sizeof(uint64_t), des_key, decrypted_hash + i) == 0)
398-
{
399-
free(pre_des_hash);
400-
return -6;
401-
}
402-
}
403-
404395
return 0;
405396
}
406397

src/dump_hashes.h

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,12 @@
2222
#include "hive.h"
2323
#include "crypto.h"
2424

25-
//#include "own_des.h"
26-
2725
#define EMPTY_LM_HASH "\xaa\xd3\xb4\x35\xb5\x14\x04\xee\xaa\xd3\xb4\x35\xb5\x14\x04\xee"
2826
#define EMPTY_NT_HASH "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0"
2927
#define NTPASSWORD "NTPASSWORD"
3028
#define LMPASSWORD "LMPASSWORD"
3129

30+
// Structs that contains main user info
3231
typedef struct
3332
{
3433
uint32_t sid;
@@ -39,12 +38,22 @@ typedef struct
3938
uint8_t* lmhash;
4039
} ntlm_user_t;
4140

41+
// Enumeration of hash types
4242
typedef enum
4343
{
4444
hash_lm,
4545
hash_nt
4646
} hash_type_e;
4747

48+
// Type for callback function of staged decryption
49+
typedef int (*decrypt_callback_t)(
50+
const uint8_t* encrypted_hash,
51+
const uint8_t* hashed_bootkey,
52+
const uint8_t* salt,
53+
const ntlm_user_t* user_info_ptr,
54+
uint8_t* output
55+
);
56+
4857
int ntlm_user_init(ntlm_user_t* user_info_ptr);
4958

5059
int ntlm_user_destroy(ntlm_user_t* user_info_ptr);
@@ -64,22 +73,32 @@ int dump_user_ntlm(ntlm_user_t* user_info_ptr, const uint8_t* hashed_bootkey);
6473
// Decrypts NT/LM hash
6574
int decrypt_ntlm_hash(ntlm_user_t* user_info_ptr, const uint8_t* hashed_bootkey, const hash_type_e hash_type);
6675

67-
// Decrypts non-salted/NTLMv1 hash
68-
int decrypt_hash(
76+
// Decrypt NTLMv1/2 hashes using callback function
77+
int decrypt_ntlm_hash_wrapper(
6978
const uint8_t* enc_hash,
7079
const uint8_t* hashed_bootkey,
71-
const uint8_t* ntlmphrase,
80+
const uint8_t* salt,
7281
ntlm_user_t* user_info_ptr,
82+
decrypt_callback_t ntlm_version,
7383
uint8_t* decrypted_hash
7484
);
7585

76-
// Decrypts salted/NTLMv2 hash
77-
int decrypt_salted_hash(
78-
const uint8_t* enc_hash,
86+
// Callback function for decrypt_ntlm_hash_wrapper, which does staged decryption of NTLMv1
87+
int decrypt_ntlmv1_callback(
88+
const uint8_t* encrypted_hash,
7989
const uint8_t* hashed_bootkey,
8090
const uint8_t* salt,
81-
ntlm_user_t* user_info_ptr,
82-
uint8_t* decrypted_hash
91+
const ntlm_user_t* user_info_ptr,
92+
uint8_t* output
93+
);
94+
95+
// Callback function for decrypt_ntlm_hash_wrapper, which does staged decryption of NTLMv2
96+
int decrypt_ntlmv2_callback(
97+
const uint8_t* encrypted_hash,
98+
const uint8_t* hashed_bootkey,
99+
const uint8_t* salt,
100+
const ntlm_user_t* user_info_ptr,
101+
uint8_t* output
83102
);
84103

85104
// Converts RID to DES keys

src/hive.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ int read_hive_header(FILE* hive_ptr, hive_header_t* hive_header_ptr)
4040
if (fread(hive_header_ptr, sizeof(hive_header_t), 1, hive_ptr) != 1)
4141
return hv_read_error;
4242

43-
#if (HV_ENDIANNESS == HV_BIG_ENDIAN)
44-
hive_header_ptr->last_write_time = BYTE_SWAP64(hive_header_ptr->last_write_time);
45-
#endif
46-
4743
// Check signature
4844
if (hive_header_ptr->signature != HIVE_SIGN)
4945
{
@@ -88,11 +84,6 @@ int read_named_key(const uint32_t root_offset, FILE* hive_ptr, named_key_t* nk_p
8884
// Inverse the size
8985
nk_ptr->size = 0 - nk_ptr->size;
9086

91-
#if (HV_ENDIANNESS == HV_BIG_ENDIAN)
92-
nk_ptr->flags = BYTE_SWAP16(nk_ptr->flags);
93-
#endif
94-
95-
9687
nk_ptr->name = malloc_check(nk_ptr->name, nk_ptr->name_length + 1, hv_alloc_error);
9788

9889
if (fread(nk_ptr->name, nk_ptr->name_length, 1, hive_ptr) != 1)
@@ -219,10 +210,6 @@ int read_value_key(const uint32_t root_offset, FILE* hive_ptr, value_key_t* vk_p
219210
// Inverse the size
220211
vk_ptr->size = 0 - vk_ptr->size;
221212

222-
#if (HV_ENDIANNESS == HV_BIG_ENDIAN)
223-
nk_ptr->flags = BYTE_SWAP16(nk_ptr->flags);
224-
#endif
225-
226213
// If value does not have a name then it is (Default)
227214
if (vk_ptr->name_length == 0)
228215
{

0 commit comments

Comments
 (0)