Example #1
0
static int single_process_pw(struct db_salt *salt, struct db_password *pw,
                             char *rule)
{
    struct list_entry *first, *second;
    int first_number, second_number;
    char pair[RULE_WORD_SIZE];
    int split;
    char *key;

    if (!(first = pw->words->head))
        return -1;

    first_number = 0;
    do {
        if ((key = rules_apply(first->data, rule, 0, NULL)))
            if (ext_filter(key))
                if (single_add_key(salt, key, 0))
                    return 1;
        if (!salt->list)
            return 2;
        if (!pw->binary)
            return 0;

        if (++first_number > words_pair_max)
            continue;

        if (!CP_isLetter[(unsigned char)first->data[0]])
            continue;

        second_number = 0;
        second = pw->words->head;

        do
            if (first != second) {
                if ((split = strlen(first->data)) < length) {
                    strnzcpy(pair, first->data, RULE_WORD_SIZE);
                    strnzcat(pair, second->data, RULE_WORD_SIZE);

                    if ((key = rules_apply(pair, rule, split, NULL)))
                        if (ext_filter(key))
                            if (single_add_key(salt, key, 0))
                                return 1;
                    if (!salt->list)
                        return 2;
                    if (!pw->binary)
                        return 0;
                }

                if (first->data[1]) {
                    pair[0] = first->data[0];
                    pair[1] = 0;
                    strnzcat(pair, second->data, RULE_WORD_SIZE);

                    if ((key = rules_apply(pair, rule, 1, NULL)))
                        if (ext_filter(key))
                            if (single_add_key(salt, key, 0))
                                return 1;
                    if (!salt->list)
                        return 2;
                    if (!pw->binary)
                        return 0;
                }
            }
        while (++second_number <= words_pair_max &&
                (second = second->next));
    } while ((first = first->next));

    return 0;
}
Example #2
0
static void hash_plugin_parse_hash(char *in_filepath)
{
	int fd;
	char buf8[8];
	uint32_t i = 0;
	int64_t cno = 0;
	int64_t data_size = 0;
	int64_t count = 0;
	unsigned char *chunk1 = NULL;
	unsigned char chunk2[4096];
	char filepath[LARGE_ENOUGH];
	char name[LARGE_ENOUGH];
	char *filename;
	int is_sparsebundle = 0;

	int filepath_length = strnzcpyn(filepath, in_filepath, LARGE_ENOUGH);

	strnzcpyn(name, in_filepath, LARGE_ENOUGH);
	if (!(filename = basename(name))) {
	    filename = filepath;
	}

	if(strstr(filepath, ".sparsebundle")) {
		// The filepath given indicates this is a sparsebundle
		// A sparsebundle is simply a directory with contents.
		// Let's check to see if that is the case.
		struct stat file_stat;
		char *token_path;
		if (stat(filepath, &file_stat) != 0) {
			fprintf(stderr, "Can't stat file: %s\n", filename);
			return;
		}

		// Determine if the filepath given is a directory.
		if (!(file_stat.st_mode & S_IFDIR)) {
			fprintf(stderr, "%s claims to be a sparsebundle but isn't a directory\n", filename);
			return;
		}

		// Let's look to see if the token file exists.
		fprintf(stderr, "filepath = %s path_length = %d\n", filepath, filepath_length);
		if (filepath_length + 6 + 1 >= LARGE_ENOUGH) {
			fprintf(stderr, "Can't create token path. Path too long.\n");
			return;
		}

		is_sparsebundle = 1;

		token_path = strnzcat(filepath, "/token", LARGE_ENOUGH);
		strnzcpyn(filepath, token_path, LARGE_ENOUGH);
		strnzcpyn(name, filepath, LARGE_ENOUGH);
		if (!(filename = basename(name))) {
		    filename = filepath;
		}

	}

	headerver = 0;
	fd = open(filepath, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open file: %s\n", filename);
		return;
	}

	if (read(fd, buf8, 8) <= 0) {
		fprintf(stderr, "%s is not a DMG file!\n", filename);
		close(fd);
		return;
	}

	if (strncmp(buf8, "encrcdsa", 8) == 0) {
		headerver = 2;
	} else {
		if (lseek(fd, -8, SEEK_END) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			close(fd);
			return;
		}
		if (read(fd, buf8, 8) <= 0) {
			fprintf(stderr, "%s is not a DMG file!\n", filename);
			close(fd);
			return;
		}
		if (strncmp(buf8, "cdsaencr", 8) == 0) {
			headerver = 1;
		}
	}

	if (headerver == 0) {
		fprintf(stderr, "%s is not an encrypted DMG file!\n", filename);
		return;
	}

	// fprintf(stderr, "Header version %d detected\n", headerver);
	if (headerver == 1) {
		if (lseek(fd, -sizeof(cencrypted_v1_header), SEEK_END) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			return;
		}
		if (read(fd, &header, sizeof(cencrypted_v1_header)) < 1) {
			fprintf(stderr, "%s is not a DMG file!\n", filename);
			return;
		}
		header_byteorder_fix(&header);

		fprintf(stderr, "%s (DMG v%d) successfully parsed, iterations "
		        "count %u\n", name, headerver,
		        header.kdf_iteration_count);

		printf("%s:$dmg$%d*%d*", name, headerver, header.kdf_salt_len);
		print_hex(header.kdf_salt, header.kdf_salt_len);
		printf("*%d*", header.len_wrapped_aes_key);
		print_hex(header.wrapped_aes_key, header.len_wrapped_aes_key);
		printf("*%d*", header.len_hmac_sha1_key);
		print_hex(header.wrapped_hmac_sha1_key, header.len_hmac_sha1_key);
		printf("*%u::::%s\n", header.kdf_iteration_count, filename);
	} else {
		cencrypted_v2_key_header_pointer header_pointer;
		int password_header_found = 0;

		if (lseek(fd, 0, SEEK_SET) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			return;
		}
		if (read(fd, &header2, sizeof(cencrypted_v2_header)) < 1) {
			fprintf(stderr, "%s is not a DMG file!\n", filename);
			return;
		}

		header2_byteorder_fix(&header2);

		chunk_size = header2.blocksize;
		// If this is a sparsebundle then there is no data to seek
		// to in this file so we skip over this particular check.
		if (!is_sparsebundle) {
			if (lseek(fd, header2.dataoffset, SEEK_SET) < 0) {
				fprintf(stderr, "Unable to seek in %s\n", filename);
				return;
			}
		}

		if(strstr(name, ".sparseimage") || is_sparsebundle) {
			// If this file is a sparseimage then we want one of the first chunks as the other chunks could be empty.
			cno = 1;
			data_size = 8192;
		} else {
			cno = ((header2.datasize + 4095ULL) / 4096) - 2;
			data_size = header2.datasize - cno * 4096ULL;
		}

		if (data_size < 0) {
			fprintf(stderr, "%s is not a valid DMG file!\n", filename);
			return;
		}

		for (i = 0; i < header2.keycount; i++) {

			// Seek to the start of the key header pointers offset by the current key which start immediately after the v2 header.
			if (lseek(fd, (sizeof(cencrypted_v2_header) + (sizeof(cencrypted_v2_key_header_pointer)*i)), SEEK_SET) < 0) {
				fprintf(stderr, "Unable to seek to header pointers in %s\n", filename);
				return;
			}

			// Read in the key header pointer
			count = read(fd, &header_pointer, sizeof(cencrypted_v2_key_header_pointer));
			if (count < 1 || count != sizeof(cencrypted_v2_key_header_pointer)) {
				fprintf(stderr, "Unable to read required data from %s\n", filename);
				return;
			}

			v2_key_header_pointer_byteorder_fix(&header_pointer);

			// We, currently, only care about the password key header. If it's not the password header type skip over it.
			if (header_pointer.header_type != 1) {
				continue;
			}

			// Seek to where the password key header is in the file.
			if (lseek(fd, header_pointer.header_offset, SEEK_SET) < 0) {
				fprintf(stderr, "Unable to seek to password header in %s\n", filename);
				return;
			}

			// Read in the password key header but avoid reading anything into the keyblob.
			count = read(fd, &v2_password_header, sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *));
			if (count < 1 || count != (sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *))) {
				fprintf(stderr, "Unable to read required data from %s\n", filename);
				return;
			}

			v2_password_header_byteorder_fix(&v2_password_header);

			// Allocate the keyblob memory
			v2_password_header.keyblob = mem_alloc(v2_password_header.keyblobsize);

			// Seek to the keyblob in the header
			if (lseek(fd, header_pointer.header_offset + sizeof(cencrypted_v2_password_header) - sizeof(unsigned char *), SEEK_SET) < 0) {
				fprintf(stderr, "Unable to seek to password header in %s\n", filename);
				free(v2_password_header.keyblob);
				return;
			}

			// Read in the keyblob
			count = read(fd, v2_password_header.keyblob, v2_password_header.keyblobsize);
			if (count < 1 || count != (v2_password_header.keyblobsize)) {
				fprintf(stderr, "Unable to read required data from %s\n", filename);
				free(v2_password_header.keyblob);
				return;
			}

			password_header_found = 1;

			// We only need one password header. Don't search any longer.
			break;
		}

		if (!password_header_found) {
			fprintf(stderr, "Password header not found in %s\n", filename);
			free(v2_password_header.keyblob);
			return;
		}

		if (v2_password_header.salt_size > 32) {
			fprintf(stderr, "%s is not a valid DMG file, salt length is too long!\n", filename);
			free(v2_password_header.keyblob);
			return;
		}

		fprintf(stderr, "%s (DMG v%d) successfully parsed, iterations "
		        "count %u\n", name, headerver,
		        v2_password_header.itercount);

		if (is_sparsebundle) {
			// If this is a sparsebundle then we need to get the chunks
			// of data out of 0 from the bands directory. Close the
			// previous file and open bands/0
			char *bands_path;
			if (close(fd) != 0) {
				fprintf(stderr, "Failed closing file %s\n", filename);
				free(v2_password_header.keyblob);
				return;
			}

			filepath_length = strnzcpyn(filepath, in_filepath, LARGE_ENOUGH);

			strnzcpyn(name, in_filepath, LARGE_ENOUGH);

			// See if we have enough room to append 'bands/0' to the path.
			if (filepath_length + 8 + 1 >= LARGE_ENOUGH) {
				fprintf(stderr, "Can't create bands path. Path too long.\n");
				free(v2_password_header.keyblob);
				return;
			}

			bands_path = strnzcat(filepath, "/bands/0", LARGE_ENOUGH);
			strnzcpyn(filepath, bands_path, LARGE_ENOUGH);
			strnzcpyn(name, filepath, LARGE_ENOUGH);
			if (!(filename = basename(name))) {
			    filename = filepath;
			}

			// Open the file for reading.
			fd = open(filepath, O_RDONLY);
			if (fd < 0) {
				fprintf(stderr, "Can't open file: %s\n", filename);
				return;
			}

			// Since we are in a different file the we can ignore the dataoffset
			header2.dataoffset = 0;
		}

		/* read starting chunk(s) */
		chunk1 = (unsigned char *) mem_alloc(data_size);
		if (lseek(fd, header2.dataoffset + cno * 4096LL, SEEK_SET) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			free(chunk1);
			free(v2_password_header.keyblob);
			return;
		}
		count = read(fd, chunk1, data_size);
		if (count < 1 || count != data_size) {
			fprintf(stderr, "Unable to read required data from %s\n", filename);
			free(chunk1);
			free(v2_password_header.keyblob);
			return;
		}
		/* read last chunk */
		if (lseek(fd, header2.dataoffset, SEEK_SET) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			free(chunk1);
			free(v2_password_header.keyblob);
			return;
		}
		count = read(fd, chunk2, 4096);
		if (count < 1 || count != 4096) {
			fprintf(stderr, "Unable to read required data from %s\n", filename);
			free(chunk1);
			free(v2_password_header.keyblob);
			return;
		}

		/* output hash */
		printf("%s:$dmg$%d*%d*", name, headerver, v2_password_header.salt_size);
		print_hex(v2_password_header.salt, v2_password_header.salt_size);
		printf("*32*");
		print_hex(v2_password_header.iv, 32);
		printf("*%d*", v2_password_header.keyblobsize);
		print_hex(v2_password_header.keyblob, v2_password_header.keyblobsize);
		printf("*%d*%d*", (int)cno, (int)data_size);
		print_hex(chunk1, data_size);
		printf("*1*");
		print_hex(chunk2, 4096);
		printf("*%u::::%s\n", v2_password_header.itercount, filename);

		free(chunk1);
		free(v2_password_header.keyblob);
	}
	close(fd);
}
Example #3
0
static int single_process_pw(struct db_salt *salt, struct db_password *pw,
	char *rule)
{
	struct db_keys *keys;
	struct list_entry *first, *second;
	int first_number, second_number;
	char pair[RULE_WORD_SIZE];
	int split;
	char *key;
	unsigned int c;

	if (!(first = pw->words->head))
		return -1;

	keys = salt->keys;

	first_number = 0;
	do {
		if ((key = rules_apply(first->data, rule, 0, NULL)))
		if (ext_filter(key))
		if (single_add_key(keys, key))
		if (single_process_buffer(salt)) return 1;
		if (!salt->list) return 2;
		if (!pw->binary) return 0;

		if (++first_number > SINGLE_WORDS_PAIR_MAX) continue;

		c = (unsigned int)first->data[0] | 0x20;
		if (c < 'a' || c > 'z') continue;

		second_number = 0;
		second = pw->words->head;

		do
		if (first != second) {
			if ((split = strlen(first->data)) < length) {
				strnzcpy(pair, first->data, RULE_WORD_SIZE);
				strnzcat(pair, second->data, RULE_WORD_SIZE);

				if ((key = rules_apply(pair, rule, split, NULL)))
				if (ext_filter(key))
				if (single_add_key(keys, key))
				if (single_process_buffer(salt)) return 1;
				if (!salt->list) return 2;
				if (!pw->binary) return 0;
			}

			if (first->data[1]) {
				pair[0] = first->data[0];
				pair[1] = 0;
				strnzcat(pair, second->data, RULE_WORD_SIZE);

				if ((key = rules_apply(pair, rule, 1, NULL)))
				if (ext_filter(key))
				if (single_add_key(keys, key))
				if (single_process_buffer(salt)) return 1;
				if (!salt->list) return 2;
				if (!pw->binary) return 0;
			}
		} while (++second_number <= SINGLE_WORDS_PAIR_MAX &&
			(second = second->next));
	} while ((first = first->next));

	return 0;
}