http://uninformed.org/index.cgi?v=8&a=2&p=20 Currently this only works for Windows 8+. The RTL_INVERTED_FUNCTION_TABLE memory layout is different for x86 on older platforms
| 264 | // Currently this only works for Windows 8+. |
| 265 | // The RTL_INVERTED_FUNCTION_TABLE memory layout is different for x86 on older platforms |
| 266 | void RtlpInsertInvertedFunctionTableEntry(PVOID ImageBase, ULONG ImageSize, PVOID ExceptionDirectory, ULONG ExceptionDirectorySize) { |
| 267 | |
| 268 | uintptr_t mrData = 0; |
| 269 | DWORD mrDataSize = 0; |
| 270 | auto table = FindLdrpInvertedFunctionTable(mrData, mrDataSize); |
| 271 | DWORD oldProtect = 0; |
| 272 | |
| 273 | if (table == nullptr) { |
| 274 | throw std::runtime_error("[!] Failed to find LdrpInvertedFunctionTable\n"); |
| 275 | } |
| 276 | |
| 277 | VirtualProtect(PVOID(mrData), mrDataSize, PAGE_READWRITE, &oldProtect); |
| 278 | |
| 279 | auto entryIndex = 1; |
| 280 | |
| 281 | if (table->Count == table->MaxCount) { |
| 282 | table->Overflow = 1; |
| 283 | } |
| 284 | else { |
| 285 | |
| 286 | InterlockedIncrement(&table->Epoch); |
| 287 | entryIndex = 1; |
| 288 | |
| 289 | if (table->Count != 1) { |
| 290 | while (entryIndex < table->Count) { |
| 291 | if (ImageBase < table->Entries[entryIndex].ImageBase) { |
| 292 | break; |
| 293 | } |
| 294 | entryIndex++; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | if (entryIndex != table->Count) { |
| 299 | memmove(&table->Entries[entryIndex + 1], |
| 300 | &table->Entries[entryIndex], |
| 301 | (table->Count - entryIndex) * sizeof(INVERTED_FUNCTION_TABLE_ENTRY)); |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | table->Entries[entryIndex].ImageBase = ImageBase; |
| 306 | table->Entries[entryIndex].SizeOfImage = ImageSize; |
| 307 | #if defined(__x86_64__) || defined(_M_X64) |
| 308 | table->Entries[entryIndex].FunctionTable = (IMAGE_RUNTIME_FUNCTION_ENTRY*)ExceptionDirectory; |
| 309 | #else |
| 310 | //x86 function table addresses are masked for additional protection |
| 311 | table->Entries[entryIndex].FunctionTable = (IMAGE_RUNTIME_FUNCTION_ENTRY*)RtlEncodeSystemPointer(ExceptionDirectory); |
| 312 | #endif |
| 313 | table->Entries[entryIndex].SizeOfTable = ExceptionDirectorySize; |
| 314 | table->Count++; |
| 315 | InterlockedIncrement(&table->Epoch); |
| 316 | |
| 317 | VirtualProtect(PVOID(mrData), mrDataSize, oldProtect, &oldProtect); |
| 318 | } |
| 319 | |
| 320 | void RtlpDeleteInvertedFunctionTableEntry(PVOID ImageBase) { |
| 321 |
no test coverage detected