// This file contains code from // https://github.com/stevemk14ebr/PolyHook_2_0/blob/master/sources/IatHook.cpp // which is licensed under the MIT License. // See PolyHook_2_0-LICENSE for more information. #pragma once template constexpr T RVA2VA(T1 base, T2 rva) { return reinterpret_cast(reinterpret_cast(base) + rva); } template constexpr T DataDirectoryFromModuleBase(void *moduleBase, size_t entryID) { auto dosHdr = reinterpret_cast(moduleBase); auto ntHdr = RVA2VA(moduleBase, dosHdr->e_lfanew); auto dataDir = ntHdr->OptionalHeader.DataDirectory; return RVA2VA(moduleBase, dataDir[entryID].VirtualAddress); } PIMAGE_THUNK_DATA FindAddressByName(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, const char *funcName) { for (; impName->u1.Ordinal; ++impName, ++impAddr) { if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal)) continue; auto import = RVA2VA(moduleBase, impName->u1.AddressOfData); if (strcmp(import->Name, funcName) != 0) continue; return impAddr; } return nullptr; } PIMAGE_THUNK_DATA FindAddressByOrdinal(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, uint16_t ordinal) { for (; impName->u1.Ordinal; ++impName, ++impAddr) { if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal) && IMAGE_ORDINAL(impName->u1.Ordinal) == ordinal) return impAddr; } return nullptr; } PIMAGE_THUNK_DATA FindIatThunkInModule(void *moduleBase, const char *dllName, const char *funcName) { auto imports = DataDirectoryFromModuleBase(moduleBase, IMAGE_DIRECTORY_ENTRY_IMPORT); for (; imports->Name; ++imports) { if (_stricmp(RVA2VA(moduleBase, imports->Name), dllName) != 0) continue; auto origThunk = RVA2VA(moduleBase, imports->OriginalFirstThunk); auto thunk = RVA2VA(moduleBase, imports->FirstThunk); return FindAddressByName(moduleBase, origThunk, thunk, funcName); } return nullptr; } PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, const char *funcName) { auto imports = DataDirectoryFromModuleBase(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); for (; imports->DllNameRVA; ++imports) { if (_stricmp(RVA2VA(moduleBase, imports->DllNameRVA), dllName) != 0) continue; auto impName = RVA2VA(moduleBase, imports->ImportNameTableRVA); auto impAddr = RVA2VA(moduleBase, imports->ImportAddressTableRVA); return FindAddressByName(moduleBase, impName, impAddr, funcName); } return nullptr; } PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, uint16_t ordinal) { auto imports = DataDirectoryFromModuleBase(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); for (; imports->DllNameRVA; ++imports) { if (_stricmp(RVA2VA(moduleBase, imports->DllNameRVA), dllName) != 0) continue; auto impName = RVA2VA(moduleBase, imports->ImportNameTableRVA); auto impAddr = RVA2VA(moduleBase, imports->ImportAddressTableRVA); return FindAddressByOrdinal(moduleBase, impName, impAddr, ordinal); } return nullptr; }