dllmain.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. #include "framework.h"
  2. #include "exception.hpp"
  3. HMODULE hm;
  4. std::vector<std::wstring> iniPaths;
  5. bool iequals(std::wstring_view s1, std::wstring_view s2)
  6. {
  7. std::wstring str1(std::move(s1));
  8. std::wstring str2(std::move(s2));
  9. std::transform(str1.begin(), str1.end(), str1.begin(), [](wchar_t c) { return ::towlower(c); });
  10. std::transform(str2.begin(), str2.end(), str2.begin(), [](wchar_t c) { return ::towlower(c); });
  11. return (str1 == str2);
  12. }
  13. std::wstring to_wstring(std::string_view cstr)
  14. {
  15. std::string str(std::move(cstr));
  16. auto charsReturned = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
  17. std::wstring wstrTo(charsReturned, 0);
  18. MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], charsReturned);
  19. return wstrTo;
  20. }
  21. std::wstring SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken)
  22. {
  23. std::wstring r;
  24. WCHAR* szSystemPath = nullptr;
  25. if (SUCCEEDED(SHGetKnownFolderPath(rfid, dwFlags, hToken, &szSystemPath)))
  26. {
  27. r = szSystemPath;
  28. }
  29. CoTaskMemFree(szSystemPath);
  30. return r;
  31. };
  32. HMODULE LoadLibraryW(const std::wstring& lpLibFileName)
  33. {
  34. return LoadLibraryW(lpLibFileName.c_str());
  35. }
  36. std::wstring GetCurrentDirectoryW()
  37. {
  38. static constexpr auto INITIAL_BUFFER_SIZE = MAX_PATH;
  39. static constexpr auto MAX_ITERATIONS = 7;
  40. std::wstring ret;
  41. auto bufferSize = INITIAL_BUFFER_SIZE;
  42. for (size_t iterations = 0; iterations < MAX_ITERATIONS; ++iterations)
  43. {
  44. ret.resize(bufferSize);
  45. auto charsReturned = GetCurrentDirectoryW(bufferSize, &ret[0]);
  46. if (charsReturned < ret.length())
  47. {
  48. ret.resize(charsReturned);
  49. return ret;
  50. }
  51. else
  52. {
  53. bufferSize *= 2;
  54. }
  55. }
  56. return L"";
  57. }
  58. UINT GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, const std::vector<std::wstring>& fileNames)
  59. {
  60. for (const auto& file : fileNames)
  61. {
  62. nDefault = GetPrivateProfileIntW(lpAppName, lpKeyName, nDefault, file.c_str());
  63. }
  64. return nDefault;
  65. }
  66. std::wstring GetSelfName()
  67. {
  68. const std::wstring moduleFileName = GetModuleFileNameW(hm);
  69. return moduleFileName.substr(moduleFileName.find_last_of(L"/\\") + 1);
  70. }
  71. template<typename T, typename... Args>
  72. void GetSections(T&& h, Args... args)
  73. {
  74. const std::set< std::string_view, std::less<> > s = { args... };
  75. size_t dwLoadOffset = (size_t)GetModuleHandle(NULL);
  76. BYTE* pImageBase = reinterpret_cast<BYTE*>(dwLoadOffset);
  77. PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(dwLoadOffset);
  78. PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(pImageBase + pDosHeader->e_lfanew);
  79. PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeader);
  80. for (int iSection = 0; iSection < pNtHeader->FileHeader.NumberOfSections; ++iSection, ++pSection)
  81. {
  82. auto pszSectionName = reinterpret_cast<const char*>(pSection->Name);
  83. if (s.find(pszSectionName) != s.end())
  84. {
  85. DWORD dwPhysSize = (pSection->Misc.VirtualSize + 4095) & ~4095;
  86. std::forward<T>(h)(pSection, dwLoadOffset, dwPhysSize);
  87. }
  88. }
  89. }
  90. enum Kernel32ExportsNames
  91. {
  92. eGetStartupInfoA,
  93. eGetStartupInfoW,
  94. eGetModuleHandleA,
  95. eGetModuleHandleW,
  96. eGetProcAddress,
  97. eGetShortPathNameA,
  98. eFindNextFileA,
  99. eFindNextFileW,
  100. eLoadLibraryA,
  101. eLoadLibraryW,
  102. eFreeLibrary,
  103. eCreateEventA,
  104. eCreateEventW,
  105. eGetSystemInfo,
  106. eInterlockedCompareExchange,
  107. eSleep,
  108. Kernel32ExportsNamesCount
  109. };
  110. enum Kernel32ExportsData
  111. {
  112. IATPtr,
  113. ProcAddress,
  114. Kernel32ExportsDataCount
  115. };
  116. size_t Kernel32Data[Kernel32ExportsNamesCount][Kernel32ExportsDataCount];
  117. static LONG OriginalLibraryLoaded = 0;
  118. void LoadOriginalLibrary()
  119. {
  120. if (_InterlockedCompareExchange(&OriginalLibraryLoaded, 1, 0) != 0) return;
  121. auto szSelfName = GetSelfName();
  122. auto szSystemPath = SHGetKnownFolderPath(FOLDERID_System, 0, nullptr) + L'\\' + szSelfName;
  123. auto szLocalPath = GetModuleFileNameW(hm); szLocalPath = szLocalPath.substr(0, szLocalPath.find_last_of(L"/\\") + 1);
  124. if (iequals(szSelfName, L"dnsapi.dll")) {
  125. dnsapi.LoadOriginalLibrary(LoadLibraryW(szSystemPath));
  126. }
  127. }
  128. void FindFiles(WIN32_FIND_DATAW* fd)
  129. {
  130. auto dir = GetCurrentDirectoryW();
  131. HANDLE dvaFile = FindFirstFileW(L"*.dva", fd);
  132. if (dvaFile != INVALID_HANDLE_VALUE)
  133. {
  134. do {
  135. if (!(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  136. {
  137. auto pos = wcslen(fd->cFileName);
  138. if (fd->cFileName[pos - 4] == '.' &&
  139. (fd->cFileName[pos - 3] == 'd' || fd->cFileName[pos - 3] == 'D') &&
  140. (fd->cFileName[pos - 2] == 'v' || fd->cFileName[pos - 2] == 'V') &&
  141. (fd->cFileName[pos - 1] == 'a' || fd->cFileName[pos - 1] == 'A'))
  142. {
  143. auto path = dir + L'\\' + fd->cFileName;
  144. if (GetModuleHandle(path.c_str()) == NULL)
  145. {
  146. auto h = LoadLibraryW(path);
  147. SetCurrentDirectoryW(dir.c_str()); //in case dva switched it
  148. if (h == NULL)
  149. {
  150. auto e = GetLastError();
  151. if (e != ERROR_DLL_INIT_FAILED) // in case dllmain returns false
  152. {
  153. std::wstring msg = L"Unable to load " + std::wstring(fd->cFileName) + L". Error: " + std::to_wstring(e);
  154. MessageBoxW(0, msg.c_str(), L"PD Loader", MB_ICONERROR);
  155. }
  156. }
  157. else
  158. {
  159. auto procedure = (void(*)())GetProcAddress(h, "InitializeDVA");
  160. if (procedure != NULL)
  161. {
  162. procedure();
  163. }
  164. }
  165. }
  166. }
  167. }
  168. } while (FindNextFileW(dvaFile, fd));
  169. FindClose(dvaFile);
  170. }
  171. }
  172. void LoadPlugins()
  173. {
  174. auto oldDir = GetCurrentDirectoryW(); // store the current directory
  175. auto szSelfPath = GetModuleFileNameW(hm).substr(0, GetModuleFileNameW(hm).find_last_of(L"/\\") + 1);
  176. SetCurrentDirectoryW(szSelfPath.c_str());
  177. auto nWantsToLoadPlugins = GetPrivateProfileIntW(L"global", L"enable", TRUE, iniPaths);
  178. if (nWantsToLoadPlugins)
  179. {
  180. WIN32_FIND_DATAW fd;
  181. SetCurrentDirectoryW(szSelfPath.c_str());
  182. if (SetCurrentDirectoryW(L"plugins\\"))
  183. FindFiles(&fd);
  184. }
  185. SetCurrentDirectoryW(oldDir.c_str()); // Reset the current directory
  186. }
  187. void InjectCode(void* address, const std::vector<uint8_t> data)
  188. {
  189. const size_t byteCount = data.size() * sizeof(uint8_t);
  190. DWORD oldProtect;
  191. VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect);
  192. memcpy(address, data.data(), byteCount);
  193. VirtualProtect(address, byteCount, oldProtect, nullptr);
  194. }
  195. static LONG LoadedPluginsYet = 0;
  196. void LoadEverything()
  197. {
  198. if (_InterlockedCompareExchange(&LoadedPluginsYet, 1, 0) != 0) return;
  199. LoadOriginalLibrary();
  200. //LoadPlugins();
  201. InjectCode((void*)0x00000001409FF58E, { 0x52, 0x54, 0x46, 0x4D });
  202. InjectCode((void*)0x00000001409FF730, { 0x53, 0x65, 0x65, 0x20, 0x52, 0x45, 0x41, 0x44, 0x4D, 0x45, 0x2E, 0x74, 0x78, 0x74, 0x2E, 0x00, 0x00 });
  203. }
  204. static LONG RestoredOnce = 0;
  205. void LoadPluginsAndRestoreIAT(uintptr_t retaddr)
  206. {
  207. bool calledFromBind = false;
  208. //steam drm check
  209. GetSections([&](PIMAGE_SECTION_HEADER pSection, size_t dwLoadOffset, DWORD dwPhysSize) {
  210. auto dwStart = static_cast<uintptr_t>(dwLoadOffset + pSection->VirtualAddress);
  211. auto dwEnd = dwStart + dwPhysSize;
  212. if (retaddr >= dwStart && retaddr <= dwEnd)
  213. calledFromBind = true;
  214. }, ".bind");
  215. if (calledFromBind) return;
  216. if (_InterlockedCompareExchange(&RestoredOnce, 1, 0) != 0) return;
  217. LoadEverything();
  218. for (size_t i = 0; i < Kernel32ExportsNamesCount; i++)
  219. {
  220. if (Kernel32Data[i][IATPtr] && Kernel32Data[i][ProcAddress])
  221. {
  222. auto ptr = (size_t*)Kernel32Data[i][IATPtr];
  223. DWORD dwProtect[2];
  224. VirtualProtect(ptr, sizeof(size_t), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
  225. *ptr = Kernel32Data[i][ProcAddress];
  226. VirtualProtect(ptr, sizeof(size_t), dwProtect[0], &dwProtect[1]);
  227. }
  228. }
  229. }
  230. void WINAPI CustomGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
  231. {
  232. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  233. return GetStartupInfoA(lpStartupInfo);
  234. }
  235. void WINAPI CustomGetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
  236. {
  237. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  238. return GetStartupInfoW(lpStartupInfo);
  239. }
  240. HMODULE WINAPI CustomGetModuleHandleA(LPCSTR lpModuleName)
  241. {
  242. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  243. return GetModuleHandleA(lpModuleName);
  244. }
  245. HMODULE WINAPI CustomGetModuleHandleW(LPCWSTR lpModuleName)
  246. {
  247. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  248. return GetModuleHandleW(lpModuleName);
  249. }
  250. FARPROC WINAPI CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
  251. {
  252. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  253. return GetProcAddress(hModule, lpProcName);
  254. }
  255. DWORD WINAPI CustomGetShortPathNameA(LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer)
  256. {
  257. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  258. return GetShortPathNameA(lpszLongPath, lpszShortPath, cchBuffer);
  259. }
  260. BOOL WINAPI CustomFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
  261. {
  262. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  263. return FindNextFileA(hFindFile, lpFindFileData);
  264. }
  265. BOOL WINAPI CustomFindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)
  266. {
  267. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  268. return FindNextFileW(hFindFile, lpFindFileData);
  269. }
  270. HMODULE WINAPI CustomLoadLibraryA(LPCSTR lpLibFileName)
  271. {
  272. LoadOriginalLibrary();
  273. return LoadLibraryA(lpLibFileName);
  274. }
  275. HMODULE WINAPI CustomLoadLibraryW(LPCWSTR lpLibFileName)
  276. {
  277. LoadOriginalLibrary();
  278. return LoadLibraryW(lpLibFileName);
  279. }
  280. BOOL WINAPI CustomFreeLibrary(HMODULE hLibModule)
  281. {
  282. if (hLibModule != hm)
  283. return FreeLibrary(hLibModule);
  284. else
  285. return !NULL;
  286. }
  287. HANDLE WINAPI CustomCreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName)
  288. {
  289. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  290. return CreateEventA(lpEventAttributes, bManualReset, bInitialState, lpName);
  291. }
  292. HANDLE WINAPI CustomCreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName)
  293. {
  294. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  295. return CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName);
  296. }
  297. void WINAPI CustomGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
  298. {
  299. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  300. return GetSystemInfo(lpSystemInfo);
  301. }
  302. LONG WINAPI CustomInterlockedCompareExchange(LONG volatile* Destination, LONG ExChange, LONG Comperand)
  303. {
  304. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  305. return _InterlockedCompareExchange(Destination, ExChange, Comperand);
  306. }
  307. void WINAPI CustomSleep(DWORD dwMilliseconds)
  308. {
  309. LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress());
  310. return Sleep(dwMilliseconds);
  311. }
  312. bool HookKernel32IAT(HMODULE mod, bool exe)
  313. {
  314. auto hExecutableInstance = (size_t)mod;
  315. IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)(hExecutableInstance + ((IMAGE_DOS_HEADER*)hExecutableInstance)->e_lfanew);
  316. IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)(hExecutableInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  317. size_t nNumImports = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;
  318. if (exe)
  319. {
  320. Kernel32Data[eGetStartupInfoA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetStartupInfoA");
  321. Kernel32Data[eGetStartupInfoW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetStartupInfoW");
  322. Kernel32Data[eGetModuleHandleA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetModuleHandleA");
  323. Kernel32Data[eGetModuleHandleW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetModuleHandleW");
  324. Kernel32Data[eGetProcAddress][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetProcAddress");
  325. Kernel32Data[eGetShortPathNameA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetShortPathNameA");
  326. Kernel32Data[eFindNextFileA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileA");
  327. Kernel32Data[eFindNextFileW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileW");
  328. Kernel32Data[eLoadLibraryA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryA");
  329. Kernel32Data[eLoadLibraryW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryW");
  330. Kernel32Data[eFreeLibrary][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FreeLibrary");
  331. Kernel32Data[eCreateEventA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateEventA");
  332. Kernel32Data[eCreateEventW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateEventW");
  333. Kernel32Data[eGetSystemInfo][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetSystemInfo");
  334. Kernel32Data[eInterlockedCompareExchange][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "InterlockedCompareExchange");
  335. Kernel32Data[eSleep][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "Sleep");
  336. }
  337. uint32_t matchedImports = 0;
  338. auto PatchIAT = [&](size_t start, size_t end, size_t exe_end)
  339. {
  340. for (size_t i = 0; i < nNumImports; i++)
  341. {
  342. if (hExecutableInstance + (pImports + i)->FirstThunk > start && !(end && hExecutableInstance + (pImports + i)->FirstThunk > end))
  343. end = hExecutableInstance + (pImports + i)->FirstThunk;
  344. }
  345. if (!end) { end = start + 0x100; }
  346. if (end > exe_end) //for very broken exes
  347. {
  348. start = hExecutableInstance;
  349. end = exe_end;
  350. }
  351. for (auto i = start; i < end; i += sizeof(size_t))
  352. {
  353. DWORD dwProtect[2];
  354. VirtualProtect((size_t*)i, sizeof(size_t), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
  355. auto ptr = *(size_t*)i;
  356. if (!ptr)
  357. continue;
  358. if (ptr == Kernel32Data[eGetStartupInfoA][ProcAddress])
  359. {
  360. if (exe) Kernel32Data[eGetStartupInfoA][IATPtr] = i;
  361. *(size_t*)i = (size_t)CustomGetStartupInfoA;
  362. matchedImports++;
  363. }
  364. else if (ptr == Kernel32Data[eGetStartupInfoW][ProcAddress])
  365. {
  366. if (exe) Kernel32Data[eGetStartupInfoW][IATPtr] = i;
  367. *(size_t*)i = (size_t)CustomGetStartupInfoW;
  368. matchedImports++;
  369. }
  370. else if (ptr == Kernel32Data[eGetModuleHandleA][ProcAddress])
  371. {
  372. if (exe) Kernel32Data[eGetModuleHandleA][IATPtr] = i;
  373. *(size_t*)i = (size_t)CustomGetModuleHandleA;
  374. matchedImports++;
  375. }
  376. else if (ptr == Kernel32Data[eGetModuleHandleW][ProcAddress])
  377. {
  378. if (exe) Kernel32Data[eGetModuleHandleW][IATPtr] = i;
  379. *(size_t*)i = (size_t)CustomGetModuleHandleW;
  380. matchedImports++;
  381. }
  382. else if (ptr == Kernel32Data[eGetProcAddress][ProcAddress])
  383. {
  384. if (exe) Kernel32Data[eGetProcAddress][IATPtr] = i;
  385. *(size_t*)i = (size_t)CustomGetProcAddress;
  386. matchedImports++;
  387. }
  388. else if (ptr == Kernel32Data[eGetShortPathNameA][ProcAddress])
  389. {
  390. if (exe) Kernel32Data[eGetShortPathNameA][IATPtr] = i;
  391. *(size_t*)i = (size_t)CustomGetShortPathNameA;
  392. matchedImports++;
  393. }
  394. else if (ptr == Kernel32Data[eFindNextFileA][ProcAddress])
  395. {
  396. if (exe) Kernel32Data[eFindNextFileA][IATPtr] = i;
  397. *(size_t*)i = (size_t)CustomFindNextFileA;
  398. matchedImports++;
  399. }
  400. else if (ptr == Kernel32Data[eFindNextFileW][ProcAddress])
  401. {
  402. if (exe) Kernel32Data[eFindNextFileW][IATPtr] = i;
  403. *(size_t*)i = (size_t)CustomFindNextFileW;
  404. matchedImports++;
  405. }
  406. else if (ptr == Kernel32Data[eLoadLibraryA][ProcAddress])
  407. {
  408. if (exe) Kernel32Data[eLoadLibraryA][IATPtr] = i;
  409. *(size_t*)i = (size_t)CustomLoadLibraryA;
  410. matchedImports++;
  411. }
  412. else if (ptr == Kernel32Data[eLoadLibraryW][ProcAddress])
  413. {
  414. if (exe) Kernel32Data[eLoadLibraryW][IATPtr] = i;
  415. *(size_t*)i = (size_t)CustomLoadLibraryW;
  416. matchedImports++;
  417. }
  418. else if (ptr == Kernel32Data[eFreeLibrary][ProcAddress])
  419. {
  420. if (exe) Kernel32Data[eFreeLibrary][IATPtr] = i;
  421. *(size_t*)i = (size_t)CustomFreeLibrary;
  422. matchedImports++;
  423. }
  424. else if (ptr == Kernel32Data[eCreateEventA][ProcAddress])
  425. {
  426. if (exe) Kernel32Data[eCreateEventA][IATPtr] = i;
  427. *(size_t*)i = (size_t)CustomCreateEventA;
  428. matchedImports++;
  429. }
  430. else if (ptr == Kernel32Data[eCreateEventW][ProcAddress])
  431. {
  432. if (exe) Kernel32Data[eCreateEventW][IATPtr] = i;
  433. *(size_t*)i = (size_t)CustomCreateEventW;
  434. matchedImports++;
  435. }
  436. else if (ptr == Kernel32Data[eGetSystemInfo][ProcAddress])
  437. {
  438. if (exe) Kernel32Data[eGetSystemInfo][IATPtr] = i;
  439. *(size_t*)i = (size_t)CustomGetSystemInfo;
  440. matchedImports++;
  441. }
  442. else if (ptr == Kernel32Data[eInterlockedCompareExchange][ProcAddress])
  443. {
  444. if (exe) Kernel32Data[eInterlockedCompareExchange][IATPtr] = i;
  445. *(size_t*)i = (size_t)CustomInterlockedCompareExchange;
  446. matchedImports++;
  447. }
  448. else if (ptr == Kernel32Data[eSleep][ProcAddress])
  449. {
  450. if (exe) Kernel32Data[eSleep][IATPtr] = i;
  451. *(size_t*)i = (size_t)CustomSleep;
  452. matchedImports++;
  453. }
  454. VirtualProtect((size_t*)i, sizeof(size_t), dwProtect[0], &dwProtect[1]);
  455. }
  456. };
  457. static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER
  458. {
  459. return reinterpret_cast<PIMAGE_SECTION_HEADER>(
  460. (UCHAR*)nt_headers->OptionalHeader.DataDirectory +
  461. nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) +
  462. section * sizeof(IMAGE_SECTION_HEADER));
  463. };
  464. static auto getSectionEnd = [](IMAGE_NT_HEADERS* ntHeader, size_t inst) -> auto
  465. {
  466. auto sec = getSection(ntHeader, ntHeader->FileHeader.NumberOfSections - 1);
  467. auto secSize = max(sec->SizeOfRawData, sec->Misc.VirtualSize);
  468. auto end = inst + max(sec->PointerToRawData, sec->VirtualAddress) + secSize;
  469. return end;
  470. };
  471. auto hExecutableInstance_end = getSectionEnd(ntHeader, hExecutableInstance);
  472. // Find kernel32.dll
  473. for (size_t i = 0; i < nNumImports; i++)
  474. {
  475. if ((size_t)(hExecutableInstance + (pImports + i)->Name) < hExecutableInstance_end)
  476. {
  477. if (!_stricmp((const char*)(hExecutableInstance + (pImports + i)->Name), "KERNEL32.DLL"))
  478. PatchIAT(hExecutableInstance + (pImports + i)->FirstThunk, 0, hExecutableInstance_end);
  479. }
  480. }
  481. // Fixing ordinals
  482. auto szSelfName = GetSelfName();
  483. static auto PatchOrdinals = [&szSelfName](size_t hInstance)
  484. {
  485. IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)(hInstance + ((IMAGE_DOS_HEADER*)hInstance)->e_lfanew);
  486. IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)(hInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  487. size_t nNumImports = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;
  488. for (size_t i = 0; i < nNumImports; i++)
  489. {
  490. if ((size_t)(hInstance + (pImports + i)->Name) < getSectionEnd(ntHeader, (size_t)hInstance))
  491. {
  492. if (iequals(szSelfName, (to_wstring((const char*)(hInstance + (pImports + i)->Name)))))
  493. {
  494. PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(hInstance + (pImports + i)->OriginalFirstThunk);
  495. size_t j = 0;
  496. while (thunk->u1.Function)
  497. {
  498. if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
  499. {
  500. PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)(hInstance + thunk->u1.AddressOfData);
  501. void** p = (void**)(hInstance + (pImports + i)->FirstThunk);
  502. }
  503. ++thunk;
  504. }
  505. }
  506. }
  507. }
  508. };
  509. ModuleList dlls;
  510. dlls.Enumerate(ModuleList::SearchLocation::LocalOnly);
  511. for (auto& e : dlls.m_moduleList)
  512. {
  513. PatchOrdinals((size_t)std::get<HMODULE>(e));
  514. }
  515. return matchedImports > 0;
  516. }
  517. LONG WINAPI CustomUnhandledExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo)
  518. {
  519. // step 1: write minidump
  520. wchar_t modulename[MAX_PATH];
  521. wchar_t filename[MAX_PATH];
  522. wchar_t timestamp[128];
  523. __time64_t time;
  524. struct tm ltime;
  525. HANDLE hFile;
  526. HWND hWnd;
  527. wchar_t* modulenameptr = NULL;
  528. if (GetModuleFileNameW(GetModuleHandle(NULL), modulename, _countof(modulename)) != 0)
  529. {
  530. modulenameptr = wcsrchr(modulename, '\\');
  531. *modulenameptr = L'\0';
  532. modulenameptr += 1;
  533. }
  534. else
  535. {
  536. *modulenameptr = L'err.err';
  537. }
  538. _time64(&time);
  539. _localtime64_s(&ltime, &time);
  540. wcsftime(timestamp, _countof(timestamp), L"%Y%m%d%H%M%S", &ltime);
  541. swprintf_s(filename, L"%s\\%s\\%s.%s.dmp", modulename, L"logs", modulenameptr, timestamp);
  542. hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  543. if (hFile != INVALID_HANDLE_VALUE)
  544. {
  545. MINIDUMP_EXCEPTION_INFORMATION ex;
  546. memset(&ex, 0, sizeof(ex));
  547. ex.ThreadId = GetCurrentThreadId();
  548. ex.ExceptionPointers = ExceptionInfo;
  549. ex.ClientPointers = TRUE;
  550. if (FAILED(MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithDataSegs, &ex, NULL, NULL)))
  551. {
  552. }
  553. CloseHandle(hFile);
  554. }
  555. // step 2: write log
  556. // Logs exception into buffer and writes to file
  557. swprintf_s(filename, L"%s\\%s\\%s.%s.log", modulename, L"logs", modulenameptr, timestamp);
  558. hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  559. if (hFile != INVALID_HANDLE_VALUE)
  560. {
  561. auto Log = [ExceptionInfo, hFile](char* buffer, size_t size, bool reg, bool stack, bool trace)
  562. {
  563. if (LogException(buffer, size, (LPEXCEPTION_POINTERS)ExceptionInfo, reg, stack, trace))
  564. {
  565. DWORD NumberOfBytesWritten = 0;
  566. WriteFile(hFile, buffer, strlen(buffer), &NumberOfBytesWritten, NULL);
  567. }
  568. };
  569. // Try to make a very descriptive exception, for that we need to malloc a huge buffer...
  570. if (auto buffer = (char*)malloc(max_logsize_ever))
  571. {
  572. Log(buffer, max_logsize_ever, true, true, true);
  573. free(buffer);
  574. }
  575. else
  576. {
  577. // Use a static buffer, no need for any allocation
  578. static const auto size = max_logsize_basic + max_logsize_regs + max_logsize_stackdump;
  579. static char static_buf[size];
  580. static_assert(size <= max_static_buffer, "Static buffer is too big");
  581. Log(buffer = static_buf, sizeof(static_buf), true, true, false);
  582. }
  583. CloseHandle(hFile);
  584. }
  585. // step 3: exit the application
  586. ShowCursor(TRUE);
  587. hWnd = FindWindowW(0, L"");
  588. SetForegroundWindow(hWnd);
  589. return EXCEPTION_CONTINUE_SEARCH;
  590. }
  591. void Init()
  592. {
  593. std::wstring modulePath = GetModuleFileNameW(hm);
  594. std::wstring moduleName = modulePath.substr(modulePath.find_last_of(L"/\\") + 1);
  595. moduleName.resize(moduleName.find_last_of(L'.'));
  596. modulePath.resize(modulePath.find_last_of(L"/\\") + 1);
  597. iniPaths.emplace_back(modulePath + moduleName + L".ini");
  598. iniPaths.emplace_back(modulePath + L"plugins\\config.ini");
  599. std::wstring m = GetModuleFileNameW(NULL);
  600. m = m.substr(0, m.find_last_of(L"/\\") + 1) + L"logs";
  601. auto FolderExists = [](LPCWSTR szPath) -> BOOL
  602. {
  603. DWORD dwAttrib = GetFileAttributes(szPath);
  604. return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
  605. };
  606. if (FolderExists(m.c_str()))
  607. {
  608. SetUnhandledExceptionFilter(CustomUnhandledExceptionFilter);
  609. // Now stub out CustomUnhandledExceptionFilter so NO ONE ELSE can set it!
  610. uint32_t ret = 0x909090C3; //ret
  611. DWORD protect[2];
  612. VirtualProtect(&SetUnhandledExceptionFilter, sizeof(ret), PAGE_EXECUTE_READWRITE, &protect[0]);
  613. memcpy(&SetUnhandledExceptionFilter, &ret, sizeof(ret));
  614. VirtualProtect(&SetUnhandledExceptionFilter, sizeof(ret), protect[0], &protect[1]);
  615. }
  616. LoadEverything();
  617. }
  618. BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID /*lpReserved*/)
  619. {
  620. if (reason == DLL_PROCESS_ATTACH)
  621. {
  622. hm = hModule;
  623. Init();
  624. }
  625. return TRUE;
  626. }