IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION for stopping module loading

In the “Kernel Filter API” documentation there is a suggested way of dealing with loading modules under Vista, in order to be able to stop them loading as necessary (this feature is not supported with the standard module loading notification which dones not allow stopping the loading-PsSetLoadImageNotifyRoutine-).

The method consist in building a minifilter and waiting for the callback IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION. If the call comes with the flag PAGE_EXECUTE enabled it would mean that an executable module is being loaded. Then, if we want to stop it, we just return STATUS_ACCESS_DENIED.

My question is: where and when should I specify the STATUS_ACCESS_DENIED ?
Is it in the pre-function or in the post-function? Should I just set the IoStatus to ACCESS_DENIED or shoudl I set also the return value to some value? If it should be done on the post-function should I cancel the I/O with FltCancelFileOpen ?

In the pre function, and then set the callback data IoStatus.Status to
STATUS_ACCESS_DENIED and return FLT_PREOP_COMPLETE from the function.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntfsd…
> In the “Kernel Filter API” documentation there is a suggested way of
> dealing with loading modules under Vista, in order to be able to stop
> them loading as necessary (this feature is not supported with the
> standard module loading notification which dones not allow stopping the
> loading-PsSetLoadImageNotifyRoutine-).
>
> The method consist in building a minifilter and waiting for the callback
> IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION. If the call comes with the
> flag PAGE_EXECUTE enabled it would mean that an executable module is
> being loaded. Then, if we want to stop it, we just return
> STATUS_ACCESS_DENIED.
>
> My question is: where and when should I specify the STATUS_ACCESS_DENIED
> ?
> Is it in the pre-function or in the post-function? Should I just set the
> IoStatus to ACCESS_DENIED or shoudl I set also the return value to some
> value? If it should be done on the post-function should I cancel the I/O
> with FltCancelFileOpen ?
>
>
>
>

Note that there is a serious issue with this approach. Most executable starts result in multiple (and a variable number too) IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks. It is not easily possible therefore to figure out if it’s a new launch of the same binary as opposed to bits and pieces of the previous launch. It’s been a showstopper for us so we’ve stayed with the other means of execution control.

Hope it helps,
Ilya Faenson

I guess I am curious as to a couple of items:

  1. Most people doing this just wish to say for a given process (or all
    processes) do not allow this module to be mapped? With this case there is
    no problem. So I am wondering what requirements you have that go beyond
    this?

  2. You say you have used other means of execution control? Would you
    consider sharing them here?


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntfsd…
> Note that there is a serious issue with this approach. Most executable
> starts result in multiple (and a variable number too)
> IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks. It is not easily
> possible therefore to figure out if it’s a new launch of the same binary
> as opposed to bits and pieces of the previous launch. It’s been a
> showstopper for us so we’ve stayed with the other means of execution
> control.
>
> Hope it helps,
> Ilya Faenson
>
>

> Note that there is a serious issue with this approach. Most executable starts

result in multiple (and a variable number too) >IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks. It is not easily possible
therefore to figure out if it’s a new launch of the same binary as opposed to
bits and pieces of the previous launch.

In my experience, this is just a part of the problem - I tried to register a callback for section synchronization, but it just does not seem to get invoked when you create a new process, at least not under XP. What you have mentioned is another side of the same story. In general, there does not seem to be one-to-one correspondence between callback invocation and ZwCreateSection() call that has to be made when a process gets launched. Furthermore, even if there was the above mentioned one-to-one correspondence, you still would have no chance to discover an ID of the process that tries to launch an executable - your callback is invoked in context of another thread, and no PID/TID of ZwCreateSection() caller is provided to it.

The funniest thing here is that the suggestion about blocking executable section creation comes from MSFT itself. In actuality, there is nothing new about this approach to blocking process creation. I even wrote an article about it - I did it by hooking ZwCreateSection() in SSDT, and in one of our discussions in MSFT newsgroup, Don suggested that the same thing can probably be done “properly” by registering IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callback. I tested Don’s proposal, but, unfortunately, it just does not seem to work (which, I believe, is 100% MSFT’s fault). Therefore, when I see MSFT’s suggestion to do it, my only reaction to the whole thing is a sarcastic smile - after all, they did everything they possibly could to make sure that this approach does not work properly…

Anton Bassov

Ilya,

Actually I don’t mind how many times it gets called. I just stop it when I detect it is being mapped for PAGE_EXECUTION, if the module meets some conditions we check.

Which method are you using then, I mean, specially to stop DLLs ?
Are you using PsSetLoadImageNotifyRoutine perhaps?
Because if you are, you may have even more trouble with it.

Stopping EXEs is *relatively* easy with PsSetCreateProcessNotifyRoutine (although it is not made to stop anything), but stopping DLLs with PsSetLoadImageNotifyRoutine is not as easy without dirty hacks.
And these hacks get even dirtier under Vista. By the way, Microsoft has promised to fix some of the problems, in Vista SP1, but not all of them.

Using other methods, like hooking system functions would not be a suitable method for Vista. Well, if you don’t hack Vista itself!

We switched to IRP_MJ_ACQURE_FOR_SECTION_SYNCHRONIZATION just to get rid of hacks.

Inaki.

-----Mensaje original-----
De: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] En nombre de xxxxx@hotmail.com
Enviado el: lunes, 03 de septiembre de 2007 19:34
Para: Windows File Systems Devs Interest List
Asunto: RE:[ntfsd] IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION for stopping module loading

Note that there is a serious issue with this approach. Most executable starts result in multiple (and a variable number too) IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks. It is not easily possible therefore to figure out if it’s a new launch of the same binary as opposed to bits and pieces of the previous launch. It’s been a showstopper for us so we’ve stayed with the other means of execution control.

Hope it helps,
Ilya Faenson


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@pandasecurity.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Anton,
This metod does work under Vista.
And the PID is the one we might expect.

Under XP we do not use this approach, so I have not tested this technique.

Inaki.

-----Mensaje original-----
De: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] En nombre de xxxxx@hotmail.com
Enviado el: martes, 04 de septiembre de 2007 0:31
Para: Windows File Systems Devs Interest List
Asunto: RE:[ntfsd] IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION for stopping module loading

Note that there is a serious issue with this approach. Most executable starts
result in multiple (and a variable number too) >IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks. It is not easily possible
therefore to figure out if it’s a new launch of the same binary as opposed to
bits and pieces of the previous launch.

In my experience, this is just a part of the problem - I tried to register a callback for section synchronization, but it just does not seem to get invoked when you create a new process, at least not under XP. What you have mentioned is another side of the same story. In general, there does not seem to be one-to-one correspondence between callback invocation and ZwCreateSection() call that has to be made when a process gets launched. Furthermore, even if there was the above mentioned one-to-one correspondence, you still would have no chance to discover an ID of the process that tries to launch an executable - your callback is invoked in context of another thread, and no PID/TID of ZwCreateSection() caller is provided to it.

The funniest thing here is that the suggestion about blocking executable section creation comes from MSFT itself. In actuality, there is nothing new about this approach to blocking process creation. I even wrote an article about it - I did it by hooking ZwCreateSection() in SSDT, and in one of our discussions in MSFT newsgroup, Don suggested that the same thing can probably be done “properly” by registering IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callback. I tested Don’s proposal, but, unfortunately, it just does not seem to work (which, I believe, is 100% MSFT’s fault). Therefore, when I see MSFT’s suggestion to do it, my only reaction to the whole thing is a sarcastic smile - after all, they did everything they possibly could to make sure that this approach does not work properly…

Anton Bassov


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@pandasecurity.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

What Don has suggested does “work” on both XP and Vista in a sense that it would block the binary start so I’m not sure what exactly does not work in this respect for Anton. However, Anton is correct: there is no one-to-one relationship between the Filter Manager IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks and NtCreateSection() calls. There are generally fewer NtCreateSection() calls with the right attributes than callbacks. Most importantly, NtCreateSection() does provide a lot more info…

Answering Don’s questions, it’s a fairly complicated logic with the PsSetCreateProcessNotifyRoutine() callbacks and lots of user mode code involved. Multiple IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks all happening before the relevant process start callback could have worked for us but unluckily they do get triggered both before and after. Therefore, we’re staying for now with the true and tried approach we’ve been using for years…

Ilya Faenson

> What Don has suggested does “work” on both XP and Vista in a sense that it would

block the binary start so I’m not sure what exactly does not work in this
respect for Anton. However, Anton is correct: there is no one-to-one
relationship between the Filter Manager
IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks and NtCreateSection() calls.
There are generally fewer NtCreateSection() calls with the right
attributes than callbacks. Most importantly, NtCreateSection() does provide a
lot more info…

The problem is that normally you have to decide whether you want to allow or disallow
process creation. Hence, you need some extra info in order to make a judgement - you need to know whether a given user is allowed to launch a given executable. Therefore,
in *practical* terms, lack of either one-to-one correspondence between IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callbacks and NtCreateSection() calls
or of information about the caller of NtCreateSection() makes the whole thing simply unusable…

Anton Bassov

wrote in message news:xxxxx@ntfsd…

> The funniest thing here is that the suggestion about blocking executable
> section creation comes from MSFT itself. In actuality, there is nothing
> new about this approach to blocking process creation. I…Therefore, when
> I see MSFT’s suggestion to do it, my only reaction to the whole thing is a
> sarcastic smile - after all, they did everything they possibly could to
> make sure that this approach does not work properly…
>
>

Actually this whole kernel filtering API document uses some very wishful and
distorted reasoning. For instance in the section about memory write access
control it says: "By filtering the DesiredAccess granted during the
upstream OpenProcess() operation, effective controls can be made on a wide
class of downstream functions, such as CreateRemoteThread(),
WriteProcessMemory(), and TerminateProcess(). " In the real world, programs
open their processes with PROCESS_ALL_ACCESS for their convenience, so
according to me this method is going to produce over 99% of false positives.

This whole document is full of unrealistic crappy APIs that nobody can use
and will only work in a very limited setting on very specific operating
systems.

/Daniel