can this be optimized (path block in pre/post create) ?

Hi,

I need to protect all files in some local directories from modification as part of a self-protection package of a malware scanner.

I use the normalized name so far. According to this forum this is slow in pre create. So I handle the destructive opens (supersede …) in pre- and the others in post create callback.

Can I get away with using the as_opened name instead of the normalized one ?

I could add a prefix to the name of the protected directories and scan the as_opened string for the prefix. If it is not found then I am not interested in this IO and let it continue. If the prefix is found then I need to look at this request more closely via the normalized name.

Would that be safe ? My gut feeling says “no” but on the other hand I have not been able to come up with an example where it would lead me astray …

Many thanks,
db

You should query normalized name format in pre-create callback only for
possible destructive opens. It will filter out the most open requests. This
query type in pre-create is really expensive (it has to open & examine each
parent’s folder, check & expand SFN, etc). I don’t understand what you check
in post-create callback, because it’s too late (you should create just a
context here for monitoring destructive IRP_MJ_SET_INFORMATION +
IRP_MJ_FILE_SYSTEM_CONTROL calls).

You can also construct file path manually, but with special checks for
FileIDs, SFNs, hardlinks, etc.

Petr

Hello Petr,

thanks a lot for your input.

At pre create I check for destructive opens. If it is not destructive then I defer it to the post create callback and cancel it there if I don’t not like it. (Currently I do not care if this leaves a few empty files that should not have been there. It is important to protect existing files from modification.)

That helps reducing the name queries that I have to in pre create.

However I have noticed that sometimes the name query for the normalized name fails in post-create with “access denied” or other error codes.
What is the best way to deal with those ?

Currently I allow opens with request “File_Read, Sync, Read_Control, Execute” and enforce sharing FILE_SHARE_READ and FILE_SHARE_WRITE if someone other than my app is opening the file. For everything else I fail the open with “access denied”.
Do I still have to look at the IRP_MJ_SET_INFORMATION or the IRP_MJ_FILE_SYSTEM_CONTROL irps ? I was hoping that this would automatically lead to access_denied for any such requests.

Many thanks,
db

>> If it is not destructive then I defer it…

you meant “if it is destructive”, right? Otherwise it doesn’t make sense.
You should check and block FS requests only in pre-create handler, because
it’s too late for post-create. As I wrote, use file normalized query only
for destructive opens (you can count how many requests it is in your OS), I
do that the same way (I use own query method only if “Asus Data Manager
Security” driver is loaded, because when it was loaded, it wasn’t able to
process those Flt- calls and system crashed).

> Currently I do not care if this leaves a few empty files

what if I try to create exact same file in your protected folder… would it
be truncated to zero? :wink:

> query for the normalized name fails in post-create with “access denied”
or other error codes

I didn’t observe this behavior – and I’d notice that because I have ASSERT
statement after this call…

> Currently I allow opens with request “File_Read, Sync, Read_Control,
Execute” and
> enforce sharing FILE_SHARE_READ and FILE_SHARE_WRITE if someone other
than my app
> is opening the file. For everything else I fail the open with “access
denied”.

How about FILE_READ_ATTRIBUTES/FILE_READ_EA, etc?
Well, it’s always better to reverse it: I mean block only flags you KNOW and
you don’t want to process (imagine some filters pass unknown/special flags
from user-mode: you would block such requests, because you don’t understand
what it means… and it’s not correct). Instead, you should block only
DELETE | WRITE_* | … flags. I would also ignore any SHARE access checks.

> Do I still have to look at the IRP_MJ_SET_INFORMATION or the
IRP_MJ_FILE_SYSTEM_CONTROL irps ?
> I was hoping that this would automatically lead to access_denied for any
such requests.

That’s not correct, how about rename operations and FSCTL_SET_REPARSE_POINT
calls?

Petr