Esempio n. 1
0
static void hash_plugin_parse_hash(char *filename)
{
	int fd;
	char buf8[8];
	int64_t cno = 0;
	int64_t data_size = 0;
	int64_t count = 0;
	unsigned char *chunk1 = NULL;
	unsigned char chunk2[4096];
	char path[LARGE_ENOUGH];
	char *name = NULL;

	headerver = 0;
	fd = open(filename, 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) {
		strnzcpyn(path, filename, LARGE_ENOUGH);

		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);

		if (!(name = basename(path)))
		    name = path;

		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 {
		strnzcpyn(path, filename, LARGE_ENOUGH);

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

		chunk_size = header2.blocksize;
		if (lseek(fd, header2.dataoffset, SEEK_SET) < 0) {
			fprintf(stderr, "Unable to seek in %s\n", filename);
			return;
		}
		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;
		}
		if (header2.kdf_salt_len > 32) {
			fprintf(stderr, "%s is not a valid DMG file, salt length is too long!\n", filename);
			return;
		}
		if (!(name = basename(path)))
		    name = path;

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

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

		/* output hash */
		printf("%s:$dmg$%d*%d*", name, headerver, header2.kdf_salt_len);
		print_hex(header2.kdf_salt, header2.kdf_salt_len);
		printf("*32*");
		print_hex(header2.blob_enc_iv, 32);
		printf("*%d*", header2.encrypted_keyblob_size);
		print_hex(header2.encrypted_keyblob, header2.encrypted_keyblob_size);
		printf("*%d*%d*", (int)cno, (int)data_size);
		print_hex(chunk1, data_size);
		printf("*1*");
		print_hex(chunk2, 4096);
		printf("*%u::::%s\n", header2.kdf_iteration_count, filename);
		free(chunk1);
	}
	close(fd);
}
Esempio n. 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);
}
Esempio n. 3
0
hash_stat hash_plugin_parse_hash(char *hashline, char *filename)
{
    int fd;
    char buf8[8];
    size_t fsize;
    size_t fromsize;

    fd = open(filename, O_RDONLY);
    if (fd<0) 
    {
	if (!hashline) elog("Can't open file: %s\n", filename);
	return hash_err;
    }
    if (read(fd,buf8,8)<=0)
    {
	if (!hashline) elog("File %s is not a DMG file!\n", filename);
	return hash_err;
    }
    if (strncmp(buf8,"encrcdsa",8)==0)
    {
	//return hash_err;
	headerver=2;
    }
    else
    {
	lseek(fd,-8,SEEK_END);
	if (read(fd,buf8,8)<=0)
	{
	    if (!hashline) elog("File %s is not a DMG file!\n", filename);
	    return hash_err;
	}
	if (strncmp(buf8,"cdsaencr",8)==0)
	{
	    headerver=1;
	}
    }
    if (headerver==0)
    {
	if (!hashline) elog("File %s is not a DMG file!\n", filename);
	return hash_err;
    }
    if (!hashline) hlog("Header version %d detected\n",headerver);

    if (headerver==1)
    {
	lseek(fd,-sizeof(cencrypted_v1_header), SEEK_END);
	if (read(fd,&header, sizeof(cencrypted_v1_header)) < 1)
	{
	    if (!hashline) elog("File %s is not a DMG file!\n", filename);
	    return hash_err;
	}
	header_byteorder_fix(&header);
    }
    else
    {
	lseek(fd,0, SEEK_SET);
	if (read(fd,&header2, sizeof(cencrypted_v2_pwheader)) < 1)
	{
	    if (!hashline) elog("File %s is not a DMG file!\n", filename);
	    return hash_err;
	}
	
	header2_byteorder_fix(&header2);
	//printf("AES key len=%d\n",header2.blob_enc_key_bits);
	chunk_size = header2.blocksize;
        lseek(fd,header2.dataoffset,SEEK_SET);
        read(fd,chunk,/*4096*/chunk_size);
        fsize = header2.dataoffset+header2.datasize;
        fromsize=fsize-header2.dataoffset;
        while ((fromsize%4096!=0)||(fromsize==fsize-header2.dataoffset)) fromsize--;
        chunk_no = ((fromsize+1) / chunk_size);
        
        chunkoffset=0;
        if ((fsize-(fromsize+header2.dataoffset))<(4095-678)) 
        {
            chunkoffset+=(fsize-(fromsize+header2.dataoffset));
            fromsize-=4096;
            chunk_no--;
        }

        //printf("fsize=%ld fromsize=%ld dataoffset=%ld at=%ld chunk_no=%d\n",fsize,header2.dataoffset,fromsize,fromsize+header2.dataoffset,chunk_no);
        lseek(fd,fromsize+header2.dataoffset,SEEK_SET);
        read(fd,chunk2,/*4096*/chunk_size);
    }


    close(fd);


    (void)hash_add_username(filename);
    (void)hash_add_hash("DMG file        ",0);
    (void)hash_add_salt("123");
    (void)hash_add_salt2("                              ");

    return hash_ok;
}