winsiderss / systeminformer

A free, powerful, multi-purpose tool that helps you monitor system resources, debug software and detect malware. Brought to you by Winsider Seminars & Solutions, Inc. @ http://www.windows-internals.com
https://systeminformer.sourceforge.io
MIT License
11.05k stars 1.4k forks source link

Show mitigation policies marked in LdrSystemDllInitBlock.MitigationOptionsMap.Map[1] and [2] #1236

Open yardenshafir opened 2 years ago

yardenshafir commented 2 years ago

Description of the feature, modification, idea or suggestion

Map[1] and [2] contains settings for loader integrity continuity, module tampering protection, XFG, CET, etc. There is some commented out code in mtgndlg.c saying those flags aren't propagated into the array but it uses Map[0] instead of [1] (https://github.com/processhacker/processhacker/blob/master/ProcessHacker/mtgndlg.c#L212). For some reason most of the values from WinBase.h start from the 3rd DWORD of the array (so top half of Map[1]) making parsing it a bit confusing. For example:

define PROCESS_CREATION_MITIGATION_POLICY2_MODULE_TAMPERING_PROTECTION_MASK (0x00000003ui64 << 12)

This is actually bit 44 in Map[1], so the check for the bit will actually be: (context->SystemDllInitBlock->MitigationOptionsMap.Map[1] >> 32) & PROCESS_CREATION_MITIGATION_POLICY2_MODULE_TAMPERING_PROTECTION_ALWAYS_ON. The values of the mitigations in Map[2] is also relative to the 3rd DWORD, so for example PROCESS_CREATION_MITIGATION_POLICY2_XTENDED_CONTROL_FLOW_GUARD_MASK (x << 40) is actually (Map[2] >> 8) & PROCESS_CREATION_MITIGATION_POLICY2_XTENDED_CONTROL_FLOW_GUARD_MASK.

Proposed implementation details (optional)

No response

dmex commented 2 years ago

There is some commented out code in mtgndlg.c saying those flags aren't propagated into the array but it uses Map[0] instead of [1

They did originally use [1] when it was written in 2015 but this was changed in 2018 with commit https://github.com/processhacker/processhacker/commit/e27a46e74f6812e5c742d9f4deb72211209d155e

For some reason most of the values from WinBase.h start from the 3rd DWORD of the array (so top half of Map[1]) making parsing it a bit confusing

Was this only added in recent builds?

yardenshafir commented 2 years ago

I didn't see these changes in master, is this in a different branch?

I'm not sure if this change happened in recent builds (or if I'm even interpreting it correctly), I see it in Windows 11 and will check if it's the same on Windows 10.

dmex commented 2 years ago

I didn't see these changes in master, is this in a different branch?

This was the original/old code from years ago.

I'm not sure if this change happened

I think the format/array changed a few times back then hence the changes. It's probably more stable now but I wonder how things like bit 44 in Map[1] are used with masks like 3 << 12. Why are some bits identical but others using different offsets?

yardenshafir commented 2 years ago

From quick testing it looks like anything starting from PROCESS_CREATION_MITIGATION_POLICY2_MODULE_TAMPERING_PROTECTION_MASK (3 << 12) is shifted by 32 bits, but PROCESS_CREATION_MITIGATION_POLICY2_LOADER_INTEGRITY_CONTINUITY_MASK and PROCESS_CREATION_MITIGATION_POLICY2_STRICT_CONTROL_FLOW_GUARD_MASK are not shifted... I still see some of the other bits in the lower DWORD of Map[1] being used, but not sure by what. I'll keep looking into it. For example, here's the map for a process that enabled module tampering protection and loader integrity continuity:

lkd> dx ((combase!_PS_SYSTEM_DLL_INIT_BLOCK*)&ntdll!LdrSystemDllInitBlock)->MitigationOptionsMap.Map
((combase!_PS_SYSTEM_DLL_INIT_BLOCK*)&ntdll!LdrSystemDllInitBlock)->MitigationOptionsMap.Map                 [Type: unsigned __int64 [3]]
    [0]              : 0x10000000032 [Type: unsigned __int64]
    [1]              : 0x2000100000000010 [Type: unsigned __int64]
    [2]              : 0x2002202 [Type: unsigned __int64]

Bit 4 in Map[1] is enabled (for loader integrity continuity) and bit 44 in Map[1] for module tampering protection (3 << 12).

Also, LdrControlFlowGuardXfgEnabled checks bit 8 in Map[2] (should be bit 40 in Map[1], so another shift by 32).