Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


intercept call CreateFile with CREATE_ALWAYS in minifilter

negbit73negbit73 Member Posts: 5
edited September 9 in NTFSD

the scenario: i have a file name "123.txt" with data in it, some usermode process call CreateFile with CREATE_ALWAYS flag will erase my file's data, and i wan intercept that in minifilter.
my code using is:
`FLT_PREOP_CALLBACK_STATUS
FsFilter2PreOperation (
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
Flt_CompletionContext_Outptr PVOID *CompletionContext
)
{
// pre operation
UNREFERENCED_PARAMETER(CompletionContext);
bool block = false;
FLT_PREOP_CALLBACK_STATUS retStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
auto param = &Data->Iopb->Parameters.Create;
ULONG CreateDispotition = ULONG((param->Options >> 24) & 0xff);

if (Data->RequestorMode == UserMode && FltObjects->FileObject)
{
    if (FltObjects->FileObject->FileName.Length > 6 && FltObjects->FileObject->FileName.Buffer)
    {
        if (wcsstr(FltObjects->FileObject->FileName.Buffer, L"Desktop\\123.txt"))
        {
            if (FlagOn(CreateDispotition, FILE_OVERWRITE_IF))
            {
                KdPrint(("123.txt CREATE_ALWAYS detected\n"));
                block = true;
            }
            else if (FlagOn(CreateDispotition, FILE_CREATE))
            {
                KdPrint(("123.txt CREATE_NEW detected\n"));
                block = true;
            }
            else
            {
                KdPrint(("123.txt undetected\n"));
            }
        }
    }
}

if (block)
{
    Data->IoStatus.Status = STATUS_ACCESS_DENIED;
    retStatus = FLT_PREOP_COMPLETE;
}

return retStatus;

}
~~~~`
check CreateDispotition flags was reference from: http://www.osronline.com/article.cfm^earticle=302.htm
but thats not run correctly:
-STATUS_ACCESS_DENIED don't work, usermode app still can open my file and the file is empty after.
-FILE_OVERWRITE_IF triggered many times, even call CloseHandle.
do you have any idea to check call CreateFile(...CREATE_ALWAYS...) exactly? and can totally block that action? pls share if you got something.
thank you!

P/S my user app code to test:

HANDLE hFile = CreateFile(file_name, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);

Comments

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,343

    Run Process Monitor in Advanced mode (Filter->Enable Advanced Output) and set a filter to only see requests from your process. You'll be able to easily see which requests are arriving and the native create flags.

    Also, your name processing is very broken. You can't assume that the name buffer is null terminated or even a valid string (see open by id). You need to use FltGetFileNameInformation to get the name for the request and use Rtl functions to match the UNICODE_STRING (e.g. FsRtlIsNameInExpression, RtlPrefixUnicodeString, etc.). I recommend spending time analyzing Process Monitor output and playing with the Minispy example to get a better foundation.

    -scott
    OSR

  • negbit73negbit73 Member Posts: 5

    thanks @Scott_Noone_(OSR) for procmon trick. the output line make me notice is:
    _
    Console1.exe 2956 IRP_MJ_CREATE C:\Users\asd\Desktop\123.txt SUCCESS Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, AllocationSize: 0, OpenResult: Overwritten
    _
    that mean i catch the right flag, but then i can't block that operation, even with STATUS_ACCESS_DENIED.
    still dont know why...

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335

    if (wcsstr(FltObjects->FileObject->FileName.Buffer, L"Desktop\\123.txt"))
    this will never match. Even if you correctly use FltGetFileNameInformation, you would not match that string.
    It's too simple, but too long to explain in details - it would be much better if you checked what the filename is like from your process.

    The open by ID is not the only case where the above won't work. Relative opens will not work either, and you must not rely on the FileName of a related file object to be accessible even, and definitely do not rely on it being correct!
    (the not being accessible part may seem strange, but it can happen)

  • negbit73negbit73 Member Posts: 5
    edited September 9

    thanks all. i found the solution, 1 line code is bad: "Data->RequestorMode == UserMode". some operation would run in KernelMode too.
    i removed it, and the minifilter blocked it immediately.
    thanks @Dejan_Maksimovic and @Scott_Noone_(OSR) for advices.

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,343

    You are very unlucky that this code worked as it is fundamentally incorrect...See the previous comments.

    -scott
    OSR

  • negbit73negbit73 Member Posts: 5

    oh, these codes just for fast check, i always use at least FltGetFileNameInformation, FltParseFileNameInformation when work with FILE_OBJECT in real project.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 30 Nov 2020 LIVE ONLINE
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Developing Minifilters Early 2021 LIVE ONLINE