In the recent years,Microsoft has add many mitigations in the Windows system. In this article i will show you the implementation of these mitigations.
The first question is how many mitigations have been added in Windows and what they are.
If you have even used a process manager tool which named Process Hacker, you can query each process's mitigation status.For example:


In fact, there is a struct named PROCESS_MITIGATION_POLICY in the SDK header file.
typedef enum _PROCESS_MITIGATION_POLICY {ProcessDEPPolicy,ProcessASLRPolicy,ProcessDynamicCodePolicy,ProcessStrictHandleCheckPolicy,ProcessSystemCallDisablePolicy,ProcessMitigationOptionsMask,ProcessExtensionPointDisablePolicy,ProcessControlFlowGuardPolicy,ProcessSignaturePolicy,ProcessFontDisablePolicy,ProcessImageLoadPolicy,ProcessSystemCallFilterPolicy,ProcessPayloadRestrictionPolicy,ProcessChildProcessPolicy,ProcessSideChannelIsolationPolicy,MaxProcessMitigationPolicy} PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY;
If you want to know the mitigation status of a process, you can use the Windows Native API NtQueryInformationProcess.
NtQueryInformationProcess declaration is following:
NtQueryInformationProcess declaration is following:
NTSYSCALLAPINTSTATUSNTAPINtQueryInformationProcess(_In_ HANDLE ProcessHandle,_In_ PROCESSINFOCLASS ProcessInformationClass,_Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,_In_ ULONG ProcessInformationLength,_Out_opt_ PULONG ReturnLength);
ProcessInformationClass is an enumeration that indicate the function code. ProcessMitigationPolicy(52) is used for querying the process mitigation policy. When you assign ProcessInformationClass argument as ProcessMitigationPolicy,the ProcessInformationLength is a pointer to a PROCESS_MITIGATION_POLICY_INFORMATION.
typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION{PROCESS_MITIGATION_POLICY Policy;union{PROCESS_MITIGATION_ASLR_POLICY ASLRPolicy;PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY StrictHandleCheckPolicy;PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY SystemCallDisablePolicy;PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY ExtensionPointDisablePolicy;PROCESS_MITIGATION_DYNAMIC_CODE_POLICY DynamicCodePolicy;PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY ControlFlowGuardPolicy;PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY SignaturePolicy;PROCESS_MITIGATION_FONT_DISABLE_POLICY FontDisablePolicy;PROCESS_MITIGATION_IMAGE_LOAD_POLICY ImageLoadPolicy;PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY SystemCallFilterPolicy;PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY PayloadRestrictionPolicy;PROCESS_MITIGATION_CHILD_PROCESS_POLICY ChildProcessPolicy;PROCESS_MITIGATION_SIDE_CHANNEL_ISOLATION_POLICY SideChannelIsolationPolicy;};} PROCESS_MITIGATION_POLICY_INFORMATION, *PPROCESS_MITIGATION_POLICY_INFORMATION;
This is a peach of NtQueryInformationProcess disassembly code in the ntoskrnl.By the reserve enginning we found that we must have the PROCESS_QUERY_INFORMATION permission with the process handle to invoke this function.
case 52: // ProcessMitigationPolicyif (ProcessInformationLength != 8 )return 0xC0000004;MitigationCode = *(_DWORD *)ProcessInformation;if ( Handle == (HANDLE)-1i64 ){pObject = (PEPROCESS)PsGetCurrentProcess();}else{result = ObReferenceObjectByHandleWithTag((ULONG_PTR)Handle,0x400, //PROCESS_QUERY_INFORMATIONPsProcessType,PreviousMode,'yQsP',(__int64)&pObject,0i64);if ( result < 0 )return result;}
So we can write a simple progarm to query the mitigation status of a process. It look like this:
ClientId.UniqueProcess = PID;NtOpenProcess(&ProcHandle,PROCESS_QUERY_INFORMATION,&ObjAttr,&ClientId);NtQueryInformationProcess(ProcHandle,ProcessMitigationPolicy,RecvBuffer,RecvBufferSize,&RetSize);
Then i query the Microsoft Edge content process by this tool, and get the mitigation policy information as below.
[*]ProcessDEPPolicy:MEM_EXECUTE_OPTION_DISABLE 1MEM_EXECUTE_OPTION_ENABLE 0MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 1MEM_EXECUTE_OPTION_PERMANENT 1MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE 0MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE 0MEM_EXECUTE_OPTION_VALID_FLAGS 1[*]ProcessASLRPolicy:EnableBottomUpRandomization 1EnableForceRelocateImages 1EnableHighEntropy 1DisallowStrippedImages 1[*]ProcessDynamicCodePolicy:ProhibitDynamicCode 0AllowThreadOptOut 0AllowRemoteDowngrade 0AuditProhibitDynamicCode 0[*]StrictHandleCheckPolicy:RaiseExceptionOnInvalidHandleReference 1HandleExceptionsPermanentlyEnabled 1[*]SystemCallDisablePolicy:DisallowWin32kSystemCalls 0AuditDisallowWin32kSystemCalls 0ProcessExtensionPointDisablePolicy:DisableExtensionPoints 0[*]ProcessControlFlowGuardPolicy:EnableControlFlowGuard 1EnableExportSuppression 1StrictMode 0[*]ProcessSignaturePolicy:MicrosoftSignedOnly 0StoreSignedOnly 0MitigationOptIn 0AuditMicrosoftSignedOnly 0AuditStoreSignedOnly 0[*]ProcessFontDisablePolicy:DisableNonSystemFonts 0AuditNonSystemFontLoading 0[*]ProcessImageLoadPolicy:NoRemoteImages 1NoLowMandatoryLabelImages 1PreferSystem32Images 0AuditNoRemoteImages 0AuditNoLowMandatoryLabelImages 0[*]SystemCallFilterPolicy:FilterId 0[*]PayloadRestrictionPolicy:EnableExportAddressFilter 0AuditExportAddressFilter 0EnableExportAddressFilterPlus 0AuditExportAddressFilterPlus 0EnableImportAddressFilter 0AuditImportAddressFilter 0EnableRopStackPivot 0AuditRopStackPivot 0EnableRopCallerCheck 0AuditRopCallerCheck 0EnableRopSimExec 0AuditRopSimExec 0[*]ProcessChildProcessPolicy:NoChildProcessCreation 1AuditNoChildProcessCreation 0AllowSecureProcessCreation 0[*]ProcessSideChannelIsolationPolicy:SmtBranchTargetIsolation 0IsolateSecurityDomain 0DisablePageCombine 0SpeculativeStoreBypassDisable 0
ProcessImageLoadPolicy
When get or set ProcessImageLoadPolicy mitigation by PROCESS_MITIGATION_IMAGE_LOAD_POLICY struct. And this struct's declaration is below.We can see there are 5 levels restricted for image loading.
typedef struct _PROCESS_MITIGATION_IMAGE_LOAD_POLICY {union {DWORD Flags;struct {DWORD NoRemoteImages : 1;DWORD NoLowMandatoryLabelImages : 1;DWORD PreferSystem32Images : 1;DWORD AuditNoRemoteImages : 1;DWORD AuditNoLowMandatoryLabelImages : 1;DWORD ReservedFlags : 27;} DUMMYSTRUCTNAME;} DUMMYUNIONNAME;} PROCESS_MITIGATION_IMAGE_LOAD_POLICY, *PPROCESS_MITIGATION_IMAGE_LOAD_POLICY;
In the Windows kernel section has three types.
PhysicalSectionImageSectionDataSection
NtCreateSection is the interface to create a section object in Windows.If we specify SEC_IMAGE flag when invoke NtCreateSection ,it will set a bit flag named MMSECTION_FLAGS in section.ControlArea after the section object has be created. Then it will execute into the MiMapViewOfImageSection when we call the NtMapViewOfSection function with this section handle.
1.NtMapViewOfSection2.MiMapViewOfSection3.MiMapViewOfImageSection4.MiAllowImageMap
The ProcessImageLoadPolicy mitigation is implement in the MiAllowImageMap function.
MiAllowImageMap is splice into two piece.
Firstly, it check for remote image load.
Firstly, it check for remote image load.
IsProhibitRemoteImageMapEnable = Process->MitigationFlags & 0x80000; // ProhibitRemoteImageMapIsAuditProhibitRemoteImageMap = Process->MitigationFlags & 0x100000; // AuditProhibitRemoteImageMapif ((IsProhibitRemoteImageMapEnable || IsAuditProhibitRemoteImageMap) &&(Section->u1.ControlArea & 3)) // AuditProhibitRemoteImageMap{if ( IsProhibitRemoteImageMapEnable )return STATUS_ACCESS_DENIED;}
Secondly, it checks for integrity level. It checks the source image file's integrity level by the image file's file object's security descripter.
MitigationFlags = Process->MitigationFlags;IsAuditProhibitLowILImageMap = MitigationFlags & 0x400000; // AuditProhibitLowILImageMapIsProhibitLowILImageMap = MitigationFlags & 0x200000; // ProhibitLowILImageMapif ( IsProhibitLowILImageMap || IsAuditProhibitLowILImageMap ){MemoryAllocated = 0;FileObject = MiReferenceControlAreaFile(pControlArea);status = ObpGetObjectSecurity(FileObject, &SecurityDescriptor, &MemoryAllocated);if (!NT_SUCCESS(status)){status = STATUS_ACCESS_DENIED;}else{if (SeQueryMandatoryLabel(SecurityDescriptor) <= 0x1000 &&!SeGetTrustLabelAce(SecurityDescriptor) )status = STATUS_ACCESS_DENIED;ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);}MiDereferenceControlAreaFile(pControlArea, FileObject);}
SeQueryMandatoryLabel is a function for getting the integrity level, it's return value indicates the integrity level value.This is because of the mandatory label is a series of SID which have the same format. You can find them out in the MSDN document,And Microsoft named them as well-known SID.
SID: S-1-16-0Name: Untrusted Mandatory LevelDescription: An untrusted integrity level. Note Added in Windows Vista and Windows Server 2008Note Added in Windows Vista and Windows Server 2008SID: S-1-16-4096Name: Low Mandatory LevelDescription: A low integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-8192Name: Medium Mandatory LevelDescription: A medium integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-8448Name: Medium Plus Mandatory LevelDescription: A medium plus integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-12288Name: High Mandatory LevelDescription: A high integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-16384Name: System Mandatory LevelDescription: A system integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-20480Name: Protected Process Mandatory LevelDescription: A protected-process integrity level.Note Added in Windows Vista and Windows Server 2008SID: S-1-16-28672Name: Secure Process Mandatory LevelDescription: A secure process integrity level.Note Added in Windows Vista and Windows Server 2008
According to this, we known if the return value less than 0x1000 it indicate the security descripter's mandatory label is equal or less than Low Mandatory Level.
ProcessChildProcessPolicy
ProcessChildProcessPolicy has tree levels.
typedef struct _PROCESS_MITIGATION_CHILD_PROCESS_POLICY {union {DWORD Flags;struct {DWORD NoChildProcessCreation : 1;DWORD AuditNoChildProcessCreation : 1;DWORD AllowSecureProcessCreation : 1;DWORD ReservedFlags : 29;} DUMMYSTRUCTNAME;} DUMMYUNIONNAME;} PROCESS_MITIGATION_CHILD_PROCESS_POLICY, *PPROCESS_MITIGATION_CHILD_PROCESS_POLICY;
At the branch that handles ProcessChildProcessPolicy logic, it invokes a function named PspGetNoChildProcessRestrictedPolicy for getting the current process's child process mitigation policy status.
ChildPolicyLevel = PspGetNoChildProcessRestrictedPolicy(TargetProcess);if(ChildPolicyLevel == 1){PolicyInfo.NoChildProcessCreation = 1;}else if(ChildPolicyLevel == 2){PolicyInfo.NoChildProcessCreation = 1;PolicyInfo.AllowSecureProcessCreation = 1;}else if(ChildPolicyLevel == 3){PolicyInfo.AuditNoChildProcessCreation = 1;}
Unusually, it does not get the policy status from the EPROCESS's MitigationFlags field.In fact, it get some bit flags from the process token's TokenFlags field.The fake code look like this.
CurThread = KeGetCurrentThread();TokenFlags = PrimaryToken->TokenFlags;*NoChildProcessCreationFlag = (TokenFlags >> 19) & 1; // 20 bit*AllowSecureProcessCreationFlag = (TokenFlags >> 20) & 1; // 21 bit*AuditNoChildProcessCreationFlag = (TokenFlags >> 21) & 1; // 22 bit
There two ways to create a process.One is the NtCreateUserProcess function, and the other is the NtCreateProcess/NtCreateProcessEx.The NtCreateUserProcess is a newer native invoke that was introduced in Windows Vista. When we call CreateProcessW in user mode code, it will invoke NtCreateUserProcess function finally.
The ProcessChildProcessPolicy mitigation is implementation in the SeSubProcessToken.
1.NtCreateUserProcess2.PspAllocateProcess3.PspInitializeProcessSecurity4.SeSubProcessToken
The SeSubProcessToken function is also invoke the PspGetNoChildProcessRestrictedPolicy to determine the the child can be created.If the creation desired is refused the NtCreateUserProcess will return the STATUS_CHILD_PROCESS_BLOCKED.
No comments:
Post a Comment