From 30bc900afa4b9e86baf5822cd9bac34e63bcd04f Mon Sep 17 00:00:00 2001 From: nastys <@> Date: Tue, 30 Jul 2019 23:40:17 +0200 Subject: [PATCH] Add fake dnsapi.dll --- README.txt | 5 +- dnsapi.dll | Bin 0 -> 36864 bytes source-code/PD-Loader.sln | 32 + source-code/source/fakedll/ModuleList.h | 186 +++++ source-code/source/fakedll/dllmain.cpp | 721 ++++++++++++++++++ source-code/source/fakedll/exception.hpp | 678 ++++++++++++++++ source-code/source/fakedll/fakedll.vcxproj | 186 +++++ .../source/fakedll/fakedll.vcxproj.filters | 38 + source-code/source/fakedll/framework.h | 89 +++ source-code/source/fakedll/x64.def | 10 + 10 files changed, 1943 insertions(+), 2 deletions(-) create mode 100644 dnsapi.dll create mode 100644 source-code/source/fakedll/ModuleList.h create mode 100644 source-code/source/fakedll/dllmain.cpp create mode 100644 source-code/source/fakedll/exception.hpp create mode 100644 source-code/source/fakedll/fakedll.vcxproj create mode 100644 source-code/source/fakedll/fakedll.vcxproj.filters create mode 100644 source-code/source/fakedll/framework.h create mode 100644 source-code/source/fakedll/x64.def diff --git a/README.txt b/README.txt index a0ad512..7403f6f 100644 --- a/README.txt +++ b/README.txt @@ -1,2 +1,3 @@ -This is the source code! -If you just want to play PDAFT, please read the wiki at https://notabug.org/nastys/PD-Loader/wiki \ No newline at end of file +This is the source code! It can NOT be used to play the game! +If you just want to play PDAFT, you downloaded the wrong thing. +Please read the wiki at https://notabug.org/nastys/PD-Loader/wiki for information on getting and installing the latest release. \ No newline at end of file diff --git a/dnsapi.dll b/dnsapi.dll new file mode 100644 index 0000000000000000000000000000000000000000..fa691fbb65863692681d4e79fc707bd4fa015a7c GIT binary patch literal 36864 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 literal 0 HcmV?d00001 diff --git a/source-code/PD-Loader.sln b/source-code/PD-Loader.sln index 9f87970..2514e87 100644 --- a/source-code/PD-Loader.sln +++ b/source-code/PD-Loader.sln @@ -13,32 +13,64 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Launcher", "source\plugins\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Render", "source\plugins\Render\Render.vcxproj", "{89F87459-768F-4638-9267-0F90CD74452D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fakedll", "source\fakedll\fakedll.vcxproj", "{B49C6ABE-931C-4F91-9A94-21A41A305FEE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CA479467-D518-46A2-AC86-3098ADA99FE5}.Debug|x64.ActiveCfg = Debug|x64 {CA479467-D518-46A2-AC86-3098ADA99FE5}.Debug|x64.Build.0 = Debug|x64 + {CA479467-D518-46A2-AC86-3098ADA99FE5}.Debug|x86.ActiveCfg = Debug|Win32 + {CA479467-D518-46A2-AC86-3098ADA99FE5}.Debug|x86.Build.0 = Debug|Win32 {CA479467-D518-46A2-AC86-3098ADA99FE5}.Release|x64.ActiveCfg = Release|x64 {CA479467-D518-46A2-AC86-3098ADA99FE5}.Release|x64.Build.0 = Release|x64 + {CA479467-D518-46A2-AC86-3098ADA99FE5}.Release|x86.ActiveCfg = Release|Win32 + {CA479467-D518-46A2-AC86-3098ADA99FE5}.Release|x86.Build.0 = Release|Win32 {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Debug|x64.ActiveCfg = Debug|x64 {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Debug|x64.Build.0 = Debug|x64 + {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Debug|x86.ActiveCfg = Debug|Win32 + {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Debug|x86.Build.0 = Debug|Win32 {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Release|x64.ActiveCfg = Release|x64 {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Release|x64.Build.0 = Release|x64 + {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Release|x86.ActiveCfg = Release|Win32 + {2B5533BB-04A1-424F-9BCA-1CA963B46B7F}.Release|x86.Build.0 = Release|Win32 {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Debug|x64.ActiveCfg = Debug|x64 {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Debug|x64.Build.0 = Debug|x64 + {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Debug|x86.ActiveCfg = Debug|Win32 + {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Debug|x86.Build.0 = Debug|Win32 {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Release|x64.ActiveCfg = Release|x64 {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Release|x64.Build.0 = Release|x64 + {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Release|x86.ActiveCfg = Release|Win32 + {3FD6ACA9-E613-4FD6-BDA2-55A91C2CF65C}.Release|x86.Build.0 = Release|Win32 {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Debug|x64.ActiveCfg = Debug|x64 {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Debug|x64.Build.0 = Debug|x64 + {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Debug|x86.ActiveCfg = Debug|Win32 + {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Debug|x86.Build.0 = Debug|Win32 {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Release|x64.ActiveCfg = Release|x64 {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Release|x64.Build.0 = Release|x64 + {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Release|x86.ActiveCfg = Release|Win32 + {60D5E9F4-335F-402B-9A07-D78674DFFC9B}.Release|x86.Build.0 = Release|Win32 {89F87459-768F-4638-9267-0F90CD74452D}.Debug|x64.ActiveCfg = Debug|x64 {89F87459-768F-4638-9267-0F90CD74452D}.Debug|x64.Build.0 = Debug|x64 + {89F87459-768F-4638-9267-0F90CD74452D}.Debug|x86.ActiveCfg = Debug|Win32 + {89F87459-768F-4638-9267-0F90CD74452D}.Debug|x86.Build.0 = Debug|Win32 {89F87459-768F-4638-9267-0F90CD74452D}.Release|x64.ActiveCfg = Release|x64 {89F87459-768F-4638-9267-0F90CD74452D}.Release|x64.Build.0 = Release|x64 + {89F87459-768F-4638-9267-0F90CD74452D}.Release|x86.ActiveCfg = Release|Win32 + {89F87459-768F-4638-9267-0F90CD74452D}.Release|x86.Build.0 = Release|Win32 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Debug|x64.ActiveCfg = Debug|x64 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Debug|x64.Build.0 = Debug|x64 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Debug|x86.ActiveCfg = Debug|Win32 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Debug|x86.Build.0 = Debug|Win32 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Release|x64.ActiveCfg = Release|x64 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Release|x64.Build.0 = Release|x64 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Release|x86.ActiveCfg = Release|Win32 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source-code/source/fakedll/ModuleList.h b/source-code/source/fakedll/ModuleList.h new file mode 100644 index 0000000..72c79e3 --- /dev/null +++ b/source-code/source/fakedll/ModuleList.h @@ -0,0 +1,186 @@ +#pragma once + +#include +#include +#include +#include +#include + +std::wstring GetModuleFileNameW(HMODULE hModule) +{ + static constexpr auto INITIAL_BUFFER_SIZE = MAX_PATH; + static constexpr auto MAX_ITERATIONS = 7; + std::wstring ret; + auto bufferSize = INITIAL_BUFFER_SIZE; + for (size_t iterations = 0; iterations < MAX_ITERATIONS; ++iterations) + { + ret.resize(bufferSize); + auto charsReturned = GetModuleFileNameW(hModule, &ret[0], bufferSize); + if (charsReturned < ret.length()) + { + ret.resize(charsReturned); + return ret; + } + else + { + bufferSize *= 2; + } + } + return L""; +} + +auto starts_with = [](const std::wstring& big_str, const std::wstring& small_str) -> auto +{ + return big_str.compare(0, small_str.length(), small_str) == 0; +}; + +// Stores a list of loaded modules with their names, WITHOUT extension +class ModuleList +{ +public: + enum class SearchLocation + { + All, + LocalOnly, + SystemOnly, + }; + + // Initializes module list + // Needs to be called before any calls to Get or GetAll + void Enumerate(SearchLocation location = SearchLocation::All) + { + constexpr size_t INITIAL_SIZE = sizeof(HMODULE) * 256; + HMODULE* modules = static_cast(malloc(INITIAL_SIZE)); + if (modules != nullptr) + { + typedef BOOL(WINAPI * Func)(HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); + + HMODULE hLib = LoadLibrary(TEXT("kernel32")); + assert(hLib != nullptr); // If this fails then everything is probably broken anyway + + Func pEnumProcessModules = reinterpret_cast(GetProcAddress(hLib, "K32EnumProcessModules")); + if (pEnumProcessModules == nullptr) + { + // Try psapi + FreeLibrary(hLib); + hLib = LoadLibrary(TEXT("psapi")); + if (hLib != nullptr) + { + pEnumProcessModules = reinterpret_cast(GetProcAddress(hLib, "EnumProcessModules")); + } + } + + if (pEnumProcessModules != nullptr) + { + const HANDLE currentProcess = GetCurrentProcess(); + DWORD cbNeeded = 0; + if (pEnumProcessModules(currentProcess, modules, INITIAL_SIZE, &cbNeeded) != 0) + { + if (cbNeeded > INITIAL_SIZE) + { + HMODULE* newModules = static_cast(realloc(modules, cbNeeded)); + if (newModules != nullptr) + { + modules = newModules; + + if (pEnumProcessModules(currentProcess, modules, cbNeeded, &cbNeeded) != 0) + { + EnumerateInternal(modules, location, cbNeeded / sizeof(HMODULE)); + } + } + } + else + { + EnumerateInternal(modules, location, cbNeeded / sizeof(HMODULE)); + } + } + } + + if (hLib != nullptr) + { + FreeLibrary(hLib); + } + + free(modules); + } + } + + // Recreates module list + void ReEnumerate(SearchLocation location = SearchLocation::All) + { + Clear(); + Enumerate(location); + } + + // Clears module list + void Clear() + { + m_moduleList.clear(); + } + + // Gets handle of a loaded module with given name, NULL otherwise + HMODULE Get(const wchar_t* moduleName) const + { + // If vector is empty then we're trying to call it without calling Enumerate first + assert(m_moduleList.size() != 0); + + auto it = std::find_if(m_moduleList.begin(), m_moduleList.end(), [&](const auto& e) { + return _wcsicmp(moduleName, std::get<1>(e).c_str()) == 0; + }); + return it != m_moduleList.end() ? std::get<0>(*it) : nullptr; + } + + // Gets handles to all loaded modules with given name + std::vector GetAll(const wchar_t* moduleName) const + { + // If vector is empty then we're trying to call it without calling Enumerate first + assert(m_moduleList.size() != 0); + + std::vector results; + for (auto& e : m_moduleList) + { + if (_wcsicmp(moduleName, std::get<1>(e).c_str()) == 0) + { + results.push_back(std::get<0>(e)); + } + } + + return results; + } + +private: + void EnumerateInternal(HMODULE* modules, SearchLocation location, size_t numModules) + { + const auto exeModulePath = GetModuleFileNameW(NULL).substr(0, GetModuleFileNameW(NULL).find_last_of(L"/\\")); + + m_moduleList.reserve(numModules); + for (size_t i = 0; i < numModules; i++) + { + // Obtain module name, with resizing if necessary + auto moduleName = GetModuleFileNameW(*modules); + + if (!moduleName.empty()) + { + const wchar_t* nameBegin = wcsrchr(moduleName.c_str(), '\\') + 1; + const wchar_t* dotPos = wcsrchr(nameBegin, '.'); + bool isLocal = starts_with(std::wstring(moduleName), exeModulePath); + + if ((isLocal && location != SearchLocation::SystemOnly) || (!isLocal && location != SearchLocation::LocalOnly)) + { + if (dotPos != nullptr) + { + m_moduleList.emplace_back(*modules, std::wstring(nameBegin, dotPos), isLocal); + } + else + { + m_moduleList.emplace_back(*modules, nameBegin, isLocal); + } + } + } + + modules++; + } + } + +public: std::vector< std::tuple > m_moduleList; +}; \ No newline at end of file diff --git a/source-code/source/fakedll/dllmain.cpp b/source-code/source/fakedll/dllmain.cpp new file mode 100644 index 0000000..febfc22 --- /dev/null +++ b/source-code/source/fakedll/dllmain.cpp @@ -0,0 +1,721 @@ +#include "framework.h" +#include "exception.hpp" + +HMODULE hm; +std::vector iniPaths; + +bool iequals(std::wstring_view s1, std::wstring_view s2) +{ + std::wstring str1(std::move(s1)); + std::wstring str2(std::move(s2)); + std::transform(str1.begin(), str1.end(), str1.begin(), [](wchar_t c) { return ::towlower(c); }); + std::transform(str2.begin(), str2.end(), str2.begin(), [](wchar_t c) { return ::towlower(c); }); + return (str1 == str2); +} + +std::wstring to_wstring(std::string_view cstr) +{ + std::string str(std::move(cstr)); + auto charsReturned = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); + std::wstring wstrTo(charsReturned, 0); + MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], charsReturned); + return wstrTo; +} + +std::wstring SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken) +{ + std::wstring r; + WCHAR* szSystemPath = nullptr; + if (SUCCEEDED(SHGetKnownFolderPath(rfid, dwFlags, hToken, &szSystemPath))) + { + r = szSystemPath; + } + CoTaskMemFree(szSystemPath); + return r; +}; + +HMODULE LoadLibraryW(const std::wstring& lpLibFileName) +{ + return LoadLibraryW(lpLibFileName.c_str()); +} + +std::wstring GetCurrentDirectoryW() +{ + static constexpr auto INITIAL_BUFFER_SIZE = MAX_PATH; + static constexpr auto MAX_ITERATIONS = 7; + std::wstring ret; + auto bufferSize = INITIAL_BUFFER_SIZE; + for (size_t iterations = 0; iterations < MAX_ITERATIONS; ++iterations) + { + ret.resize(bufferSize); + auto charsReturned = GetCurrentDirectoryW(bufferSize, &ret[0]); + if (charsReturned < ret.length()) + { + ret.resize(charsReturned); + return ret; + } + else + { + bufferSize *= 2; + } + } + return L""; +} + +UINT GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, const std::vector& fileNames) +{ + for (const auto& file : fileNames) + { + nDefault = GetPrivateProfileIntW(lpAppName, lpKeyName, nDefault, file.c_str()); + } + return nDefault; +} + +std::wstring GetSelfName() +{ + const std::wstring moduleFileName = GetModuleFileNameW(hm); + return moduleFileName.substr(moduleFileName.find_last_of(L"/\\") + 1); +} + +template +void GetSections(T&& h, Args... args) +{ + const std::set< std::string_view, std::less<> > s = { args... }; + size_t dwLoadOffset = (size_t)GetModuleHandle(NULL); + BYTE* pImageBase = reinterpret_cast(dwLoadOffset); + PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast(dwLoadOffset); + PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast(pImageBase + pDosHeader->e_lfanew); + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeader); + for (int iSection = 0; iSection < pNtHeader->FileHeader.NumberOfSections; ++iSection, ++pSection) + { + auto pszSectionName = reinterpret_cast(pSection->Name); + if (s.find(pszSectionName) != s.end()) + { + DWORD dwPhysSize = (pSection->Misc.VirtualSize + 4095) & ~4095; + std::forward(h)(pSection, dwLoadOffset, dwPhysSize); + } + } +} + +enum Kernel32ExportsNames +{ + eGetStartupInfoA, + eGetStartupInfoW, + eGetModuleHandleA, + eGetModuleHandleW, + eGetProcAddress, + eGetShortPathNameA, + eFindNextFileA, + eFindNextFileW, + eLoadLibraryA, + eLoadLibraryW, + eFreeLibrary, + eCreateEventA, + eCreateEventW, + eGetSystemInfo, + eInterlockedCompareExchange, + eSleep, + + Kernel32ExportsNamesCount +}; + +enum Kernel32ExportsData +{ + IATPtr, + ProcAddress, + + Kernel32ExportsDataCount +}; + +size_t Kernel32Data[Kernel32ExportsNamesCount][Kernel32ExportsDataCount]; + +static LONG OriginalLibraryLoaded = 0; +void LoadOriginalLibrary() +{ + if (_InterlockedCompareExchange(&OriginalLibraryLoaded, 1, 0) != 0) return; + + auto szSelfName = GetSelfName(); + auto szSystemPath = SHGetKnownFolderPath(FOLDERID_System, 0, nullptr) + L'\\' + szSelfName; + auto szLocalPath = GetModuleFileNameW(hm); szLocalPath = szLocalPath.substr(0, szLocalPath.find_last_of(L"/\\") + 1); + + if (iequals(szSelfName, L"dnsapi.dll")) { + dnsapi.LoadOriginalLibrary(LoadLibraryW(szSystemPath)); + } +} + +void FindFiles(WIN32_FIND_DATAW* fd) +{ + auto dir = GetCurrentDirectoryW(); + + HANDLE dvaFile = FindFirstFileW(L"*.dva", fd); + if (dvaFile != INVALID_HANDLE_VALUE) + { + do { + if (!(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + auto pos = wcslen(fd->cFileName); + + if (fd->cFileName[pos - 4] == '.' && + (fd->cFileName[pos - 3] == 'd' || fd->cFileName[pos - 3] == 'D') && + (fd->cFileName[pos - 2] == 'v' || fd->cFileName[pos - 2] == 'V') && + (fd->cFileName[pos - 1] == 'a' || fd->cFileName[pos - 1] == 'A')) + { + auto path = dir + L'\\' + fd->cFileName; + + if (GetModuleHandle(path.c_str()) == NULL) + { + auto h = LoadLibraryW(path); + SetCurrentDirectoryW(dir.c_str()); //in case dva switched it + + if (h == NULL) + { + auto e = GetLastError(); + if (e != ERROR_DLL_INIT_FAILED) // in case dllmain returns false + { + std::wstring msg = L"Unable to load " + std::wstring(fd->cFileName) + L". Error: " + std::to_wstring(e); + MessageBoxW(0, msg.c_str(), L"PD Loader", MB_ICONERROR); + } + } + else + { + auto procedure = (void(*)())GetProcAddress(h, "InitializeDVA"); + + if (procedure != NULL) + { + procedure(); + } + } + } + } + } + } while (FindNextFileW(dvaFile, fd)); + FindClose(dvaFile); + } +} + +void LoadPlugins() +{ + auto oldDir = GetCurrentDirectoryW(); // store the current directory + + auto szSelfPath = GetModuleFileNameW(hm).substr(0, GetModuleFileNameW(hm).find_last_of(L"/\\") + 1); + SetCurrentDirectoryW(szSelfPath.c_str()); + + auto nWantsToLoadPlugins = GetPrivateProfileIntW(L"global", L"enable", TRUE, iniPaths); + + if (nWantsToLoadPlugins) + { + WIN32_FIND_DATAW fd; + + SetCurrentDirectoryW(szSelfPath.c_str()); + + if (SetCurrentDirectoryW(L"plugins\\")) + FindFiles(&fd); + } + + SetCurrentDirectoryW(oldDir.c_str()); // Reset the current directory +} + +void InjectCode(void* address, const std::vector data) +{ + const size_t byteCount = data.size() * sizeof(uint8_t); + + DWORD oldProtect; + VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect); + memcpy(address, data.data(), byteCount); + VirtualProtect(address, byteCount, oldProtect, nullptr); +} + +static LONG LoadedPluginsYet = 0; +void LoadEverything() +{ + if (_InterlockedCompareExchange(&LoadedPluginsYet, 1, 0) != 0) return; + + LoadOriginalLibrary(); + //LoadPlugins(); + InjectCode((void*)0x00000001409FF730, { 0x53, 0x65, 0x65, 0x20, 0x52, 0x45, 0x41, 0x44, 0x4D, 0x45, 0x2E, 0x74, 0x78, 0x74, 0x2E, 0x00, 0x00 }); +} + +static LONG RestoredOnce = 0; +void LoadPluginsAndRestoreIAT(uintptr_t retaddr) +{ + bool calledFromBind = false; + + //steam drm check + GetSections([&](PIMAGE_SECTION_HEADER pSection, size_t dwLoadOffset, DWORD dwPhysSize) { + auto dwStart = static_cast(dwLoadOffset + pSection->VirtualAddress); + auto dwEnd = dwStart + dwPhysSize; + if (retaddr >= dwStart && retaddr <= dwEnd) + calledFromBind = true; + }, ".bind"); + + if (calledFromBind) return; + + if (_InterlockedCompareExchange(&RestoredOnce, 1, 0) != 0) return; + + LoadEverything(); + + for (size_t i = 0; i < Kernel32ExportsNamesCount; i++) + { + if (Kernel32Data[i][IATPtr] && Kernel32Data[i][ProcAddress]) + { + auto ptr = (size_t*)Kernel32Data[i][IATPtr]; + DWORD dwProtect[2]; + VirtualProtect(ptr, sizeof(size_t), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + *ptr = Kernel32Data[i][ProcAddress]; + VirtualProtect(ptr, sizeof(size_t), dwProtect[0], &dwProtect[1]); + } + } +} + +void WINAPI CustomGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetStartupInfoA(lpStartupInfo); +} + +void WINAPI CustomGetStartupInfoW(LPSTARTUPINFOW lpStartupInfo) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetStartupInfoW(lpStartupInfo); +} + +HMODULE WINAPI CustomGetModuleHandleA(LPCSTR lpModuleName) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetModuleHandleA(lpModuleName); +} + +HMODULE WINAPI CustomGetModuleHandleW(LPCWSTR lpModuleName) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetModuleHandleW(lpModuleName); +} + +FARPROC WINAPI CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetProcAddress(hModule, lpProcName); +} + +DWORD WINAPI CustomGetShortPathNameA(LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetShortPathNameA(lpszLongPath, lpszShortPath, cchBuffer); +} + +BOOL WINAPI CustomFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return FindNextFileA(hFindFile, lpFindFileData); +} + +BOOL WINAPI CustomFindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return FindNextFileW(hFindFile, lpFindFileData); +} + +HMODULE WINAPI CustomLoadLibraryA(LPCSTR lpLibFileName) +{ + LoadOriginalLibrary(); + + return LoadLibraryA(lpLibFileName); +} + +HMODULE WINAPI CustomLoadLibraryW(LPCWSTR lpLibFileName) +{ + LoadOriginalLibrary(); + + return LoadLibraryW(lpLibFileName); +} + +BOOL WINAPI CustomFreeLibrary(HMODULE hLibModule) +{ + if (hLibModule != hm) + return FreeLibrary(hLibModule); + else + return !NULL; +} + +HANDLE WINAPI CustomCreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return CreateEventA(lpEventAttributes, bManualReset, bInitialState, lpName); +} + +HANDLE WINAPI CustomCreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return CreateEventW(lpEventAttributes, bManualReset, bInitialState, lpName); +} + +void WINAPI CustomGetSystemInfo(LPSYSTEM_INFO lpSystemInfo) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return GetSystemInfo(lpSystemInfo); +} + +LONG WINAPI CustomInterlockedCompareExchange(LONG volatile* Destination, LONG ExChange, LONG Comperand) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return _InterlockedCompareExchange(Destination, ExChange, Comperand); +} + +void WINAPI CustomSleep(DWORD dwMilliseconds) +{ + LoadPluginsAndRestoreIAT((uintptr_t)_ReturnAddress()); + return Sleep(dwMilliseconds); +} + +bool HookKernel32IAT(HMODULE mod, bool exe) +{ + auto hExecutableInstance = (size_t)mod; + IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)(hExecutableInstance + ((IMAGE_DOS_HEADER*)hExecutableInstance)->e_lfanew); + IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)(hExecutableInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + size_t nNumImports = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; + + if (exe) + { + Kernel32Data[eGetStartupInfoA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetStartupInfoA"); + Kernel32Data[eGetStartupInfoW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetStartupInfoW"); + Kernel32Data[eGetModuleHandleA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetModuleHandleA"); + Kernel32Data[eGetModuleHandleW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetModuleHandleW"); + Kernel32Data[eGetProcAddress][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetProcAddress"); + Kernel32Data[eGetShortPathNameA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetShortPathNameA"); + Kernel32Data[eFindNextFileA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileA"); + Kernel32Data[eFindNextFileW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FindNextFileW"); + Kernel32Data[eLoadLibraryA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryA"); + Kernel32Data[eLoadLibraryW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "LoadLibraryW"); + Kernel32Data[eFreeLibrary][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "FreeLibrary"); + Kernel32Data[eCreateEventA][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateEventA"); + Kernel32Data[eCreateEventW][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "CreateEventW"); + Kernel32Data[eGetSystemInfo][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "GetSystemInfo"); + Kernel32Data[eInterlockedCompareExchange][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "InterlockedCompareExchange"); + Kernel32Data[eSleep][ProcAddress] = (size_t)GetProcAddress(GetModuleHandle(TEXT("KERNEL32.DLL")), "Sleep"); + } + + uint32_t matchedImports = 0; + + auto PatchIAT = [&](size_t start, size_t end, size_t exe_end) + { + for (size_t i = 0; i < nNumImports; i++) + { + if (hExecutableInstance + (pImports + i)->FirstThunk > start && !(end && hExecutableInstance + (pImports + i)->FirstThunk > end)) + end = hExecutableInstance + (pImports + i)->FirstThunk; + } + + if (!end) { end = start + 0x100; } + if (end > exe_end) //for very broken exes + { + start = hExecutableInstance; + end = exe_end; + } + + for (auto i = start; i < end; i += sizeof(size_t)) + { + DWORD dwProtect[2]; + VirtualProtect((size_t*)i, sizeof(size_t), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + + auto ptr = *(size_t*)i; + if (!ptr) + continue; + + if (ptr == Kernel32Data[eGetStartupInfoA][ProcAddress]) + { + if (exe) Kernel32Data[eGetStartupInfoA][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetStartupInfoA; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetStartupInfoW][ProcAddress]) + { + if (exe) Kernel32Data[eGetStartupInfoW][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetStartupInfoW; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetModuleHandleA][ProcAddress]) + { + if (exe) Kernel32Data[eGetModuleHandleA][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetModuleHandleA; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetModuleHandleW][ProcAddress]) + { + if (exe) Kernel32Data[eGetModuleHandleW][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetModuleHandleW; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetProcAddress][ProcAddress]) + { + if (exe) Kernel32Data[eGetProcAddress][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetProcAddress; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetShortPathNameA][ProcAddress]) + { + if (exe) Kernel32Data[eGetShortPathNameA][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetShortPathNameA; + matchedImports++; + } + else if (ptr == Kernel32Data[eFindNextFileA][ProcAddress]) + { + if (exe) Kernel32Data[eFindNextFileA][IATPtr] = i; + *(size_t*)i = (size_t)CustomFindNextFileA; + matchedImports++; + } + else if (ptr == Kernel32Data[eFindNextFileW][ProcAddress]) + { + if (exe) Kernel32Data[eFindNextFileW][IATPtr] = i; + *(size_t*)i = (size_t)CustomFindNextFileW; + matchedImports++; + } + else if (ptr == Kernel32Data[eLoadLibraryA][ProcAddress]) + { + if (exe) Kernel32Data[eLoadLibraryA][IATPtr] = i; + *(size_t*)i = (size_t)CustomLoadLibraryA; + matchedImports++; + } + else if (ptr == Kernel32Data[eLoadLibraryW][ProcAddress]) + { + if (exe) Kernel32Data[eLoadLibraryW][IATPtr] = i; + *(size_t*)i = (size_t)CustomLoadLibraryW; + matchedImports++; + } + else if (ptr == Kernel32Data[eFreeLibrary][ProcAddress]) + { + if (exe) Kernel32Data[eFreeLibrary][IATPtr] = i; + *(size_t*)i = (size_t)CustomFreeLibrary; + matchedImports++; + } + else if (ptr == Kernel32Data[eCreateEventA][ProcAddress]) + { + if (exe) Kernel32Data[eCreateEventA][IATPtr] = i; + *(size_t*)i = (size_t)CustomCreateEventA; + matchedImports++; + } + else if (ptr == Kernel32Data[eCreateEventW][ProcAddress]) + { + if (exe) Kernel32Data[eCreateEventW][IATPtr] = i; + *(size_t*)i = (size_t)CustomCreateEventW; + matchedImports++; + } + else if (ptr == Kernel32Data[eGetSystemInfo][ProcAddress]) + { + if (exe) Kernel32Data[eGetSystemInfo][IATPtr] = i; + *(size_t*)i = (size_t)CustomGetSystemInfo; + matchedImports++; + } + else if (ptr == Kernel32Data[eInterlockedCompareExchange][ProcAddress]) + { + if (exe) Kernel32Data[eInterlockedCompareExchange][IATPtr] = i; + *(size_t*)i = (size_t)CustomInterlockedCompareExchange; + matchedImports++; + } + else if (ptr == Kernel32Data[eSleep][ProcAddress]) + { + if (exe) Kernel32Data[eSleep][IATPtr] = i; + *(size_t*)i = (size_t)CustomSleep; + matchedImports++; + } + + VirtualProtect((size_t*)i, sizeof(size_t), dwProtect[0], &dwProtect[1]); + } + }; + + static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER + { + return reinterpret_cast( + (UCHAR*)nt_headers->OptionalHeader.DataDirectory + + nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) + + section * sizeof(IMAGE_SECTION_HEADER)); + }; + + static auto getSectionEnd = [](IMAGE_NT_HEADERS* ntHeader, size_t inst) -> auto + { + auto sec = getSection(ntHeader, ntHeader->FileHeader.NumberOfSections - 1); + auto secSize = max(sec->SizeOfRawData, sec->Misc.VirtualSize); + auto end = inst + max(sec->PointerToRawData, sec->VirtualAddress) + secSize; + return end; + }; + + auto hExecutableInstance_end = getSectionEnd(ntHeader, hExecutableInstance); + + // Find kernel32.dll + for (size_t i = 0; i < nNumImports; i++) + { + if ((size_t)(hExecutableInstance + (pImports + i)->Name) < hExecutableInstance_end) + { + if (!_stricmp((const char*)(hExecutableInstance + (pImports + i)->Name), "KERNEL32.DLL")) + PatchIAT(hExecutableInstance + (pImports + i)->FirstThunk, 0, hExecutableInstance_end); + } + } + + // Fixing ordinals + auto szSelfName = GetSelfName(); + + static auto PatchOrdinals = [&szSelfName](size_t hInstance) + { + IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)(hInstance + ((IMAGE_DOS_HEADER*)hInstance)->e_lfanew); + IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)(hInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + size_t nNumImports = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; + + for (size_t i = 0; i < nNumImports; i++) + { + if ((size_t)(hInstance + (pImports + i)->Name) < getSectionEnd(ntHeader, (size_t)hInstance)) + { + if (iequals(szSelfName, (to_wstring((const char*)(hInstance + (pImports + i)->Name))))) + { + PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(hInstance + (pImports + i)->OriginalFirstThunk); + size_t j = 0; + while (thunk->u1.Function) + { + if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) + { + PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)(hInstance + thunk->u1.AddressOfData); + void** p = (void**)(hInstance + (pImports + i)->FirstThunk); + } + ++thunk; + } + } + } + } + }; + + ModuleList dlls; + dlls.Enumerate(ModuleList::SearchLocation::LocalOnly); + for (auto& e : dlls.m_moduleList) + { + PatchOrdinals((size_t)std::get(e)); + } + return matchedImports > 0; +} + +LONG WINAPI CustomUnhandledExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo) +{ + // step 1: write minidump + wchar_t modulename[MAX_PATH]; + wchar_t filename[MAX_PATH]; + wchar_t timestamp[128]; + __time64_t time; + struct tm ltime; + HANDLE hFile; + HWND hWnd; + + wchar_t* modulenameptr = NULL; + if (GetModuleFileNameW(GetModuleHandle(NULL), modulename, _countof(modulename)) != 0) + { + modulenameptr = wcsrchr(modulename, '\\'); + *modulenameptr = L'\0'; + modulenameptr += 1; + } + else + { + *modulenameptr = L'err.err'; + } + + _time64(&time); + _localtime64_s(<ime, &time); + wcsftime(timestamp, _countof(timestamp), L"%Y%m%d%H%M%S", <ime); + swprintf_s(filename, L"%s\\%s\\%s.%s.dmp", modulename, L"logs", modulenameptr, timestamp); + + hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile != INVALID_HANDLE_VALUE) + { + MINIDUMP_EXCEPTION_INFORMATION ex; + memset(&ex, 0, sizeof(ex)); + ex.ThreadId = GetCurrentThreadId(); + ex.ExceptionPointers = ExceptionInfo; + ex.ClientPointers = TRUE; + + if (FAILED(MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithDataSegs, &ex, NULL, NULL))) + { + } + + CloseHandle(hFile); + } + + // step 2: write log + // Logs exception into buffer and writes to file + swprintf_s(filename, L"%s\\%s\\%s.%s.log", modulename, L"logs", modulenameptr, timestamp); + hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile != INVALID_HANDLE_VALUE) + { + auto Log = [ExceptionInfo, hFile](char* buffer, size_t size, bool reg, bool stack, bool trace) + { + if (LogException(buffer, size, (LPEXCEPTION_POINTERS)ExceptionInfo, reg, stack, trace)) + { + DWORD NumberOfBytesWritten = 0; + WriteFile(hFile, buffer, strlen(buffer), &NumberOfBytesWritten, NULL); + } + }; + + // Try to make a very descriptive exception, for that we need to malloc a huge buffer... + if (auto buffer = (char*)malloc(max_logsize_ever)) + { + Log(buffer, max_logsize_ever, true, true, true); + free(buffer); + } + else + { + // Use a static buffer, no need for any allocation + static const auto size = max_logsize_basic + max_logsize_regs + max_logsize_stackdump; + static char static_buf[size]; + static_assert(size <= max_static_buffer, "Static buffer is too big"); + + Log(buffer = static_buf, sizeof(static_buf), true, true, false); + } + + CloseHandle(hFile); + } + + // step 3: exit the application + ShowCursor(TRUE); + hWnd = FindWindowW(0, L""); + SetForegroundWindow(hWnd); + + return EXCEPTION_CONTINUE_SEARCH; +} + +void Init() +{ + std::wstring modulePath = GetModuleFileNameW(hm); + std::wstring moduleName = modulePath.substr(modulePath.find_last_of(L"/\\") + 1); + moduleName.resize(moduleName.find_last_of(L'.')); + modulePath.resize(modulePath.find_last_of(L"/\\") + 1); + iniPaths.emplace_back(modulePath + moduleName + L".ini"); + iniPaths.emplace_back(modulePath + L"plugins\\config.ini"); + + std::wstring m = GetModuleFileNameW(NULL); + m = m.substr(0, m.find_last_of(L"/\\") + 1) + L"logs"; + + auto FolderExists = [](LPCWSTR szPath) -> BOOL + { + DWORD dwAttrib = GetFileAttributes(szPath); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); + }; + + if (FolderExists(m.c_str())) + { + SetUnhandledExceptionFilter(CustomUnhandledExceptionFilter); + // Now stub out CustomUnhandledExceptionFilter so NO ONE ELSE can set it! + uint32_t ret = 0x909090C3; //ret + DWORD protect[2]; + VirtualProtect(&SetUnhandledExceptionFilter, sizeof(ret), PAGE_EXECUTE_READWRITE, &protect[0]); + memcpy(&SetUnhandledExceptionFilter, &ret, sizeof(ret)); + VirtualProtect(&SetUnhandledExceptionFilter, sizeof(ret), protect[0], &protect[1]); + } + + LoadEverything(); + +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID /*lpReserved*/) +{ + if (reason == DLL_PROCESS_ATTACH) + { + hm = hModule; + Init(); + } + return TRUE; +} diff --git a/source-code/source/fakedll/exception.hpp b/source-code/source/fakedll/exception.hpp new file mode 100644 index 0000000..ff7958c --- /dev/null +++ b/source-code/source/fakedll/exception.hpp @@ -0,0 +1,678 @@ +#pragma once +/* + * Unhandled Exception Tracer + * by LINK/2012 + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include +#include +#include +#include +#include +#include +#pragma comment(lib, "Dbghelp.lib") + + /* + * Special Note: + * Try not to allocate any memory in this file! + * Allocation after a exception may not be a good idea... + */ + +#define LODWORD(_qw) ((DWORD)(_qw)) +#define HIDWORD(_qw) ((DWORD)(((_qw) >> 32) & 0xffffffff)) + + // General constants +static const int sizeof_word = sizeof(void*); // Size of a CPU word (4 bytes on x86) +static const int max_chars_per_print = MAX_PATH + 256; // Max characters per Print() call +static const int symbol_max = 256; // Max size of a symbol (func symbol, var symbol, etc) +static const int max_static_buffer = 4096; // Max static buffer for logging + +// Stackdump constants +static const int stackdump_max_words = 60; // max number of CPU words that the stackdump should dump +static const int stackdump_words_per_line = 6; // max CPU words in a single line +static const int stackdump_line_count = (stackdump_max_words / stackdump_words_per_line) + 1; + +// Backtrace constants +static const int max_backtrace_ever = 100; +static const int max_backtrace = 20; + +// Maximum log size constants +static const int max_logsize_basic = (MAX_PATH + 200); // module path + other text +static const int max_logsize_regs = 32 + (4 * 4 * 28); // info + (regsPerLine * numLines * charsPerReg) +static const int max_logsize_stackdump = 32 + 80 + (stackdump_line_count * 32) + (10 * stackdump_words_per_line * stackdump_line_count); +static const int max_logsize_backtrace = 32 + max_backtrace_ever * (MAX_PATH + symbol_max + 90); +static const int max_logsize_ever = 32 + max_logsize_basic + max_logsize_regs + max_logsize_stackdump + max_logsize_backtrace; + +// Internal +class ExceptionTracer; +class StackTrace; +static HMODULE GetModuleFromAddress(LPVOID address); +static const char* GetExceptionCodeString(unsigned int code); +static const char* FindModuleName(HMODULE module, char* output, DWORD size); +static int LogException(char* buffer, size_t max, LPEXCEPTION_POINTERS pException, bool bLogRegisters, bool bLogStack, bool bLogBacktrace); +static LPTOP_LEVEL_EXCEPTION_FILTER PrevFilter = nullptr; +static void(*ExceptionCallback)(const char* buffer) = nullptr; + +// Exportable +int InstallExceptionCatcher(void(*OnException)(const char* log)); + +/* + * ExceptionTrace + * This class is responssible for tracing all possible informations about an LPEXCEPTION_POINTER + */ +class ExceptionTracer +{ +public: + ExceptionTracer(char* buffer, size_t max, LPEXCEPTION_POINTERS pException); + void PrintUnhandledException(); + void PrintRegisters(); + void PrintStackdump(); + void PrintBacktrace(); + + void EnterScope(); + void LeaveScope(); + void Print(const char* fmt, ...); + void NewLine() { Print("\n%s", spc); } + +protected: + EXCEPTION_POINTERS& exception; + EXCEPTION_RECORD& record; + CONTEXT& context; + HMODULE module; + + char* buffer; // Logging buffer + size_t len; // Logged length + size_t max; // Maximum we can log in that buffer + + char spc[(10 * 4) + 1]; // Scope/spacing buffer, 4 spaces per scope, max 10 scopes + size_t nspc; // Number spaces used up there +}; + +/* + * StackTracer + * Responssible for backtracing an stack from a context + */ +class StackTracer +{ +public: + struct Trace + { + // The following values may be null (any) + HMODULE module; // The module the func related to this frame is located + void* pc; // Program counter at func related to this frame (EIP) + void* ret; // Return address for the frame + void* frame; // The frame address (EBP) + void* stack; // The stack pointer at the frame (ESP) + }; + + StackTracer(const CONTEXT& context); + Trace* Walk(); + +private: + Trace trace; + DWORD old_options; + CONTEXT context; + STACKFRAME64 frame; +}; + +/* + * TheUnhandledExceptionFilter + * Logs an unhandled exception + */ +static LONG CALLBACK TheUnhandledExceptionFilter(LPEXCEPTION_POINTERS pException) +{ + // Logs exception into buffer and calls the callback + auto Log = [pException](char* buffer, size_t size, bool reg, bool stack, bool trace) + { + if (LogException(buffer, size, (LPEXCEPTION_POINTERS)pException, reg, stack, trace)) + ExceptionCallback(buffer); + }; + + // Try to make a very descriptive exception, for that we need to malloc a huge buffer... + if (auto buffer = (char*)malloc(max_logsize_ever)) + { + Log(buffer, max_logsize_ever, true, true, true); + free(buffer); + } + else + { + // Use a static buffer, no need for any allocation + static const auto size = max_logsize_basic + max_logsize_regs + max_logsize_stackdump; + static char static_buf[size]; + static_assert(size <= max_static_buffer, "Static buffer is too big"); + + Log(buffer = static_buf, sizeof(static_buf), true, true, false); + } + + // Continue exception propagation + return (PrevFilter ? PrevFilter(pException) : EXCEPTION_CONTINUE_SEARCH); // I'm not really sure about this return +} + +/* + * InstallExceptionCatcher + * Installs a exception handler to call the specified callback when it happens with human readalbe information. + */ +int InstallExceptionCatcher(void(*cb)(const char* log)) +{ + PrevFilter = SetUnhandledExceptionFilter(TheUnhandledExceptionFilter); + ExceptionCallback = cb; + return 1; +} + +/* + * LogException + * Takes an LPEXCEPTION_POINTERS and transforms in a string that is put in the logging steam + */ +static int LogException(char* buffer, size_t max, LPEXCEPTION_POINTERS pException, bool bLogRegisters, bool bLogStack, bool bLogBacktrace) +{ + ExceptionTracer trace(buffer, max, pException); + trace.PrintUnhandledException(); + trace.EnterScope(); + if (bLogRegisters) trace.PrintRegisters(); + if (bLogStack) trace.PrintStackdump(); + if (bLogBacktrace) trace.PrintBacktrace(); + trace.LeaveScope(); + return 1; +} + +/* + * ExceptionTracer + * Contructs a exception trace object, responssible for tracing informations about an exception + */ +ExceptionTracer::ExceptionTracer(char* buffer, size_t max, LPEXCEPTION_POINTERS pException) : + buffer(buffer), exception(*pException), record(*pException->ExceptionRecord), context(*pException->ContextRecord) +{ + this->buffer = buffer; + this->buffer[this->len = 0] = 0; + this->spc[this->nspc = 0] = 0; + this->max = max; + + // Acquiere common information that we'll access + this->module = GetModuleFromAddress(record.ExceptionAddress); +} + +/* + * Print + * Prints some formated text into the logging buffer + */ +void ExceptionTracer::Print(const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); + if ((this->max - this->len) > max_chars_per_print) + this->len += vsprintf(&this->buffer[len], fmt, va); + va_end(va); +} + +/* + * EnterScope + * Enters a new scope in the logging buffer (scope is related to indentation) + * This also prints a new line + */ +void ExceptionTracer::EnterScope() +{ + nspc += 4; + spc[nspc - 4] = ' '; + spc[nspc - 3] = ' '; + spc[nspc - 2] = ' '; + spc[nspc - 1] = ' '; + spc[nspc - 0] = 0; + NewLine(); +} + +/* + * LeaveScope + * Leaves the scope + */ +void ExceptionTracer::LeaveScope() +{ + assert(nspc > 0); + nspc -= 4; + spc[nspc] = 0; + NewLine(); +} + +/* + * PrintUnhandledException + * Prints the well known "Unhandled exception at ..." into the logging buffer + */ +void ExceptionTracer::PrintUnhandledException() +{ + char module_name[MAX_PATH]; + auto dwExceptionCode = record.ExceptionCode; + uintptr_t address = (uintptr_t)record.ExceptionAddress; + + // Find out our module name for logging + if (!this->module || !GetModuleFileNameA(this->module, module_name, sizeof(module_name))) + strcpy(module_name, "unknown"); + + // Log the exception in a similar format similar to debuggers format + Print("Unhandled exception at 0x%p in %s", address, FindModuleName(module, module_name, sizeof(module_name))); + if (module) Print(" (+0x%x)", address - (uintptr_t)(module)); + Print(": 0x%X: %s", dwExceptionCode, GetExceptionCodeString(dwExceptionCode)); + + // If exception is IN_PAGE_ERROR or ACCESS_VIOLATION, we have additional information such as an address + if (dwExceptionCode == EXCEPTION_IN_PAGE_ERROR || dwExceptionCode == EXCEPTION_ACCESS_VIOLATION) + { + auto rw = (DWORD)record.ExceptionInformation[0]; // read or write? + auto addr = (ULONG_PTR)record.ExceptionInformation[1]; // which address? + + Print(" %s 0x%p", + rw == 0 ? "reading location" : rw == 1 ? "writing location" : rw == 8 ? "DEP at" : "", + addr); + + // IN_PAGE_ERROR have another information... + if (dwExceptionCode == EXCEPTION_IN_PAGE_ERROR) + { + NewLine(); + Print("Underlying NTSTATUS code that resulted in the exception is 0x%p", + record.ExceptionInformation[2]); + } + } + + Print("."); +} + +/* + * PrintRegisters + * Prints the content of the assembly registers into the logging buffer + */ +void ExceptionTracer::PrintRegisters() +{ + int regs_in_line = 0; // Amount of registers currently printed on this line + + // Prints a register, followed by spaces + auto PrintRegister = [this, ®s_in_line](const char* reg_name, size_t reg_value, const char* spaces) + { + Print("%s: 0x%p%s", reg_name, reg_value, spaces); + if (++regs_in_line >= 4) { this->NewLine(); regs_in_line = 0; } + }; + + auto PrintFloatRegister = [this, ®s_in_line](const char* reg_name, int reg_num, uint32_t reg_value1, uint32_t reg_value2, uint32_t reg_value3, uint32_t reg_value4) + { + Print("%s%02d: 0x%08X 0x%08X 0x%08X 0x%08X [ %f %f %f %f ]", reg_name, reg_num, reg_value1, reg_value2, reg_value3, reg_value4, + *(float*)& reg_value1, *(float*)& reg_value2, *(float*)& reg_value3, *(float*)& reg_value4); + if (++regs_in_line >= 1) { this->NewLine(); regs_in_line = 0; } + }; + + // Prints a general purposes register + auto PrintIntRegister = [PrintRegister](const char* reg_name, size_t reg_value) + { + PrintRegister(reg_name, reg_value, " "); + }; + + // Prints a segment register + auto PrintSegRegister = [PrintRegister](const char* reg_name, size_t reg_value) + { + PrintRegister(reg_name, reg_value, " "); + }; + + Print("Register dump:"); + EnterScope(); + { + // Print main general purposes registers + if (context.ContextFlags & CONTEXT_INTEGER) + { +#if !_M_X64 + PrintIntRegister("EAX", context.Eax); + PrintIntRegister("EBX", context.Ebx); + PrintIntRegister("ECX", context.Ecx); + PrintIntRegister("EDX", context.Edx); + PrintIntRegister("EDI", context.Edi); + PrintIntRegister("ESI", context.Esi); +#else + PrintIntRegister("RAX", context.Rax); + PrintIntRegister("RCX", context.Rcx); + PrintIntRegister("RDX", context.Rdx); + PrintIntRegister("RBX", context.Rbx); + PrintIntRegister("RBP", context.Rbp); + PrintIntRegister("RSI", context.Rsi); + PrintIntRegister("RDI", context.Rdi); + PrintIntRegister("R08", context.R8); + PrintIntRegister("R09", context.R9); + PrintIntRegister("R10", context.R10); + PrintIntRegister("R11", context.R11); + PrintIntRegister("R12", context.R12); + PrintIntRegister("R13", context.R13); + PrintIntRegister("R14", context.R14); + PrintIntRegister("R15", context.R15); +#endif + } + + // Print control registers + if (context.ContextFlags & CONTEXT_CONTROL) + { +#if !_M_X64 + PrintIntRegister("EBP", context.Ebp); + PrintIntRegister("EIP", context.Eip); + PrintIntRegister("ESP", context.Esp); + PrintIntRegister("EFL", context.EFlags); + this->NewLine(); this->NewLine(); regs_in_line = 0; + PrintSegRegister("CS", context.SegCs); + PrintSegRegister("SS", context.SegSs); +#else + PrintIntRegister("RIP", context.Rip); + PrintIntRegister("RSP", context.Rsp); + PrintIntRegister("EFL", context.EFlags); + this->NewLine(); this->NewLine(); regs_in_line = 0; + PrintSegRegister("CS", context.SegCs); + PrintSegRegister("SS", context.SegSs); +#endif + } + + this->NewLine(); regs_in_line = 0; + + // Print segment registers + if (context.ContextFlags & CONTEXT_SEGMENTS) + { + PrintSegRegister("GS", context.SegGs); + PrintSegRegister("FS", context.SegFs); + this->NewLine(); regs_in_line = 0; + PrintSegRegister("ES", context.SegEs); + PrintSegRegister("DS", context.SegDs); + } + + this->NewLine(); this->NewLine(); regs_in_line = 0; + + // Print floating point registers + if (context.ContextFlags & CONTEXT_FLOATING_POINT) + { + for (int i = 0; i < 8; i++) + { +#if !_M_X64 + auto f = *(M128A*) & (context.FloatSave.RegisterArea[i * 10]); + PrintFloatRegister("ST", i, LODWORD(f.Low), HIDWORD(f.Low), LODWORD(f.High), HIDWORD(f.High)); +#else + PrintFloatRegister("ST", i, + LODWORD(context.FltSave.FloatRegisters[i].Low), HIDWORD(context.FltSave.FloatRegisters[i].Low), + LODWORD(context.FltSave.FloatRegisters[i].High), HIDWORD(context.FltSave.FloatRegisters[i].High)); +#endif + } + + this->NewLine(); + + for (int i = 0; i < 16; i++) + { +#if !_M_X64 + auto f = *(M128A*) & (context.ExtendedRegisters[(i + 10) * 16]); + PrintFloatRegister("XMM", i, LODWORD(f.Low), HIDWORD(f.Low), LODWORD(f.High), HIDWORD(f.High)); + + if (i >= 7) + break; +#else + PrintFloatRegister("XMM", i, + LODWORD(context.FltSave.XmmRegisters[i].Low), HIDWORD(context.FltSave.XmmRegisters[i].Low), + LODWORD(context.FltSave.XmmRegisters[i].High), HIDWORD(context.FltSave.XmmRegisters[i].High)); +#endif + } + } + } + LeaveScope(); +} + +/* + * PrintStackdump + * Prints the content of the stack into the logging buffer + */ +void ExceptionTracer::PrintStackdump() +{ + // We need the ESP of the exception context to execute a stack dump, make sure we have access to it + if ((context.ContextFlags & CONTEXT_CONTROL) == 0) + return; + + static const auto align = sizeof_word; // Stack aligment + static const auto max_words_in_line_magic = stackdump_words_per_line + 10; + + MEMORY_BASIC_INFORMATION mbi; +#if !_M_X64 + uintptr_t base, bottom, top = (uintptr_t)context.Esp; +#else + uintptr_t base, bottom, top = (uintptr_t)context.Rsp; +#endif + auto words_in_line = max_words_in_line_magic; + + // Finds the bottom of the stack from it's base pointer + // Note: mbi will get overriden on this function + auto GetStackBottom = [&mbi](uintptr_t base) + { + VirtualQuery((void*)base, &mbi, sizeof(mbi)); // Find uncommited region of the stack + VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi)); // Find guard page + VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi)); // Find commited region of the stack + auto last = (uintptr_t)mbi.BaseAddress; + return (base + (last - base) + mbi.RegionSize); // base + distanceToLastRegion + lastRegionSize + }; + + // Prints an CPU word at the specified stack address + auto PrintWord = [this, &words_in_line](uintptr_t addr) + { + if (words_in_line++ >= stackdump_words_per_line) + { + // Print new line only if it's not the first time we enter here (i.e. words_in_line has magical value) + if (words_in_line != max_words_in_line_magic + 1) NewLine(); + words_in_line = 1; + Print("0x%p: ", addr); + } + Print(" %p", *(size_t*)addr); + }; + + Print("Stack dump:"); + EnterScope(); + { + // Makes sure the pointer at top (ESP) is valid and readable memory + if (VirtualQuery((void*)(top), &mbi, sizeof(mbi)) + && (mbi.State & MEM_COMMIT) + && (mbi.Protect & (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_READWRITE | PAGE_READONLY)) != 0) + { + base = (uintptr_t)mbi.AllocationBase; // Base of the stack (uncommited) + bottom = GetStackBottom(base); // Bottom of the stack (commited) + + // Align the stack top (esp) in a 4 bytes boundary + auto remainder = top % align; + uintptr_t current = remainder ? top + (align - remainder) : top; + + // on x86 stack grows downward! (i.e. from bottom to base) + for (int n = 0; n < stackdump_max_words && current < bottom; ++n, current += align) + PrintWord(current); + + NewLine(); + Print("base: 0x%p top: 0x%p bottom: 0x%p", base, top, bottom); + NewLine(); + } + } + LeaveScope(); +} + +/* + * PrintBacktrace + * Prints a call backtrace into the logging buffer + */ +void ExceptionTracer::PrintBacktrace() +{ + StackTracer tracer(this->context); + + char module_name[MAX_PATH]; + char sym_buffer[sizeof(SYMBOL_INFO) + symbol_max]; + + int backtrace_count = 0; // Num of frames traced + bool has_symbol_api = false; // True if we have the symbol API available for use + DWORD old_options; // Saves old symbol API options + + SYMBOL_INFO& symbol = *(SYMBOL_INFO*)sym_buffer; + symbol.SizeOfStruct = sizeof(SYMBOL_INFO); + symbol.MaxNameLen = symbol_max; + + // Tries to get the symbol api + if (SymInitialize(GetCurrentProcess(), 0, TRUE)) + { + has_symbol_api = true; + old_options = SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_NO_PROMPTS | SYMOPT_FAIL_CRITICAL_ERRORS); + } + + Print("Backtrace (may be wrong):"); + EnterScope(); + { + // Walks on the stack until there's no frame to trace or we traced 'max_backtrace' frames + while (auto trace = tracer.Walk()) + { + if (++backtrace_count >= max_backtrace) + break; + + bool has_sym = false; // This EIP has a symbol associated with it? + DWORD64 displacement; // EIP displacement relative to symbol + + // If we have access to the symbol api, try to get symbol name from pc (eip) + if (has_symbol_api) + has_sym = trace->pc ? !!SymFromAddr(GetCurrentProcess(), (DWORD64)trace->pc, &displacement, &symbol) : false; + + // Print everything up, this.... Ew, this looks awful! + Print(backtrace_count == 1 ? "=>" : " "); // First line should have '=>' to specify where it crashed + Print("0x%p ", trace->pc); // Print EIP at frame + if (has_sym) Print("%s+0x%x ", symbol.Name, (DWORD)displacement); // Print frame func symbol + Print("in %s (+0x%x) ", // Print module + trace->module ? FindModuleName(trace->module, module_name, sizeof(module_name)) : "unknown", + (uintptr_t)(trace->pc) - (uintptr_t)(trace->module) // Module displacement + ); + if (trace->frame) Print("(0x%p) ", trace->frame); // Print frame pointer + + NewLine(); + } + } + LeaveScope(); + + // Cleanup the symbol api + if (has_symbol_api) + { + SymSetOptions(old_options); + SymCleanup(GetCurrentProcess()); + } +} + +/* + * GetExceptionCodeString + * Returns an description by an exception code + */ +static const char* GetExceptionCodeString(unsigned int code) +{ + switch (code) + { + case EXCEPTION_ACCESS_VIOLATION: return "Access violation"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded"; + case EXCEPTION_BREAKPOINT: return "Breakpoint exception"; + case EXCEPTION_DATATYPE_MISALIGNMENT: return "Data type misalignment exception"; + case EXCEPTION_FLT_DENORMAL_OPERAND: return "Denormal float operand"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "Floating-point division by zero"; + case EXCEPTION_FLT_INEXACT_RESULT: return "Floating-point inexact result"; + case EXCEPTION_FLT_INVALID_OPERATION: return "Floating-point invalid operation"; + case EXCEPTION_FLT_OVERFLOW: return "Floating-point overflow"; + case EXCEPTION_FLT_STACK_CHECK: return "Floating-point stack check"; + case EXCEPTION_FLT_UNDERFLOW: return "Floating-point underflow"; + case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal instruction."; + case EXCEPTION_IN_PAGE_ERROR: return "In page error"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer division by zero"; + case EXCEPTION_INT_OVERFLOW: return "Integer overflow"; + case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Non-continuable exception"; + case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction"; + case EXCEPTION_SINGLE_STEP: return "Single step exception"; + case EXCEPTION_STACK_OVERFLOW: return "Stack overflow"; + default: return "NO_DESCRIPTION"; + } +} + +/* + * FindModuleName + * Finds module filename or "unknown" + */ +static const char* FindModuleName(HMODULE module, char* output, DWORD maxsize) +{ + if (GetModuleFileNameA(module, output, maxsize)) + { + // Finds the filename part in the output string + char* filename = strrchr(output, '\\'); + if (!filename) filename = strrchr(output, '/'); + + // If filename found (i.e. output isn't already a filename but full path), make output be filename + if (filename) + { + size_t size = strlen(++filename); + memmove(output, filename, size); + output[size] = 0; + } + } + else + { + // Unknown module + strcpy(output, "unknown"); + } + return output; +} + +/* + * GetModuleFromAddress + * Finds module handle from some address inside it + */ +static HMODULE GetModuleFromAddress(LPVOID address) +{ + HMODULE module; + if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (char*)address, &module)) + return module; + return nullptr; +} + +/* +* StackTracer +* Constructs the tracer, we basically need to initialize the symbol api +*/ +StackTracer::StackTracer(const CONTEXT& context) +{ + // Initialise basic values + memset(&this->frame, 0, sizeof(frame)); + memcpy(&this->context, &context, sizeof(context)); + + // Setup the initial frame context +#if !_M_X64 + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrPC.Offset = context.Eip; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; +#else + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrPC.Offset = context.Rip; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Rsp; +#endif +} + +/* + * StackTracer::Walk + * Walks on the stack, each walk is one frame of backtrace + * Returns a frame or null if the walk on the park is not possible anymore + */ +StackTracer::Trace* StackTracer::Walk() +{ + if (StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), + &frame, &context, NULL, NULL, NULL, NULL)) + { + trace.module = GetModuleFromAddress((void*)frame.AddrPC.Offset); + trace.frame = (void*)frame.AddrFrame.Offset; + trace.stack = (void*)frame.AddrStack.Offset; + trace.pc = (void*)frame.AddrPC.Offset; + trace.ret = (void*)frame.AddrReturn.Offset; + return &trace; + } + return nullptr; +} \ No newline at end of file diff --git a/source-code/source/fakedll/fakedll.vcxproj b/source-code/source/fakedll/fakedll.vcxproj new file mode 100644 index 0000000..fc4f3f0 --- /dev/null +++ b/source-code/source/fakedll/fakedll.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {B49C6ABE-931C-4F91-9A94-21A41A305FEE} + Win32Proj + fakedll + 10.0 + + + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + fakednsapi + + + false + + + false + fakednsapi + + + + NotUsing + Level3 + Disabled + true + X64;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + ..\MemoryModule;%(AdditionalIncludeDirectories) + + + Windows + true + false + x64.def + + + + + NotUsing + Level3 + Disabled + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;PDLOADER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + ..\dependencies\MemoryModule;%(AdditionalIncludeDirectories) + stdcpp17 + + + Windows + true + false + x64.def + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;PDLOADER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + true + false + x64.def + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;PDLOADER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + ..\dependencies\MemoryModule;%(AdditionalIncludeDirectories) + stdcpp17 + + + Windows + true + true + true + false + x64.def + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source-code/source/fakedll/fakedll.vcxproj.filters b/source-code/source/fakedll/fakedll.vcxproj.filters new file mode 100644 index 0000000..046fb1b --- /dev/null +++ b/source-code/source/fakedll/fakedll.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Source Files + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/source-code/source/fakedll/framework.h b/source-code/source/fakedll/framework.h new file mode 100644 index 0000000..97f1cea --- /dev/null +++ b/source-code/source/fakedll/framework.h @@ -0,0 +1,89 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include +#pragma once +#include +#include +#include +#include "ModuleList.h" +#include +#pragma intrinsic(_ReturnAddress) + +struct shared +{ + FARPROC DllCanUnloadNow; + FARPROC DllGetClassObject; + FARPROC DllRegisterServer; + FARPROC DllUnregisterServer; + FARPROC DebugSetMute; + + void LoadOriginalLibrary(HMODULE dll) + { + DllCanUnloadNow = GetProcAddress(dll, "DllCanUnloadNow"); + DllGetClassObject = GetProcAddress(dll, "DllGetClassObject"); + DllRegisterServer = GetProcAddress(dll, "DllRegisterServer"); + DllUnregisterServer = GetProcAddress(dll, "DllUnregisterServer"); + DebugSetMute = GetProcAddress(dll, "DebugSetMute"); + } +} shared; + +struct dnsapi_dll +{ + HMODULE dll; + + // only some functions are implemented. + // PDAFT doesn't use many, so this should hopefully be fine + FARPROC DnsFree; + FARPROC DnsQuery_A; + FARPROC DnsQueryEx; + FARPROC DnsCancelQuery; + + // DnsQueryEx and DnsCancelQuery take pointers to structs as parameters + // (three for DnsQueryEx and one for DnsCancelQuery) + // fortunately they should fit in registers so the stack doesn't matter + // hopefully this works fine... I have no clue what I'm doing + static LONG WINAPI DnsQueryExStub() + { + return 9004; // DNS_ERROR_RCODE_NOT_IMPLEMENTED + } + static LONG WINAPI DnsCancelQueryStub() + { + return 9004; // DNS_ERROR_RCODE_NOT_IMPLEMENTED + } + + void LoadOriginalLibrary(HMODULE module) + { + dll = module; + shared.LoadOriginalLibrary(dll); + DnsFree = GetProcAddress(dll, "DnsFree"); + DnsQuery_A = GetProcAddress(dll, "DnsQuery_A"); + DnsQueryEx = GetProcAddress(dll, "DnsQueryEx"); + DnsCancelQuery = GetProcAddress(dll, "DnsCancelQuery"); + + // if entry points aren't found, GetProcAddress should return null + // I hope this is correct + // Thanks to somewhatlurker + if (DnsQueryEx == NULL) { DnsQueryEx = (FARPROC)& DnsQueryExStub; }; + if (DnsCancelQuery == NULL) { DnsCancelQuery = (FARPROC)& DnsCancelQueryStub; }; + } +} dnsapi; + +void _DnsFree() { dnsapi.DnsFree(); } +void _DnsQuery_A() { dnsapi.DnsQuery_A(); } +void _DnsQueryEx() { dnsapi.DnsQueryEx(); } +void _DnsCancelQuery() { dnsapi.DnsCancelQuery(); } + +#pragma runtime_checks( "", off ) + +#ifdef _DEBUG +#pragma message ("You are compiling the code in Debug - be warned that wrappers for export functions may not have correct code generated") +#endif + +void _DllRegisterServer() { shared.DllRegisterServer(); } +void _DllUnregisterServer() { shared.DllUnregisterServer(); } +void _DllCanUnloadNow() { shared.DllCanUnloadNow(); } +void _DllGetClassObject() { shared.DllGetClassObject(); } + +#pragma runtime_checks( "", restore ) \ No newline at end of file diff --git a/source-code/source/fakedll/x64.def b/source-code/source/fakedll/x64.def new file mode 100644 index 0000000..9fa3e38 --- /dev/null +++ b/source-code/source/fakedll/x64.def @@ -0,0 +1,10 @@ +LIBRARY "dnsapi" +EXPORTS +DnsFree = _DnsFree +DnsQuery_A = _DnsQuery_A +DnsQueryEx = _DnsQueryEx +DnsCancelQuery = _DnsCancelQuery +DllCanUnloadNow = _DllCanUnloadNow PRIVATE +DllGetClassObject = _DllGetClassObject PRIVATE +DllRegisterServer = _DllRegisterServer PRIVATE +DllUnregisterServer = _DllUnregisterServer PRIVATE \ No newline at end of file