What is Windows Kernel Driver written with the WDK?
What is different from normal app or service?
Kernel drivers are programs written against Windows NT's native API (rather than the Win32 Subsystem's API) and which execute in kernel mode on the underlying hardware. This means that a driver needs to be able to deal with switching virtual memory contexts between processes, and needs to be written to be incredibly stable -- because kernel drivers run in kernel mode, if one crashes, it brings down the entire system. Kernel drivers are unsuitable for anything but hardware devices because they require administrative access to install or start, and because they remove the security the kernel normally provides to programs that crash -- namely, that they crash themselves and not the entire system.
Long story short:
Drivers use the native API rather than the Win32 API
This means that drivers generally cannot display any UI.
Drivers need to manage memory and how memory is paged explicitly -- using things like paged pool and nonpaged pool.
Drivers need to deal with process context switching and not depend on which process happens to have the page table while they're running.
Drivers cannot be installed into the kernel by limited users.
Drivers run with privileged rights at the processor level.
A fault in a user-level program results in termination of that program's process. A fault in a driver brings down the system with a Blue Screen of Death.
Drivers need to deal with low level hardware bits like Interrupts and Interrupt Request Levels (IRQLs).
It is code that runs in kernel mode rather than user mode. Kernel mode code has direct access to the internals of the OS, hardware etc.
Invariably you write kernel mode modules to implement device drivers.
A kernel driver is a low-level implementation of an "application".
Because it runs in the kernel context, it has the ability to access the kernel API and memory directly.
For example, a kernel driver should be used to:
Control access to files (password protection,hiding)
Allow accessing non-standard filesystems (like ext, reiserfs, zfs and etc.) and devices
True API hooks
...and for many other reasons
If you'd like to get know more, you can search for keyword "ring0" with your favorite search engine.
Others have explained the difference as the perspective of system level.
If you are doing development in C++, there are below differences in User mode development and kernel-mode development.
Unhandled exceptions crash the process in User mode, but in kernel mode, it crashes the whole system(face BSOD).
When the user-mode process terminates without free private memory, the system implicitly free process memory. But in kernel mode, remaining memory free after system boot.
The user-mode code is written and execute in PASSIVE_LEVEL. In kernel mode, there are more IRQL level.
Kernel code debugging done using separate machines. But you can debug user mode on same machine.
you can't use all C++ functionality in kernel-mode such as Exception handling and STL.
Entry points are different, in user mode, you use the main as the entry point. But in kernel mode, we need to use DriverEntry.
You can't use new operator in kernel mode, you need to overload it explictly.
Related
I am developing an embedded system on a PowerPC processor and there is need for communication with an FPGA via PCIe. I wish to use Linux/embedded-Linux as a bootloader to leverage its PCIe initialization code and driver API for simplified PCIe driver development. However in the end I want to be running bare-metal code (no OS running). So I am looking at using PetitBoot/kexec to jump from Linux to my own code.
Is this possible?
My current understanding of PCIe drivers leads me to believe that once the device is initialized, so long as I have a pointer to the address space, I should be able to simply execute MMIO R/W operations directly to the memory space. So even if kexec overwrites the driver code I should be able to use the device because the driver has done its job already.
Is this correct?
If not, what are my alternatives?
I don't think this approach would be a good idea. Drivers that were written with the Linux OS in mind are going to assume that all of the OS's resources are available, not just memory allocations. For example, it may configure interrupt handlers, but when the OS is not longer available, your hardware may get hung because nothing is acknowledging and servicing its interrupt requests.
I'm skeptical of the memory initialization as well. I suppose you could theoretically allocate some DMA memory and pass the resulting physical address to your bare-metal application as it takes over, but the whole process seems sketchy. It would be very difficult to make sure everything in Linux is shut down cleanly while leaving the PCIe subsystem running. You'll have to look at the driver's shut down routines and see what it does to the card to make sure it doesn't shut down the device and make it unresponsive to your bare-metal code.
I would suggest that you instead go through the Linux-based driver and use it as a guide to construct a new bare-metal driver. Copy the initialization code that you need, and leave out the Linux-specific configuration details.
Never develop any driver before.
Anyway I'm now writing 2 simple windows kernel mode drivers, and the 2 drivers will be installed onto 2 different devices which connect to 2 different buses(ISA bus / PCI bus), and somehow the 2 drivers need to talk to each other and data exchange is also expected, is there any efficient way to achieve that??
Kernel event might be able to enable the synchronization, but how about the data exchange?
In user mode, pipe/socket might be an option, but in kernel mode, is there a counterpart of named pipe or something? Google said that there's no documented API for kernel mode pipe usage...
I'm not quite familiar with windows driver framework, hope I'm making sense..
thanks!
There is IRP_MJ_INTERNAL_DEVICE_CONTROL for communication between kernel-mode components. Driver #1 opens Driver #2 by its name and sends internal IOCTLs with input or/and output data.
#Harry Johnston: You do need to be careful about writing to a shared memory location. I presume you were responding with the context of implementing a serial buffer between the two devices (only one device can write, and the other can only read), but it should obviously be added that you should approach shared memory locations between devices with caution, especially if there is going to be frequent writes to that location by both devices and cause undefined behavior or lock-ups from interrupts being serviced seemingly unexpectedly.
I would like to be able to plug in a physical address, and read the data stored at that address.
Under Linux, I would use /dev/mem to acquire this data. Under Windows 8, I'm not sure what mechanism is available to do this.
My use case is inspecting a PCI Express device. The PCI Express device creates a ring buffer at a known address, that I can determine from the PCIe BAR. Once this address has been set, it won't change until the computer restarts.
Currently, I can use applications like RW Everything to see the data there, but I would like to be able to do this without user interaction (Without the GUI) so that I have fewer issues with the ring buffers wrapping before I can access the data.
Does anyone know if there is a privileged Windows system call I can make from userspace (to mmap a region for example) or do I need to use a custom kernel module to do this? I imagine that there is some way to do it without a custom kernel module, because I don't believe I installed one when I installed RW Everything.
Since Windows Server 2003 SP1, user-mode access to physical memory has not been possible. You will have to develop a driver to do it (or find a third-party tool that includes one).
From Technet:
In Windows Server 2003 SP1, user-mode access to the \Device\PhysicalMemory object is not permitted. All forms of access (read, write) are refused when the \Device\PhysicalMemory object is accessed from a user-mode application. Access to the \Device\PhysicalMemory object is refused regardless of the user context (Administrators, Users, Local System, etc.) the application is running in.
There are many windows software to access the physical memory, however, many of them cannot access the physical memory in windows vista or 7 because of physical memory protection feature in these OS's.
There are many windows tools similar to dev/mem unix's one, such as:
Belkasoft Live RAM Caputer
WindowsSCOPE Pro and Ultimate, available at http://www.windowsscope.com
WindowsSCOPE Live
winen.exe (Guidance Software - included with Encase 6.11 and higher)
Mdd (Memory DD) (ManTech)
MANDIANT Memoryze
Kntdd
Moonsols
HBGary
FTK Imager
OSForensics
WinPmem; and
Windows Memory Reader
Check this wiki for more info:
http://www.forensicswiki.org/wiki/Tools:Memory_Imaging
I was actually under the impression that this was kind of old fashioned, and that modern operating systems (Windows, Linux) were calling the CPU directly.
EDIT:
I read it on the BIOS interrupt call article on wikipedia.
For example, to print a character to the screen using BIOS interrupt 0x10 [...]
No, a modern application does not and cannot use BIOS interrupts (as they must be called from 16-bit mode).
Software interrupts are used for system calls, which let an application pass control to the operating system to do something (e.g. file access) which the application is not allowed to do (like writing to video memory or accessing the hardware).
I'm curious about how, running Windows 7 on x86, you could execute some code in kernel mode. This is for my own personal use; so I'm not bothered about giving Windows a trillion permissions or whatever. Does kernel mode code have to be specially compiled or linked? etc
Only code from the kernel itself, and from certain device drivers, can run in kernel (supervisor, ring 0) mode.
So you will have to write a device driver.
EDIT: the question has already been answered here.
Ring 0 drivers can execute code in kernel mode.
You will need Windows Device Driver Kit for such development.
Also you have to be extremely careful with driver development because unhandled exception occurring in the kernel indicates a serious bug that exists in the operating system or (more likely) in a device driver and not in an application. Once memory in the kernel gets potentially corrupt, it isn't safe for the system to continue running and you see what is typically called "the Blue Screen of Death."
So normally your drivers should be WHQL certified.