Exemplo n.º 1
0
NTSTATUS wddDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
				  IN PIRP Irp)
{
  UNICODE_STRING DestinationPath;
  PIO_STACK_LOCATION IrpStack;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  ULONG IoControlCode;
  PVOID IoBuffer;
  PULONG OutputBuffer;
  PDEVICE_EXTENSION ext;
  ULONG InputLen, OutputLen;

  ULONG Level;
  ULONG Type;

  // We must be running in PASSIVE_LEVEL or we bluescreen here. We
  // theoretically should always be running at PASSIVE_LEVEL here, but
  // in case we ended up here at the wrong IRQL its better to bail
  // than to bluescreen.
  if(KeGetCurrentIrql() != PASSIVE_LEVEL) {
    status = STATUS_ABANDONED;
    goto exit;
  };

  ext = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

  Irp->IoStatus.Information = 0;

  IrpStack = IoGetCurrentIrpStackLocation(Irp);

  IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  OutputLen = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  InputLen = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;

  switch ((IoControlCode & 0xFFFFFF0F)) {

  // The old deprecated ioctrl interface for backwards
  // compatibility. Do not use for new code.
  case IOCTL_GET_INFO_DEPRECATED: {
    char *buffer = ExAllocatePoolWithTag(NonPagedPoolNx, 0x1000, PMEM_POOL_TAG);

    if (buffer) {
      struct DeprecatedPmemMemoryInfo *info = (void *)IoBuffer;
      struct PmemMemoryInfo *memory_info = (void *)buffer;

      status = AddMemoryRanges(memory_info, 0x1000);
      if (status != STATUS_SUCCESS) {
        ExFreePoolWithTag(buffer, PMEM_POOL_TAG);
        goto exit;
      };

      info->CR3.QuadPart = CR3.QuadPart;
      info->NumberOfRuns = (unsigned long)memory_info->NumberOfRuns.QuadPart;

      // Is there enough space in the user supplied buffer?
      if (OutputLen < (info->NumberOfRuns * sizeof(PHYSICAL_MEMORY_RANGE) +
                       sizeof(struct DeprecatedPmemMemoryInfo))) {
        status = STATUS_INFO_LENGTH_MISMATCH;
        ExFreePoolWithTag(buffer, PMEM_POOL_TAG);
        goto exit;
      };

      // Copy the runs over.
      RtlCopyMemory(&info->Run[0], &memory_info->Run[0],
                    info->NumberOfRuns * sizeof(PHYSICAL_MEMORY_RANGE));

      // This is the total length of the response.
      Irp->IoStatus.Information =
        sizeof(struct DeprecatedPmemMemoryInfo) +
        info->NumberOfRuns * sizeof(PHYSICAL_MEMORY_RANGE);

      WinDbgPrint("Returning info on the system memory using deprecated "
		  "interface!\n");

      ExFreePoolWithTag(buffer, PMEM_POOL_TAG);
      status = STATUS_SUCCESS;
    };
  }; break;

    // Return information about memory layout etc through this ioctrl.
  case IOCTL_GET_INFO: {
    struct PmemMemoryInfo *info = (void *)IoBuffer;

    if (OutputLen < sizeof(struct PmemMemoryInfo)) {
        status = STATUS_INFO_LENGTH_MISMATCH;
        goto exit;
    };

    // Ensure we clear the buffer first.
    RtlZeroMemory(IoBuffer, sizeof(struct PmemMemoryInfo));

    // Get the memory ranges according to the mode.
    if (ext->mode == ACQUISITION_MODE_PTE_MMAP_WITH_PCI_PROBE) {
      status = PCI_AddMemoryRanges(info, OutputLen);
    } else {
      status = AddMemoryRanges(info, OutputLen);
    }

    if (status != STATUS_SUCCESS) {
      goto exit;
    };

    WinDbgPrint("Returning info on the system memory.\n");

    // We are currently running in user context which means __readcr3() will
    // return the process CR3. So we return the kernel CR3 we found
    // when loading.
    info->CR3.QuadPart = CR3.QuadPart;

    info->NtBuildNumber.QuadPart = *NtBuildNumber;
    info->NtBuildNumberAddr.QuadPart = (uintptr_t)NtBuildNumber;
    info->KernBase.QuadPart = (uintptr_t)KernelGetModuleBaseByPtr(
       NtBuildNumber, "NtBuildNumber");

    // Fill in KPCR.
    GetKPCR(info);

    // This is the length of the response.
    Irp->IoStatus.Information =
      sizeof(struct PmemMemoryInfo) +
      info->NumberOfRuns.LowPart * sizeof(PHYSICAL_MEMORY_RANGE);

    status = STATUS_SUCCESS;
  }; break;

  case IOCTL_SET_MODE: {
    WinDbgPrint("Setting Acquisition mode.\n");

    /* First u32 is the acquisition mode. */
    if (InputLen >= sizeof(u32)) {
      enum PMEM_ACQUISITION_MODE mode = *(u32 *)IoBuffer;

      switch(mode) {
      case ACQUISITION_MODE_PHYSICAL_MEMORY:
        // These are all the requirements for this method.
        if (!Pmem_KernelExports.MmGetPhysicalMemoryRanges) {
          WinDbgPrint("Kernel APIs required for this method are not "
                      "available.");
          status = STATUS_UNSUCCESSFUL;
        } else {
          WinDbgPrint("Using physical memory device for acquisition.\n");
          status = STATUS_SUCCESS;
	  ext->mode = mode;
        };
        break;

      case ACQUISITION_MODE_MAP_IO_SPACE:
        if (!Pmem_KernelExports.MmGetPhysicalMemoryRanges ||
            !Pmem_KernelExports.MmMapIoSpace ||
            !Pmem_KernelExports.MmUnmapIoSpace) {
          WinDbgPrint("Kernel APIs required for this method are not "
                      "available.");
          status = STATUS_UNSUCCESSFUL;
        } else {
          WinDbgPrint("Using MmMapIoSpace for acquisition.\n");
          status = STATUS_SUCCESS;
	  ext->mode = mode;
        };
        break;

      case ACQUISITION_MODE_PTE_MMAP:
        if (!Pmem_KernelExports.MmGetVirtualForPhysical ||
            !Pmem_KernelExports.MmGetPhysicalMemoryRanges ||
            !ext->pte_mmapper) {
          WinDbgPrint("Kernel APIs required for this method are not "
                      "available.");
          status = STATUS_UNSUCCESSFUL;
        } else {
          WinDbgPrint("Using PTE Remapping for acquisition.\n");
          status = STATUS_SUCCESS;
	  ext->mode = mode;
        };
        break;

      case ACQUISITION_MODE_PTE_MMAP_WITH_PCI_PROBE:
        if (!Pmem_KernelExports.MmGetVirtualForPhysical ||
            !ext->pte_mmapper) {
          WinDbgPrint("Kernel APIs required for this method are not "
                      "available.");
          status = STATUS_UNSUCCESSFUL;
        } else {
          WinDbgPrint("Using PTE Remapping with PCI probe for acquisition.\n");
          status = STATUS_SUCCESS;
	  ext->mode = mode;
        };
        break;

      default:
        WinDbgPrint("Invalid acquisition mode %d.\n", mode);
        status = STATUS_INVALID_PARAMETER;
      };

    } else {
      status = STATUS_INFO_LENGTH_MISMATCH;
    };
  }; break;

#if PMEM_WRITE_ENABLED == 1
  case IOCTL_WRITE_ENABLE: {
    ext->WriteEnabled = !ext->WriteEnabled;
    WinDbgPrint("Write mode is %d. Do you know what you are doing?\n",
		ext->WriteEnabled);
    status = STATUS_SUCCESS;
  }; break;
#endif

  default: {
    WinDbgPrint("Invalid IOCTRL %d\n", IoControlCode);
    status = STATUS_INVALID_PARAMETER;
  };
  }

 exit:
  Irp->IoStatus.Status = status;
  IoCompleteRequest(Irp,IO_NO_INCREMENT);
  return status;
}
Exemplo n.º 2
0
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryString )
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	UNICODE_STRING uDeviceName, uDosDeviceName;
	unsigned int iCount = 0;
	PVOID pStackAttach = NULL;
	HANDLE hThreadHandle = NULL;
	OBJECT_ATTRIBUTES ObjectAttributes;

	SCOPE(__FUNCTION__);
	RtlInitUnicodeString( &uDeviceName, DeviceName );
	RtlInitUnicodeString( &uDosDeviceName, DosDeviceName );

	// We are assigned to the device of null.sys and create a new symbolic link
	//ntStatus = IoCreateSymbolicLink( &uDosDeviceName, &uDeviceName );
	//if( !NT_SUCCESS(ntStatus) )
	//{
	//	KdPrint(("Fail on IoCreateSymbolicLink. ntStatus: 0x%08x", ntStatus));
	//	return ntStatus;
	//}

	KdPrint(("Loading driver. pDriverObject 0x%08x\n pRegistryString %wZ\n Build at "__TIME__" "__DATE__"\n",
		pDriverObject, pRegistryString));

	/* Only for testing purposes */
	IoCreateDevice( pDriverObject, 0,
		&uDeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &g_Device );
	IoCreateSymbolicLink( &uDosDeviceName, &uDeviceName );

	// Set new major functions
	for( iCount = 0; iCount < IRP_MJ_MAXIMUM_FUNCTION; iCount++ )
		pDriverObject->MajorFunction[iCount] = OnDispatch;

	pDriverObject->DriverUnload = DriverUnload;

	// Retrieve process offset in EPROCESS
	if( !GetProcessNameOffset() )
	{
		KdPrint(("Error getting process name offset!\n"));
		ntStatus = STATUS_UNSUCCESSFUL;
		return ntStatus;
	}

	// Retrieve kernel base pointer
	pStackAttach = (PVOID)&KeStackAttachProcess;
	g_pKrnlBase = KernelGetModuleBaseByPtr( pStackAttach, "KeStackAttachProcess" );
	if( !g_pKrnlBase )
	{
		KdPrint(("Error getting ntoskrnl base!\n"));
		ntStatus = STATUS_UNSUCCESSFUL;
		return ntStatus;
	}
	KdPrint(("Kernel base: 0x%08x\n", g_pKrnlBase));

	// Retrieve kernel name (differs from system to system)
	if( !GetModuleNameByBase( g_pKrnlBase, szKernelName, NULL ) )
	{
		KdPrint(("Error getting kernel name by base\n"));
		ntStatus = STATUS_UNSUCCESSFUL;
		return ntStatus;
	}
	KdPrint(("NT OS Kernel Name: %s\n", szKernelName));

	/* We ignore errors here. Cheat just won't work if something fails */
	InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );
	PsCreateSystemThread( &hThreadHandle, GENERIC_ALL, &ObjectAttributes, NULL, NULL,
		InitializeThread, NULL );
	ZwClose( hThreadHandle );

	DESCOPE();
	return ntStatus;
}