We need to handle IRQ in KMDF driver
I've registered EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY callback function but system does not call it.
EVT_WDF_DEVICE_PREPARE_HARDWARE is called without any resources allocated.
Attempt to call WdfInterruptCreate() here results STATUS_INVALID_DEVICE_STATE
What is the right way to get free IRQ number from system and attach an interrupt handler?
Upd:
After we have successfully created WDFINTERRUPT object in our AddDevice handler system still does not ask us about resources (EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY)
After discussion on social.msdn.microsoft.com we've found only one solution: use another OS
Related
I'm working on a way to hook any API call to perform some verification on the function. (I'm creating a SandBox)
The first way that I think about, is with register key, and implement our own dll into MicrosoftNT to be able to redirect any defined syscall. https://www.apriorit.com/dev-blog/160-apihooks .
Problem? only work on 32 bit, and if the binarie is loading User32.dll, so it's abig issue.
The second way is to inject a dll into a process? Simple but impossible, most program is defended from those injection, so it's not possible.
The last way that I think was to modify the SSDT to change the function address by mine and redirect to the original by creating a driver. Or by InlineHook and just modify the first byte of each address that I want.
The Problem, only working on 32 bit, because windows add a PatchGuard on the Kernel, so we can't do that.
We can delete de PatchGuard but, anticheat will notice the technique.
For the Sandbox I think it won't be a problem to delete a PatchGuard.
The main problem is for real time analysis, I have no more idea how I can do to hook every API call that I want, on any windows OS. I mean on 32 and 62 bit.
I'm a beginner in this domain I started this week so I'm open to any suggestion.
You say you want to hook every API call for a sandbox but then reference the SSDT? Those are two very different things. Do you want to hook VirtualQuery(Ex) or do you want to hook NtQueryVirtualMemory? From kernel or user mode? Or maybe you're referring to all loaded module exports as well as kernel system services?
WinApi
Iterate all loaded modules as well as installing an event to hook all future modules loaded. For each one you will iterate all exports and apply a hook of your preference which all jump to some handler. This handler should be raw assembly that preserves the CPU state, calls some method that does the logging and filtering, restores CPU state, before finally jumping to the original.
Syscalls
Disable Patchguard and apply hooks to every method in the service table similar to the WinApi method described above. This is definitely not suitable for production for obvious reasons.
Use an instrumentation callback which uses ZwSetInformationProcess to redirect most syscalls to an arbitrary assembly block. You can extract the syscall id here as well as parameters. Universal support is an issue though as it wasn't introduced until W7 iirc and you have a lot of limitations prior to W10.
Map a wrapper module that has a hook for every syscall into each newly loaded process from kernel. These hooks will apply to ntdll and simply invoke an NtDeviceIoControlFile call with the syscall id and arguments, forwarding it to your kernel driver for processing. This is commonly employed by antivirus software to monitor user mode system calls without disrupting Patchguard.
The most approved method would probably be callbacks. You can register process and thread callbacks in kernel, stripping handle access at your leisure. This will give you full control over process and thread access from external processes, and you can add a file minfilter to similarly restrict access to the file system.
I have question about device removal.
When we want to notify PnP manager that device has disappeared we call IoInvalidateDeviceRelations with BusRelations. After that OS will send IRP_MN_QUERY_DEVICE_RELATIONS request with BusRelations. In this request handler we will exclude device from array and will do another necessary job to "disconnect" it from bus, also we will set RemovePending flag in its device extension.
I don't understand how to deal with incoming IO requests to the device after it becomes "remove pending" and before OS sends IRP_MN_REMOVE_DEVICE request. Should we check RemovePending flag and return STATUS_DEVICE_DOES_NOT_EXIST or should we proceed as usual?
Now imagine that IRP_MN_REMOVE_DEVICE request has finally arrived. MSDN says that we must call IoReleaseRemoveLockAndWait that releases the current acquisition of remove lock, prevents subsequent acquisitions and waits while existing acquisitions are released. So it forces us to always acquire remove lock inside PnP request handler with IoAcquireRemoveLock; and release it with IoReleaseRemoveLockAndWait for IRP_MN_REMOVE_DEVICE or with IoReleaseRemoveLock for another minor codes.
I don't understand why we need to acquire remove lock inside PnP request handler? In my understanding we need to acquire remove lock only for pending irp and release it when such irp is completed. So Windows folks could provide us with IoWaitForExistingRemoveLocks routine instead of IoReleaseRemoveLockAndWait.
Sorry if it's kinda messy, I just can't figure it out. Thanks.
After that OS will send IRP_MN_QUERY_DEVICE_RELATIONS request with
BusRelations. In this request handler we will exclude device from
array and will do another necessary job to "disconnect" it from bus,
also we will set RemovePending flag in its device extension.
here need only exclude device from array and set RemovePending flag in its device extension. but do another necessary job to "disconnect" it from bus - need do only when you process IRP_MN_REMOVE_DEVICE (after device was not included in the bus driver's most recent response to an IRP_MN_QUERY_DEVICE_RELATIONS request for BusRelations - or in another words - when RemovePending flag in its device extension)
how to deal with incoming IO requests to the device after it becomes
"remove pending" and before OS sends IRP_MN_REMOVE_DEVICE request.
Should we check RemovePending flag and return
STATUS_DEVICE_DOES_NOT_EXIST or should we proceed as usual?
i think possible both behavior - you can process it as usual and can return STATUS_DEVICE_DOES_NOT_EXIST too. and assume next situation - you get some IO request in concurrent with removal device process. when you check RemovePending flag - it yet not set. and you begin process request "as usual". but just after you check RemovePending flag inside IO request you can set it while handling IRP_MN_QUERY_DEVICE_RELATIONS request with BusRelations. and this situation direct related to sense using Remove Locks or Run-Down Protection.
we really can use Run-Down Protection instead Remove Locks almost in same way and exactly in same places and for same reason as Remove Locks. and i think Run-Down Protection api (more new compare remove locks) - better design and better for use (however different is minimal)
I don't understand why we need to acquire remove lock inside PnP
request handler?
first of all note that about remove lock said only in Removing a Device in a Function Driver. you how i understand have not function, but bus driver- so Removing a Device in a Bus Driver more suitable for you. and in documentation for Removing a Device in a Function Driver exist serious error - advice first call IoReleaseRemoveLockAndWait at point 4 - before point 8 - Pass the IRP_MN_REMOVE_DEVICE request down to the next driver. but correct must be
driver should call IoReleaseRemoveLockAndWait after it passes
the IRP_MN_REMOVE_DEVICE request to the next-lower driver, and
before it releases memory, calls IoDetachDevice, or calls
IoDeleteDevice.
this is correct and stated in Using Remove Locks and IoReleaseRemoveLockAndWait. funny that in old msdn versions was
call IoReleaseRemoveLockAndWait before it passes..
but now this is fixed. why after ? because next-lower driver can pending some IRPs (on which we call IoAcquireRemoveLock or ExAcquireRundownProtection) and complete it only when got IRP_MN_REMOVE_DEVICE and our driver call IoReleaseRemoveLock or ExReleaseRundownProtection only when this IRP will be completed. as result if call IoReleaseRemoveLockAndWait or ExWaitForRundownProtectionRelease before passes the remove IRP to the next-lower driver - we can wait here forever - next-lower driver can not complete some IRP (until not got remove request) and we not release remove lock or rundown protection.
so for what we need remove locks or rundown protection ? because we can got IRP_MN_REMOVE_DEVICE in concurrent with another IO requests. and this IO requests can use some resources on device. from another sized when we process IRP_MN_REMOVE_DEVICE we destroy this resources. what be if we will use some resource in IO request after he will be destroyed in IRP_MN_REMOVE_DEVICE ? think not need answer. for prevent this and exist removal locks or rundown protection. before use any resource (which will be destroyed in remove) need call IoAcquireRemoveLock or ExAcquireRundownProtection and use it only if ok status returned. after we finish use resource call IoReleaseRemoveLock or ExReleaseRundownProtection. and in IRP_MN_REMOVE_DEVICE we call IoReleaseRemoveLockAndWait or ExWaitForRundownProtectionRelease. after this call is returned - we can be sure that nobody use our resources and never will be used more (calls to IoAcquireRemoveLock or ExAcquireRundownProtection return error status (false)). at this point we can safe begin destroy resources: releases memory (etc), calls IoDetachDevice, IoDeleteDevice.
the pointer to the next-lower device - this is also resource, which we use in process IO request and destroy in IRP_MN_REMOVE_DEVICE (by call IoDetachDevice). really are correct call IofCallDriver(_nextDeviceObject, Irp); (while process some IO request) after call IoDetachDevice(_nextDeviceObject); (inside IRP_MN_REMOVE_DEVICE) ? because this removal locks (or i use yourself rundown-protection here ) always used in functions and filter drivers. for bus driver, where we usually have not pointer to the next-lower device (PDO not attached to another device, when FDO attached to PDO and filter always attached to something) - may be not need locks (or rundown protection at all). this is depend - are exist another resources - used and destroyed (on removal).
and for bus devices - usual situation when we got IRP_MN_REMOVE_DEVICE 2 time - first before device marked as RemovePending - so we go to point 4. and after device marked as RemovePending (so device was not included in the bus driver's most recent response to an IRP_MN_QUERY_DEVICE_RELATIONS request for BusRelations) we finally destroy resources and call IoDeleteDevice
My problem is:
Interrupt handler get triggered when free_irq is called. I noticed in kernel messages that handler is invoked but since our device hasn't requested interrupt it prompted that no interrupt has received.
Is it expected behavior ? Can anybody please help ?
When you are registering a handler for a (possibly) shared interrupt (with IRQF_SHARED), the interrupt can be triggered by other devices over which your driver has no control, so your driver must be prepared to receive an interrupt at any time.
To help with debugging drivers, the kernel will (when CONFIG_DEBUG_SHIRQ is set) fake some interrupts to check that your driver works correctly.
[source code]
If I understood your post right - you must turn off issuing interrupts in your hardware before you call free_irq() then you won't receive interrupts while free_irq().
It's simple and straightforward in user mode because of those APIs.
How do you read/write specified process's userspace memory from a windows kernel module?
driver target platform is windows xp/2003
Use NtWriteVirtualMemory / NtReadVirtualMemory to write to other processes - you will need to open a handle to the process first.
Note that if you're already in the process, you can just write directly - for example if you're responding to a DeviceIoControl request from a process you can write directly to user-mode addresses and they will be in the address space of the process that called you.
I'm also starting in the world of windows drivers and from what I've read XxxProcessMemory calls NtXxxVirtualMemory in ntdll (R3-UserMode).
The NtXxxVirtualMemory calls the ZwXxxVirtualMemory (R0-KernelMode) also in the ntdll.
I believe you should use the ZwXxxVirtualMemory.
In the krnel, ZwXxx routines are just wrappers around NtXxx ones, telling the kernel that the caller is a kernel mode component, rather than an user application. When a call comes from usermode, the kernel performs additional security checks.
So, use ZwXxx when in the kernel.
An alternative approach for reading/writing memory from/to another process is:
obtain address of its process object (PsLookupProcessByProcessId),
switch the current thread to its address space (KeStackAttachProcess),
perform the operation (read/write...),
switch the address space back (KeUnstackDetachProcess),
decrement reference count incremented by (1) (ObDereferenceObject).
I'd like to call my app from my driver when an interesting event happens in the Windows kernel. I need to be able to pass at least 4 bytes of data back to user mode. How to achieve this? These events might happen quite, but not too, often, so I don't want to build a queue system and use IOCTLs.
I was thinking of something like the driver gets loaded, the user mode app registers its callback using IOCTL and kernel keeps calling that callback when events happen and finally the user mode client unregisters the callback and no more data is send to user mode. Is this possible?
I'm new to kernel programming, so after a day of googling I decided to ask here. I've noticed that there isn't much discussion about the kernel and drivers. And even less proper docs.