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

Home NTDEV
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/


Using ZwProtectVirtualMemory with usermode address returns INVALID_PARAMETER_3

NotAnNtDevNotAnNtDev Member Posts: 3

So I recently began coding kernel drivers and I'm trying to change the page protection of my usermode app to simulate shellcode injection using my custom kernel driver specifically from PAGE_EXECUTE_READ to PAGE_EXECUTE_READWRITE.

I decided to use ZwProtectVirtualMemory since I cannot use mdl's because of it only working on kernelmode addresses.

The function that I am currently using is this:

//Takes the pid of the usermode process, the usermode address and the page size
NTSTATUS VirtualProtectMem(ULONG64 pid, PVOID address, ULONG pageSize)
{
//some basic checking for invalid values
if (!pid || !address || !size)
        return STATUS_INVALID_PARAMETER;

    NTSTATUS status = STATUS_SUCCESS;
    PEPROCESS process = nullptr;

    //Fetch the eprocess structure from the process id
    if (!NT_SUCCESS(PsLookupProcessByProcessId(reinterpret_cast<HANDLE>(pid), &process)))
        return STATUS_NOT_FOUND;

   //attach our thread to the usermode process adress space
    KAPC_STATE state;
    KeStackAttachProcess(target_process, &state);

    ULONG curProtection = NULL;//variable to store the previous page protection   

    //Attempting to change the page protection
    status = ZwProtectVirtualMemory(ZwCurrentProcess(), &address, &size, PAGE_EXECUTE_READWRITE, &curProtection);

    //Detach our thread from the user space
    KeUnstackDetachProcess(&state);

    if (NT_SUCCESS(status))
        KernelPrint("Succeeded");
    else
        KernelPrint("Failed");
    //Free the pointer to the EPROCESS structure
    ObDereferenceObject(process);
    return status;
}

However after calling this function with parameters such as (3fe4, 0000000100002B0F, 0x8), the ZwProtectVirtualMemory function returns an NTSTATUS of c00000f1 which means INVALID_PARAMETER_3.

Any ideas?

Thanks in advance

Comments

  • Jeremy_HurrenJeremy_Hurren Member - All Emails Posts: 18

    I'll just state the seemingly obvious... INVALID_PARAMETER_3 means the function call doesn't like the size parameter. If your example parameters are actually correct, you seem to be passing an 8 as the size, rather than a pointer to the variable that contains the 8. The code looks okay though, so perhaps that is just a simplification in your question. The function wants the range of memory to be within the usermode virtual address space, which it appears to be.

    So if none of the above helps, I would say step into this in your debugger and see why the function is returning that status. :)

  • NotAnNtDevNotAnNtDev Member Posts: 3
    edited October 9

    @Jeremy_Hurren said:
    I'll just state the seemingly obvious... INVALID_PARAMETER_3 means the function call doesn't like the size parameter. If your example parameters are actually correct, you seem to be passing an 8 as the size, rather than a pointer to the variable that contains the 8. The code looks okay though, so perhaps that is just a simplification in your question. The function wants the range of memory to be within the usermode virtual address space, which it appears to be.

    So if none of the above helps, I would say step into this in your debugger and see why the function is returning that status. :)

    Thank you for your answer, however I was actually passing the address of the value 8. I fixed it though, the problem seemed to be with the buffer, I didn't create a kernelmode buffer by allocating a pool, I directly took the buffer from usermode; I'm not sure if that was the origin of this error however. What do you think?

  • 0xrepnz0xrepnz Member Posts: 42

    ZwProtectVirtualMemory function returns an NTSTATUS of 0xc00000f1 which means INVALID_PARAMETER_3

    ZwProtectVirtualMemory returns INVALID_PARAMETER_3 in the following cases:
    1 - (*BaseAddress + *RegionSize) > MM_HIGHEST_USER_ADDRESS - The region size is too big - the range is not in the user mode range.
    2 - *RegionSize == 0 - the region size is zero.

    Remember this function is undocumented, so there can be more cases in the future.

    - Ori Damari
  • NotAnNtDevNotAnNtDev Member Posts: 3

    @0xrepnz said:

    ZwProtectVirtualMemory function returns an NTSTATUS of 0xc00000f1 which means INVALID_PARAMETER_3

    ZwProtectVirtualMemory returns INVALID_PARAMETER_3 in the following cases:
    1 - (*BaseAddress + *RegionSize) > MM_HIGHEST_USER_ADDRESS - The region size is too big - the range is not in the user mode range.
    2 - *RegionSize == 0 - the region size is zero.

    Remember this function is undocumented, so there can be more cases in the future.

    Oh, thanks a lot I'll keep this in mind :)

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!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters 8 March 2021 LIVE ONLINE