├── .gitignore ├── docs └── img │ ├── start_error_c0000142.png │ └── user32_dll_cffexplorer.png ├── include └── mem.h ├── LICENSE.md ├── src ├── mem.c └── main.c ├── win32k-mitigation.vcxproj.filters ├── win32k-mitigation.sln ├── README.md └── win32k-mitigation.vcxproj /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | Win32/ 3 | x64/ 4 | *.vcxproj.user 5 | *.swp 6 | Thumbs.db 7 | -------------------------------------------------------------------------------- /docs/img/start_error_c0000142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtth-bfft/win32k-mitigation/HEAD/docs/img/start_error_c0000142.png -------------------------------------------------------------------------------- /docs/img/user32_dll_cffexplorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtth-bfft/win32k-mitigation/HEAD/docs/img/user32_dll_cffexplorer.png -------------------------------------------------------------------------------- /include/mem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | PVOID safe_alloc(SIZE_T dwBytes); 5 | PVOID safe_realloc(PVOID pBuf, SIZE_T dwBytes); 6 | PVOID safe_dup(const VOID *pBuf, SIZE_T dwBytes); 7 | VOID safe_free(PVOID pBuf); 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Matthieu Buffet 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/mem.c: -------------------------------------------------------------------------------- 1 | #include "mem.h" 2 | #include 3 | #include 4 | #include 5 | 6 | PVOID safe_alloc(SIZE_T dwBytes) 7 | { 8 | PVOID pRes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes); 9 | if (pRes == NULL) 10 | { 11 | _ftprintf(stderr, TEXT("Error: unable to allocate %zu bytes: code %u\n"), 12 | dwBytes, GetLastError()); 13 | _exit(ERROR_OUTOFMEMORY); 14 | } 15 | return pRes; 16 | } 17 | 18 | PVOID safe_realloc(PVOID pBuf, SIZE_T dwBytes) 19 | { 20 | PVOID pRes = NULL; 21 | if (pBuf == NULL) 22 | return safe_alloc(dwBytes); 23 | pRes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pBuf, dwBytes); 24 | if (pRes == NULL) 25 | { 26 | _ftprintf(stderr, TEXT("Error: unable to extend allocation to %zu bytes: code %u\n"), 27 | dwBytes, GetLastError()); 28 | _exit(ERROR_OUTOFMEMORY); 29 | } 30 | return pRes; 31 | } 32 | 33 | PVOID safe_dup(const VOID *pBuf, SIZE_T dwBytes) 34 | { 35 | PVOID pRes = safe_alloc(dwBytes); 36 | memcpy(pRes, pBuf, dwBytes); 37 | return pRes; 38 | } 39 | 40 | VOID safe_free(PVOID pBuf) 41 | { 42 | if (pBuf == NULL || !HeapFree(GetProcessHeap(), 0, pBuf)) 43 | { 44 | _ftprintf(stderr, TEXT("Error: tried to free %p, heap corrupted\n"), pBuf); 45 | _exit(ERROR_OUTOFMEMORY); 46 | } 47 | } -------------------------------------------------------------------------------- /win32k-mitigation.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /win32k-mitigation.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.271 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32k-mitigation", "win32k-mitigation.vcxproj", "{C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Debug|x64.ActiveCfg = Debug|x64 17 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Debug|x64.Build.0 = Debug|x64 18 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Debug|x86.Build.0 = Debug|Win32 20 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Release|x64.ActiveCfg = Release|x64 21 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Release|x64.Build.0 = Release|x64 22 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Release|x86.ActiveCfg = Release|Win32 23 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {9DEC4CB7-2ED5-47B6-B9FE-45E2658ADA9F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Win32k mitigation 2 | 3 | This project is just a test case to try the new win32k.sys system call filtering mitigation in Windows 8. 4 | 5 | The win32k mitigation policy is a per-thread mitigation which, if enabled, denies the thread the right to call most graphics-related system call within `wink32.sys`. There are way too many of them (~1000, compared to the kernel's 400 ones), and most of their implementations is old code, so this mitigation is quite important since it blocks a high-value target for vulnerability researchers. Unfortunately, only Microsoft Edge and Chrome use it as part of their sandbox, because there is no supported way to use it. 6 | 7 | # Filtering mechanism 8 | 9 | When a thread first calls a graphics syscall, it gets converted to a "GUI thread". This conversion happens once, and so that's where the mitigation ended up being implemented, probably for performance considerations. The problem is, enforcing the mitigation on an existing process leaves room for many threads to already be converted and thus allowed to make arbitrary system calls. 10 | 11 | The mitigation can be enabled in one of two ways : 12 | - calling SetProcessMitigationPolicy(ProcessSystemCallDisablePolicy) with a handle to an existing process. This can only be really effective for that process' child processes, as explained earlier; 13 | - calling CreateProcess(EXTENDED_STARTUPINFO_PRESENT) with a `PROC_THREAD_ATTRIBUTE_LIST` containing a `PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY` attribute. This will necessarily affect all the threads. 14 | 15 | # Compatibility issues 16 | 17 | When enabled, the mitigation only allows startup of small programs compiled with no graphics imports and linked for the Console subsystem. 18 | 19 | However, when linked against a graphics library (say, `user32.dll`), `CreateProcess()` returns an error, and a message box shows an unfriendly `0xC0000142` NT status to the user ([STATUS_DLL_INIT_FAILED](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55)) : 20 | 21 | ![Dialog box with status 0xC0000142](https://github.com/mtth-bfft/win32k-mitigation/raw/master/docs/img/start_error_c0000142.png) 22 | 23 | A detour in WinDBG shows that, right after it loaded `imm32.dll` (as a dependency of user32.dll), `ntdll!_LdrpInitialize()` called `ntdll!LdrpInitializationFailure()` which, in turn, called `NtRaiseHardError()` with that status code. 24 | 25 | Since debugging processes during their startup (when nothing has been initialized yet) is hard, I tried importing all these graphics library at runtime (using `LoadLibrary`) instead of load time (using an import in the PE header). Results are a bit clearer: 26 | 27 | ``` 28 | [.] Running from Z:\win32k-mitigation.exe 29 | [.] Child process created: pid 5000 30 | [.] Child process started successfully 31 | [+] Child running with filtered Win32k syscalls 32 | 33 | [.] Trying all gdi32full dependencies: 34 | [!] Unable to load GDI32.dll: code 8 35 | [!] Unable to load USER32.dll: code 8 36 | 37 | [.] Trying all user32 dependencies: 38 | [!] Unable to load GDI32.dll: code 8 39 | 40 | [.] Trying all gdi32 dependencies: 41 | [!] Unable to load api-ms-win-gdi-internal-uap-l1-1-0.dll: code 8 42 | 43 | [+] Child exiting successfully 44 | [.] Child process exited with code 0x00000000 45 | [.] All done, return code 0 46 | ``` 47 | 48 | With runtime loading, we can see exactly at which loading step `LoadLibrary()` fails (with a `ERROR_NOT_ENOUGH_MEMORY` code, this time (?)). It seems loading any one of user32.dll or gdi32.dll will fail because of `api-ms-win-gdi-internal-uap-l1-1-0.dll`. This is not an actual DLL name, but an [ApiSet](https://docs.microsoft.com/en-us/windows/desktop/apiindex/windows-apisets), so we have to get back to runtime debugging to sort it out. To be continued... 49 | 50 | # TODO 51 | 52 | - Find out whether SetProcessMitigationPolicy() actually enforces the restriction flag on all existing threads, and where 53 | - Find out if there is a way to generically stub win32k system calls at DLL load time 54 | - Automate (e.g. JS WinDBG script) listing filtered/non-filtered Win32k syscalls 55 | 56 | # References 57 | 58 | - [MSDN documentation on SetProcessMitigationPolicy](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setprocessmitigationpolicy) 59 | - [MSDN documentation on the system call disable policy](https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-process_mitigation_system_call_disable_policy) 60 | - [Win32k System Call Filtering Deep Dive - Morten Schenk](https://improsec.com/tech-blog/win32k-system-call-filtering-deep-dive) 61 | - [The Windows Sandbox Paradox - James Forshaw Nullcon 2015](https://nullcon.net/website/archives/ppt/goa-15/the-windows-sandbox-paradox.pdf) 62 | -------------------------------------------------------------------------------- /win32k-mitigation.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {C2211BE4-6A40-4295-9EEB-BED1D53B5BD3} 24 | win32kmitigation 25 | 10.0.17763.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | false 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | false 42 | 43 | 44 | Application 45 | true 46 | v141 47 | Unicode 48 | false 49 | 50 | 51 | Application 52 | false 53 | v141 54 | true 55 | Unicode 56 | false 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | $(SolutionDir)$(Platform)\$(Configuration)\ 78 | $(Platform)\$(Configuration)\ 79 | false 80 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include 81 | 82 | 83 | $(SolutionDir)$(Platform)\$(Configuration)\ 84 | $(Platform)\$(Configuration)\ 85 | false 86 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include 87 | 88 | 89 | false 90 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include 91 | 92 | 93 | false 94 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)\include 95 | 96 | 97 | 98 | Level4 99 | Disabled 100 | true 101 | true 102 | true 103 | MultiThreadedDebug 104 | CompileAsC 105 | ProgramDatabase 106 | 107 | 108 | true 109 | Console 110 | 111 | 112 | 113 | 114 | Level4 115 | Disabled 116 | true 117 | true 118 | true 119 | MultiThreadedDebug 120 | CompileAsC 121 | ProgramDatabase 122 | 123 | 124 | true 125 | Console 126 | 127 | 128 | 129 | 130 | Level4 131 | MaxSpeed 132 | true 133 | true 134 | true 135 | true 136 | true 137 | MultiThreaded 138 | CompileAsC 139 | 140 | 141 | true 142 | true 143 | true 144 | Console 145 | 146 | 147 | 148 | 149 | Level4 150 | MaxSpeed 151 | true 152 | true 153 | true 154 | true 155 | true 156 | MultiThreaded 157 | CompileAsC 158 | 159 | 160 | true 161 | true 162 | true 163 | Console 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "mem.h" 5 | 6 | static BOOL TestLoadLib(PCTSTR swzName) 7 | { 8 | if (LoadLibrary(swzName) == NULL) 9 | { 10 | _tprintf(TEXT(" [!] Unable to load %s: code %u\n"), swzName, GetLastError()); 11 | return FALSE; 12 | } 13 | return TRUE; 14 | } 15 | 16 | int _tmain(int argc, PCTSTR argv[]) 17 | { 18 | int res = 0; 19 | HMODULE hSelf = NULL; 20 | TCHAR swzSelfPath[MAX_PATH + 1] = { 0 }; 21 | PPROC_THREAD_ATTRIBUTE_LIST pAttr = NULL; 22 | SIZE_T dwBufLen = 0; 23 | DWORD dwMitigationPolicy = PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; 24 | STARTUPINFOEX startInfo = { 0 }; 25 | PROCESS_INFORMATION procInfo = { 0 }; 26 | DWORD dwExitCode = 0; 27 | PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY effectivePolicy = { 0 }; 28 | 29 | if (argc >= 1 && _tcsicmp(argv[0], TEXT("self-run")) == 0) 30 | { 31 | _tprintf(TEXT(" [.] Child process started successfully\n")); 32 | 33 | if (!GetProcessMitigationPolicy(GetCurrentProcess(), ProcessSystemCallDisablePolicy, &effectivePolicy, sizeof(effectivePolicy))) 34 | { 35 | _tprintf(TEXT(" [!] Could not query system call filter policy in child: code %u\n"), GetLastError()); 36 | } 37 | else if (!effectivePolicy.DisallowWin32kSystemCalls) 38 | { 39 | _tprintf(TEXT(" [!] Child running with no filtering on Win32k syscalls\n")); 40 | } 41 | else 42 | { 43 | _tprintf(TEXT(" [+] Child running with filtered Win32k syscalls\n")); 44 | } 45 | 46 | if (LoadLibrary(TEXT("gdi32full.dll")) == NULL) 47 | { 48 | _tprintf(TEXT("\n")); 49 | _tprintf(TEXT(" [.] Trying all gdi32full dependencies:\n")); 50 | TestLoadLib(TEXT("msvcp_win.dll")); 51 | TestLoadLib(TEXT("api-ms-win-crt-string-l1-1-0.dll")); 52 | TestLoadLib(TEXT("api-ms-win-crt-runtime-l1-1-0.dll")); 53 | TestLoadLib(TEXT("api-ms-win-crt-private-l1-1-0.dll")); 54 | TestLoadLib(TEXT("api-ms-win-core-string-l1-1-0.dll")); 55 | TestLoadLib(TEXT("api-ms-win-core-localization-l1-2-0.dll")); 56 | TestLoadLib(TEXT("api-ms-win-core-heap-l2-1-0.dll")); 57 | TestLoadLib(TEXT("api-ms-win-core-rtlsupport-l1-1-0.dll")); 58 | TestLoadLib(TEXT("api-ms-win-core-libraryloader-l1-2-0.dll")); 59 | TestLoadLib(TEXT("api-ms-win-core-sysinfo-l1-1-0.dll")); 60 | TestLoadLib(TEXT("api-ms-win-core-memory-l1-1-1.dll")); 61 | TestLoadLib(TEXT("api-ms-win-core-errorhandling-l1-1-0.dll")); 62 | TestLoadLib(TEXT("api-ms-win-core-processenvironment-l1-1-0.dll")); 63 | TestLoadLib(TEXT("api-ms-win-core-file-l1-1-0.dll")); 64 | TestLoadLib(TEXT("api-ms-win-core-handle-l1-1-0.dll")); 65 | TestLoadLib(TEXT("api-ms-win-core-registry-l1-1-0.dll")); 66 | TestLoadLib(TEXT("api-ms-win-core-file-l1-2-0.dll")); 67 | TestLoadLib(TEXT("api-ms-win-core-synch-l1-1-0.dll")); 68 | TestLoadLib(TEXT("api-ms-win-core-heap-l1-1-0.dll")); 69 | TestLoadLib(TEXT("api-ms-win-core-file-l2-1-0.dll")); 70 | TestLoadLib(TEXT("api-ms-win-core-memory-l1-1-0.dll")); 71 | TestLoadLib(TEXT("api-ms-win-core-threadpool-l1-2-0.dll")); 72 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-0.dll")); 73 | TestLoadLib(TEXT("api-ms-win-core-debug-l1-1-0.dll")); 74 | TestLoadLib(TEXT("api-ms-win-core-string-l2-1-0.dll")); 75 | TestLoadLib(TEXT("api-ms-win-security-base-l1-1-0.dll")); 76 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-1.dll")); 77 | TestLoadLib(TEXT("api-ms-win-core-profile-l1-1-0.dll")); 78 | TestLoadLib(TEXT("api-ms-win-core-interlocked-l1-1-0.dll")); 79 | TestLoadLib(TEXT("api-ms-win-core-kernel32-legacy-l1-1-0.dll")); 80 | TestLoadLib(TEXT("api-ms-win-core-heap-obsolete-l1-1-0.dll")); 81 | TestLoadLib(TEXT("api-ms-win-core-string-obsolete-l1-1-0.dll")); 82 | TestLoadLib(TEXT("api-ms-win-core-stringansi-l1-1-0.dll")); 83 | TestLoadLib(TEXT("ntdll.dll")); 84 | TestLoadLib(TEXT("win32u.dll")); 85 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-1.dll")); 86 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-0.dll")); 87 | TestLoadLib(TEXT("api-ms-win-core-privateprofile-l1-1-0.dll")); 88 | TestLoadLib(TEXT("api-ms-win-core-localization-private-l1-1-0.dll")); 89 | TestLoadLib(TEXT("GDI32.dll")); 90 | TestLoadLib(TEXT("USER32.dll")); 91 | _tprintf(TEXT("\n")); 92 | 93 | if (LoadLibrary(TEXT("USER32.dll")) == NULL) 94 | { 95 | _tprintf(TEXT("\n")); 96 | _tprintf(TEXT(" [.] Trying all user32 dependencies:\n")); 97 | TestLoadLib(TEXT("win32u.dll")); 98 | TestLoadLib(TEXT("ntdll.dll")); 99 | TestLoadLib(TEXT("api-ms-win-core-localization-l1-2-0.dll")); 100 | TestLoadLib(TEXT("api-ms-win-core-registry-l1-1-0.dll")); 101 | TestLoadLib(TEXT("api-ms-win-core-heap-l2-1-0.dll")); 102 | TestLoadLib(TEXT("api-ms-win-core-libraryloader-l1-2-0.dll")); 103 | TestLoadLib(TEXT("api-ms-win-eventing-provider-l1-1-0.dll")); 104 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-0.dll")); 105 | TestLoadLib(TEXT("api-ms-win-core-synch-l1-1-0.dll")); 106 | TestLoadLib(TEXT("api-ms-win-core-string-l1-1-0.dll")); 107 | TestLoadLib(TEXT("api-ms-win-core-sysinfo-l1-1-0.dll")); 108 | TestLoadLib(TEXT("api-ms-win-security-base-l1-1-0.dll")); 109 | TestLoadLib(TEXT("api-ms-win-core-handle-l1-1-0.dll")); 110 | TestLoadLib(TEXT("api-ms-win-core-errorhandling-l1-1-0.dll")); 111 | TestLoadLib(TEXT("api-ms-win-core-string-l2-1-0.dll")); 112 | TestLoadLib(TEXT("api-ms-win-core-synch-l1-2-0.dll")); 113 | TestLoadLib(TEXT("api-ms-win-core-processenvironment-l1-1-0.dll")); 114 | TestLoadLib(TEXT("api-ms-win-core-file-l1-1-0.dll")); 115 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-1.dll")); 116 | TestLoadLib(TEXT("api-ms-win-core-memory-l1-1-0.dll")); 117 | TestLoadLib(TEXT("api-ms-win-core-profile-l1-1-0.dll")); 118 | TestLoadLib(TEXT("api-ms-win-core-heap-l1-1-0.dll")); 119 | TestLoadLib(TEXT("api-ms-win-core-memory-l1-1-3.dll")); 120 | TestLoadLib(TEXT("api-ms-win-core-privateprofile-l1-1-0.dll")); 121 | TestLoadLib(TEXT("api-ms-win-core-atoms-l1-1-0.dll")); 122 | TestLoadLib(TEXT("api-ms-win-core-heap-obsolete-l1-1-0.dll")); 123 | TestLoadLib(TEXT("api-ms-win-core-string-obsolete-l1-1-0.dll")); 124 | TestLoadLib(TEXT("api-ms-win-core-localization-obsolete-l1-2-0.dll")); 125 | TestLoadLib(TEXT("api-ms-win-core-stringansi-l1-1-0.dll")); 126 | TestLoadLib(TEXT("api-ms-win-core-sidebyside-l1-1-0.dll")); 127 | TestLoadLib(TEXT("api-ms-win-core-kernel32-private-l1-1-0.dll")); 128 | TestLoadLib(TEXT("KERNELBASE.dll")); 129 | TestLoadLib(TEXT("api-ms-win-core-kernel32-legacy-l1-1-0.dll")); 130 | TestLoadLib(TEXT("api-ms-win-core-appinit-l1-1-0.dll")); 131 | TestLoadLib(TEXT("GDI32.dll")); 132 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-1.dll")); 133 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-0.dll")); 134 | TestLoadLib(TEXT("api-ms-win-core-apiquery-l1-1-0.dll")); 135 | _tprintf(TEXT("\n")); 136 | } 137 | 138 | if (LoadLibrary(TEXT("GDI32.dll")) == NULL) 139 | { 140 | _tprintf(TEXT("\n")); 141 | _tprintf(TEXT(" [.] Trying all gdi32 dependencies:\n")); 142 | TestLoadLib(TEXT("ntdll.dll")); 143 | TestLoadLib(TEXT("api-ms-win-core-heap-l2-1-0.dll")); 144 | TestLoadLib(TEXT("api-ms-win-core-libraryloader-l1-2-0.dll")); 145 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-1.dll")); 146 | TestLoadLib(TEXT("api-ms-win-core-processthreads-l1-1-0.dll")); 147 | TestLoadLib(TEXT("api-ms-win-core-profile-l1-1-0.dll")); 148 | TestLoadLib(TEXT("api-ms-win-core-sysinfo-l1-1-0.dll")); 149 | TestLoadLib(TEXT("api-ms-win-core-errorhandling-l1-1-0.dll")); 150 | TestLoadLib(TEXT("api-ms-win-gdi-internal-uap-l1-1-0.dll")); 151 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-1.dll")); 152 | TestLoadLib(TEXT("api-ms-win-core-delayload-l1-1-0.dll")); 153 | TestLoadLib(TEXT("api-ms-win-core-apiquery-l1-1-0.dll")); 154 | _tprintf(TEXT("\n")); 155 | } 156 | } 157 | 158 | _tprintf(TEXT(" [+] Child exiting successfully\n")); 159 | ExitProcess(0); 160 | } 161 | 162 | hSelf = GetModuleHandle(NULL); 163 | GetModuleFileName(hSelf, swzSelfPath, MAX_PATH); 164 | 165 | _tprintf(TEXT(" [.] Running from %s\n"), swzSelfPath); 166 | 167 | if (InitializeProcThreadAttributeList(NULL, 1, 0, &dwBufLen) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) 168 | { 169 | res = GetLastError(); 170 | _ftprintf(stderr, TEXT("Error: unable to get InitializeProcThreadAttributeList()'s required buffer length, code %u\n"), res); 171 | goto cleanup; 172 | } 173 | pAttr = (PPROC_THREAD_ATTRIBUTE_LIST)safe_alloc(dwBufLen); 174 | if (!InitializeProcThreadAttributeList(pAttr, 1, 0, &dwBufLen)) 175 | { 176 | res = GetLastError(); 177 | _ftprintf(stderr, TEXT("Error: InitializeProcThreadAttributeList() failed with code %d\n"), res); 178 | goto cleanup; 179 | } 180 | if (!UpdateProcThreadAttribute(pAttr, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &dwMitigationPolicy, sizeof(dwMitigationPolicy), NULL, NULL)) 181 | { 182 | res = GetLastError(); 183 | _ftprintf(stderr, TEXT("Error: UpdateProcThreadAttribute() failed with code %d\n"), res); 184 | goto cleanup; 185 | } 186 | 187 | ZeroMemory(&startInfo, sizeof(startInfo)); 188 | ZeroMemory(&procInfo, sizeof(procInfo)); 189 | startInfo.lpAttributeList = pAttr; 190 | startInfo.StartupInfo.cb = sizeof(startInfo); 191 | 192 | if (!CreateProcess(swzSelfPath, TEXT("self-run"), NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, (STARTUPINFO*)&startInfo, &procInfo)) 193 | { 194 | res = GetLastError(); 195 | _ftprintf(stderr, TEXT("Error: CreateProcess() failed with code %d\n"), res); 196 | goto cleanup; 197 | } 198 | 199 | _tprintf(TEXT(" [.] Child process created: pid %u\n"), procInfo.dwProcessId); 200 | 201 | WaitForSingleObject(procInfo.hProcess, INFINITE); 202 | 203 | if (!GetExitCodeProcess(procInfo.hProcess, &dwExitCode)) 204 | { 205 | res = GetLastError(); 206 | _ftprintf(stderr, TEXT("Error: GetExitCodeProcess() failed with code %d\n"), res); 207 | } 208 | else 209 | { 210 | _tprintf(TEXT(" [.] Child process exited with code 0x%08X\n"), dwExitCode); 211 | } 212 | 213 | cleanup: 214 | _tprintf(TEXT(" [.] All done, return code %d\n"), res); 215 | return res; 216 | } --------------------------------------------------------------------------------