PatchGuard and DRIVER_OBJECT MajorFunction Table

Will PatchGuard check the MajorFunction table (DRIVER_OBJECT) for modifications?

I want to hook one functions on one PDO for the purpose of now allowing certain operation going to that device. Doing a filter won’t work since some apps talk directly to the PDO so I have to hook this PDO. Will PatchGuard BSOD the machine as a result of MajorTable change?

Thanks!

What do you mean apps talk directly to the PDO? Apps talk to a stack of
device objects, which your filter can one of.


Don Burn (MVP, Windows DDK)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
> Will PatchGuard check the MajorFunction table (DRIVER_OBJECT) for
> modifications?
>
> I want to hook one functions on one PDO for the purpose of now allowing
> certain operation going to that device. Doing a filter won’t work since
> some apps talk directly to the PDO so I have to hook this PDO. Will
> PatchGuard BSOD the machine as a result of MajorTable change?
>
> Thanks!
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4197 (20090629)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4197 (20090629)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

> What do you mean apps talk directly to the PDO? Apps talk to a stack of

device objects, which your filter can one of.

They load their own driver which opens the PDO and sends IRPs to the PDO. Anyway, that’s beside the point. My question is: Will PatchGuard do any kind of checking on the MajorFunction table within a DEVICE_OBJECT instance?

As of right now, no. (I will not spend time typing on how bad of an idea this is).

I know, and I agree with you! :slight_smile: But what am I supposed to do? Maybe we should start explaining this to Microsoft instead of ourselves, after all this is as a result of bad design. Because the kernel allows applications (drivers installed by apps) to send IRPs directly to PDOs, I have no choice but to filter at that point. I will certainly not create a bus filer for all the different drivers that this PDO can exist on.
Thanks!

Several widely used legitimate products overwrite dispatch entry points of
other driver objects in the system so I don’t think this is detected by PG
for any driver in any way. This is not a beautiful thing to do and there are
several ways how this can go wrong in particular if two or more products are
trying to do the same thing.

//Daniel

wrote in message news:xxxxx@ntfsd…
> Will PatchGuard check the MajorFunction table (DRIVER_OBJECT) for
> modifications?
>
> I want to hook one functions on one PDO for the purpose of now allowing
> certain operation going to that device. Doing a filter won’t work since
> some apps talk directly to the PDO so I have to hook this PDO. Will
> PatchGuard BSOD the machine as a result of MajorTable change?
>
> Thanks!
>

> Maybe we should start explaining this to Microsoft instead of ourselves, after all this is as a

result of bad design. Because the kernel allows applications (drivers installed by apps)
to send IRPs directly to PDOs

They will tell you that one is not supposed to send IRPs directly to PDO, and that’s it -they will tell you that if someone does it it means that it “violates a contract”. I had a discussion with Doron about it few months ago, so that I am just repeating his arguments. They’ve got quite interesting approach that can be described approximately like “you are not supposed to get this pointer directly but if you wish to get it I will happily provide you with the one - it is all your fault anyway”.

Furthermore, they may throw in a specious argument that once you are in the kernel mode there is no way to protect the system against you. Sorry, but this kind of argument is irrelevant to the situation that we discuss here. After all, this “violation of a contract” is done in a way that is 100% legal, and their API is doing everything possible to make this “violation of a contract” work smoothly (unlike some other “violations” that they fight against with strategies like PatchGuard)…

Anton Bassov

>>Several widely used legitimate products overwrite dispatch entry points of other driver objects in the system so I don’t think this is detected by PG for any driver in any way. This is not a beautiful thing to do and there are several ways how this can go wrong in particular …

True in all aspects. I found many AV drivers hooking filesystem’s dispatch entry points with SSDT,
Many firewall drivers hooking ndis, tdi, tcp, and
many anti rootkit solution hooking ssdt and few dispatch functions of certain drivers.

>They load their own driver which opens the PDO and sends IRPs to the PDO. Anyway, that’s beside the point. My question is: Will PatchGuard do any kind of checking on the MajorFunction table within a DEVICE_OBJECT instance?

I read about this few weeks back and some where found that, it will check for SSDT, GDT/IDT and *System Images*.

System Images currently means that (as per the doc I read), ntoskrnl, HAL and NDIS, but I do not know what exactly is this system images list now. So if your driver is not in this list than you are good else …

Do you really think your software need to worry about this? What type of control you are seeking?

Thanks
Aditya

It is not possible to stop drivers from hijacking the dispatch table of
another driver. Both run a ring zero, so nothing can stop it though careful
checking could detect that they were pointing outside the image of the
driver being examined. However, that will fail for all miniports since
KMDF, NDIS, StorPort, SCSI Port, etc. all grab the entry points of their
miniports to get first crack at the call.

wrote in message news:xxxxx@ntfsd…
>>>Several widely used legitimate products overwrite dispatch entry points
>>>of other driver objects in the system so I don’t think this is detected
>>>by PG for any driver in any way. This is not a beautiful thing to do and
>>>there are several ways how this can go wrong in particular …
>
> True in all aspects. I found many AV drivers hooking filesystem’s dispatch
> entry points with SSDT,
> Many firewall drivers hooking ndis, tdi, tcp, and
> many anti rootkit solution hooking ssdt and few dispatch functions of
> certain drivers.
>
>>>They load their own driver which opens the PDO and sends IRPs to the PDO.
>>>Anyway, that’s beside the point. My question is: Will PatchGuard do any
>>>kind of checking on the MajorFunction table within a DEVICE_OBJECT
>>>instance?
>
> I read about this few weeks back and some where found that, it will check
> for SSDT, GDT/IDT and System Images.
>
> System Images currently means that (as per the doc I read), ntoskrnl, HAL
> and NDIS, but I do not know what exactly is this system images list now.
> So if your driver is not in this list than you are good else …
>
> Do you really think your software need to worry about this? What type of
> control you are seeking?
>
> Thanks
> Aditya
>

> after all, this “violation of a contract” is done in a way that is 100% legal, and their

API is doing everything possible to make this “violation of a contract” work
smoothly (unlike some other “violations” that they fight against with strategies
like PatchGuard)…

hehe I know :slight_smile: they are still in denial. They should just toughen up, take responsibility, and support it instead of poisoning us with political talk, BS and propaganda.
Thanks Anton, Daniel, Matt and Aditya!

Interesting thread.

Firstly, I’m one of the “they” who are in denial, and probably would say something similar to Doron.

Secondly, I’m one of the “they” in the filesystems group. I can’t speak for who would want to do this to arbitrary drivers; there may be a good reason/need to do this somewhere. I’m really struggling with the idea that there is a good reason/need to do so in the filesystem space.

As Don pointed out, the correct calling model is through the entire stack. It’s true that a caller could grovel to the bottom of the stack and call it; doing so will obviously bypass all filters, and may leave the caller very broken as a result. How broken depends on the filters that it is bypassing. It does not seem logical to me that a filter would change a driver dispatch table in order to allow another driver like this to function. Doing so is likely to break more than it fixes. This smacks of “two wrongs don’t make a right” applied to development.

In the past few months, late in the Windows 7 cycle, I have been tasked with investigating various crashes caused by third party drivers. I noticed that a surprisingly large number of dispatch tables were being manipulated, and perhaps coincidentally, I was looking at a lot of crashes generated by this practice. The crashes I saw were really the tip of the iceberg. These drivers were going to generate many other problems as well, just problems far more latent (like tampering with filesystem synchronization and getting it wrong.) So I thought to myself, “In Windows 8, the filesystem should bugcheck if it discovers a tampered dispatch table”, which brings us back to where this thread started.

What I’m missing from reading this thread is why it is necessary to patch a dispatch table, at least in the filesystem context. If there was a compelling reason for this practice, then perhaps I would take Vance’s lead in advocating supporting it. However, after reading the thread, I’m still not seeing the compelling reason. I’m still left leaning towards Vance’s other lead of “toughen up” and bugcheck.

Can somebody please enlighten me on why patching a filesystem dispatch table is a practice worthy of support?

Thanks,

  • M

Hey Malcolm, here are few comments:

First:

The only reason to support is because there are drivers that bypass the device stack. What it means for me: I can’t provide a solution that works for 100% of the devices out here. The only way to accomplish this is by patching the PDO dispatch table, since eventually the request has to get to the bus driver.

If you bugcheck the machine when you find that someone is violating the rule and not sending stuff down the device stack then OK. This will solve my problem in future releases, and I will be happy, since if a driver exits that violates this principal, there code will crash and also my driver will never be bypassed.

Second:

Anton put it very well:

After all, this “violation of a contract” is done in a way that is 100% legal, and their
API is doing everything possible to make this “violation of a contract” work
smoothly (unlike some other “violations” that they fight against with strategies
like PatchGuard)…

If we are not supposed to modify the dispatch table for other devices but our own, then you should not let us change it and give us complete access to it, otherwise you should support it. I should not have to go and ask if something is ok to do when i am using the publicly documented APIs but you should never do XYZ with them. It is kind of ridiculous. Thats why there are so many exceptions and to get a 100% working solutions it takes a lot, and the APIs open the door wide open for a lot of things.

[I should have posted this under NTDEV]

Okay, I understand that a driver can bypass your filter by calling an underlying filesystem directly. And I’d agree with Doron/Anton, that this is a “violation of a contract.”

In kernel space, there is little to no enforcement for violating a contract, but contracts must be followed to get anywhere. A contract may be as simple as a calling convention, a structure layout, which locks protect which parts of which structures, and ultimately, how to call a requested service. If you violate these contracts, your driver may still run, but the result will be a myriad of bugs.

I’m afraid I cannot prevent drivers bypassing your driver. I’m also afraid that you can’t either. Another driver could have read the old dispatch table and cached its contents, calling behind your driver. Or it could grovel through the target driver’s export table looking for a particular function, and call it directly. Or, it could “know” that it wants to call TargetDriver+0x1000, manually push something onto the stack, and jmp. Your driver and their driver exist in the same security domain. You can try to make a war of escalation, but you can never be sure that you’ve won it. Whether you patch the dispatch table or not, you can be bypassed by code hell-bent on bypassing you.

In terms of the support question, we have a model which enables you to perform this task in the filesystem space (called the filter stack.) Yes, you can be bypassed, just as you could be bypassed by patching a dispatch table. But, when drivers behave themselves, we can load multiple drivers patching the same routines with predictable behavior; synchronize load and unload; attach on a per device rather than per driver basis, etc, etc, etc.

So again, I return to my previous post: I’m looking for a compelling reason. I understand your frustration about being bypassed, but this (IMO) does not amount to a compelling reason, since patching the dispatch table cannot reliably prevent this bypass vector. It only closes the hole for drivers which are “well behaved”, and “well behaved” drivers should be calling through the filter stack. The main result is a myriad of other bugs (most of the ones I debugged involved load/unload being completely unsychronized, and what happens to in-flight requests at this time.) These are solved by using the filter stack.

>>First: The only reason to support is because there are drivers that bypass the device stack.

So what exactly will happen if they do so? It will be easier to visualize your point if you provide some details about the type of your driver.

let me take one hypothetical scenario where I think your driver is a FS filter driver and doing encryption or compression. Now if some one connect directly to the PDO or FDO your driver will not intercept the call and hence the caller will get encrypted/compressed data. But I am not able to see any problem here, the fault is not at your side. It is true for even MS filesystem which supports these features, one can go directly and below them and collect data from sector. They can not stop it, neither they care for.

your driver’s objective may help in decision.

Thanks
Aditya

All right, Thanks

Aditya, think security, and preventing malicious activity