Search code examples
winapicode-security

Trying to set ProcessStrictHandleCheckPolicy returns 87 - Incorrect Function


I am trying to use SetProcessMitigationPolicy on Windows 10 to enable the ProcessStrictHandleCheckPolicy:

The process will receive a fatal error if it manipulates a handle that is not valid.

As a general rule, strict handle checking cannot be turned off once it is turned on. Therefore, when calling the SetProcessMitigationPolicy function with this policy, the values of the RaiseExceptionOnInvalidHandleReference and HandleExceptionsPermanentlyEnabled substructure members must be the same. It is not possible to enable invalid handle exceptions only temporarily.

I can enable a number of the other mitigations:

  • ProcessDynamicCodePolicy: The dynamic code policy of the process. When turned on, the process cannot generate dynamic code or modify existing executable code.
  • ProcessExtensionPointDisablePolicy: Contains process mitigation policy settings for legacy extension point DLLs.
  • ProcessSignaturePolicy: The policy of a process that can restrict image loading to those images that are either signed by Microsoft, by the Windows Store, or by Microsoft, the Windows Store and the Windows Hardware Quality Labs (WHQL).
  • ProcessFontDisablePolicy: The policy regarding font loading for the process. When turned on, the process cannot load non-system fonts.
  • ProcessImageLoadPolicy: The policy regarding image loading for the process, which determines the types of executable images that are allowed to be mapped into the process. When turned on, images cannot be loaded from some locations, such a remote devices or files that have the low mandatory label.

But ProcessStrictHandleCheckPolicy:

PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy;
policy.RaiseExceptionOnInvalidHandleReference = 1;
policy.HandleExceptionsPermanentlyEnabled = 1;

BOOL res = SetProcessMitigationPolicy(ProcessStrictHandleCheckPolicy, policy, sizeof(policy));

if (!res) 
   RaiseLastWin32Error();

fails with error code 87:

ERROR_INVALID_PARAMETER
The parameter is incorrect

What is wrong?

Bonus Chatter

The ProcessDynamicCodePolicy policy prevents an embedded web browser from running Javascript:

  • ProhibitDynamicCode: Set (0x1) to prevent the process from generating dynamic code or modifying existing executable code; otherwise leave unset (0x0).
  • AllowThreadOptOut: Set (0x1) to allow threads to opt out of the restrictions on dynamic code generation by calling the SetThreadInformation function with the ThreadInformation parameter set to ThreadDynamicCodePolicy; otherwise leave unset (0x0). You should not use the AllowThreadOptOut and ThreadDynamicCodePolicy settings together to provide strong security. These settings are only intended to enable applications to adapt their code more easily for full dynamic code restrictions.

More Bonuser

I'm actually in Delphi, so the syntax is different from the above C/C++/C# pseudo-code:

type
    //ProcessStrictHandleCheckPolicy - The process will receive a fatal error if it manipulates an invalid handle. Useful for preventing downstream problems in a process due to handle misuse.
    PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY = record
        Flags: DWORD;
                //DWORD RaiseExceptionOnInvalidHandleReference : 1;
                //DWORD HandleExceptionsPermanentlyEnabled : 1;
                //DWORD ReservedFlags : 30;
    end;

procedure SetMitigationPolicy;
var
    policy: PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY;
    res: BOOL;
begin
    policy.Flags := $00000002;
    res := SetProcessMitigationPolicy(ProcessStrictHandleCheckPolicy, @policy, sizeof(policy));
    if not res then
        RaiseLastWin32Error;
end;

It doesn't change the question:

  • sometimes when i post Delphi code, and it's not strictly Delphi related, i get comments that i should have included the Delphi tag
  • sometimes when i post Delphi code, and it's not strictly Delphi related, i get comments that i should not have included the Delphi tag

rolls the dice

Don't include delphi delphi-xe6 tags.

Bonus Reading


Solution

  • From the PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY documentation:

    As a general rule, strict handle checking cannot be turned off once it is turned on. Therefore, when calling the SetProcessMitigationPolicy function with this policy, the values of the RaiseExceptionOnInvalidHandleReference and HandleExceptionsPermanentlyEnabled substructure members must be the same. It is not possible to enable invalid handle exceptions only temporarily.

    When you wrote:

    policy.Flags := $00000002;
    

    You only set the HandleExceptionsPermanentlyEnabled flag, but not the RaiseExceptionOnInvalidHandleReference flag. It should be this instead, which sets both flags:

    policy.Flags := $00000003;
    

    I'm fairly sure that you never actually ran your C++ code because it does not compile. If you fix the obvious compilation errors, then it will run successfully.

    #define  _WIN32_WINNT 0x0602
    
    #include <Windows.h>
    #include <Processthreadsapi.h>
    #include <iostream>
    
    int main()
    {
        PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = { 0 };
        policy.RaiseExceptionOnInvalidHandleReference = 1;
        policy.HandleExceptionsPermanentlyEnabled = 1;
    
        BOOL res = SetProcessMitigationPolicy(ProcessStrictHandleCheckPolicy, &policy, 
            sizeof(policy));
        DWORD err = 0;
        if (!res)
            err = GetLastError();
        std::cout << res << ", " << err;
    }
    

    This program outputs 1, 0 as expected. If you add

    policy.Flags = 0x00000002;
    

    immediately before the call to SetProcessMitigationPolicy, then the output is 0, 87.