Disable Image Signing Enforcement (Code Integrity Protect) in Hyper-V worker process vmwp.exe
In Windows 10 18H2 or 19H1, Hypev-V hardened their worker process: https://msrc-blog.microsoft.com/2019/09/11/attacking-the-vm-worker-process/, which enables the Enabled CIG (Code Integrity Guard), and that means “Doesn’t allow loading of unsigned DLLs.”
And in fact, it’s refusing to load ANY dll without a Microsoft signature:
And that’s shitty. Hyper-V’s UEFI firmware and all sorts of things are simply embedded in the DLL (vmchipset.dll), which are loaded by vmwp.exe through DCOM calls, so if it enforces the signature, we have no way to replace the UEFI firmware ourselves. And that’s pretty annoying if you want a seamless anti-anti-VM detection experience on Windows Sandbox, so we need to patch it.
If you know a little about the EMET or its child Windows Defender ATP, then you must know that the these options are stored in the “Image File Execution Options”, with a value named “MitigationOptions”. And there are REALLY vmwp.exe and vmcompute.exe’s entry there, so we can simply delete them and kick those mitigation into the hell.
BUT, if you try it, you’ll find that does NOTHING. Even if you delete them, or change them to other value, it simply doesn’t work. That’s pretty strange, as most mitigation are applied in this way. So we have to wonder if there’re any other places to inject these configs. And there’re two directions for us:
The first one is the executable itself. For UAC, exe files will enclose a manifest file to indicate it needs admin privilege. So for EMET, there may also have something similar. But after digging in the Internet for quite a while, there’s no trace of manifest or settings at all, so although this way is possible, it isn’t used by Microsoft.
The other one is somehow promising. When creating processes, you can pass additional parameters to the CreateProcess api, and then restrict some process in the container, like UWP process’s starting. The vmwp.exe is created by vmcompute.exe, so I searched the CreateProcess api in the vmcompute.exe. And without doubt, there’s a CreateProcessAsUserW in the import list. And you can easily find the only reference to it is in the StartWorkerProcess function.
And if we trace up, we can find the dwCreationFlags is either 0x80008 or 0xc0008
After looking up in MSDN, it show:
0x80008 corresponds to: EXTENDED_STARTUPINFO_PRESENT | DETACHED_PROCESS
0xC0008 corresponds to: CREATE_PROTECTED_PROCESS | DETACHED_PROCESS | EXTENDED_STARTUPINFO_PRESENT
If you look at the CREATE_PROTECTED_PROCESS, you can find that it also enables various mitigations:
The process is to be run as a protected process. The system restricts access to protected processes and the threads of protected processes. For more information on how processes can interact with protected processes, see Process Security and Access Rights.
To activate a protected process, the binary must have a special signature. This signature is provided by Microsoft but not currently available for non-Microsoft binaries. There are currently four protected processes: media foundation, audio engine, Windows error reporting, and system. Components that load into these binaries must also be signed. Multimedia companies can leverage the first two protected processes. For more information, see Overview of the Protected Media Path.
Windows Server 2003 and Windows XP: This value is not supported.
So we patch the branch, making it always 0x80008, and then replace the vmcompute.exe
BUT, do you think everything is over? No, not at all. If you apply it, you’ll find the vmwp.exe is still restricted to Microsoft signing. So WHY?
And that’s final evil. Did you notice the EXTENDED_STARTUPINFO_PRESENT flag? In fact, it’s specifying an additional container option:
Then in the attribute list, it’s setting the PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, so that it can dynamically override the mitigation options.
And the options (a.k.a. a2 in the pic), is set in the StartWorkerProcess
By default, the options will be 0x1111101111111305
And if we entered this branch, it will be changed to 0x1111001111111305, which in fact is PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON.
And the priority of these options are PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY > CREATE_PROTECTED_PROCESS > MitigationOptions
So in the last we can simply add a DWORD RelaxWorkerSigning with value 1 into HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization, and the signing enforcement will be disabled.
P.S: Why will I need to patch the UEFI firmware? That’s because I need a anti-anti-sandbox/VM detection in Windows sandbox.
At first, I thought these informations are retrived from hardware, so I globally searched “Virtual Machine” in unicode, and found vmcompute.exe & vmwp.exe has this string. But after some analysis, it shows that the string in vmcompute.exe is the VM name showed in host side. So instead, I reverse engineered the WMI implementation Win32_ComputerSystem. In cimwin32.dll, it shows that it’s querying Smbios using MSSmBios_RawSMBiosTables interface, which is implemented in ntoskrnl.exe… So the easiest way to achieve the our goal, is to patch Hyper-V itself.