What are MSI interrupt domains an why are they needed? - linux-kernel

In latest kernel I see MSI interrupt domain. These API's are being implemented for supporting MSI interrupts and an irq hierarchy manner.
struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
struct msi_domain_info *info,
struct irq_domain *parent)
Here in the last parent parameter we are sending parent domain, created using irq_domain_add_linear.
I would like to know why do we need two domains to handle MSI?

Related

Serializing the driver's init call order, which were registered at the same init level

I have come across a scenario where two drivers (driver1 and driver2) are registering with kernel using module_init(). driver1 is configuring the chip and driver2 is accessing that chip, so driver1's module_init() has to be called before driver2's module_init() call. How we can create this order, as both driver1 and driver2 are registering at the same init call level (i.e using module_init()).
Can driver2 somehow determine that the chip has been properly configured, using either device status (preferred) or the value of a shared variable (messy)?
If so, then driver2's probe routine should return with -EPROBE_DEFER when the chip has not yet been configured (by driver1).
See https://lwn.net/Articles/485194/
drivercore: Add driver probe deferral mechanism
Allow drivers to report at probe time that they cannot get all the resources
required by the device, and should be retried at a later time.
This should completely solve the problem of getting devices
initialized in the right order. Right now this is mostly handled by
mucking about with initcall ordering which is a complete hack, and
doesn't even remotely handle the case where device drivers are in
modules. This approach completely sidesteps the issues by allowing
driver registration to occur in any order, and any driver can request
to be retried after a few more other drivers get probed.

How to hook any API call on windows x64, x86?

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.

Detect the Application which requests "services.exe" to start a service in Windows

As a part of my project, I get an event notification every time a Service is Started or Stopped using the WMI class Win32_Service through an EventSink.
I want to detect the application which had requested "services.exe" to start a particular service.
Till now, I tried Monitoring ALPC calls between any process and "services.exe" and got a Message_ID every time a process communicates (sends/receives) any information to/from "services.exe" using the ALPC Class. I would like to know what these messages are so that I can decode a StartService() or a StopService() procedure.
Is there any way to detect which application starts/stops a service?
The best way to do this, in my opinion, would be from kernel-mode using the PsSetCreateProcessNotifyRoutine/Ex/Ex2 kernel-mode callback.
If you're going to be using PsSetCreateProcessNotifyRoutine, you will receive less information than if you were using the Extended version of the kernel-mode callback (the Ex one). However, you can still query information such as the image file path of the parent process (or the one being created) by using PsLookupProcessByProcessId to get a pointer to the _EPROCESS structure and then relying on SeLocateProcessImageName (undocumented, however it is accessible in WDK by default).
The SeLocateProcessImageName routine will rely internally on that _EPROCESS structure, since information like the path of the process image on-disk is all tracked by the Windows kernel there.
If you're going to be using the Ex version of the kernel-mode callback, then you eliminate the need to do what is mentioned above. The Ex version of the routine is more recent than the non-Ex version.
The routine prototype for the callback routine will be:
VOID
CreateProcessNotifyRoutineEx(
PEPROCESS Process,
HANDLE ProcessId,
PPS_CREATE_NOTIFY_INFO CreateInfo
)
As seen above, you get a pointer to the _PS_CREATE_NOTIFY_INFO structure. You can then access the ImageFileName and CommandLine fields to filter for services.exe (make sure you filter properly to not catch it for a rogue copy - so ensure full path indicates its the real one) and gain more insight into why it was being invoked (if such information is exposed via the command-line... I cannot remember - nonetheless, you can still detect its creation and be aware of who spawned it).
To determine the parent who was responsible for the process creation operation of services.exe (e.g. if it relied on the Service Manager which in turn resulted in the spawning of it), you can rely on the ParentProcessId field (under the _PS_CREATE_NOTIFY_INFO structure as well). The SeLocateProcessImageName trick will work perfectly here.
SeLocateProcessImageName is undocumented so here is the routine prototype:
NTSTATUS
NTAPI
SeLocateProcessImageName(
PEPROCESS Process,
PUNICODE_STRING *ImageName
);
At-least with the latest Windows 10 WDK, it's already available by default. If you wanted to though, you can use a dynamic import with MmGetSystemRoutineAddress.
Resources:
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutine
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex2
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-mmgetsystemroutineaddress
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-pslookupprocessbyprocessid
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_ps_create_notify_info

Why does calling ZwCreateKey in kernel mode seem to circumvent windows security?

The team I work with has recently been faced with the challenge of making our software compatible with a third party peice of virtualization software. This software uses a kernel driver to perform hooking of the Windows native registry API (ZwCreateKey, etc). It works by hooking the calls in Ntdll. Our software is also fairly low level and in some contexts requires access to the real registry without being hooked.
We're exploring the possibility of using our own kernel driver to call ZwCreateKey, etc, on our behalf circumventing their hooking. This essentially has meant creating an NT Legacy driver and a user mode library which provides our own native registry functions. The library and driver are very simple, we simply use an IOCTL to pass all the parameters for ZwCreateKey, etc into our driver then we call the kernel version of the call and return the results.
The approach has worked well, and we appear to now have a system of reading/writing to the real registry when virtualized. The only problem is that our new system appears to circument Windows security on registry objects.
ZwCreateKey takes an access mask like so:
NTSTATUS ZwCreateKey(
__out PHANDLE KeyHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__reserved ULONG TitleIndex,
__in_opt PUNICODE_STRING Class,
__in ULONG CreateOptions,
__out_opt PULONG Disposition
);
My understanding was that although we were now running in kernel mode, we still had the context of the user's token. This should mean that the kernel version of ZwCreateKey will fail just as the user one would have if the access mask test fails. What's actually happening is that even with a limited token, when our driver is called, it's able to create keys in restricted parts HKLM when invoked by a limited user. What gives? Should we be performing the ACL checks ourselves? Do we need to do something to limit our own privileges in kernel mode? Any help much appreciated.
Check this for explanation. Basically Nt/Zw in User-mode (ntdll) are the same thing - they first perform extensive checks before actually performing the action. Where as when calling Zw functions from kernel-mode ( as is the case with a device driver) those checks are ommitted because it is assumed information coming from kernel-mode component (e.g. a driver) is to be trusted by default

In Linux 2.6 device driver model, what's the entry point of the creation of struct device?

If a USB device driver is loaded, and at some time the device plugs in, then which part of the kernel will create struct device and register it?
When the driver is loaded, the system calls the function, which you assigned in module_init. You will want to call there usb_register(struct usb_driver skel_driver), where skel_driver is a struct with pointers to methods servicing the device, like the probe method.
The probe method is the one which is called, when a new usb device is introduced in to the system. In this place you can fill your struct (usb_skel) with what you will need in the future, initiate a char device or whatever you do, when the device is introduced.
The system mostly won't create anything by itself, it has to have most of the structs prepared and filled with device specific data.
Please see usb-skeleton in lxr for reference and learn to use it, besides read writing usb drivers from LDD.
Cheers

Resources