Exemplo n.º 1
0
void bt_dis_unref(struct bt_dis *dis)
{
	if (!dis)
		return;

	if (__sync_sub_and_fetch(&dis->ref_count, 1))
		return;

	dis_free(dis);
}
Exemplo n.º 2
0
/**
 * Get the dataset present in a .BEK file
 *
 * @param fd The file descriptor to the .BEK file
 * @param bek_dataset The extracted dataset
 * @return TRUE if result can be trusted, FALSE otherwise
 */
int get_bek_dataset(int fd, void** bek_dataset)
{
	if(!bek_dataset)
	{
		dis_printf(L_ERROR, "Invalid parameter given to get_bek_dataset().\n");
		return FALSE;
	}

	bitlocker_dataset_t dataset;

	/* Read the dataset header */
	ssize_t nb_read = dis_read(fd, &dataset, sizeof(bitlocker_dataset_t));

	// Check if we read all we wanted
	if(nb_read != sizeof(bitlocker_dataset_t))
	{
		dis_printf(
			L_ERROR,
			"get_bek_dataset::Error, not all byte read (bek dataset header).\n"
		);
		return FALSE;
	}

	if(dataset.size <= sizeof(bitlocker_dataset_t))
	{
		dis_printf(
			L_ERROR,
			"get_bek_dataset::Error, dataset size < dataset header size.\n"
		);
		return FALSE;
	}

	*bek_dataset = dis_malloc(dataset.size);

	memset(*bek_dataset, 0, dataset.size);
	memcpy(*bek_dataset, &dataset, sizeof(bitlocker_dataset_t));

	size_t rest = dataset.size - sizeof(bitlocker_dataset_t);

	/* Read the data included in the dataset */
	nb_read = dis_read(fd, *bek_dataset + sizeof(bitlocker_dataset_t), rest);

	// Check if we read all we wanted
	if((size_t) nb_read != rest)
	{
		dis_printf(
			L_ERROR,
			"get_bek_dataset::Error, not all byte read (bek dataset content).\n"
		);
		dis_free(*bek_dataset);
		return FALSE;
	}

	return TRUE;
}
Exemplo n.º 3
0
int dis_destroy(dis_context_t dis_ctx)
{
	/* Finish cleaning things */
	if(dis_ctx->io_data.vmk)
		dis_free(dis_ctx->io_data.vmk);

	if(dis_ctx->io_data.fvek)
		dis_free(dis_ctx->io_data.fvek);

	dis_crypt_destroy(dis_ctx->io_data.crypt);

	dis_metadata_destroy(dis_ctx->metadata);

	dis_free_args(dis_ctx);

	dis_close(dis_ctx->io_data.volume_fd);

	dis_stdio_end();

	dis_free(dis_ctx);

	return EXIT_SUCCESS;
}
Exemplo n.º 4
0
/*
 * Return the previous instruction.  On x86, we have no choice except to
 * disassemble everything from the start of the symbol, and stop when we have
 * reached our instruction address.  If we're not in the middle of a known
 * symbol, then we return the same address to indicate failure.
 */
static uint64_t
dis_i386_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
{
	uint64_t *hist, addr, start;
	int cur, nseen;
	uint64_t res = pc;

	if (n <= 0)
		return (pc);

	if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 ||
	    start == pc)
		return (res);

	hist = dis_zalloc(sizeof (uint64_t) * n);

	for (cur = 0, nseen = 0, addr = start; addr < pc; addr = dhp->dh_addr) {
		hist[cur] = addr;
		cur = (cur + 1) % n;
		nseen++;

		/* if we cannot make forward progress, give up */
		if (dis_disassemble(dhp, addr, NULL, 0) != 0)
			goto done;
	}

	if (addr != pc) {
		/*
		 * We scanned past %pc, but didn't find an instruction that
		 * started at %pc.  This means that either the caller specified
		 * an invalid address, or we ran into something other than code
		 * during our scan.  Virtually any combination of bytes can be
		 * construed as a valid Intel instruction, so any non-code bytes
		 * we encounter will have thrown off the scan.
		 */
		goto done;
	}

	res = hist[(cur + n - MIN(n, nseen)) % n];

done:
	dis_free(hist, sizeof (uint64_t) * n);
	return (res);
}
Exemplo n.º 5
0
struct bt_dis *bt_dis_new(void *primary)
{
	struct bt_dis *dis;

	dis = g_try_new0(struct bt_dis, 1);
	if (!dis)
		return NULL;

	dis->gatt_op = queue_new();
	if (!dis->gatt_op) {
		dis_free(dis);
		return NULL;
	}

	if (primary)
		dis->primary = g_memdup(primary, sizeof(*dis->primary));

	return bt_dis_ref(dis);
}
Exemplo n.º 6
0
dis_handle_t *
dis_handle_create(int flags, void *data, dis_lookup_f lookup_func,
    dis_read_f read_func)
{
	dis_handle_t *dhp;
	dis_arch_t *arch = NULL;
	int i;

	/* Select an architecture based on flags */
	for (i = 0; dis_archs[i] != NULL; i++) {
		if (dis_archs[i]->da_supports_flags(flags)) {
			arch = dis_archs[i];
			break;
		}
	}
	if (arch == NULL) {
		(void) dis_seterrno(E_DIS_UNSUPARCH);
		return (NULL);
	}

	if ((dhp = dis_zalloc(sizeof (dis_handle_t))) == NULL) {
		(void) dis_seterrno(E_DIS_NOMEM);
		return (NULL);
	}
	dhp->dh_arch = arch;
	dhp->dh_lookup = lookup_func;
	dhp->dh_read = read_func;
	dhp->dh_flags = flags;
	dhp->dh_data = data;

	/*
	 * Allow the architecture-specific code to allocate
	 * its private data.
	 */
	if (arch->da_handle_attach(dhp) != 0) {
		dis_free(dhp, sizeof (dis_handle_t));
		/* dis errno already set */
		return (NULL);
	}

	return (dhp);
}
Exemplo n.º 7
0
dis_context_t dis_new()
{
	/* Allocate dislocker's context */
	dis_context_t dis_ctx = dis_malloc(sizeof(struct _dis_ctx));
	memset(dis_ctx, 0, sizeof(struct _dis_ctx));

#ifndef __DIS_CORE_DUMPS
	/* As we manage passwords and secrets, do not authorize core dumps */
	struct rlimit limit;
	limit.rlim_cur = 0;
	limit.rlim_max = 0;
	if (setrlimit(RLIMIT_CORE, &limit) != 0)
	{
		fprintf(stderr, "Cannot disable core dumps.\n");
		dis_free(dis_ctx);
		return NULL;
	}
#endif

	dis_ctx->fve_fd = -1;

	return dis_ctx;
}
Exemplo n.º 8
0
static void
dis_i386_handle_detach(dis_handle_t *dhp)
{
	dis_free(dhp->dh_arch_private, sizeof (dis_handle_i386_t));
	dhp->dh_arch_private = NULL;
}
Exemplo n.º 9
0
/**
 * Get the VMK datum using a bek file (external key)
 *
 * @param dataset The dataset of BitLocker's metadata on the volume
 * @param bek_file The path to the .BEK file to use
 * @param vmk_datum The datum_key_t found, containing the unencrypted VMK
 * @return TRUE if result can be trusted, FALSE otherwise
 */
int get_vmk_from_bekfile2(dis_metadata_t dis_meta,
                          char* bek_file,
                          void** vmk_datum)
{
	// Check parameters
	if(!dis_meta || !vmk_datum)
		return FALSE;

	guid_t key_guid = {0,};
	char rec_id[37] = {0,};

	bitlocker_dataset_t* bek_dataset = NULL;
	uint8_t* recovery_key = NULL;
	size_t rk_size = 0;

	int result = FALSE;
	int fd_bek = 0;


	if(bek_file)
	{
		/* Check if the bek file exists */
		fd_bek = dis_open(bek_file, O_RDONLY);
		if(fd_bek < 0)
		{
			dis_printf(L_ERROR, "Cannot open FVEK file (%s)\n", bek_file);
			return FALSE;
		}
	}
	else
	{
		dis_printf(
			L_ERROR,
			"Using bekfile method (USB) but missing the bekfile name. Abort.\n"
		);
		return FALSE;
	}

	dis_printf(
		L_INFO,
		"Using the bekfile '%s' to decrypt the VMK.\n",
		bek_file
	);

	/*
	 * We need the recovery key id which can be found in the bek file
	 * to find its match in a datum of the volume's metadata
	 */
	if(!get_bek_dataset(fd_bek, (void**) &bek_dataset))
	{
		dis_printf(L_ERROR, "Unable to retrieve the dataset. Abort.\n");
		dis_close(fd_bek);
		return FALSE;
	}

	/* We have what we wanted, so close the file */
	dis_close(fd_bek);


	/* Get the external datum */
	void* dataset = dis_metadata_set_dataset(dis_meta, bek_dataset);
	get_next_datum(
		dis_meta,
		UINT16_MAX,
		DATUMS_VALUE_EXTERNAL_KEY,
		NULL,
		vmk_datum
	);
	dis_metadata_set_dataset(dis_meta, dataset);

	/* Check the result datum */
	if(!*vmk_datum ||
	   !datum_value_type_must_be(*vmk_datum, DATUMS_VALUE_EXTERNAL_KEY))
	{
		dis_printf(
			L_ERROR,
			"Error processing the bekfile: datum of type %hd not found. "
			"Internal failure, abort.\n",
			DATUMS_VALUE_EXTERNAL_KEY
		);
		*vmk_datum = NULL;
		memclean(bek_dataset, bek_dataset->size);
		return FALSE;
	}

	/* Now that we are sure of the type, take care of copying the recovery key id */
	datum_external_t* datum_exte = (datum_external_t*) *vmk_datum;
	memcpy(key_guid, datum_exte->guid, 16);

	format_guid(key_guid, rec_id);
	dis_printf(
		L_INFO,
		"Bekfile GUID found: '%s', looking for the same in metadata...\n",
		rec_id
	);

	/* Grab the datum nested in the last, we will need it to decrypt the VMK */
	if(!get_nested_datumvaluetype(*vmk_datum, DATUMS_VALUE_KEY, vmk_datum) ||
	   !*vmk_datum)
	{
		dis_printf(
			L_ERROR,
			"Error processing the bekfile: no nested datum found. "
			"Internal failure, abort.\n"
		);
		*vmk_datum = NULL;
		memclean(bek_dataset, bek_dataset->size);
		return FALSE;
	}

	if(!get_payload_safe(*vmk_datum, (void**) &recovery_key, &rk_size))
	{
		dis_printf(
			L_ERROR,
			"Error getting the key to decrypt VMK from the bekfile. "
			"Internal failure, abort.\n"
		);
		*vmk_datum = NULL;
		memclean(bek_dataset, bek_dataset->size);
		return FALSE;
	}

	memclean(bek_dataset, bek_dataset->size);


	/*
	 * Now that we have the key to decrypt the VMK, we need to
	 * find the VMK datum in the BitLocker metadata in order to
	 * decrypt the VMK using this already found key in the bekfile
	 */
	if(!get_vmk_datum_from_guid(dis_meta, key_guid, vmk_datum))
	{
		format_guid(key_guid, rec_id);

		dis_printf(
			L_ERROR,
			"\n\tError, can't find a valid and matching VMK datum.\n"
			"\tThe GUID researched was '%s', check if you have the right "
			"bek file for the right volume.\n"
			"\tAbort.\n",
			rec_id
		);
		*vmk_datum = NULL;
		dis_free(recovery_key);
		return FALSE;
	}

	dis_printf(
		L_INFO,
		"VMK datum of id '%s' found. Trying to reach the Key datum...\n",
		rec_id
	);


	/*
	 * We have the datum containing other data, so get in there and take the
	 * nested one with type 5 (aes-ccm)
	 */
	if(!get_nested_datumvaluetype(*vmk_datum, DATUMS_VALUE_AES_CCM, vmk_datum))
	{
		dis_printf(
			L_ERROR,
			"Error looking for the nested datum in the VMK one. "
			"Internal failure, abort.\n"
		);
		*vmk_datum = NULL;
		dis_free(recovery_key);
		return FALSE;
	}


	dis_printf(L_INFO, "Key datum found and payload extracted!\n");

	result = get_vmk(
		(datum_aes_ccm_t*) *vmk_datum,
		recovery_key,
		rk_size,
		(datum_key_t**) vmk_datum
	);

	dis_free(recovery_key);

	return result;
}
Exemplo n.º 10
0
void
dis_handle_destroy(dis_handle_t *dhp)
{
	dhp->dh_arch->da_handle_detach(dhp);
	dis_free(dhp, sizeof (dis_handle_t));
}
Exemplo n.º 11
0
/**
 * Get the VMK datum using a recovery password
 *
 * @param dis_metadata The metadata structure
 * @param recovery_password The recovery password provided by the user
 * @param vmk_datum The datum_key_t found, containing the unencrypted VMK
 * @return TRUE if result can be trusted, FALSE otherwise
 */
int get_vmk_from_rp2(dis_metadata_t dis_meta, uint8_t* recovery_password,
	void** vmk_datum)
{
	// Check parameters
	if(!dis_meta)
		return FALSE;

	uint8_t* recovery_key = NULL;
	uint8_t salt[16] = {0,};

	int result = FALSE;

	/* If the recovery password wasn't provide, ask for it */
	if(!recovery_password)
		if(!prompt_rp(&recovery_password))
		{
			dis_printf(L_ERROR, "Cannot get valid recovery password. Abort.\n");
			return FALSE;
		}


	dis_printf(L_DEBUG, "Using the recovery password: '******'.\n",
	                (char *)recovery_password);


	/*
	 * We need a salt contained in the VMK datum associated to the recovery
	 * password, so go get this salt and the VMK datum first
	 * We use here the range which should be upper (or equal) than 0x800
	 */
	if(!get_vmk_datum_from_range(dis_meta, 0x800, 0xfff, (void**) vmk_datum))
	{
		dis_printf(
			L_ERROR,
			"Error, can't find a valid and matching VMK datum. Abort.\n"
		);
		*vmk_datum = NULL;
		return FALSE;
	}


	/*
	 * We have the datum containing other data, so get in there and take the
	 * nested one with type 3 (stretch key)
	 */
	void* stretch_datum = NULL;
	if(!get_nested_datumvaluetype(
			*vmk_datum,
			DATUMS_VALUE_STRETCH_KEY,
			&stretch_datum
		) ||
	   !stretch_datum)
	{
		char* type_str = datumvaluetypestr(DATUMS_VALUE_STRETCH_KEY);
		dis_printf(
			L_ERROR,
			"Error looking for the nested datum of type %hd (%s) in the VMK one"
			". Internal failure, abort.\n",
			DATUMS_VALUE_STRETCH_KEY,
			type_str
		);
		dis_free(type_str);
		*vmk_datum = NULL;
		return FALSE;
	}


	/* The salt is in here, don't forget to keep it somewhere! */
	memcpy(salt, ((datum_stretch_key_t*) stretch_datum)->salt, 16);


	/* Get data which can be decrypted with this password */
	void* aesccm_datum = NULL;
	if(!get_nested_datumvaluetype(
			*vmk_datum,
			DATUMS_VALUE_AES_CCM,
			&aesccm_datum
		) ||
	   !aesccm_datum)
	{
		dis_printf(
			L_ERROR,
			"Error finding the AES_CCM datum including the VMK. "
			"Internal failure, abort.\n"
		);
		*vmk_datum = NULL;
		return FALSE;
	}


	/*
	 * We have all the things we need to compute the intermediate key from
	 * the recovery password, so do it!
	 */
	recovery_key = dis_malloc(32 * sizeof(uint8_t));

	if(!intermediate_key(recovery_password, salt, recovery_key))
	{
		dis_printf(
			L_ERROR,
			"Error computing the recovery password to the recovery key. "
			"Abort.\n"
		);
		*vmk_datum = NULL;
		dis_free(recovery_key);
		return FALSE;
	}

	/* As the computed key length is always the same, use a direct value */
	result = get_vmk(
		(datum_aes_ccm_t*) aesccm_datum,
		recovery_key,
		32,
		(datum_key_t**) vmk_datum
	);

	dis_free(recovery_key);

	return result;
}