| 1185 | static size_t vmread(size_t field); |
| 1186 | |
| 1187 | class EptHandler final |
| 1188 | { |
| 1189 | private: |
| 1190 | EPT_TABLES* m_Ept; |
| 1191 | std::unordered_map<uint64_t, LARGE_PAGE_DESCRIPTOR> m_PageDescriptors; // Guest PA (aligned by 2Mb) -> 4Kb PTEs describing a 2Mb page |
| 1192 | std::unordered_map<uint64_t, EPT_PTE_HANDLER> m_Handlers; // Guest PA (aligned by 4Kb) -> Page handlers (EPT entries for RWX) |
| 1193 | VMX::INVEPT_DESCRIPTOR m_InveptDescriptor; |
| 1194 | |
| 1195 | struct |
| 1196 | { |
| 1197 | const void* Rip; |
| 1198 | EPT_PTE* Pte; |
| 1199 | EPT_PTE PendingPrevEntry; |
| 1200 | } m_PendingHandler; |
| 1201 | |
| 1202 | constexpr static unsigned int PageSize = 4096; |
| 1203 | constexpr static unsigned int LargePageSize = 2 * 1048576; |
| 1204 | |
| 1205 | inline void invept() |
| 1206 | { |
| 1207 | __invept(VMX::INVEPT_TYPE::SingleContextInvalidation, &m_InveptDescriptor); |
| 1208 | } |
| 1209 | |
| 1210 | public: |
| 1211 | EptHandler(__in EPT_TABLES* Ept) |
| 1212 | : m_Ept(Ept) |
| 1213 | , m_PendingHandler({}) |
| 1214 | , m_InveptDescriptor({}) |
| 1215 | {} |
| 1216 | |
| 1217 | ~EptHandler() |
| 1218 | { |
| 1219 | for (auto& [_, Desc] : m_PageDescriptors) |
| 1220 | { |
| 1221 | *Desc.Pde = Desc.OriginalPde; |
| 1222 | Supplementation::FreePhys(Desc.Layout); |
| 1223 | } |
| 1224 | } |
| 1225 | |
| 1226 | void CompleteInitialization(VMX::EPTP Eptp) |
| 1227 | { |
| 1228 | m_InveptDescriptor.Eptp = Eptp.Value; |
| 1229 | } |
| 1230 | |
| 1231 | void InterceptPage( |
| 1232 | unsigned long long Pa, |
| 1233 | unsigned long long ReadPa, |
| 1234 | unsigned long long WritePa, |
| 1235 | unsigned long long ExecutePa, |
| 1236 | unsigned long long ExecuteReadPa, |
| 1237 | unsigned long long ExecuteWritePa |
| 1238 | ) { |
| 1239 | unsigned long long Pa4Kb = ALIGN_DOWN_BY(Pa, PageSize); |
| 1240 | auto HandlerEntry = m_Handlers.find(Pa4Kb); |
| 1241 | if (HandlerEntry != m_Handlers.end()) |
| 1242 | { |
| 1243 | PAGE_HANDLER Handler = {}; |
| 1244 | BuildPageHandler(static_cast<MTRR_MEMORY_TYPE>(HandlerEntry->second.Handlers.OnRead.Page4Kb.Type), ReadPa, WritePa, ExecutePa, ExecuteReadPa, ExecuteWritePa, OUT Handler); |
nothing calls this directly
no outgoing calls
no test coverage detected