1 #if !defined (_MSC_VER)
2 /* Modified by Dhiru Kholia for JtR in August, 2012
3 *
4 * dmg.c
5 *
6 * hashkill - a hash cracking tool
7 * Copyright (C) 2010 Milen Rangelov <gat3way@gat3way.eu>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #if AC_BUILT
24 #include "autoconfig.h"
25 #endif
26
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <math.h>
30 #if (!AC_BUILT || HAVE_UNISTD_H) && !_MSC_VER
31 #include <unistd.h>
32 #endif
33 #include <string.h>
34 #if (!AC_BUILT || HAVE_FCNTL_H)
35 #include <fcntl.h>
36 #endif
37 #include <stdlib.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #include "arch.h"
42 #include "filevault.h"
43 #include "misc.h"
44 #include "jumbo.h"
45 #include "memory.h"
46
47 #ifndef ntohl
48 #if ARCH_LITTLE_ENDIAN
49 #define htonl(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
50 (((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
51
52 #define ntohl(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
53 (((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
54 #else
55 #define htonl(x) (x)
56 #define ntohl(x) (x)
57 #endif
58 #endif
59
60 #ifndef ntohll
61 #define ntohll(x) (((uint64_t) ntohl((x) >> 32)) | (((uint64_t) ntohl((uint32_t) ((x) & 0xFFFFFFFF))) << 32))
62 #endif
63
64 #define LARGE_ENOUGH 8192
65
header_byteorder_fix(cencrypted_v1_header * hdr)66 static void header_byteorder_fix(cencrypted_v1_header *hdr)
67 {
68 hdr->kdf_iteration_count = htonl(hdr->kdf_iteration_count);
69 hdr->kdf_salt_len = htonl(hdr->kdf_salt_len);
70 hdr->len_wrapped_aes_key = htonl(hdr->len_wrapped_aes_key);
71 hdr->len_hmac_sha1_key = htonl(hdr->len_hmac_sha1_key);
72 hdr->len_integrity_key = htonl(hdr->len_integrity_key);
73 }
74
header2_byteorder_fix(cencrypted_v2_header * header)75 static void header2_byteorder_fix(cencrypted_v2_header *header)
76 {
77 header->version = ntohl(header->version);
78 header->enc_iv_size = ntohl(header->enc_iv_size);
79 header->encMode = ntohl(header->encMode);
80 header->encAlg = ntohl(header->encAlg);
81 header->keyBits = ntohl(header->keyBits);
82 header->prngalg = ntohl(header->prngalg);
83 header->prngkeysize = ntohl(header->prngkeysize);
84 header->blocksize = ntohl(header->blocksize);
85 header->datasize = ntohll(header->datasize);
86 header->dataoffset = ntohll(header->dataoffset);
87 header->keycount = ntohl(header->keycount);
88 }
89
v2_key_header_pointer_byteorder_fix(cencrypted_v2_key_header_pointer * key_header_pointer)90 static void v2_key_header_pointer_byteorder_fix(cencrypted_v2_key_header_pointer *key_header_pointer)
91 {
92 key_header_pointer->header_type = ntohl(key_header_pointer->header_type);
93 key_header_pointer->header_offset = ntohl(key_header_pointer->header_offset);
94 key_header_pointer->header_size = ntohl(key_header_pointer->header_size);
95 }
96
v2_password_header_byteorder_fix(cencrypted_v2_password_header * password_header)97 static void v2_password_header_byteorder_fix(cencrypted_v2_password_header *password_header)
98 {
99 password_header->algorithm = ntohl(password_header->algorithm);
100 password_header->prngalgo = ntohl(password_header->prngalgo);
101 password_header->itercount = ntohl(password_header->itercount);
102 password_header->salt_size = ntohl(password_header->salt_size);
103 password_header->iv_size = ntohl(password_header->iv_size);
104 password_header->blob_enc_keybits = ntohl(password_header->blob_enc_keybits);
105 password_header->blob_enc_algo = ntohl(password_header->blob_enc_algo);
106 password_header->blob_enc_padding = ntohl(password_header->blob_enc_padding);
107 password_header->blob_enc_mode = ntohl(password_header->blob_enc_mode);
108 password_header->keyblobsize = ntohl(password_header->keyblobsize);
109 }
110
print_hex(unsigned char * str,int len)111 static void print_hex(unsigned char *str, int len)
112 {
113 int i;
114 for (i = 0; i < len; ++i)
115 printf("%02x", str[i]);
116 }
117
118 // Remove these duplicated strnXYZ functions after refactoring misc.c. Trying
119 // to link dmg2john.o with misc.o results in linking errors, as parts of misc.o
120 // depends on other parts of JtR jumbo. These linking problems are not easily
121 // solvable without refactoring misc.c file.
strnzcpyn(char * dst,const char * src,int size)122 int strnzcpyn(char *dst, const char *src, int size)
123 {
124 char *dptr;
125 if (!size) return 0;
126
127 dptr = dst;
128
129 while (--size)
130 if (!(*dptr++ = *src++)) return (dptr-dst)-1;
131 *dptr = 0;
132
133 return (dptr-dst);
134 }
135
strnzcat(char * dst,const char * src,int size)136 char *strnzcat(char *dst, const char *src, int size)
137 {
138 char *dptr = dst;
139
140 if (size) {
141 while (size && *dptr) {
142 size--; dptr++;
143 }
144 if (size)
145 while (--size)
146 if (!(*dptr++ = *src++)) break;
147 }
148 *dptr = 0;
149
150 return dst;
151 }
152
hash_plugin_parse_hash(char * in_filepath)153 static void hash_plugin_parse_hash(char *in_filepath)
154 {
155 int fd;
156 char buf8[8];
157 uint32_t i = 0;
158 int64_t cno = 0;
159 int64_t data_size = 0;
160 int64_t count = 0;
161 unsigned char *chunk1 = NULL;
162 unsigned char chunk2[4096];
163 char filepath[LARGE_ENOUGH];
164 char name[LARGE_ENOUGH];
165 char *filename;
166 int is_sparsebundle = 0;
167 int headerver;
168 cencrypted_v1_header header;
169 cencrypted_v2_header header2;
170 cencrypted_v2_password_header v2_password_header;
171
172 int filepath_length = strnzcpyn(filepath, in_filepath, LARGE_ENOUGH);
173
174 memset(&header, 0, sizeof(cencrypted_v2_header));
175 memset(&header2, 0, sizeof(cencrypted_v2_header));
176 memset(&v2_password_header, 0, sizeof(cencrypted_v2_password_header));
177 strnzcpyn(name, in_filepath, LARGE_ENOUGH);
178 if (!(filename = basename(name))) {
179 filename = filepath;
180 }
181
182 if (strstr(filepath, ".sparsebundle")) {
183 // The filepath given indicates this is a sparsebundle
184 // A sparsebundle is simply a directory with contents.
185 // Let's check to see if that is the case.
186 struct stat file_stat;
187 char *token_path;
188 if (stat(filepath, &file_stat) != 0) {
189 fprintf(stderr, "Can't stat file: %s\n", filename);
190 return;
191 }
192
193 // Determine if the filepath given is a directory.
194 if (!(file_stat.st_mode & S_IFDIR)) {
195 fprintf(stderr, "%s claims to be a sparsebundle but isn't a directory\n", filename);
196 return;
197 }
198
199 // Let's look to see if the token file exists.
200 fprintf(stderr, "filepath = %s path_length = %d\n", filepath, filepath_length);
201 if (filepath_length + 6 + 1 >= LARGE_ENOUGH) {
202 fprintf(stderr, "Can't create token path. Path too long.\n");
203 return;
204 }
205
206 is_sparsebundle = 1;
207
208 token_path = strnzcat(filepath, "/token", LARGE_ENOUGH);
209 strnzcpyn(filepath, token_path, LARGE_ENOUGH);
210 strnzcpyn(name, filepath, LARGE_ENOUGH);
211 if (!(filename = basename(name))) {
212 filename = filepath;
213 }
214
215 }
216
217 headerver = 0;
218 fd = open(filepath, O_RDONLY);
219 if (fd < 0) {
220 fprintf(stderr, "Can't open file: %s\n", filename);
221 return;
222 }
223
224 if (read(fd, buf8, 8) <= 0) {
225 fprintf(stderr, "%s is not a DMG file!\n", filename);
226 goto bailout;
227 }
228
229 if (strncmp(buf8, "encrcdsa", 8) == 0) {
230 headerver = 2;
231 } else {
232 if (lseek(fd, -8, SEEK_END) < 0) {
233 fprintf(stderr, "Unable to seek in %s\n", filename);
234 goto bailout;
235 }
236 if (read(fd, buf8, 8) <= 0) {
237 fprintf(stderr, "%s is not a DMG file!\n", filename);
238 goto bailout;
239 }
240 if (strncmp(buf8, "cdsaencr", 8) == 0) {
241 headerver = 1;
242 }
243 }
244
245 if (headerver == 0) {
246 fprintf(stderr, "%s is not an encrypted DMG file!\n", filename);
247 goto bailout;
248 }
249
250 // fprintf(stderr, "Header version %d detected\n", headerver);
251 if (headerver == 1) {
252 if (lseek(fd, -(off_t)sizeof(cencrypted_v1_header), SEEK_END) < 0) {
253 fprintf(stderr, "Unable to seek in %s\n", filename);
254 goto bailout;
255 }
256 if (read(fd, &header, sizeof(cencrypted_v1_header)) < 1) {
257 fprintf(stderr, "%s is not a DMG file!\n", filename);
258 goto bailout;
259 }
260 header_byteorder_fix(&header);
261 if (header.kdf_salt_len > sizeof(header.kdf_salt)) {
262 fprintf(stderr, "%s has bad kdf_salt_len value!\n", filename);
263 goto bailout;
264 }
265 if (header.len_wrapped_aes_key > sizeof(header.wrapped_aes_key)) {
266 fprintf(stderr, "%s has bad len_wrapped_aes_key value!\n", filename);
267 goto bailout;
268 }
269 if (header.len_hmac_sha1_key > sizeof(header.wrapped_hmac_sha1_key)) {
270 fprintf(stderr, "%s has bad len_hmac_sha1_key value!\n", filename);
271 goto bailout;
272 }
273
274 fprintf(stderr, "%s (DMG v%d) successfully parsed, iterations "
275 "count %u\n", name, headerver,
276 header.kdf_iteration_count);
277
278 printf("%s:$dmg$%d*%d*", name, headerver, header.kdf_salt_len);
279 print_hex(header.kdf_salt, header.kdf_salt_len);
280 printf("*%d*", header.len_wrapped_aes_key);
281 print_hex(header.wrapped_aes_key, header.len_wrapped_aes_key);
282 printf("*%d*", header.len_hmac_sha1_key);
283 print_hex(header.wrapped_hmac_sha1_key, header.len_hmac_sha1_key);
284 printf("*%u::::%s\n", header.kdf_iteration_count, filename);
285 } else {
286 cencrypted_v2_key_header_pointer header_pointer;
287 int password_header_found = 0;
288
289 if (lseek(fd, 0, SEEK_SET) < 0) {
290 fprintf(stderr, "Unable to seek in %s\n", filename);
291 goto bailout;
292 }
293 if (read(fd, &header2, sizeof(cencrypted_v2_header)) < 1) {
294 fprintf(stderr, "%s is not a DMG file!\n", filename);
295 goto bailout;
296 }
297
298 header2_byteorder_fix(&header2);
299
300 // If this is a sparsebundle then there is no data to seek
301 // to in this file so we skip over this particular check.
302 if (!is_sparsebundle) {
303 if (lseek(fd, header2.dataoffset, SEEK_SET) < 0) {
304 fprintf(stderr, "Unable to seek in %s\n", filename);
305 goto bailout;
306 }
307 }
308
309 if (strstr(name, ".sparseimage") || is_sparsebundle) {
310 // If this file is a sparseimage then we want one of the first chunks as the other chunks could be empty.
311 cno = 1;
312 data_size = 8192;
313 } else {
314 cno = ((header2.datasize + 4095ULL) / 4096) - 2;
315 data_size = header2.datasize - cno * 4096ULL;
316 }
317
318 if (data_size < 0) {
319 fprintf(stderr, "%s is not a valid DMG file!\n", filename);
320 goto bailout;
321 }
322
323 for (i = 0; i < header2.keycount; i++) {
324 // Seek to the start of the key header pointers offset by the current key which start immediately after the v2 header.
325 if (lseek(fd, (sizeof(cencrypted_v2_header) + (sizeof(cencrypted_v2_key_header_pointer)*i)), SEEK_SET) < 0) {
326 fprintf(stderr, "Unable to seek to header pointers in %s\n", filename);
327 goto bailout;
328 }
329
330 // Read in the key header pointer
331 count = read(fd, &header_pointer, sizeof(cencrypted_v2_key_header_pointer));
332 if (count < 1 || count != sizeof(cencrypted_v2_key_header_pointer)) {
333 fprintf(stderr, "Unable to read required data from %s\n", filename);
334 goto bailout;
335 }
336
337 v2_key_header_pointer_byteorder_fix(&header_pointer);
338
339 // We, currently, only care about the password key header. If it's not the password header type skip over it.
340 if (header_pointer.header_type != 1) {
341 continue;
342 }
343
344 // Seek to where the password key header is in the file.
345 if (lseek(fd, header_pointer.header_offset, SEEK_SET) < 0) {
346 fprintf(stderr, "Unable to seek to password header in %s\n", filename);
347 goto bailout;
348 }
349
350 // Read in the password key header but avoid reading anything into the keyblob.
351 count = read(fd, &v2_password_header, sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *));
352 if (count < 1 || count != (sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *))) {
353 fprintf(stderr, "Unable to read required data from %s\n", filename);
354 goto bailout;
355 }
356
357 v2_password_header_byteorder_fix(&v2_password_header);
358
359 // Allocate the keyblob memory
360 if (v2_password_header.keyblobsize > 1024) {
361 fprintf(stderr, "Unusual keyblobsize found in %s\n", filename);
362 goto bailout;
363 }
364 v2_password_header.keyblob = malloc(v2_password_header.keyblobsize);
365 if (!v2_password_header.keyblob) {
366 fprintf(stderr, "Error allocating memory while processing %s\n", filename);
367 goto bailout;
368 }
369
370 // Seek to the keyblob in the header
371 if (lseek(fd, header_pointer.header_offset + sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *), SEEK_SET) < 0) {
372 fprintf(stderr, "Unable to seek to password header in %s\n", filename);
373 free(v2_password_header.keyblob);
374 goto bailout;
375 }
376
377 // Read in the keyblob
378 count = read(fd, v2_password_header.keyblob, v2_password_header.keyblobsize);
379 if (count < 1 || count != (v2_password_header.keyblobsize)) {
380 fprintf(stderr, "Unable to read required data from %s\n", filename);
381 free(v2_password_header.keyblob);
382 goto bailout;
383 }
384
385 password_header_found = 1;
386
387 // We only need one password header. Don't search any longer.
388 break;
389 }
390
391 if (!password_header_found) {
392 fprintf(stderr, "Password header not found in %s\n", filename);
393 free(v2_password_header.keyblob);
394 goto bailout;
395 }
396
397 if (v2_password_header.salt_size > 32) {
398 fprintf(stderr, "%s is not a valid DMG file, salt length is too long!\n", filename);
399 free(v2_password_header.keyblob);
400 goto bailout;
401 }
402
403 fprintf(stderr, "%s (DMG v%d) successfully parsed, iterations "
404 "count %u\n", name, headerver,
405 v2_password_header.itercount);
406
407 if (is_sparsebundle) {
408 // If this is a sparsebundle then we need to get the chunks
409 // of data out of 0 from the bands directory. Close the
410 // previous file and open bands/0
411 char *bands_path;
412 if (close(fd) != 0) {
413 fprintf(stderr, "Failed closing file %s\n", filename);
414 free(v2_password_header.keyblob);
415 goto bailout;
416 }
417
418 filepath_length = strnzcpyn(filepath, in_filepath, LARGE_ENOUGH);
419
420 strnzcpyn(name, in_filepath, LARGE_ENOUGH);
421
422 // See if we have enough room to append 'bands/0' to the path.
423 if (filepath_length + 8 + 1 >= LARGE_ENOUGH) {
424 fprintf(stderr, "Can't create bands path. Path too long.\n");
425 free(v2_password_header.keyblob);
426 goto bailout;
427 }
428
429 bands_path = strnzcat(filepath, "/bands/0", LARGE_ENOUGH);
430 strnzcpyn(filepath, bands_path, LARGE_ENOUGH);
431 strnzcpyn(name, filepath, LARGE_ENOUGH);
432 if (!(filename = basename(name))) {
433 filename = filepath;
434 }
435
436 // Open the file for reading.
437 close(fd);
438 fd = open(filepath, O_RDONLY);
439 if (fd < 0) {
440 fprintf(stderr, "Can't open file: %s\n", filename);
441 return;
442 }
443
444 // Since we are in a different file, so we can ignore the dataoffset
445 header2.dataoffset = 0;
446 }
447
448 /* read starting chunk(s) */
449 chunk1 = (unsigned char *)malloc(data_size);
450 if (lseek(fd, header2.dataoffset + cno * 4096LL, SEEK_SET) < 0) {
451 fprintf(stderr, "Unable to seek in %s\n", filename);
452 free(chunk1);
453 free(v2_password_header.keyblob);
454 goto bailout;
455 }
456 count = read(fd, chunk1, data_size);
457 if (count < 1 || count != data_size) {
458 fprintf(stderr, "Unable to read required data from %s\n", filename);
459 free(chunk1);
460 free(v2_password_header.keyblob);
461 goto bailout;
462 }
463 /* read last chunk */
464 if (lseek(fd, header2.dataoffset, SEEK_SET) < 0) {
465 fprintf(stderr, "Unable to seek in %s\n", filename);
466 free(chunk1);
467 free(v2_password_header.keyblob);
468 goto bailout;
469 }
470 count = read(fd, chunk2, 4096);
471 if (count < 1 || count != 4096) {
472 fprintf(stderr, "Unable to read required data from %s\n", filename);
473 free(chunk1);
474 free(v2_password_header.keyblob);
475 goto bailout;
476 }
477
478 /* output hash */
479 printf("%s:$dmg$%d*%d*", name, headerver, v2_password_header.salt_size);
480 print_hex(v2_password_header.salt, v2_password_header.salt_size);
481 printf("*32*");
482 print_hex(v2_password_header.iv, 32);
483 printf("*%d*", v2_password_header.keyblobsize);
484 print_hex(v2_password_header.keyblob, v2_password_header.keyblobsize);
485 printf("*%d*%d*", (int)cno, (int)data_size);
486 print_hex(chunk1, data_size);
487 printf("*1*");
488 print_hex(chunk2, 4096);
489 printf("*%u::::%s\n", v2_password_header.itercount, filename);
490
491 free(chunk1);
492 free(v2_password_header.keyblob);
493 }
494
495 bailout:
496 close(fd);
497 }
498
499 #ifdef HAVE_LIBFUZZER
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)500 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
501 {
502 int fd;
503 char name[] = "/tmp/libFuzzer-XXXXXX";
504
505 fd = mkstemp(name);
506 if (fd < 0) {
507 fprintf(stderr, "Problem detected while creating the input file, %s, aborting!\n", strerror(errno));
508 exit(-1);
509 }
510 write(fd, data, size);
511 close(fd);
512 hash_plugin_parse_hash(name);
513 remove(name);
514
515 return 0;
516 }
517 #else
main(int argc,char ** argv)518 int main(int argc, char **argv)
519 {
520 int i;
521
522 if (argc < 2) {
523 puts("Usage: dmg2john [DMG files]");
524 return -1;
525 }
526 for (i = 1; i < argc; i++)
527 hash_plugin_parse_hash(argv[i]);
528
529 return 0;
530 }
531 #endif // HAVE_LIBFUZZER
532
533 #endif
534