Esempio n. 1
0
NTSTATUS dc_drv_control_irp(PDEVICE_OBJECT dev_obj, PIRP irp)
{
	PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp);
	NTSTATUS           status = STATUS_INVALID_DEVICE_REQUEST; // returned status
	ULONG              length = 0; // returned length
	//
	void              *data    = irp->AssociatedIrp.SystemBuffer;
	u32                in_len  = irp_sp->Parameters.DeviceIoControl.InputBufferLength;
	u32                out_len = irp_sp->Parameters.DeviceIoControl.OutputBufferLength;
	
	switch (irp_sp->Parameters.DeviceIoControl.IoControlCode)
	{
		case DC_GET_VERSION:
			if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			*((PULONG)irp->AssociatedIrp.SystemBuffer) = DC_DRIVER_VER;
			status = STATUS_SUCCESS;
			length = sizeof(ULONG);
		break;
		case DC_CTL_CLEAR_PASS:
			dc_clean_pass_cache();
			status = STATUS_SUCCESS;
		break;
		case DC_CTL_ADD_SEED:
			if (irp_sp->Parameters.DeviceIoControl.InputBufferLength == 0)
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			cp_rand_add_seed(irp->AssociatedIrp.SystemBuffer, irp_sp->Parameters.DeviceIoControl.InputBufferLength);
			status = STATUS_SUCCESS;
			// prevent leaks
			RtlSecureZeroMemory(irp->AssociatedIrp.SystemBuffer, irp_sp->Parameters.DeviceIoControl.InputBufferLength);
		break;
		case DC_CTL_GET_RAND:
			if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength == 0)
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if ( (data = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority)) == NULL )
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}
			if (cp_rand_bytes(data, irp_sp->Parameters.DeviceIoControl.OutputBufferLength) == 0)
			{
				status = STATUS_INTERNAL_ERROR;
				break;
			}
			status = STATUS_SUCCESS;
			length = irp_sp->Parameters.DeviceIoControl.OutputBufferLength;
		break;
		case DC_CTL_LOCK_MEM:
			if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DC_LOCK_MEMORY))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			status = mm_lock_user_memory( PsGetProcessId(IoGetRequestorProcess(irp)), ((PDC_LOCK_MEMORY)irp->AssociatedIrp.SystemBuffer)->ptr,
				                                                                      ((PDC_LOCK_MEMORY)irp->AssociatedIrp.SystemBuffer)->length );
		break;
		case DC_CTL_UNLOCK_MEM:
			if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(PVOID*))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			status = mm_unlock_user_memory( PsGetProcessId(IoGetRequestorProcess(irp)), *((PVOID*)irp->AssociatedIrp.SystemBuffer) );
		break;
		case DC_CTL_GET_FLAGS:
			if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(DC_FLAGS))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->conf_flags = dc_conf_flags;
			((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->load_flags = dc_load_flags;
			status = STATUS_SUCCESS;
			length = sizeof(DC_FLAGS);
		break;
		case DC_CTL_SET_FLAGS:
			if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DC_FLAGS))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			dc_conf_flags = ((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->conf_flags;

			if ( !(dc_conf_flags & CONF_CACHE_PASSWORD) ) dc_clean_pass_cache();
			dc_init_encryption();

			status = STATUS_SUCCESS;
		break;
		case DC_CTL_BSOD:
			mm_clean_secure_memory();
			dc_clean_keys();

			KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
		break;
		case DC_GET_DUMP_HELPERS: // This IOCTL is allowed only from kernel mode
			if (irp->RequestorMode != KernelMode)
			{
				status = STATUS_ACCESS_DENIED;
				break;
			}
			if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(DC_DUMP_HELPERS))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			memcpy(irp->UserBuffer, &dc_dump_helpers, sizeof(DC_DUMP_HELPERS));
			status = STATUS_SUCCESS;
			length = sizeof(DC_DUMP_HELPERS);
		break;
		//
		case DC_CTL_STATUS:
			{
				dc_ioctl  *dctl = data;
				dc_status *stat = data;
				dev_hook  *hook;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_status)) )
				{
					dctl->device[MAX_DEVICE] = 0;

					if (hook = dc_find_hook(dctl->device))
					{
						if (hook->pdo_dev->Flags & DO_SYSTEM_BOOT_PARTITION) {
							hook->flags |= F_SYSTEM;
						}

						dc_get_mount_point(hook, stat->mnt_point, sizeof(stat->mnt_point));

						stat->crypt        = hook->crypt;
						stat->dsk_size     = hook->dsk_size;
						stat->tmp_size     = hook->tmp_size;
						stat->flags        = hook->flags;
						stat->mnt_flags    = hook->mnt_flags;
						stat->disk_id      = hook->disk_id;
						stat->paging_count = hook->paging_count;
						stat->vf_version   = hook->vf_version;
						status             = STATUS_SUCCESS; 
						length             = sizeof(dc_status);

						dc_deref_hook(hook);
					}
				}
			}
		break;
		case DC_CTL_BENCHMARK:
			{
				 if ( (in_len == sizeof(int)) && (out_len == sizeof(dc_bench_info)) )
				 {
					 if (dc_k_benchmark(p32(data)[0], pv(data)) == ST_OK) {
						 status = STATUS_SUCCESS; 
						 length = sizeof(dc_bench_info);
					 }
				 }
			}
		break;
		
		case DC_BACKUP_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_backup_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					length = sizeof(dc_backup_ctl);
				}
			}
		break;
		case DC_RESTORE_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_restore_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					length = sizeof(dc_backup_ctl);
				}
			}
		break;
		default: 
			{
				dc_ioctl *dctl = data;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_ioctl)) )
				{					
					/* limit null-terminated string length */
					dctl->device[MAX_DEVICE] = 0;
					
					/* process IOCTL */
					dctl->status = dc_ioctl_process(irp_sp->Parameters.DeviceIoControl.IoControlCode, dctl);

					/* prevent leaks  */
					burn(&dctl->passw1, sizeof(dctl->passw1));
					burn(&dctl->passw2, sizeof(dctl->passw2));

					status = STATUS_SUCCESS;
					length = sizeof(dc_ioctl);
				}
			}
		break;
	}
	return dc_complete_irp(irp, status, length);
}
Esempio n. 2
0
NTSTATUS dc_drv_control_irp(PDEVICE_OBJECT dev_obj, PIRP irp)
{
	PIO_STACK_LOCATION  irp_sp  = IoGetCurrentIrpStackLocation(irp);
	NTSTATUS            status  = STATUS_INVALID_DEVICE_REQUEST;
	void               *data    = irp->AssociatedIrp.SystemBuffer;
	u32                 in_len  = irp_sp->Parameters.DeviceIoControl.InputBufferLength;
	u32                 out_len = irp_sp->Parameters.DeviceIoControl.OutputBufferLength;
	u32                 code    = irp_sp->Parameters.DeviceIoControl.IoControlCode;
	u32                 bytes   = 0;
	
	switch (code)
	{
		case DC_GET_VERSION:
			{
				if (out_len == sizeof(u32)) 
				{
					p32(data)[0] = DC_DRIVER_VER;
					bytes        = sizeof(u32);
					status       = STATUS_SUCCESS;
				}
			}
		break;
		case DC_CTL_CLEAR_PASS:
			{
				dc_clean_pass_cache();
				status = STATUS_SUCCESS;
			}
		break;		
		case DC_CTL_STATUS:
			{
				dc_ioctl  *dctl = data;
				dc_status *stat = data;
				dev_hook  *hook;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_status)) )
				{
					dctl->device[MAX_DEVICE] = 0;

					if (hook = dc_find_hook(dctl->device))
					{
						if (hook->pdo_dev->Flags & DO_SYSTEM_BOOT_PARTITION) {
							hook->flags |= F_SYSTEM;
						}

						dc_get_mount_point(hook, stat->mnt_point, sizeof(stat->mnt_point));

						stat->crypt        = hook->crypt;
						stat->dsk_size     = hook->dsk_size;
						stat->tmp_size     = hook->tmp_size;
						stat->flags        = hook->flags;
						stat->mnt_flags    = hook->mnt_flags;
						stat->disk_id      = hook->disk_id;
						stat->paging_count = hook->paging_count;
						stat->vf_version   = hook->vf_version;
						status             = STATUS_SUCCESS; 
						bytes              = sizeof(dc_status);

						dc_deref_hook(hook);
					}
				}
			}
		break;
		case DC_CTL_ADD_SEED:
			{
				 if (in_len != 0) 
				 {
					 cp_rand_add_seed(data, in_len);
					 status = STATUS_SUCCESS;
					 /* prevent leaks */
					 burn(data, in_len);
				 }
			}
		break;
		case DC_CTL_GET_RAND:
			{
				dc_rand_ctl *rctl = data;
				
				if (in_len == sizeof(dc_rand_ctl))
				{
					__try
					{
						ProbeForWrite(rctl->buff, rctl->size, sizeof(u8));

						if (cp_rand_bytes(rctl->buff, rctl->size) != 0) {
							status = STATUS_SUCCESS;
						}
					} 
					__except(EXCEPTION_EXECUTE_HANDLER) {
						status = GetExceptionCode();
					}
				}
			}
		break;
		case DC_CTL_BENCHMARK:
			{
				 if ( (in_len == sizeof(int)) && (out_len == sizeof(dc_bench_info)) )
				 {
					 if (dc_k_benchmark(p32(data)[0], pv(data)) == ST_OK) {
						 status = STATUS_SUCCESS; 
						 bytes  = sizeof(dc_bench_info);
					 }
				 }
			}
		break;
		case DC_CTL_BSOD:
			{
				lock_inc(&dc_dump_disable);
				dc_clean_pass_cache();
				mm_unlock_user_memory(NULL, NULL);
				dc_clean_keys();

				KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
			}
		break;
		case DC_CTL_GET_CONF:
			{
				dc_conf *conf = data;

				if (out_len == sizeof(dc_conf)) {
					conf->conf_flags = dc_conf_flags;
					conf->load_flags = dc_load_flags;
					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_conf);
				}
			}
		break;
		case DC_CTL_SET_CONF:
			{
				dc_conf *conf = data;
				
				if (in_len == sizeof(dc_conf))
				{
					dc_conf_flags = conf->conf_flags;
					status        = STATUS_SUCCESS;

					if ( !(dc_conf_flags & CONF_CACHE_PASSWORD) ) {
						dc_clean_pass_cache();
					}
					dc_init_encryption();
				}
			}
		break;
		case DC_CTL_LOCK_MEM:
			{
				PEPROCESS    process = IoGetRequestorProcess(irp);
				dc_lock_ctl *smem = data;				

				if ( (process != NULL) && (in_len == sizeof(dc_lock_ctl)) && (out_len == in_len) ) 
				{
					smem->resl = mm_lock_user_memory(smem->data, smem->size, process);

					status = STATUS_SUCCESS; bytes = sizeof(dc_lock_ctl);
				}
			}
		break;
		case DC_CTL_UNLOCK_MEM:
			{
				PEPROCESS    process = IoGetRequestorProcess(irp);
				dc_lock_ctl *smem = data;

				if ( (process != NULL) && (in_len == sizeof(dc_lock_ctl)) && (out_len == in_len) )
				{
					mm_unlock_user_memory(smem->data, process);

					status = STATUS_SUCCESS; bytes = sizeof(dc_lock_ctl);
					smem->resl = ST_OK;
				}
			}
		break; 
		case DC_BACKUP_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_backup_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_backup_ctl);
				}
			}
		break;
		case DC_RESTORE_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_restore_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_backup_ctl);
				}
			}
		break;
		default: 
			{
				dc_ioctl *dctl = data;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_ioctl)) )
				{					
					/* limit null-terminated string length */
					dctl->device[MAX_DEVICE] = 0;
					
					/* process IOCTL */
					dctl->status = dc_ioctl_process(code, dctl);

					/* prevent leaks  */
					burn(&dctl->passw1, sizeof(dctl->passw1));
					burn(&dctl->passw2, sizeof(dctl->passw2));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_ioctl);
				}
			}
		break;
	}