Microsoft Edge binary injection mitigation overview

In Windows 10 TH2 update (build 10586), Microsoft implemented a new mechanism in order to avoid binary injection in sensitive processes. This feature is not dedicated to Microsoft Edge but the editor communicated about its implementation in this new browser that should replace Internet Explorer in the future. The communication can be found there. The Microsoft blog post explains that the mitigation avoids loading unauthorized DLLs into Microsoft Edge content processes.

The experts of SEKOIA’s CERT analyzed this mitigation and wrote this blog post in order to explain it.

The new structures available in winnt.h build 10586

The first thing to do when we want to analyze a new Microsoft feature is to download the latest Windows SDK available there. If you are familiar with binary mitigation, you should know the Windows function GetProcessMitigationPolicy(). This function is partially documented on the MSDN there. The documentation mentioned the type PROCESS_MITIGATION_POLICY. Let’s check it on the winnt.h:

typedef enum _PROCESS_MITIGATION_POLICY {
   ProcessDEPPolicy,
   ProcessASLRPolicy,
   ProcessDynamicCodePolicy,
   ProcessStrictHandleCheckPolicy,
   ProcessSystemCallDisablePolicy,
   ProcessMitigationOptionsMask,
   ProcessExtensionPointDisablePolicy,
   ProcessControlFlowGuardPolicy,
   ProcessSignaturePolicy,
   ProcessFontDisablePolicy,
   ProcessImageLoadPolicy,
   MaxProcessMitigationPolicy
} PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY;

We can see that the type contains more values than the documentation. For the Microsoft Edge binary injection mitigation the interesting value is ProcessSignaturePolicy. Here is the returned structure in winnt.h:

typedef struct _PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY {
   union {
      DWORD Flags;
      struct {
         DWORD MicrosoftSignedOnly : 1;
         DWORD StoreSignedOnly : 1;
         DWORD MitigationOptIn : 1;
         DWORD ReservedFlags : 29;
      } DUMMYSTRUCTNAME;
   } DUMMYUNIONNAME;
} PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY, *PPROCESS_MITIGATION_BINARY_SIGNATURE_POLICY;

We can see some flags in this structure: a flag that allows Microsoft signed loading, a flag that allows Store signed (from Microsoft Store) loading and a flag that enables opt-in mitigation.

How does it work?

The mitigation is performed during the LoadLibrary() API call. When a binary is loaded, the kernel calls NtCreateSection(). Then MiCreateSection()is called. This function finally calls MiValidateSectionCreate() which uses ci.dll (Code Integrity) in order to check signatures. If the verification does not match the policy, the kernel won’t create the section and will return an error. The mitigation is performed by the kernel, so to turn off the mitigation, we must have the ring 0 privilege.

Something interesting: to optimize the performance, Microsoft Edge keeps a cache of invalid libraries. If one of them is loaded a second time, the loading is directly refused without asking to the kernel. To perform this task, Microsoft Edge performs some API hooks (such as LoadLibrary() hook) via the Edge Shims (more information about the shims there). Here is the complete list of the hooks:

0:000> x EShims!*APIHook_*
00007ffa`7c496900 EShims!NS_AppContainers::APIHook_WNetGetConnectionW
00007ffa`7c494b20 EShims!NS_LRIECoCreate::APIHook_CoGetClassObject
00007ffa`7c4917f0 EShims!NS_EdgeAppContainers::APIHook_LoadLibraryExW
00007ffa`7c4919c0 EShims!NS_EdgeAppContainers::APIHook_GetFocus
00007ffa`7c493190 EShims!NS_HangResistanceInternal::APIHook_CreateWindowExA
00007ffa`7c494260 EShims!NS_LRIECoCreate::APIHook_CoCreateInstanceEx
00007ffa`7c497ad0 EShims!NS_OneCoreAppContainers::APIHook_WNetGetConnectionW
00007ffa`7c491720 EShims!NS_EdgeAppContainers::APIHook_LoadLibraryExA
00007ffa`7c496260 EShims!NS_AppContainers::APIHook_FindFirstFileW
00007ffa`7c4927d0 EShims!NS_EdgeCILoadLibrary::APIHook_LoadLibraryW
00007ffa`7c496580 EShims!NS_AppContainers::APIHook_GetFullPathNameW
00007ffa`7c4974e0 EShims!NS_OneCoreAppContainers::APIHook_GetFileAttributesW
00007ffa`7c492760 EShims!NS_EdgeCILoadLibrary::APIHook_LoadLibraryA
00007ffa`7c497430 EShims!NS_OneCoreAppContainers::APIHook_FindFirstFileW
00007ffa`7c4975c0 EShims!NS_OneCoreAppContainers::APIHook_GetFileAttributesExW
00007ffa`7c4936b0 EShims!NS_HangResistanceInternal::APIHook_DefWindowProcA
00007ffa`7c492f60 EShims!NS_OneCoreGetProcAddressShim::APIHook_GetProcAddress
00007ffa`7c497750 EShims!NS_OneCoreAppContainers::APIHook_GetFullPathNameW
00007ffa`7c496100 EShims!NS_AppContainers::APIHook_CreateFileW
00007ffa`7c4935f0 EShims!NS_HangResistanceInternal::APIHook_DefWindowProcW
00007ffa`7c491510 EShims!NS_EdgeAppContainers::APIHook_GetModuleFileNameW
00007ffa`7c4972d0 EShims!NS_OneCoreAppContainers::APIHook_CreateFileW
00007ffa`7c4933c0 EShims!NS_HangResistanceInternal::APIHook_CreateWindowExW
00007ffa`7c496200 EShims!NS_AppContainers::APIHook_FindClose
00007ffa`7c496760 EShims!NS_AppContainers::APIHook_GetLongPathNameW
00007ffa`7c4918e0 EShims!NS_EdgeAppContainers::APIHook_WindowFromPoint
00007ffa`7c4963f0 EShims!NS_AppContainers::APIHook_GetFileAttributesExW
00007ffa`7c4915e0 EShims!NS_EdgeAppContainers::APIHook_LoadLibraryA
00007ffa`7c491680 EShims!NS_EdgeAppContainers::APIHook_LoadLibraryW
00007ffa`7c4946f0 EShims!NS_LRIECoCreate::APIHook_CoCreateInstance
00007ffa`7c491940 EShims!NS_EdgeAppContainers::APIHook_ScreenToClient
00007ffa`7c4973d0 EShims!NS_OneCoreAppContainers::APIHook_FindClose
00007ffa`7c4918c0 EShims!APIHook_IEIsProtectedModeProcess
00007ffa`7c496310 EShims!NS_AppContainers::APIHook_GetFileAttributesW
00007ffa`7c4928d0 EShims!NS_EdgeCILoadLibrary::APIHook_LoadLibraryExW
00007ffa`7c497930 EShims!NS_OneCoreAppContainers::APIHook_GetLongPathNameW
00007ffa`7c492840 EShims!NS_EdgeCILoadLibrary::APIHook_LoadLibraryExA
00007ffa`7c492c00 EShims!NS_Flash10WaitFix::APIHook_WaitForSingleObject
00007ffa`7c492e00 EShims!NS_GetProcAddressShim::APIHook_GetProcAddress

How to get the signature policy of a process?

The experts of SEKOIA’s CERT published a tool to get the signature policy of a running process. The tool is available there: https://github.com/SekoiaLab/BinaryInjectionMitigation/ (GetSignatureMitigation). The tool is using the undocumented structure mentioned previously. Here is the output of our code on the MicrosoftEdgeCP.exe process:

C:\>GetSignatureMitigation.exe 3704
Get SeDebugPrivilege: OK
Open process 3704: OK

Signature Microsoft Signed Only: 0
Signature Store Signed Only: 1
Signature Mitigation Opt-In: 1

The Microsoft Edge process accepts DLL signed by the Store and above. Here is the output of the tool for few Windows processes:

  MicrosoftSignedOnly StoreSignedOnly MitigationOptIn
MicrosoftEgdeCP.exe

0

1

1

cmd.exe

0

0

0

Calculator.exe

0

1

0

Explorer.exe

0

0

0

Excel.exe

0

0

0

svchost.exe

0

0

0

winword.exe

0

0

0

HxMail.exe

0

1

0

Globally the processes with the StoreSignedOnly flag to 1 are located in C:\Windows\SystemApps (where Microsoft Edge is installed) and C:\Program Files\WindowsApps\ (where the Windows store apps are installed).

Is it a silver bullet?

Obviously not! As Microsoft mentioned on its blog post: “requiring DLLs to be signed is not a silver bullet”. An attacker cannot load an unsigned library in Microsoft Edge. However he can always execute shellcode (that does not contain LoadLibrary() call) in the remote process or perform API inline hooks (a common technique used by banking Trojans).

To prove this approach, we created a code injector which is available there: https://github.com/SekoiaLab/BinaryInjectionMitigation/ (injector). Here is the usage:

C:\>injector.exe
Usage of the injector.

injector.exe /d dll_file PID
injector.exe /s shellcode_file PID
   /d dll_file PID: dll injection via LoadLibrary().
   /s shellcode_file PID: shellcode injection.

The tool accepts two kinds of injections:

  • /d: injection thanks to LoadLibrary(). As expected, this technique fails for Microsoft Edge TH2 because the LoadLibrary() call won’t be accepted by the kernel. All the processes do not include this new feature. For example, cmd.exe is not protected, that’s why this technique of injection still perfectly works for this process in Windows 10 TH2.

  • /s: injection of a shellcode. This technique works perfectly for Microsoft Edge TH2 with signature mitigation (if the shellcode in argument does not contain a LoadLibrary() call).

Conclusion

Microsoft implemented an interesting and promising new signature mitigation in Windows 10 TH2. However, with the current implementation, malware developers can easily bypass it and continue to inject malicious code in Microsoft Edge in order to alter it.

Paul Rascagneres

Senior threat researcher, malware analyst and IT conf speaker…

Recent Posts

Categories

Archives

Paul Rascagneres Written by:

Senior threat researcher, malware analyst and IT conf speaker...

Comments are closed.