2

I'm aware about communicating to kernel-mode from user-mode and I also know of events/inverted calls however I need to send a string value down to a user-mode process from a kernel-mode device driver and then wait in KM for a response (e.g. TRUE or FALSE BOOLEAN).

Take the string "c:\file.txt". Now I need the KM device driver to send this string down to user-mode and then have that UM program re-send back a TRUE or FALSE response for the driver to process.

I've been through a lot of website topics/posts, documentation samples and cannot find what I am looking for.

I was thinking that maybe I could setup a thread in the user-mode program which just continuously waits for data to come down and then in KM I somehow pause until a response is returned back... not sure

Any help is appreciated.

Dinoflame33
  • 41
  • 1
  • 2
  • Welcome to Stack Overflow. Your post in its current form is unclear and not a good fit for Stack Overflow. Please visit the [help center](http://stackoverflow.com/help) and read the section [how do I ask a good question](http://stackoverflow.com/help/how-to-ask). – Captain Obvlious Jul 19 '17 at 23:21
  • The canonical method is an IOCTL. The user-mode call is the DeviceIoControl function. You can either call this in a separate thread or use asynchronous I/O. One of the ways the kernel mode driver might deal with such a request when it arrives would be to requeue it to a separate queue that is configured to use the manual dispatch method; that way, when you needed to send the message to user mode, you would just pull the pending request out of the queue with WdfIoQueueRetrieveNextRequest and then complete it as normal. – Harry Johnston Jul 20 '17 at 01:28
  • ... the message from the driver should probably include an ID number of some kind, so that when the user-mode program sends an IOCTL to say "true" or "false" it can include the ID number so the driver knows which message the IOCTL is responding to. – Harry Johnston Jul 20 '17 at 01:30
  • ioctl or read call from the user is the correct way. Call it and wait for the data. You can't push from the kernel because you don't know where to push it to or whether the user process still exists. – stark Jul 20 '17 at 01:59

2 Answers2

4

You have loads of options.

  1. Ports
  2. Named Pipes
  3. Pending IOCTLs
  4. Code injection
  5. Shared Events -> now read a configuration file from user-mode

The first mentioned technique is officially supported for File-System Mini-Filter device drivers, and #3 and #5 are relatively straight-forward. Whereas, #2 and #4 are more complicated and less reliable/appropriate 9 times out of 10.

However, you can implement Named Pipes from kernel-mode with some undocumented magic; the address for NtCreateNamedPipeFile can be extracted from the KeServiceDescriptorTable. NtCreateNamedPipeFile will rely on IoCreateFile - IoCreateFile is an exported kernel-mode routine which you can freely access. Everything else is simple to implement for a named pipe server in kernel-mode, and if you're only after client implementation, it's even simpler because all you'll need to use is simple Native API routines such as ZwCreateFile, ZwWriteFile, ZwReadFile, etc.

I recommend you look into Ports for communication, Microsoft have some samples of their own for it over on GitHub.

2

You probably need three IOCTLs.

  1. IOCTL_READ_FROM_KERNEL. Initially sent after connection, and waits for the first kernel message
  2. IOCTL_RESPOND_AND_READ_FROM_KERNEL. Sends a response, and waits for the next message.
  3. IOCTL_RESPOND. Sends a response.

The user mode code calls an IOCTL. IOCTL_RESPOND returns immediately, and the thread probably exits.

The other 2 IOCTLs will wait till kernel has something to send. This will include some form of ID which can be used to identify the message. When kernel has a message, it can look for waiting UM threads to send to, or alternatively queue up the message for later delivery.

When a UM connects, it pulls off the delivery queue, or gets added to the waiter queue.

mksteve
  • 12,614
  • 3
  • 28
  • 50