diff --git a/COPYING.txt b/COPYING.txt index 2325837..f5d30bb 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -17,4 +17,4 @@ The MinHook library is used in this project. All MinHook files are under libs/MinHook. -The license for MinHook is at libs/MinHook/Copying.txt. +The license for MinHook is at libs/MinHook/LICENSE.txt. diff --git a/CreateRelease/CreateRelease.bat b/CreateRelease/CreateRelease.bat index 7c21919..feb9f46 100644 --- a/CreateRelease/CreateRelease.bat +++ b/CreateRelease/CreateRelease.bat @@ -1,4 +1,4 @@ -call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat" +call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" devenv ..\Heapy.sln /Rebuild "Release|Win32" devenv ..\Heapy.sln /Rebuild "Release|x64" diff --git a/Heapy.sln b/Heapy.sln index 480695b..92334bc 100644 --- a/Heapy.sln +++ b/Heapy.sln @@ -1,14 +1,15 @@  -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Heapy", "Heapy\Heapy.vcxproj", "{964F661B-8FA0-4DEF-836F-0D0720972D02}" ProjectSection(ProjectDependencies) = postProject {F3C8DD27-15AB-4B73-A499-C32181ACACC9} = {F3C8DD27-15AB-4B73-A499-C32181ACACC9} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HeapyInject", "HeapyInject\HeapyInject.vcxproj", "{F3C8DD27-15AB-4B73-A499-C32181ACACC9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libs\MinHook\build\libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}" + ProjectSection(ProjectDependencies) = postProject + {529CF76D-94CA-4127-96F2-0EEB77A9DB19} = {529CF76D-94CA-4127-96F2-0EEB77A9DB19} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApplication", "TestApplication\TestApplication.vcxproj", "{2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}" EndProject @@ -18,72 +19,52 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProfileTestApplication", "P {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D} = {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook\libMinHook.vcxproj", "{529CF76D-94CA-4127-96F2-0EEB77A9DB19}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 - Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|Mixed Platforms.Build.0 = Debug|x64 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|Win32.ActiveCfg = Debug|Win32 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|Win32.Build.0 = Debug|Win32 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|x64.ActiveCfg = Debug|x64 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Debug|x64.Build.0 = Debug|x64 - {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|Mixed Platforms.Build.0 = Release|Win32 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|Win32.ActiveCfg = Release|Win32 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|Win32.Build.0 = Release|Win32 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|x64.ActiveCfg = Release|x64 {964F661B-8FA0-4DEF-836F-0D0720972D02}.Release|x64.Build.0 = Release|x64 - {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|Mixed Platforms.Build.0 = Debug|x64 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|Win32.ActiveCfg = Debug|Win32 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|Win32.Build.0 = Debug|Win32 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|x64.ActiveCfg = Debug|x64 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Debug|x64.Build.0 = Debug|x64 - {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|Mixed Platforms.Build.0 = Release|Win32 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|Win32.ActiveCfg = Release|Win32 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|Win32.Build.0 = Release|Win32 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|x64.ActiveCfg = Release|x64 {F3C8DD27-15AB-4B73-A499-C32181ACACC9}.Release|x64.Build.0 = Release|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Mixed Platforms.Build.0 = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64 - {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|Win32.ActiveCfg = Debug|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|Win32.Build.0 = Debug|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|x64.ActiveCfg = Debug|x64 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Debug|x64.Build.0 = Debug|x64 - {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|Mixed Platforms.Build.0 = Release|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|Win32.ActiveCfg = Release|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|Win32.Build.0 = Release|Win32 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|x64.ActiveCfg = Release|x64 {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D}.Release|x64.Build.0 = Release|x64 - {00772643-280F-44BE-8839-14E06137A705}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {00772643-280F-44BE-8839-14E06137A705}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {00772643-280F-44BE-8839-14E06137A705}.Debug|Win32.ActiveCfg = Debug|Win32 {00772643-280F-44BE-8839-14E06137A705}.Debug|x64.ActiveCfg = Debug|x64 - {00772643-280F-44BE-8839-14E06137A705}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {00772643-280F-44BE-8839-14E06137A705}.Release|Mixed Platforms.Build.0 = Release|Win32 {00772643-280F-44BE-8839-14E06137A705}.Release|Win32.ActiveCfg = Release|Win32 {00772643-280F-44BE-8839-14E06137A705}.Release|x64.ActiveCfg = Release|x64 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Debug|Win32.ActiveCfg = Debug|Win32 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Debug|Win32.Build.0 = Debug|Win32 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Debug|x64.ActiveCfg = Debug|x64 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Debug|x64.Build.0 = Debug|x64 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Release|Win32.ActiveCfg = Release|Win32 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Release|Win32.Build.0 = Release|Win32 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Release|x64.ActiveCfg = Release|x64 + {529CF76D-94CA-4127-96F2-0EEB77A9DB19}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Heapy/Heapy.cpp b/Heapy/Heapy.cpp index 7f4ae3c..43abfbc 100644 --- a/Heapy/Heapy.cpp +++ b/Heapy/Heapy.cpp @@ -1,31 +1,151 @@ #include #include -#include +#include #include -#include -#include -#include #include #include #include +typedef NTSTATUS (NTAPI *pfnNtQueryInformationProcess)( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + +void* GetEntryPointAddress(HANDLE hProcess){ + HMODULE hModule = GetModuleHandleA("ntdll.dll"); + pfnNtQueryInformationProcess pNtQueryInformationProcess + = (pfnNtQueryInformationProcess)GetProcAddress(hModule, "NtQueryInformationProcess"); + + if (pNtQueryInformationProcess != NULL){ + PROCESS_BASIC_INFORMATION pbi; + memset(&pbi, 0, sizeof(pbi)); + + NTSTATUS status = pNtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); + if (NT_SUCCESS(status)){ + PEB* pPeb = pbi.PebBaseAddress; + + void* pImageBaseAddress; + SIZE_T NumOfBytesRead; + if (ReadProcessMemory(hProcess, + &pPeb->Reserved3[1], + &pImageBaseAddress, + sizeof(pImageBaseAddress), + &NumOfBytesRead) == 0 + || NumOfBytesRead != sizeof(pImageBaseAddress)) + return NULL; + + LONG e_lfanew; + if (ReadProcessMemory(hProcess, + (char*)pImageBaseAddress + offsetof(IMAGE_DOS_HEADER, e_lfanew), + &e_lfanew, + sizeof(e_lfanew), + &NumOfBytesRead) == 0 + || NumOfBytesRead != sizeof(e_lfanew)) + return NULL; + + IMAGE_NT_HEADERS* pImageHeaders = (IMAGE_NT_HEADERS*)((char*)pImageBaseAddress + e_lfanew); + + DWORD EntryPointOffset; + if (ReadProcessMemory(hProcess, + (char*)pImageHeaders + offsetof(IMAGE_NT_HEADERS, OptionalHeader.AddressOfEntryPoint), + &EntryPointOffset, + sizeof(EntryPointOffset), + &NumOfBytesRead) == 0 + || NumOfBytesRead != sizeof(EntryPointOffset)) + return NULL; + + void* pEntryPointAddress = (char*)pImageBaseAddress + EntryPointOffset; + return pEntryPointAddress; + } + } + return NULL; +} + +bool PatchEntryPoint(HANDLE hProcess, void* pEntryPointAddress, unsigned char* pWriteBytes, unsigned char* pOriginalBytes, unsigned int unSize){ + SIZE_T NumOfBytesRead; + if (pOriginalBytes != NULL){ + if (ReadProcessMemory(hProcess, pEntryPointAddress, pOriginalBytes, unSize, &NumOfBytesRead) == 0 + || NumOfBytesRead != unSize) + { + return false; + } + } + if (WriteProcessMemory(hProcess, pEntryPointAddress, pWriteBytes, unSize, &NumOfBytesRead) == 0 + || NumOfBytesRead != unSize){ + return false; + } + + FlushInstructionCache(hProcess, pEntryPointAddress, unSize); + return true; +} + +struct ProcessStartContext{ + void* pEntryPointAddress; + unsigned char OldOpCodes[2]; +}; + +bool WaitForProcessStart(HANDLE hProcess, HANDLE hThread, ProcessStartContext* pProcessContext){ + void* pEntryPointAddress = GetEntryPointAddress(hProcess); + if (pEntryPointAddress == NULL) + return false; + + unsigned char OldBytes[2]; + unsigned char NewBytes[2] = { 0xEB, 0xFE }; + if (!PatchEntryPoint(hProcess, pEntryPointAddress, NewBytes, OldBytes, 2)) + return false; + + pProcessContext->pEntryPointAddress = pEntryPointAddress; + memcpy(pProcessContext->OldOpCodes, OldBytes, 2); + + ResumeThread(hThread); + + CONTEXT context; + memset(&context, 0, sizeof(context)); +#ifdef _WIN64 + for (unsigned int i = 0; i < 50 && context.Rip != (decltype(context.Rip))pEntryPointAddress; ++i){ +#else + for (unsigned int i = 0; i < 50 && context.Eip != (decltype(context.Eip))pEntryPointAddress; ++i){ +#endif + // patience. + Sleep(100); + + // read the thread context + context.ContextFlags = CONTEXT_CONTROL; + GetThreadContext(hThread, &context); + } + + return true; +} + +bool ResumeProcessStart(HANDLE hProcess, HANDLE hThread, ProcessStartContext* pProcessContext){ + SuspendThread(hThread); + if (!PatchEntryPoint(hProcess, pProcessContext->pEntryPointAddress, pProcessContext->OldOpCodes, NULL, 2)) + return false; + + ResumeThread(hThread); + return true; +} + // Inject a DLL into the target process by creating a new thread at LoadLibrary // Waits for injected thread to finish and returns its exit code. // // Originally from : // http://www.codeproject.com/Articles/2082/API-hooking-revealed -DWORD LoadLibraryInjection(HANDLE proc, const char *dllName){ +DWORD LoadLibraryInjection(HANDLE proc, const wchar_t *dllName){ LPVOID RemoteString, LoadLibAddy; - LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); + LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"); - RemoteString = (LPVOID)VirtualAllocEx(proc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + RemoteString = (LPVOID)VirtualAllocEx(proc, NULL, (wcslen(dllName)+1)*sizeof(wchar_t), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); if(RemoteString == NULL){ CloseHandle(proc); // Close the process handle. throw std::runtime_error("LoadLibraryInjection: Error on VirtualAllocEx."); } - if(WriteProcessMemory(proc, (LPVOID)RemoteString, dllName,strlen(dllName), NULL) == 0){ + if(WriteProcessMemory(proc, (LPVOID)RemoteString, dllName, (wcslen(dllName)+1)*sizeof(wchar_t), NULL) == 0){ VirtualFreeEx(proc, RemoteString, 0, MEM_RELEASE); // Free the memory we were going to use. CloseHandle(proc); // Close the process handle. throw std::runtime_error("LoadLibraryInjection: Error on WriteProcessMemeory."); @@ -33,7 +153,7 @@ DWORD LoadLibraryInjection(HANDLE proc, const char *dllName){ HANDLE hThread; - if((hThread = CreateRemoteThread(proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)) == NULL){ + if((hThread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, 0, NULL)) == NULL){ VirtualFreeEx(proc, RemoteString, 0, MEM_RELEASE); // Free the memory we were going to use. CloseHandle(proc); // Close the process handle. throw std::runtime_error("LoadLibraryInjection: Error on CreateRemoteThread."); @@ -55,68 +175,183 @@ DWORD LoadLibraryInjection(HANDLE proc, const char *dllName){ return dwThreadExitCode; } -std::string getDirectoryOfFile(const std::string &file){ - size_t pos = (std::min)(file.find_last_of("/"), file.find_last_of("\\")); +std::wstring getDirectoryOfFile(const std::wstring &file){ + size_t pos = (std::min)(file.find_last_of(L"/"), file.find_last_of(L"\\")); if(pos == std::string::npos) - return "."; + return L"."; else return file.substr(0, pos); } +/*++ + +Routine Description: + + This routine appends the given argument to a command line such + that CommandLineToArgvW will return the argument string unchanged. + Arguments in a command line should be separated by spaces; this + function does not add these spaces. + +Arguments: + + Argument - Supplies the argument to encode. + + CommandLine - Supplies the command line to which we append the encoded argument string. + + Force - Supplies an indication of whether we should quote + the argument even if it does not contain any characters that would + ordinarily require quoting. + +From: https://docs.microsoft.com/en-gb/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way + +--*/ + +void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine, bool Force){ + // + // Unless we're told otherwise, don't quote unless we actually + // need to do so --- hopefully avoid problems if programs won't + // parse quotes properly + // + + if (Force == false && + Argument.empty() == false && + Argument.find_first_of(L" \t\n\v\"") == Argument.npos) + { + CommandLine.append(Argument); + } + else { + CommandLine.push_back(L'"'); + + for (auto It = Argument.begin(); ; ++It) { + unsigned NumberBackslashes = 0; + + while (It != Argument.end() && *It == L'\\') { + ++It; + ++NumberBackslashes; + } + + if (It == Argument.end()) { + + // + // Escape all backslashes, but let the terminating + // double quotation mark we add below be interpreted + // as a metacharacter. + // + + CommandLine.append(NumberBackslashes * 2, L'\\'); + break; + } + else if (*It == L'"') { + + // + // Escape all backslashes and the following + // double quotation mark. + // + + CommandLine.append(NumberBackslashes * 2 + 1, L'\\'); + CommandLine.push_back(*It); + } + else { + + // + // Backslashes aren't special here. + // + + CommandLine.append(NumberBackslashes, L'\\'); + CommandLine.push_back(*It); + } + } + + CommandLine.push_back(L'"'); + } +} + extern "C" int main(int argc, char* argv[]){ if(argc < 2){ std::cout << "No exe specified!\n\n"; std::cout << "Usage: Heapy [args to pass to exe]\n\n" - " The first argument specifies the exe to launch.\n" - " Subsequent arguments are passed to launched exe.\n"; + " The first argument specifies the exe to launch.\n" + " Subsequent arguments are passed to launched exe.\n"; return -1; } - char *injectionTarget = argv[1]; bool win64 = false; #ifdef _WIN64 win64 = true; #endif // Select correct dll name depending on whether x64 or win32 version launched. - std::string heapyInjectDllName; + std::wstring heapyInjectDllName; if(win64) - heapyInjectDllName = "HeapyInject_x64.dll"; + heapyInjectDllName = L"HeapyInject_x64.dll"; else - heapyInjectDllName = "HeapyInject_Win32.dll"; + heapyInjectDllName = L"HeapyInject_Win32.dll"; // Assume that the injection payload dll is in the same directory as the exe. - CHAR exePath[MAX_PATH]; - GetModuleFileNameA(NULL, exePath, MAX_PATH ); - std::string dllPath = getDirectoryOfFile(std::string(exePath)) + "\\" + heapyInjectDllName; + wchar_t exePath[MAX_PATH]; + GetModuleFileNameW(NULL, exePath, MAX_PATH ); + + std::wstring dllPath = getDirectoryOfFile(std::wstring(exePath)) + L"\\" + heapyInjectDllName; + + std::wstring commandLine; + + // + // Form command line... + // + { + wchar_t **wArgList; + int nArgs; + wArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); + + + commandLine += L"\""; + commandLine += std::wstring(wArgList[1]); + commandLine += L"\""; + for (int i = 2; i < nArgs; ++i) { + + std::wstring argQuoted; + + ArgvQuote(std::wstring(wArgList[i]), argQuoted, false); + + std::wcout << argQuoted << "\n"; - std::string commandLine = injectionTarget; - for(int i = 2; i < argc; ++i){ - commandLine += " " + std::string(argv[i]); + commandLine += L" " + argQuoted; + } + + std::wcout << commandLine << "\n"; + LocalFree(wArgList); } // Start our new process with a suspended main thread. std::cout << "Starting process with heap profiling enabled..." << std::endl; - std::cout << "Target exe path: " << injectionTarget << std::endl; - std::cout << "Target execommand line: " << commandLine << std::endl; - std::cout << "Dll to inject: " << dllPath << std::endl; + std::wcout << "Target exe command line: " << commandLine << std::endl; + std::wcout << "Dll to inject: " << dllPath << std::endl; + DWORD flags = CREATE_SUSPENDED; PROCESS_INFORMATION pi; - STARTUPINFOA si; - GetStartupInfoA(&si); + STARTUPINFOW si; - // CreatePRocessA can modify input arg so do this to be safe. - std::vector commandLineMutable(commandLine.begin(), commandLine.end()); - commandLineMutable.push_back(0); + GetStartupInfoW(&si); - if(CreateProcessA(NULL, commandLineMutable.data(), NULL, NULL, 0, flags, NULL, - (LPSTR)".", &si, &pi) == 0){ - std::cerr << "Error creating process " << injectionTarget << std::endl; + // CreateProcessW can modify input arg so do this to be safe. + std::vector commandLineMutable(commandLine.begin(), commandLine.end()); + commandLineMutable.push_back('\0'); + + if(CreateProcessW(NULL, commandLineMutable.data(), NULL, NULL, 0, flags, NULL, + NULL, &si, &pi) == 0){ + std::wcerr << "Error creating process, command line " << commandLine << std::endl; + Sleep(10000); return -1; } - + + ProcessStartContext ProcessContext; + if (!WaitForProcessStart(pi.hProcess, pi.hThread, &ProcessContext)) { + Sleep(10000); + return -1; + } + // Inject our dll. // This method returns only when injection thread returns. try{ @@ -126,17 +361,18 @@ extern "C" int main(int argc, char* argv[]){ }catch(const std::exception &e){ std::cerr << "\n"; std::cerr << "Error while injecting process: " << e.what() << "\n\n"; - std::cerr << "Check that the hook dll (" << dllPath << " is in the correct location.\n\n"; + std::wcerr << "Check that the hook dll (" << dllPath << " is in the correct location.\n\n"; std::cerr << "Are you trying to inject a " << (win64 ? " 32 bit " : " 64 bit ") << " application using the " << (win64 ? " 64 bit " : " 32 bit ") << " injector?\n\n"; // TODO: figure out how to terminate thread. This does not always work. TerminateProcess(pi.hProcess, 0); + Sleep(10000); return -1; } - + // Once the injection thread has returned it is safe to resume the main thread. - ResumeThread(pi.hThread); + ResumeProcessStart(pi.hProcess, pi.hThread, &ProcessContext); // Wait for the target application to exit. // This doesn't matter to much, but makes heapy nicer to use in test scripts. diff --git a/Heapy/Heapy.vcxproj b/Heapy/Heapy.vcxproj index fffc077..66624f1 100644 --- a/Heapy/Heapy.vcxproj +++ b/Heapy/Heapy.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,31 @@ {964F661B-8FA0-4DEF-836F-0D0720972D02} Win32Proj Heapy - 10.0.17763.0 Application true - v120 + v100 Unicode Application true - v120 + v100 Unicode Application false - v120 + v100 true Unicode Application false - v141 + v100 true Unicode diff --git a/HeapyInject/HeapProfiler.cpp b/HeapyInject/HeapProfiler.cpp index 1b593ce..84c1fa3 100644 --- a/HeapyInject/HeapProfiler.cpp +++ b/HeapyInject/HeapProfiler.cpp @@ -10,7 +10,7 @@ StackTrace::StackTrace() : hash(0){ memset(backtrace, 0, sizeof(void*)*backtraceSize); } - +#pragma optimize("", off) void StackTrace::trace(){ int framesCnt = CaptureStackBackTrace(0, backtraceSize, backtrace, 0); // Compute simple polynomial hash of the stack trace. @@ -20,7 +20,7 @@ void StackTrace::trace(){ for (int i = 0; i < framesCnt; i++) hash = hash * BASE + (size_t)backtrace[i]; } - +#pragma optimize("", on) void StackTrace::print(std::ostream &stream) const { HANDLE process = GetCurrentProcess(); @@ -30,8 +30,8 @@ void StackTrace::print(std::ostream &stream) const { symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); symbol->MaxNameLength = MAXSYMBOLNAME - 1; - // Print out stack trace. Skip the first frame (that's our hook function.) - for(size_t i = 1; i < backtraceSize; ++i){ + // Print out stack trace. Skip first frame (that's our trace function) and second frmae (that's our hook function) + for(size_t i = 2; i < backtraceSize; ++i){ if(backtrace[i]){ // Output stack frame symbols if available. if(SymGetSymFromAddr(process, (DWORD64)backtrace[i], 0, symbol)){ @@ -57,30 +57,45 @@ void StackTrace::print(std::ostream &stream) const { } } +HeapProfiler::HeapProfiler(){ + +} + +HeapProfiler::~HeapProfiler(){ + +} + void HeapProfiler::malloc(void *ptr, size_t size, const StackTrace &trace){ - std::lock_guard lk(mutex); + lock_guard lk(mutex); if (ptrs.find(ptr) != ptrs.end()) - return; //two buffers at same address! + { + //two buffers at same address! + //heap overflow? + return; + } // Locate or create this stacktrace in the allocations map. if(stackTraces.find(trace.hash) == stackTraces.end()){ - auto &stack = stackTraces[trace.hash]; + CallStackInfo &stack = stackTraces[trace.hash]; stack.trace = trace; stack.totalSize = 0; + stack.n = 0; } // Store the size for this allocation this stacktraces allocation map. - stackTraces[trace.hash].totalSize += size; + CallStackInfo& callStackInfo = stackTraces[trace.hash]; + callStackInfo.totalSize += size; + callStackInfo.n++; // Store the stracktrace hash of this allocation in the pointers map. - auto &ptrInfo = ptrs[ptr]; + PointerInfo &ptrInfo = ptrs[ptr]; ptrInfo.size = size; ptrInfo.stack = trace.hash; } void HeapProfiler::free(void *ptr, const StackTrace &trace){ - std::lock_guard lk(mutex); + lock_guard lk(mutex); // On a free we remove the pointer from the ptrs map and the // allocating stack traces map. @@ -94,12 +109,13 @@ void HeapProfiler::free(void *ptr, const StackTrace &trace){ } } -void HeapProfiler::getAllocationSiteReport(std::vector> &allocs){ - std::lock_guard lk(mutex); +void HeapProfiler::getAllocationSiteReport(std::vector &allocs){ + lock_guard lk(mutex); allocs.clear(); - - for(auto it = stackTraces.begin(); it != stackTraces.end(); it++){ - const auto &info = it->second; - allocs.push_back(std::make_pair(info.trace, info.totalSize)); + allocs.reserve(stackTraces.size()); + typedef StackTraceCollection_t::iterator StackTraceIterator; + for(StackTraceIterator it = stackTraces.begin(); it != stackTraces.end(); it++){ + const CallStackInfo &info = it->second; + allocs.push_back(info); } -} \ No newline at end of file +} diff --git a/HeapyInject/HeapProfiler.h b/HeapyInject/HeapProfiler.h index c04b54f..cb3a6eb 100644 --- a/HeapyInject/HeapProfiler.h +++ b/HeapyInject/HeapProfiler.h @@ -3,9 +3,9 @@ #include #include #include -#include +#include -const int backtraceSize = 64; +const int backtraceSize = 62; typedef size_t StackHash; struct StackTrace{ @@ -17,26 +17,172 @@ struct StackTrace{ void print(std::ostream &stream) const; }; + +// We define our own Mutex type since we can't use any standard library features inside parts of heapy. +struct Mutex{ + CRITICAL_SECTION criticalSection; + Mutex(){ + InitializeCriticalSectionAndSpinCount(&criticalSection, 400); + } + ~Mutex(){ + DeleteCriticalSection(&criticalSection); + } +}; + +struct lock_guard{ + Mutex& mutex; + lock_guard(Mutex& mutex) : mutex(mutex){ + EnterCriticalSection(&mutex.criticalSection); + } + ~lock_guard(){ + LeaveCriticalSection(&mutex.criticalSection); + } +}; + +template +struct HeapAllocator +{ +public: + typedef _Ty value_type; +#if _MSC_VER <= 1700 + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type* const_pointer; + typedef const value_type& const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + template + struct rebind + { // convert this type to _ALLOCATOR<_Other> + typedef HeapAllocator<_Other> other; + }; + + pointer address(reference _Val) const + { // return address of mutable _Val + return ((pointer) &(char&)_Val); + } + + const_pointer address(const_reference _Val) const + { // return address of nonmutable _Val + return ((const_pointer) &(char&)_Val); + } +#endif + HeapAllocator() _THROW0() + { // construct default allocator (do nothing) + } +#if _MSC_VER <= 1700 + HeapAllocator(const HeapAllocator<_Ty>&) _THROW0() + { // construct by copying (do nothing) + } +#endif + template + HeapAllocator(const HeapAllocator<_Other>&) _THROW0() + { // construct from a related allocator (do nothing) + } +#if _MSC_VER <= 1700 + template + HeapAllocator<_Ty>& operator=(const HeapAllocator<_Other>&) + { // assign from a related allocator (do nothing) + return (*this); + } +#endif + void deallocate(value_type* _Ptr, size_t) + { // deallocate object at _Ptr, ignore size + HeapFree(GetProcessHeap(), 0, _Ptr); + } + + value_type* allocate(size_t _Count) + { // allocate array of _Count elements + void *_Ptr = 0; + + if (_Count <= 0) + _Count = 0; + else if ((size_t)(-1) / sizeof (_Ty) < _Count) + throw std::bad_array_new_length(); + else if ((_Ptr = HeapAlloc(GetProcessHeap(), 0, _Count * sizeof (_Ty))) == 0) + throw std::bad_alloc(); + + return ((_Ty*)_Ptr); + } +#if _MSC_VER <= 1700 + pointer allocate(size_type _Count, const void*) + { // allocate array of _Count elements, ignore hint + return (allocate(_Count)); + } + + void construct(pointer _Ptr, const _Ty& _Val) + { // construct object at _Ptr with value _Val + _Construct(_Ptr, _Val); + } + + void construct(pointer _Ptr, _Ty&& _Val) + { // construct object at _Ptr with value _Val + ::new ((void*)_Ptr) _Ty(std::forward<_Ty>(_Val)); + } + + template + void construct(pointer _Ptr, _Other&& _Val) + { // construct object at _Ptr with value _Val + ::new ((void*)_Ptr) _Ty(std::forward<_Other>(_Val)); + } + + void destroy(pointer _Ptr) + { // destroy object at _Ptr + _Destroy(_Ptr); + } + + size_t max_size() const _THROW0() + { // estimate maximum array size + size_t _Count = (size_t)(-1) / sizeof (_Ty); + return (0 < _Count ? _Count : 1); + } +#endif +}; + +template inline + bool operator==(const HeapAllocator<_Ty>&, + const HeapAllocator<_Other>&) _THROW0() + { // test for allocator equality + return (true); + } + +template inline + bool operator!=(const HeapAllocator<_Ty>& _Left, + const HeapAllocator<_Other>& _Right) _THROW0() + { // test for allocator inequality + return (!(_Left == _Right)); + } + class HeapProfiler{ public: + HeapProfiler(); + ~HeapProfiler(); + void malloc(void *ptr, size_t size, const StackTrace &trace); void free(void *ptr, const StackTrace &trace); - // Return a list of allocation sites (a particular stack trace) and the amount - // of memory currently allocated by each site. - void getAllocationSiteReport(std::vector> &allocs); -private: - std::mutex mutex; struct CallStackInfo { StackTrace trace; size_t totalSize; + size_t n; }; + + // Return a list of allocation sites (a particular stack trace) and the amount + // of memory currently allocated by each site. + void getAllocationSiteReport(std::vector &allocs); +private: + Mutex mutex; + struct PointerInfo { StackHash stack; size_t size; }; - - std::unordered_map stackTraces; - std::unordered_map ptrs; - -}; \ No newline at end of file + typedef std::unordered_map, std::equal_to, HeapAllocator > > StackTraceCollection_t; + StackTraceCollection_t stackTraces; + typedef std::unordered_map, std::equal_to, HeapAllocator > > PtrCollection_t; + PtrCollection_t ptrs; +}; diff --git a/HeapyInject/HeapyInject.cpp b/HeapyInject/HeapyInject.cpp index b319b11..6353300 100644 --- a/HeapyInject/HeapyInject.cpp +++ b/HeapyInject/HeapyInject.cpp @@ -1,9 +1,6 @@ -#include -#include #include #include #include -#include #include #include #include @@ -14,36 +11,48 @@ #include "dbghelp.h" #include +typedef __int64 int64_t; typedef void * (__cdecl *PtrMalloc)(size_t); typedef void (__cdecl *PtrFree)(void *); +typedef void* (__cdecl *PtrRealloc)(void *, size_t); +typedef void * (__cdecl *PtrCalloc)(size_t, size_t); // Hook tables. (Lot's of static data, but it's the only way to do this.) const int numHooks = 128; -std::mutex hookTableMutex; -int nUsedMallocHooks = 0; -int nUsedFreeHooks = 0; +Mutex hookTableMutex; +int nUsedMallocHooks = 0; +int nUsedFreeHooks = 0; +int nUsedReallocHooks = 0; +int nUsedCallocHooks = 0; PtrMalloc mallocHooks[numHooks]; PtrFree freeHooks[numHooks]; +PtrRealloc reallocHooks[numHooks]; +PtrCalloc callocHooks[numHooks]; PtrMalloc originalMallocs[numHooks]; PtrFree originalFrees[numHooks]; +PtrRealloc originalReallocs[numHooks]; +PtrCalloc originalCallocs[numHooks]; // TODO?: Special case for debug build malloc/frees? HeapProfiler *heapProfiler; // Mechanism to stop us profiling ourself. -static __declspec( thread ) int _depthCount = 0; // use thread local count +DWORD tlsIndex; struct PreventSelfProfile{ PreventSelfProfile(){ - _depthCount++; + intptr_t depthCount = (intptr_t)TlsGetValue(tlsIndex); + TlsSetValue(tlsIndex, (LPVOID)(depthCount+1)); } ~PreventSelfProfile(){ - _depthCount--; + intptr_t depthCount = (intptr_t)TlsGetValue(tlsIndex); + TlsSetValue(tlsIndex, (LPVOID)(depthCount-1)); } inline bool shouldProfile(){ - return _depthCount <= 1; + intptr_t depthCount = (intptr_t)TlsGetValue(tlsIndex); + return depthCount <= 1; } private: PreventSelfProfile(const PreventSelfProfile&){} @@ -51,20 +60,27 @@ struct PreventSelfProfile{ }; void PreventEverProfilingThisThread(){ - _depthCount++; + intptr_t depthCount = (intptr_t)TlsGetValue(tlsIndex); + TlsSetValue(tlsIndex, (LPVOID)(depthCount+1)); } // Malloc hook function. Templated so we can hook many mallocs. template void * __cdecl mallocHook(size_t size){ - PreventSelfProfile preventSelfProfile; - - void * p = originalMallocs[N](size); - if(preventSelfProfile.shouldProfile()){ - StackTrace trace; - trace.trace(); - heapProfiler->malloc(p, size, trace); + void * p; + DWORD lastError; + { + PreventSelfProfile preventSelfProfile; + + p = originalMallocs[N](size); + lastError = GetLastError(); + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + trace.trace(); + heapProfiler->malloc(p, size, trace); + } } + SetLastError(lastError); return p; } @@ -72,52 +88,200 @@ void * __cdecl mallocHook(size_t size){ // Free hook function. template void __cdecl freeHook(void * p){ - PreventSelfProfile preventSelfProfile; + DWORD lastError; + { + PreventSelfProfile preventSelfProfile; + + originalFrees[N](p); + lastError = GetLastError(); + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + //trace.trace(); + heapProfiler->free(p, trace); + } + } + SetLastError(lastError); +} + +// Realloc hook function. Templated so we can hook many mallocs. +template +void * __cdecl reallocHook(void* memblock, size_t size){ + void * p; + DWORD lastError; + { + PreventSelfProfile preventSelfProfile; + + p = originalReallocs[N](memblock, size); + lastError = GetLastError(); + if (memblock == NULL){ + // memblock == NULL -> call malloc() + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + trace.trace(); + heapProfiler->malloc(p, size, trace); + } + } + else if (size == 0){ + // size == 0 -> call free() + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + //trace.trace(); + heapProfiler->free(memblock, trace); + } + } + else if (p == NULL){ + // p == NULL -> no memory, memblock not touched + } + else { + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + trace.trace(); + heapProfiler->free(memblock, trace); + heapProfiler->malloc(p, size, trace); + } + } + } + SetLastError(lastError); + + return p; +} - originalFrees[N](p); - if(preventSelfProfile.shouldProfile()){ - StackTrace trace; - //trace.trace(); - heapProfiler->free(p, trace); +// Calloc hook function. Templated so we can hook many Callocs. +template +void * __cdecl callocHook(size_t num, size_t size){ + void * p; + DWORD lastError; + { + PreventSelfProfile preventSelfProfile; + + p = originalCallocs[N](num, size); + lastError = GetLastError(); + if(preventSelfProfile.shouldProfile()){ + StackTrace trace; + trace.trace(); + heapProfiler->malloc(p, num * size, trace); + } } + SetLastError(lastError); + + return p; } // Template recursion to init a hook table. template struct InitNHooks{ - static void initHook(){ - InitNHooks::initHook(); // Compile time recursion. + static void initHook(){ + InitNHooks::initHook(); // Compile time recursion. mallocHooks[N-1] = &mallocHook; freeHooks[N-1] = &freeHook; - } + reallocHooks[N-1] = &reallocHook; + callocHooks[N-1] = &callocHook; + } }; template<> struct InitNHooks<0>{ - static void initHook(){ + static void initHook(){ // stop the recursion - } + } }; +// Internal function to reverse string buffer +static void internal_reverse(char str[], int length){ + int start = 0; + int end = length -1; + while (start < end){ + char c = str[start]; + str[start] = str[end]; + str[end] = c; + + start++; + end--; + } +} + +// Internal itoa() +static char* internal_itoa(__int64 num, char* str, int base){ + int i = 0; + bool isNegative = false; + + // Handle 0 explicitely, otherwise empty string is printed for 0 + if (num == 0){ + str[i++] = '0'; + str[i] = '\0'; + return str; + } + + // In standard itoa(), negative numbers are handled only with + // base 10. Otherwise numbers are considered unsigned. + if (num < 0 && base == 10){ + isNegative = true; + num = -num; + } + + // Process individual digits + while (num != 0){ + int rem = num % base; + str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0'; + num = num/base; + } + + // If number is negative, append '-' + if (isNegative) + str[i++] = '-'; + + str[i] = '\0'; // Append string terminator + + // Reverse the string + internal_reverse(str, i); + + return str; +} + +// Internal function to write inject log to InjectLog.txt +void InjectLog(const char* szStr1, const char* szStr2=NULL, const char* szStr3=NULL, const char* szStr4=NULL, const char* szStr5=NULL){ + HANDLE hFile = CreateFileA("InjectLog.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE){ + LARGE_INTEGER lEndOfFilePointer; + LARGE_INTEGER lTemp; + lTemp.QuadPart = 0; + SetFilePointerEx(hFile, lTemp, &lEndOfFilePointer, FILE_END); + + DWORD dwByteWritten; + WriteFile(hFile, szStr1, strlen(szStr1), &dwByteWritten, NULL); + if (szStr2 != NULL) + WriteFile(hFile, szStr2, strlen(szStr2), &dwByteWritten, NULL); + if (szStr3 != NULL) + WriteFile(hFile, szStr3, strlen(szStr3), &dwByteWritten, NULL); + if (szStr4 != NULL) + WriteFile(hFile, szStr4, strlen(szStr4), &dwByteWritten, NULL); + if (szStr5 != NULL) + WriteFile(hFile, szStr5, strlen(szStr5), &dwByteWritten, NULL); + CloseHandle(hFile); + } +} + // Callback which recieves addresses for mallocs/frees which we hook. BOOL CALLBACK enumSymbolsCallback(PSYMBOL_INFO symbolInfo, ULONG symbolSize, PVOID userContext){ - std::lock_guard lk(hookTableMutex); + lock_guard lk(hookTableMutex); PreventSelfProfile preventSelfProfile; PCSTR moduleName = (PCSTR)userContext; - + char logBuffer[30]; + // Hook mallocs. if(strcmp(symbolInfo->Name, "malloc") == 0){ if(nUsedMallocHooks >= numHooks){ - printf("All malloc hooks used up!\n"); + InjectLog("All malloc hooks used up!\r\n"); return true; } - printf("Hooking malloc from module %s into malloc hook num %d.\n", moduleName, nUsedMallocHooks); + internal_itoa(nUsedMallocHooks, logBuffer, 10); + InjectLog("Hooking malloc from module ", moduleName, " into malloc hook num ", logBuffer, ".\r\n"); if(MH_CreateHook((void*)symbolInfo->Address, mallocHooks[nUsedMallocHooks], (void **)&originalMallocs[nUsedMallocHooks]) != MH_OK){ - printf("Create hook malloc failed!\n"); + InjectLog("Create hook malloc failed!\r\n"); } if(MH_EnableHook((void*)symbolInfo->Address) != MH_OK){ - printf("Enable malloc hook failed!\n"); + InjectLog("Enable malloc hook failed!\r\n"); } nUsedMallocHooks++; @@ -126,44 +290,85 @@ BOOL CALLBACK enumSymbolsCallback(PSYMBOL_INFO symbolInfo, ULONG symbolSize, PVO // Hook frees. if(strcmp(symbolInfo->Name, "free") == 0){ if(nUsedFreeHooks >= numHooks){ - printf("All free hooks used up!\n"); + InjectLog("All free hooks used up!\r\n"); return true; } - printf("Hooking free from module %s into free hook num %d.\n", moduleName, nUsedFreeHooks); + internal_itoa(nUsedFreeHooks, logBuffer, 10); + InjectLog("Hooking free from module ", moduleName, " into free hook num ", logBuffer, ".\r\n"); if(MH_CreateHook((void*)symbolInfo->Address, freeHooks[nUsedFreeHooks], (void **)&originalFrees[nUsedFreeHooks]) != MH_OK){ - printf("Create hook free failed!\n"); + InjectLog("Create hook free failed!\r\n"); } if(MH_EnableHook((void*)symbolInfo->Address) != MH_OK){ - printf("Enable free failed!\n"); + InjectLog("Enable free failed!\r\n"); } nUsedFreeHooks++; } + // Hook reallocs. + if(strcmp(symbolInfo->Name, "realloc") == 0){ + if(nUsedReallocHooks >= numHooks){ + InjectLog("All realloc hooks used up!\r\n"); + return true; + } + internal_itoa(nUsedReallocHooks, logBuffer, 10); + InjectLog("Hooking realloc from module ", moduleName, " into realloc hook num ", logBuffer, ".\r\n"); + if(MH_CreateHook((void*)symbolInfo->Address, reallocHooks[nUsedReallocHooks], (void **)&originalReallocs[nUsedReallocHooks]) != MH_OK){ + InjectLog("Create hook realloc failed!\r\n"); + } + + if(MH_EnableHook((void*)symbolInfo->Address) != MH_OK){ + InjectLog("Enable realloc hook failed!\r\n"); + } + + nUsedReallocHooks++; + } + + // Hook Callocs. + if(strcmp(symbolInfo->Name, "calloc") == 0){ + if(nUsedCallocHooks >= numHooks){ + InjectLog("All calloc hooks used up!\r\n"); + return true; + } + internal_itoa(nUsedCallocHooks, logBuffer, 10); + InjectLog("Hooking calloc from module ", moduleName, " into calloc hook num ", logBuffer, ".\r\n"); + if(MH_CreateHook((void*)symbolInfo->Address, callocHooks[nUsedCallocHooks], (void **)&originalCallocs[nUsedCallocHooks]) != MH_OK){ + InjectLog("Create hook calloc failed!\r\n"); + } + + if(MH_EnableHook((void*)symbolInfo->Address) != MH_OK){ + InjectLog("Enable calloc hook failed!\r\n"); + } + + nUsedCallocHooks++; + } + return true; } // Callback which recieves loaded module names which we search for malloc/frees to hook. BOOL CALLBACK enumModulesCallback(PCSTR ModuleName, DWORD_PTR BaseOfDll, PVOID UserContext){ - // TODO: Hooking msvcrt causes problems with cleaning up stdio - avoid for now. - if(strcmp(ModuleName, "msvcrt") == 0) - return true; - - SymEnumSymbols(GetCurrentProcess(), BaseOfDll, "malloc", enumSymbolsCallback, (void*)ModuleName); - SymEnumSymbols(GetCurrentProcess(), BaseOfDll, "free", enumSymbolsCallback, (void*)ModuleName); + HANDLE currentProcess = GetCurrentProcess(); + SymEnumSymbols(currentProcess, BaseOfDll, "malloc", enumSymbolsCallback, (void*)ModuleName); + SymEnumSymbols(currentProcess, BaseOfDll, "free", enumSymbolsCallback, (void*)ModuleName); + SymEnumSymbols(currentProcess, BaseOfDll, "realloc", enumSymbolsCallback, (void*)ModuleName); + SymEnumSymbols(currentProcess, BaseOfDll, "calloc", enumSymbolsCallback, (void*)ModuleName); return true; } -void printTopAllocationReport(int numToPrint){ - - std::vector> allocsSortedBySize; +void printTopAllocationReport(int numToPrint, bool profileNumberOfAllocations){ + std::vector allocsSortedBySize; heapProfiler->getAllocationSiteReport(allocsSortedBySize); + auto size = [profileNumberOfAllocations](const HeapProfiler::CallStackInfo &i) { + return profileNumberOfAllocations ? i.n : i.totalSize; + }; + // Sort retured allocation sites by size of memory allocated, descending. std::sort(allocsSortedBySize.begin(), allocsSortedBySize.end(), - [](const std::pair &a, const std::pair &b){ - return a.second < b.second; + [size](const HeapProfiler::CallStackInfo &a, const HeapProfiler::CallStackInfo &b){ + return size(a)< size(b); } ); @@ -178,26 +383,37 @@ void printTopAllocationReport(int numToPrint){ double bytesInAMegaByte = 1024*1024; for(size_t i = (size_t)(std::max)(int64_t(allocsSortedBySize.size())-numToPrint, int64_t(0)); i < allocsSortedBySize.size(); ++i){ - if(allocsSortedBySize[i].second == 0) + if(size(allocsSortedBySize[i]) == 0) continue; - stream << "Alloc size " << precision << allocsSortedBySize[i].second/bytesInAMegaByte << "Mb, stack trace: \n"; - allocsSortedBySize[i].first.print(stream); + if(!profileNumberOfAllocations) + stream << "Alloc size " << precision << size(allocsSortedBySize[i])/bytesInAMegaByte << "Mb, stack trace: \n"; + else + stream << "Number of allocs " << size(allocsSortedBySize[i]) << ", stack trace: \n"; + + allocsSortedBySize[i].trace.print(stream); + stream << "\n"; - totalPrintedAllocSize += allocsSortedBySize[i].second; + totalPrintedAllocSize += size(allocsSortedBySize[i]); numPrintedAllocations++; } size_t totalAlloctaions = std::accumulate(allocsSortedBySize.begin(), allocsSortedBySize.end(), size_t(0), - [](size_t a, const std::pair &b){ - return a + b.second; + [size](size_t a, const HeapProfiler::CallStackInfo &b){ + return a + size(b); } ); - stream << "Top " << numPrintedAllocations << " allocations: " << precision << totalPrintedAllocSize/bytesInAMegaByte << "Mb\n"; - stream << "Total allocations: " << precision << totalAlloctaions/bytesInAMegaByte << "Mb" << - " (difference between total and top " << numPrintedAllocations << " allocations : " << (totalAlloctaions - totalPrintedAllocSize)/bytesInAMegaByte << "Mb)\n\n"; + if (!profileNumberOfAllocations) { + stream << "Top " << numPrintedAllocations << " allocations: " << precision << totalPrintedAllocSize/bytesInAMegaByte << "Mb\n"; + stream << "Total allocations: " << precision << totalAlloctaions / bytesInAMegaByte << "Mb" << + " (difference between total and top " << numPrintedAllocations << " allocations : " << (totalAlloctaions - totalPrintedAllocSize)/bytesInAMegaByte << "Mb)\n\n"; + }else { + stream << "Top " << numPrintedAllocations << " allocations: " << precision << totalPrintedAllocSize<< "\n"; + stream << "Total number of allocations: " << totalAlloctaions << + " (difference between total and top " << numPrintedAllocations << " number of allocations : " << (totalAlloctaions - totalPrintedAllocSize) << ")\n\n"; + } } // Do an allocation report on exit. @@ -216,7 +432,7 @@ void printTopAllocationReport(int numToPrint){ struct CatchExit{ ~CatchExit(){ PreventSelfProfile p; - printTopAllocationReport(25); + printTopAllocationReport(25, false); } }; CatchExit catchExit; @@ -225,18 +441,22 @@ int heapProfileReportThread(){ PreventEverProfilingThisThread(); while(true){ Sleep(10000); - printTopAllocationReport(25); + printTopAllocationReport(25, false); } } void setupHeapProfiling(){ - // We use printfs thoughout injection becasue it's just safer/less troublesome - // than iostreams for this sort of low-level/hacky/threaded work. - printf("Injecting library...\n"); + // We use InjectLog() thoughout injection becasue it's just safer/less troublesome + // than printf/iostreams for this sort of low-level/hacky/threaded work. + InjectLog("Injecting library...\r\n"); nUsedMallocHooks = 0; nUsedFreeHooks = 0; + nUsedReallocHooks = 0; + nUsedCallocHooks = 0; + tlsIndex = TlsAlloc(); + TlsSetValue(tlsIndex, (LPVOID)0); PreventEverProfilingThisThread(); // Create our hook pointer tables using template meta programming fu. @@ -247,13 +467,14 @@ void setupHeapProfiling(){ // Init dbghelp framework. if(!SymInitialize(GetCurrentProcess(), NULL, true)) - printf("SymInitialize failed\n"); + InjectLog("SymInitialize failed\n"); // Yes this leaks - cleauing it up at application exit has zero real benefit. // Might be able to clean it up on CatchExit but I don't see the point. - heapProfiler = new HeapProfiler(); + void* p = HeapAlloc(GetProcessHeap(), 0, sizeof(HeapProfiler)); + heapProfiler = new(p) HeapProfiler(); - // Trawl though loaded modules and hook any mallocs and frees we find. + // Trawl though loaded modules and hook any mallocs, frees, reallocs and callocs we find. SymEnumerateModules(GetCurrentProcess(), enumModulesCallback, NULL); // Spawn and a new thread which prints allocation report every 10 seconds. diff --git a/HeapyInject/HeapyInject.vcxproj b/HeapyInject/HeapyInject.vcxproj index c2d4c29..76311bc 100644 --- a/HeapyInject/HeapyInject.vcxproj +++ b/HeapyInject/HeapyInject.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,31 @@ {F3C8DD27-15AB-4B73-A499-C32181ACACC9} Win32Proj HeapyInject - 10.0.17763.0 DynamicLibrary true - v120 + v100 Unicode DynamicLibrary true - v120 + v100 Unicode DynamicLibrary false - v120 + v100 true Unicode DynamicLibrary false - v141 + v100 true Unicode @@ -74,7 +73,7 @@ true $(ProjectName)_x64 - $(SolutionDir)\$(Configuration)\ + $(SolutionDir)$(Configuration)\ false @@ -83,7 +82,7 @@ false $(ProjectName)_x64 - $(SolutionDir)\$(Configuration)\ + $(SolutionDir)$(Configuration)\ @@ -99,8 +98,8 @@ Windows true - $(SolutionDir)\libs\dbghelp\lib\x86 - dbghelp.lib;%(AdditionalDependencies) + $(SolutionDir)libs\dbghelp\lib\x86;$(SolutionDir)lib\$(ConfigurationName) + dbghelp.lib;LibMinHook.x86.lib;%(AdditionalDependencies) @@ -116,8 +115,8 @@ Windows true - $(SolutionDir)\libs\dbghelp\lib\x64 - dbghelp.lib;%(AdditionalDependencies) + $(SolutionDir)libs\dbghelp\lib\x64;$(SolutionDir)lib\$(ConfigurationName) + dbghelp.lib;LibMinHook.x64.lib;%(AdditionalDependencies) @@ -137,8 +136,8 @@ true true true - $(SolutionDir)\libs\dbghelp\lib\x86 - dbghelp.lib;%(AdditionalDependencies) + $(SolutionDir)libs\dbghelp\lib\x86;$(SolutionDir)lib\$(ConfigurationName) + dbghelp.lib;LibMinHook.x86.lib;%(AdditionalDependencies) @@ -158,8 +157,8 @@ true true true - $(SolutionDir)\libs\dbghelp\lib\x64 - dbghelp.lib;%(AdditionalDependencies) + $(SolutionDir)libs\dbghelp\lib\x64;$(SolutionDir)lib\$(ConfigurationName) + dbghelp.lib;LibMinHook.x64.lib;%(AdditionalDependencies) @@ -169,11 +168,6 @@ - - - {65021938-d251-46fa-bc3d-85c385d4c06d} - - diff --git a/ProfileTestApplication/ProfileTestApplication.vcxproj b/ProfileTestApplication/ProfileTestApplication.vcxproj index 656a6c2..d82de07 100644 --- a/ProfileTestApplication/ProfileTestApplication.vcxproj +++ b/ProfileTestApplication/ProfileTestApplication.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -21,32 +21,31 @@ {00772643-280F-44BE-8839-14E06137A705} ProfileTestApplication - 10.0.17763.0 Application true - v120 + v100 MultiByte Application true - v120 + v100 MultiByte Application false - v120 + v100 true MultiByte Application false - v141 + v100 true MultiByte @@ -96,10 +95,10 @@ $(SolutionDir)$(Configuration)\Heapy_Win32.exe $(SolutionDir)$(Configuration)\Te true - del $(SolutionDir)$(Configuration)\Heapy_Profile.txt + del "$(SolutionDir)$(Configuration)\Heapy_Profile.txt" echo Running command: $(SolutionDir)$(Configuration)\Heapy_x64.exe $(SolutionDir)$(Configuration)\TestApplication_x64.exe echo ====== -$(SolutionDir)$(Configuration)\Heapy_x64.exe $(SolutionDir)$(Configuration)\TestApplication_x64.exe +"$(SolutionDir)$(Configuration)\Heapy_x64.exe" "$(SolutionDir)$(Configuration)\TestApplication_x64.exe" NonExistentFileToPromptRebuild.txt @@ -150,10 +149,10 @@ $(SolutionDir)$(Configuration)\Heapy_Win32.exe $(SolutionDir)$(Configuration)\Te - del $(SolutionDir)$(Configuration)\Heapy_Profile.txt + del "$(SolutionDir)$(Configuration)\Heapy_Profile.txt" echo Running command: $(SolutionDir)$(Configuration)\Heapy_x64.exe $(SolutionDir)$(Configuration)\TestApplication_x64.exe echo ====== -$(SolutionDir)$(Configuration)\Heapy_x64.exe $(SolutionDir)$(Configuration)\TestApplication_x64.exe +"$(SolutionDir)$(Configuration)\Heapy_x64.exe" "$(SolutionDir)$(Configuration)\TestApplication_x64.exe" NonExistentFileToPromptRebuild.txt diff --git a/Readme.md b/Readme.md index a3af836..4ac0a82 100644 --- a/Readme.md +++ b/Readme.md @@ -5,18 +5,18 @@ Heapy, a very simple heap profiler (or memory profiler), supports 32 and 64 bit It lets you see what parts of an application are allocating the most memory. -Heapy will hook and profile any `malloc` and `free` functions it can find, which will in turn cause `new` and `delete` to be profiled too (at least on MSVC `new` and `delete` call `malloc` and `free`). +Heapy will hook and profile any `malloc`, `realloc`, `calloc` and `free` functions it can find, which will in turn cause `new` and `delete` to be profiled too (at least on MSVC `new` and `delete` call `malloc` and `free`). Download -------- -You can download the latest release of heapy [here.](https://github.com/lukedodd/Heapy/releases) +You can download the latest Luke Dodd's offical release of Heapy at [here.](https://github.com/lukedodd/Heapy/releases) Build ----- -Simply clone this repository and build the `Heapy.sln` in Visual Studio 2017. More recent versions of visual studio should work, older versions will not. +Simply clone this repository and build the `Heapy.sln` in Visual Studio 2010. More recent versions of visual studio should work, older versions will not. Be sure to select the correct configuration for your needs: a release Win32 or x64 configuration depending on whether you want to profile 32 or 64 bit applications. diff --git a/TestApplication/Main.cpp b/TestApplication/Main.cpp index aa0d110..8ac331d 100644 --- a/TestApplication/Main.cpp +++ b/TestApplication/Main.cpp @@ -1,24 +1,55 @@ #include #include -void LeakyFunction(){ +void MallocLeakyFunction(){ malloc(1024*1024*5); // leak 5Mb } -void NonLeakyFunction(){ +void MallocNonLeakyFunction(){ auto p = malloc(1024*1024); // allocate 1Mb std::cout << "TestApplication: Sleeping..." << std::endl; Sleep(15000); free(p); // free the Mb } +void CallocLeakyFunction(){ + calloc(1024, 1024*5); // leak 5Mb +} + +void CallocNonLeakyFunction(){ + auto p = calloc(1024, 1024); // allocate 1Mb + std::cout << "TestApplication: Sleeping..." << std::endl; + Sleep(15000); + free(p); // free the Mb +} + +void ReallocLeakyFunction(){ + auto p = realloc(NULL, 1024*1024*1); // allocate 1Mb + auto p2 = realloc(p, 1024*1024*5); // reallocate and leak 5Mb +} + +void ReallocNonLeakyFunction(){ + auto p = realloc(NULL, 1024*1024); // allocate 1Mb + std::cout << "TestApplication: Sleeping..." << std::endl; + Sleep(15000); + auto p2 = realloc(p, 1024*1024*2); // reallocate 2Mb + if (p2 != NULL) + p = p2; + Sleep(15000); + realloc(p, 0); // free the Mb (as specified by CRT reference) +} + int main() { std::cout << "TestApplication: Creating some leaks..." << std::endl; for(int i = 0; i < 5; ++i){ - LeakyFunction(); + MallocLeakyFunction(); + CallocLeakyFunction(); + ReallocLeakyFunction(); } - NonLeakyFunction(); + MallocNonLeakyFunction(); + CallocNonLeakyFunction(); + ReallocNonLeakyFunction(); std::cout << "TestApplication: Exiting..." << std::endl; return 0; } diff --git a/TestApplication/TestApplication.vcxproj b/TestApplication/TestApplication.vcxproj index f88dbde..03c7fe6 100644 --- a/TestApplication/TestApplication.vcxproj +++ b/TestApplication/TestApplication.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,31 @@ {2CDA5A6B-3B49-40CC-AC3F-819167EE2C9D} Win32Proj TestApplication - 10.0.17763.0 Application true - v120 + v100 Unicode Application true - v120 + v100 Unicode Application false - v120 + v100 true Unicode Application false - v141 + v100 true Unicode diff --git a/libMinHook/libMinHook.vcxproj b/libMinHook/libMinHook.vcxproj new file mode 100644 index 0000000..26a21c5 --- /dev/null +++ b/libMinHook/libMinHook.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {529CF76D-94CA-4127-96F2-0EEB77A9DB19} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + + + false + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + + + false + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + + + true + AnySuitable + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + + + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libMinHook/libMinHook.vcxproj.filters b/libMinHook/libMinHook.vcxproj.filters new file mode 100644 index 0000000..64c124c --- /dev/null +++ b/libMinHook/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + + + \ No newline at end of file diff --git a/libs/MinHook/.editorconfig b/libs/MinHook/.editorconfig new file mode 100644 index 0000000..36c09e6 --- /dev/null +++ b/libs/MinHook/.editorconfig @@ -0,0 +1,22 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Windows-style newlines with a newline ending every file +[*] +end_of_line = crlf +insert_final_newline = true + +# 4 space indentation +[*.{c,h,def}] +indent_style = space +indent_size = 4 + +# Trim trailing whitespaces +[*.{c,h,def,txt}] +trim_trailing_whitespace = true + +# UTF-8 with BOM +[*.{c,h,def,txt}] +charset=utf-8-bom diff --git a/libs/MinHook/.gitignore b/libs/MinHook/.gitignore index bbfc50d..083653c 100644 --- a/libs/MinHook/.gitignore +++ b/libs/MinHook/.gitignore @@ -30,3 +30,10 @@ obj/ [Dd]ebug*/ [Rr]elease*/ Ankh.NoLoad + +#GCC files +*.o +*.d +*.res +*.dll +*.a diff --git a/libs/MinHook/AUTHORS.txt b/libs/MinHook/AUTHORS.txt new file mode 100644 index 0000000..ebef1a6 --- /dev/null +++ b/libs/MinHook/AUTHORS.txt @@ -0,0 +1,8 @@ +Tsuda Kageyu + Creator, maintainer + +Michael Maltsev + Added "Queue" functions. A lot of bug fixes. + +Andrey Unis + Rewrote the hook engine in plain C. diff --git a/libs/MinHook/COPYING.txt b/libs/MinHook/COPYING.txt deleted file mode 100644 index c86deea..0000000 --- a/libs/MinHook/COPYING.txt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * MinHook - The Minimalistic API Hooking Library for x64/x86 - * Copyright (c) 2009 Tsuda Kageyu. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -================================================================================ -Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. -================================================================================ -/* - * Hacker Disassembler Engine 32 C - * Copyright (c) 2008-2009, Vyacheslav Patkov. - * All rights reserved. - * - */ - -/* - * Hacker Disassembler Engine 64 C - * Copyright (c) 2008-2009, Vyacheslav Patkov. - * All rights reserved. - * - */ - -================================================================================ -Portions of this software are Copyright (c) 2005-2007 Paul Hsieh. -================================================================================ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/MinHook/LICENSE.txt b/libs/MinHook/LICENSE.txt new file mode 100644 index 0000000..e4f9a7a --- /dev/null +++ b/libs/MinHook/LICENSE.txt @@ -0,0 +1,81 @@ +MinHook - The Minimalistic API Hooking Library for x64/x86 +Copyright (C) 2009-2015 Tsuda Kageyu. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ +Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. +================================================================================ +Hacker Disassembler Engine 32 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +Hacker Disassembler Engine 64 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/MinHook/MinHook.vcxproj b/libs/MinHook/MinHook.vcxproj deleted file mode 100644 index e96b259..0000000 --- a/libs/MinHook/MinHook.vcxproj +++ /dev/null @@ -1,96 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {672868F4-6952-4D53-9BCA-22277B95027D} - Win32Proj - MinHook - - - - StaticLibrary - true - v110 - Unicode - - - StaticLibrary - false - v110 - true - Unicode - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/MinHook/MinHook.vcxproj.filters b/libs/MinHook/MinHook.vcxproj.filters deleted file mode 100644 index 59b1c1b..0000000 --- a/libs/MinHook/MinHook.vcxproj.filters +++ /dev/null @@ -1,69 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;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 - - - {018ae07f-8130-433b-b3b3-bc48d89587bc} - - - {c216d12c-6586-4678-ab38-9858bbd7d255} - - - - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\HDE32 - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\HDE32 - - - Source Files\HDE32 - - - \ No newline at end of file diff --git a/libs/MinHook/README.md b/libs/MinHook/README.md index 3e08822..6130b5b 100644 --- a/libs/MinHook/README.md +++ b/libs/MinHook/README.md @@ -1,14 +1,82 @@ # MinHook -A Windows API hooking library originally written by Tsuda Kageyu. +The Minimalistic x86/x64 API Hooking Library for Windows http://www.codeproject.com/KB/winsdk/LibMinHook.aspx -## Main differences from original v1.1 +### Donation please -* Removed boost dependency ([jarredholman](https://github.com/jarredholman/minhook)). -* Fixed a small bug in the GetRelativeBranchDestination function ([pillbug99](http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx)). -* Added the `MH_RemoveHook` function, which removes a hook created with the `MH_CreateHook` function. -* Added the following functions to enable or disable multiple hooks in one go: `MH_QueueEnableHook`, `MH_QueueDisableHook`, `MH_ApplyQueued`. This is the preferred way of handling multiple hooks as every call to `MH_EnableHook` or `MH_DisableHook` suspends and resumes all threads. -* Made the functions `MH_EnableHook` and `MH_DisableHook` enable/disable all created hooks when the `MH_ALL_HOOKS` parameter is passed. This, too, is an efficient way of handling multiple hooks. -* If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the `MH_CreateHook` function returns `MH_ERROR_UNSUPPORTED_FUNCTION`. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 ([reported by Obble](http://www.codeproject.com/Messages/4578613/Re-Bug-LoadLibraryExW-hook-fails-on-windows-2008-r.aspx)). +I need some funds to continue developing this library. All contributions gratefully accepted. + +Click here to lend your support to: MinHook - Help me continue to develop this library and make a donation at pledgie.com ! + +### Version history + +- ####v1.3.2.1 - 9 Nov 2015 (Nuget package only) + * Fixed an insufficient support for Visual Studio 2015. + +- ####v1.3.2 - 1 Nov 2015 + * Support Visual Studio 2015. + * Support MinGW. + +- ####v1.3.2-beta3 - 21 Jul 2015 (Nuget package only) + * Support MinGW. (Experimental) + +- ####v1.3.2-beta2 - 18 May 2015 + * Fixed some subtle bugs. (Thanks to RaMMicHaeL) + * Added a helper function ```MH_StatusToString```. (Thanks to Jan Klass) + +- ####v1.3.2-beta - 12 May 2015 + * Fixed a possible thread deadlock in x64 mode. (Thanks to Aleh Kazakevich) + * Reduced the footprint a little more. + * Support Visual Studio 2015 RC. (Experimental) + +- ####v1.3.1.1 - 7 Apr 2015 (Nuget package only) + * Support for WDK8.0 and 8.1. + +- ####v1.3.1 - 19 Mar 2015 + * No major changes from v1.3.1-beta. + +- ####v1.3.1-beta - 11 Mar 2015 + * Added a helper function ```MH_CreateHookApi```. (Thanks to uniskz). + * Fixed a false memory leak reported by some tools. + * Fixed a degradated compatibility issue. + +- ####v1.3 - 13 Sep 2014 + * No major changes from v1.3-beta3. + +- ####v1.3-beta3 - 31 Jul 2014 + + * Fixed some small bugs. + * Improved the memory management. + +- ####v1.3-beta2 - 21 Jul 2014 + + * Changed the parameters to Windows-friendly types. (void* to LPVOID) + * Fixed some small bugs. + * Reorganized the source files. + * Reduced the footprint a little more. + +- ####v1.3-beta - 17 Jul 2014 + + * Rewrote in plain C to reduce the footprint and memory usage. (suggested by Andrey Unis) + * Simplified the overall code base to make it more readable and maintainable. + * Changed the license from 3-clause to 2-clause BSD License. + +- ####v1.2 - 28 Sep 2013 + + * Removed boost dependency ([jarredholman](https://github.com/jarredholman/minhook)). + * Fixed a small bug in the GetRelativeBranchDestination function ([pillbug99](http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx)). + * Added the ```MH_RemoveHook``` function, which removes a hook created with the ```MH_CreateHook``` function. + * Added the following functions to enable or disable multiple hooks in one go: ```MH_QueueEnableHook```, ```MH_QueueDisableHook```, ```MH_ApplyQueued```. This is the preferred way of handling multiple hooks as every call to `MH_EnableHook` or `MH_DisableHook` suspends and resumes all threads. + * Made the functions ```MH_EnableHook``` and ```MH_DisableHook``` enable/disable all created hooks when the ```MH_ALL_HOOKS``` parameter is passed. This, too, is an efficient way of handling multiple hooks. + * If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the ```MH_CreateHook``` function returns ```MH_ERROR_UNSUPPORTED_FUNCTION```. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 ([reported by Obble](http://www.codeproject.com/Messages/4578613/Re-Bug-LoadLibraryExW-hook-fails-on-windows-2008-r.aspx)). + +- ####v1.1 - 26 Nov 2009 + + * Changed the interface to create a hook and a trampoline function in one go to prevent the detour function from being called before the trampoline function is created. ([reported by xliqz](http://www.codeproject.com/Messages/3280374/Unsafe.aspx)) + * Shortened the function names from ```MinHook_*``` to ```MH_*``` to make them handier. + +- ####v1.0 - 22 Nov 2009 + + * Initial release. diff --git a/libs/MinHook/build/MinGW/Makefile b/libs/MinHook/build/MinGW/Makefile new file mode 100644 index 0000000..b0f6e96 --- /dev/null +++ b/libs/MinHook/build/MinGW/Makefile @@ -0,0 +1,33 @@ +WINDRES:=$(CROSS_PREFIX)windres +DLLTOOL:=$(CROSS_PREFIX)dlltool +AR:=$(CROSS_PREFIX)ar +CC:=$(CROSS_PREFIX)gcc +CCLD:=$(CC) +SRCS:=$(wildcard src/*.c src/HDE/*.c) +OBJS:=$(SRCS:%.c=%.o) +DEPS:=$(SRCS:%.c=%.d) +INCS:=-Isrc -Iinclude +CFLAGS:=-masm=intel -Wall -Werror -std=c11 +LDFLAGS:=-Wl,-enable-stdcall-fixup -s -static-libgcc + +all: MinHook.dll libMinHook.dll.a libMinHook.a + +-include $(DEPS) + +libMinHook.a: $(OBJS) + $(AR) r $@ $^ +libMinHook.dll.a: MinHook.dll dll_resources/MinHook.def + $(DLLTOOL) --dllname MinHook.dll --def dll_resources/MinHook.def --output-lib $@ +MinHook.dll: $(OBJS) dll_resources/MinHook.res dll_resources/MinHook.def + $(CCLD) -o $@ -shared $(LDFLAGS) $^ + +.rc.res: + $(WINDRES) -o $@ --input-format=rc --output-format=coff $< +.c.o: + $(CC) -o $@ -c -MMD -MP $(INCS) $(CFLAGS) $< + +clean: + rm -f $(OBJS) $(DEPS) MinHook.dll libMinHook.dll.a libMinHook.a dll_resources/MinHook.res + +.PHONY: clean +.SUFFIXES: .rc .res diff --git a/libs/MinHook/build/MinGW/make.bat b/libs/MinHook/build/MinGW/make.bat new file mode 100644 index 0000000..7671878 --- /dev/null +++ b/libs/MinHook/build/MinGW/make.bat @@ -0,0 +1 @@ +windres -i ../../dll_resources/MinHook.rc -o MinHook_rc.o && dllwrap --driver-name g++ -o MinHook.dll -masm=intel --def ../../dll_resources/MinHook.def -Wl,-enable-stdcall-fixup -Wall MinHook_rc.o ../../src/*.c ../../src/HDE/*.c -I../../include -I../../src -Werror -std=c++11 -s -static-libgcc -static-libstdc++|| pause \ No newline at end of file diff --git a/libs/MinHook/build/MinHookVC10.sln b/libs/MinHook/build/MinHookVC10.sln deleted file mode 100644 index 1fdc0c3..0000000 --- a/libs/MinHook/build/MinHookVC10.sln +++ /dev/null @@ -1,36 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/MinHook/build/MinHookVC11.sln b/libs/MinHook/build/MinHookVC11.sln deleted file mode 100644 index 1281c7e..0000000 --- a/libs/MinHook/build/MinHookVC11.sln +++ /dev/null @@ -1,36 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/MinHook/build/MinHookVC9.sln b/libs/MinHook/build/MinHookVC9.sln deleted file mode 100644 index 78b5aca..0000000 --- a/libs/MinHook/build/MinHookVC9.sln +++ /dev/null @@ -1,39 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}" - ProjectSection(ProjectDependencies) = postProject - {65021938-D251-46FA-BC3D-85C385D4C06D} = {65021938-D251-46FA-BC3D-85C385D4C06D} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64 - {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64 - {CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/MinHook/build/VC10/MinHook.vcxproj b/libs/MinHook/build/VC10/MinHook.vcxproj new file mode 100644 index 0000000..3944d80 --- /dev/null +++ b/libs/MinHook/build/VC10/MinHook.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {027FAC75-3FDB-4044-8DD0-BC297BD4C461} + MinHook + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + + + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + + + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + + + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + + + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + X64 + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + + + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC10/MinHookVC10.sln b/libs/MinHook/build/VC10/MinHookVC10.sln new file mode 100644 index 0000000..dcc1d5c --- /dev/null +++ b/libs/MinHook/build/VC10/MinHookVC10.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/VC10/libMinHook.vcxproj b/libs/MinHook/build/VC10/libMinHook.vcxproj new file mode 100644 index 0000000..77673e9 --- /dev/null +++ b/libs/MinHook/build/VC10/libMinHook.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + + + false + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + + + false + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + + + true + AnySuitable + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + + + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC10/libMinHook.vcxproj.filters b/libs/MinHook/build/VC10/libMinHook.vcxproj.filters new file mode 100644 index 0000000..f2d1d97 --- /dev/null +++ b/libs/MinHook/build/VC10/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {9d24b740-be2e-4cfd-b9a4-340a50946ee9} + + + {76381bc7-2863-4cc5-aede-926ec2c506e4} + + + {56ddb326-6179-430d-ae19-e13bfd767bfa} + + + \ No newline at end of file diff --git a/libs/MinHook/build/MinHook.vcxproj b/libs/MinHook/build/VC11/MinHook.vcxproj similarity index 66% rename from libs/MinHook/build/MinHook.vcxproj rename to libs/MinHook/build/VC11/MinHook.vcxproj index d6dcbe5..4c0e212 100644 --- a/libs/MinHook/build/MinHook.vcxproj +++ b/libs/MinHook/build/VC11/MinHook.vcxproj @@ -19,7 +19,7 @@ - {CA4EE302-D012-4826-86D6-80D23641AB4E} + {027FAC75-3FDB-4044-8DD0-BC297BD4C461} MinHook Win32Proj @@ -64,75 +64,41 @@ <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)\..\bin\ - $(SolutionDir)\..\bin\ - $(SolutionDir)\..\bin\ - $(SolutionDir)\..\bin\ - $(Configuration)\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ true - $(Configuration)\$(ProjectName)\ - false + $(SolutionDir)bin\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(SolutionDir)bin\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - $(ProjectName).x86 $(ProjectName).x86 - $(ProjectName).x64 $(ProjectName).x64 + $(ProjectName).x64 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) - true + false EnableFastChecks MultiThreadedDebug - Use - Level3 - EditAndContinue - NoExtensions - - - ..\dll_resources\MinHook.def - true - Windows - 0x68000000 - MachineX86 - - - - - MaxSpeed - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) - MultiThreaded - true - Use + + Level3 - ProgramDatabase - NoExtensions + None - ..\dll_resources\MinHook.def + $(SolutionDir)..\..\dll_resources\MinHook.def false Windows - true - true - 0x68000000 MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) @@ -142,18 +108,45 @@ Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) - true + false EnableFastChecks MultiThreadedDebug - Use + + Level3 - ProgramDatabase + None - ..\dll_resources\MinHook.def - true + $(SolutionDir)..\..\dll_resources\MinHook.def + false Windows MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + + + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + true + .CRT=.text @@ -161,54 +154,34 @@ X64 - MaxSpeed + MinSpace true WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) MultiThreaded true - Use + + Level3 - ProgramDatabase + None + false - ..\dll_resources\MinHook.def + $(SolutionDir)..\..\dll_resources\MinHook.def false Windows true true - 0x68000000 MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + true + .CRT=.text - - - - false - - - false - - - false - - - false - - - - - - - - - - + - - {65021938-d251-46fa-bc3d-85c385d4c06d} - + diff --git a/libs/MinHook/build/VC11/MinHookVC11.sln b/libs/MinHook/build/VC11/MinHookVC11.sln new file mode 100644 index 0000000..5b56553 --- /dev/null +++ b/libs/MinHook/build/VC11/MinHookVC11.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/VC11/libMinHook.vcxproj b/libs/MinHook/build/VC11/libMinHook.vcxproj new file mode 100644 index 0000000..73e8b2f --- /dev/null +++ b/libs/MinHook/build/VC11/libMinHook.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + v110_xp + + + StaticLibrary + Unicode + v110_xp + + + StaticLibrary + Unicode + true + v110_xp + + + StaticLibrary + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NoExtensions + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + true + AnySuitable + NoExtensions + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC11/libMinHook.vcxproj.filters b/libs/MinHook/build/VC11/libMinHook.vcxproj.filters new file mode 100644 index 0000000..f2d1d97 --- /dev/null +++ b/libs/MinHook/build/VC11/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {9d24b740-be2e-4cfd-b9a4-340a50946ee9} + + + {76381bc7-2863-4cc5-aede-926ec2c506e4} + + + {56ddb326-6179-430d-ae19-e13bfd767bfa} + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC12/MinHook.vcxproj b/libs/MinHook/build/VC12/MinHook.vcxproj new file mode 100644 index 0000000..40ec836 --- /dev/null +++ b/libs/MinHook/build/VC12/MinHook.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {027FAC75-3FDB-4044-8DD0-BC297BD4C461} + MinHook + Win32Proj + + + + DynamicLibrary + Unicode + true + v120_xp + + + DynamicLibrary + Unicode + v120_xp + + + DynamicLibrary + Unicode + true + v120_xp + + + DynamicLibrary + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + + + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + X64 + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC12/MinHookVC12.sln b/libs/MinHook/build/VC12/MinHookVC12.sln new file mode 100644 index 0000000..cfd928b --- /dev/null +++ b/libs/MinHook/build/VC12/MinHookVC12.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/libMinHook.vcxproj b/libs/MinHook/build/VC12/libMinHook.vcxproj similarity index 60% rename from libs/MinHook/build/libMinHook.vcxproj rename to libs/MinHook/build/VC12/libMinHook.vcxproj index be09e82..7d92bf9 100644 --- a/libs/MinHook/build/libMinHook.vcxproj +++ b/libs/MinHook/build/VC12/libMinHook.vcxproj @@ -1,176 +1,174 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {65021938-D251-46FA-BC3D-85C385D4C06D} - libMinHook - Win32Proj - 10.0.17763.0 - - - - StaticLibrary - Unicode - true - v120_xp - - - StaticLibrary - Unicode - v120_xp - - - StaticLibrary - Unicode - true - v141 - - - StaticLibrary - Unicode - v120_xp - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - $(ProjectDir)\..\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - NoExtensions - - - - - - X64 - - - Disabled - $(ProjectDir)\..\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - ProgramDatabase - - - - - - MaxSpeed - true - $(ProjectDir)\..\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - true - - - Level3 - ProgramDatabase - NoExtensions - - - - - - X64 - - - MaxSpeed - true - $(ProjectDir)\..\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - true - - - Level3 - ProgramDatabase - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + v120_xp + + + StaticLibrary + Unicode + v120_xp + + + StaticLibrary + Unicode + true + v120_xp + + + StaticLibrary + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NoExtensions + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NotSet + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + AnySuitable + CompileAsC + true + NoExtensions + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC12/libMinHook.vcxproj.filters b/libs/MinHook/build/VC12/libMinHook.vcxproj.filters new file mode 100644 index 0000000..f2d1d97 --- /dev/null +++ b/libs/MinHook/build/VC12/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {9d24b740-be2e-4cfd-b9a4-340a50946ee9} + + + {76381bc7-2863-4cc5-aede-926ec2c506e4} + + + {56ddb326-6179-430d-ae19-e13bfd767bfa} + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC14/MinHook.vcxproj b/libs/MinHook/build/VC14/MinHook.vcxproj new file mode 100644 index 0000000..d5ecda2 --- /dev/null +++ b/libs/MinHook/build/VC14/MinHook.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {027FAC75-3FDB-4044-8DD0-BC297BD4C461} + MinHook + Win32Proj + + + + DynamicLibrary + Unicode + true + v140_xp + + + DynamicLibrary + Unicode + v140_xp + + + DynamicLibrary + Unicode + true + v140_xp + + + DynamicLibrary + Unicode + v140_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + + + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + X64 + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC14/MinHookVC14.sln b/libs/MinHook/build/VC14/MinHookVC14.sln new file mode 100644 index 0000000..258c192 --- /dev/null +++ b/libs/MinHook/build/VC14/MinHookVC14.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.22823.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/VC14/libMinHook.vcxproj b/libs/MinHook/build/VC14/libMinHook.vcxproj new file mode 100644 index 0000000..49b98a6 --- /dev/null +++ b/libs/MinHook/build/VC14/libMinHook.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + v140_xp + + + StaticLibrary + Unicode + v140_xp + + + StaticLibrary + Unicode + true + v140_xp + + + StaticLibrary + Unicode + v140_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NoExtensions + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NotSet + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + AnySuitable + CompileAsC + true + NoExtensions + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC14/libMinHook.vcxproj.filters b/libs/MinHook/build/VC14/libMinHook.vcxproj.filters new file mode 100644 index 0000000..f2d1d97 --- /dev/null +++ b/libs/MinHook/build/VC14/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {9d24b740-be2e-4cfd-b9a4-340a50946ee9} + + + {76381bc7-2863-4cc5-aede-926ec2c506e4} + + + {56ddb326-6179-430d-ae19-e13bfd767bfa} + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC15/MinHook.vcxproj b/libs/MinHook/build/VC15/MinHook.vcxproj new file mode 100644 index 0000000..d5ecda2 --- /dev/null +++ b/libs/MinHook/build/VC15/MinHook.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {027FAC75-3FDB-4044-8DD0-BC297BD4C461} + MinHook + Win32Proj + + + + DynamicLibrary + Unicode + true + v140_xp + + + DynamicLibrary + Unicode + v140_xp + + + DynamicLibrary + Unicode + true + v140_xp + + + DynamicLibrary + Unicode + v140_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + true + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(SolutionDir)bin\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + false + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + + + Level3 + None + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + + + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX86 + $(SolutionDir)lib\$(Configuration)\libMinHook.x86.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + X64 + + + MinSpace + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + None + false + + + $(SolutionDir)..\..\dll_resources\MinHook.def + false + Windows + true + true + MachineX64 + $(SolutionDir)lib\$(Configuration)\libMinHook.x64.lib;%(AdditionalDependencies) + true + .CRT=.text + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC15/MinHookVC15.sln b/libs/MinHook/build/VC15/MinHookVC15.sln new file mode 100644 index 0000000..946dc70 --- /dev/null +++ b/libs/MinHook/build/VC15/MinHookVC15.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/VC15/libMinHook.vcxproj b/libs/MinHook/build/VC15/libMinHook.vcxproj new file mode 100644 index 0000000..49b98a6 --- /dev/null +++ b/libs/MinHook/build/VC15/libMinHook.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + libMinHook + Win32Proj + + + + StaticLibrary + Unicode + true + v140_xp + + + StaticLibrary + Unicode + v140_xp + + + StaticLibrary + Unicode + true + v140_xp + + + StaticLibrary + Unicode + v140_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)lib\$(Configuration)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName).x86 + $(ProjectName).x86 + $(ProjectName).x64 + $(ProjectName).x64 + + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NoExtensions + + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebug + Level3 + None + NotSet + + + + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + AnySuitable + CompileAsC + true + NoExtensions + + + + + + X64 + + + MinSpace + true + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + false + MultiThreaded + true + Level3 + None + true + AnySuitable + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/MinHook/build/VC15/libMinHook.vcxproj.filters b/libs/MinHook/build/VC15/libMinHook.vcxproj.filters new file mode 100644 index 0000000..f2d1d97 --- /dev/null +++ b/libs/MinHook/build/VC15/libMinHook.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + HDE + + + HDE + + + + + Header Files + + + Header Files + + + + HDE + + + HDE + + + HDE + + + HDE + + + HDE + + + + + {9d24b740-be2e-4cfd-b9a4-340a50946ee9} + + + {76381bc7-2863-4cc5-aede-926ec2c506e4} + + + {56ddb326-6179-430d-ae19-e13bfd767bfa} + + + \ No newline at end of file diff --git a/libs/MinHook/build/MinHook.vcproj b/libs/MinHook/build/VC9/MinHook.vcproj similarity index 73% rename from libs/MinHook/build/MinHook.vcproj rename to libs/MinHook/build/VC9/MinHook.vcproj index b4fe7dd..4bad257 100644 --- a/libs/MinHook/build/MinHook.vcproj +++ b/libs/MinHook/build/VC9/MinHook.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9.00" Name="MinHook" - ProjectGUID="{CA4EE302-D012-4826-86D6-80D23641AB4E}" + ProjectGUID="{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" RootNamespace="MinHook" Keyword="Win32Proj" TargetFrameworkVersion="196613" @@ -21,8 +21,8 @@ @@ -45,10 +45,10 @@ Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS" - MinimalRebuild="true" + MinimalRebuild="false" BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="2" + RuntimeLibrary="1" + UsePrecompiledHeader="0" WarningLevel="3" DebugInformationFormat="4" /> @@ -65,10 +65,9 @@ Name="VCLinkerTool" OutputFile="$(OutDir)\$(ProjectName).x86.dll" LinkIncremental="2" - ModuleDefinitionFile="..\dll_resources\MinHook.def" - GenerateDebugInformation="true" + ModuleDefinitionFile="$(SolutionDir)..\..\dll_resources\MinHook.def" + GenerateDebugInformation="false" SubSystem="2" - BaseAddress="0x68000000" TargetMachine="1" /> @@ -138,15 +137,12 @@ /> @@ -215,12 +212,16 @@ /> @@ -292,12 +294,13 @@ Name="VCLinkerTool" OutputFile="$(OutDir)\$(ProjectName).x64.dll" LinkIncremental="1" - ModuleDefinitionFile="..\dll_resources\MinHook.def" + ModuleDefinitionFile="$(SolutionDir)..\..\dll_resources\MinHook.def" GenerateDebugInformation="false" SubSystem="2" OptimizeReferences="2" EnableCOMDATFolding="2" - BaseAddress="0x68000000" + ResourceOnlyDLL="true" + MergeSections=".CRT=.text" TargetMachine="17" /> - - - - - - - - - - - - - - - - diff --git a/libs/MinHook/build/VC9/MinHookVC9.sln b/libs/MinHook/build/VC9/MinHookVC9.sln new file mode 100644 index 0000000..869f5b6 --- /dev/null +++ b/libs/MinHook/build/VC9/MinHookVC9.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcproj", "{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcproj", "{027FAC75-3FDB-4044-8DD0-BC297BD4C461}" + ProjectSection(ProjectDependencies) = postProject + {F142A341-5EE0-442D-A15F-98AE9B48DBAE} = {F142A341-5EE0-442D-A15F-98AE9B48DBAE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|Win32.Build.0 = Debug|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.ActiveCfg = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Debug|x64.Build.0 = Debug|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.ActiveCfg = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|Win32.Build.0 = Release|Win32 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.ActiveCfg = Release|x64 + {F142A341-5EE0-442D-A15F-98AE9B48DBAE}.Release|x64.Build.0 = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.ActiveCfg = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|Win32.Build.0 = Debug|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.ActiveCfg = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Debug|x64.Build.0 = Debug|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.ActiveCfg = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|Win32.Build.0 = Release|Win32 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.ActiveCfg = Release|x64 + {027FAC75-3FDB-4044-8DD0-BC297BD4C461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/MinHook/build/libMinHook.vcproj b/libs/MinHook/build/VC9/libMinHook.vcproj similarity index 59% rename from libs/MinHook/build/libMinHook.vcproj rename to libs/MinHook/build/VC9/libMinHook.vcproj index eb27ee0..fefb517 100644 --- a/libs/MinHook/build/libMinHook.vcproj +++ b/libs/MinHook/build/VC9/libMinHook.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9.00" Name="libMinHook" - ProjectGUID="{65021938-D251-46FA-BC3D-85C385D4C06D}" + ProjectGUID="{F142A341-5EE0-442D-A15F-98AE9B48DBAE}" RootNamespace="libMinHook" Keyword="Win32Proj" TargetFrameworkVersion="196613" @@ -21,8 +21,8 @@ @@ -44,14 +44,14 @@ - - - - - - - - - + - - - - - + + - - - + + + - - - - - - - - - - - - + + + - - - + + + + + + - - + + - - + + + + + + - - + + - - + + + + + + + + + + + - - diff --git a/libs/MinHook/build/libMinHook.vcxproj.filters b/libs/MinHook/build/libMinHook.vcxproj.filters deleted file mode 100644 index 3cf0b3e..0000000 --- a/libs/MinHook/build/libMinHook.vcxproj.filters +++ /dev/null @@ -1,76 +0,0 @@ - - - - - {d2fc03a6-683a-49e0-87fa-844d1529a19c} - - - {76b54476-8b6d-4556-84dc-311115cff274} - - - {b2dbe4c4-a42e-40cd-b744-92327b9acf3e} - - - {df59be5b-00d3-495b-8a79-ea0c6df20e74} - - - {c5cf3151-e815-430f-9743-6ec94394b47d} - - - - - src\HDE32 - - - src\HDE64 - - - src\Source Files - - - src\Source Files - - - src\Source Files - - - src\Source Files - - - src\Source Files - - - - - src\HDE32 - - - src\HDE32 - - - src\HDE64 - - - src\HDE64 - - - src\Header Files - - - src\Header Files - - - src\Header Files - - - src\Header Files - - - src\Header Files - - - - - - - \ No newline at end of file diff --git a/libs/MinHook/dll_resources/MinHook.def b/libs/MinHook/dll_resources/MinHook.def index 9bd1cd8..66c80b3 100644 --- a/libs/MinHook/dll_resources/MinHook.def +++ b/libs/MinHook/dll_resources/MinHook.def @@ -1,11 +1,13 @@ EXPORTS - MH_Initialize - MH_Uninitialize - - MH_CreateHook - MH_RemoveHook - MH_EnableHook - MH_DisableHook - MH_QueueEnableHook - MH_QueueDisableHook - MH_ApplyQueued + MH_Initialize + MH_Uninitialize + + MH_CreateHook + MH_CreateHookApi + MH_RemoveHook + MH_EnableHook + MH_DisableHook + MH_QueueEnableHook + MH_QueueDisableHook + MH_ApplyQueued + MH_StatusToString diff --git a/libs/MinHook/dll_resources/MinHook.rc b/libs/MinHook/dll_resources/MinHook.rc index e9d9d74..7f34d09 100644 --- a/libs/MinHook/dll_resources/MinHook.rc +++ b/libs/MinHook/dll_resources/MinHook.rc @@ -1,102 +1,32 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// “ú–{Œê resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) -#ifdef _WIN32 -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT -#pragma code_page(932) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,1,0 - PRODUCTVERSION 1,2,1,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", "Tsuda Kageyu" - VALUE "FileDescription", "MinHook - The Minimalistic API Hook Library for x64/x86" - VALUE "FileVersion", "1, 2, 1, 0" - VALUE "InternalName", "MinHookD" - VALUE "LegalCopyright", "Copyright (c) 2009 Tsuda Kageyu. All rights reserved." - VALUE "LegalTrademarks", "Tsuda Kageyu" - VALUE "ProductName", "MinHook DLL" - VALUE "ProductVersion", "1, 2, 1, 0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // “ú–{Œê resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +1 VERSIONINFO + FILEVERSION 1,3,2,0 + PRODUCTVERSION 1,3,2,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Tsuda Kageyu" + VALUE "FileDescription", "MinHook - The Minimalistic API Hook Library for x64/x86" + VALUE "FileVersion", "1.3.2.0" + VALUE "InternalName", "MinHookD" + VALUE "LegalCopyright", "Copyright (C) 2009-2015 Tsuda Kageyu. All rights reserved." + VALUE "LegalTrademarks", "Tsuda Kageyu" + VALUE "ProductName", "MinHook DLL" + VALUE "ProductVersion", "1.3.2.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/libs/MinHook/dll_resources/dllmain.cpp b/libs/MinHook/dll_resources/dllmain.cpp deleted file mode 100644 index 6822b41..0000000 --- a/libs/MinHook/dll_resources/dllmain.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) -{ - return TRUE; -} - diff --git a/libs/MinHook/dll_resources/resource.h b/libs/MinHook/dll_resources/resource.h deleted file mode 100644 index 708ebf6..0000000 --- a/libs/MinHook/dll_resources/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by MinHook.rc - -// V‚µ‚¢ƒIƒuƒWƒFƒNƒg‚ÌŽŸ‚ÌŠù’è’l -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/libs/MinHook/include/MinHook.h b/libs/MinHook/include/MinHook.h index cfc602c..8b467f0 100644 --- a/libs/MinHook/include/MinHook.h +++ b/libs/MinHook/include/MinHook.h @@ -1,129 +1,186 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#if !(defined _M_IX86) && !(defined _M_X64) + #error MinHook supports only x86 and x64 systems. +#endif + +#include // MinHook Error Codes. typedef enum MH_STATUS { - // Unknown error. Should not be returned. - MH_UNKNOWN = -1, + // Unknown error. Should not be returned. + MH_UNKNOWN = -1, + + // Successful. + MH_OK = 0, + + // MinHook is already initialized. + MH_ERROR_ALREADY_INITIALIZED, - // Successful. - MH_OK = 0, + // MinHook is not initialized yet, or already uninitialized. + MH_ERROR_NOT_INITIALIZED, - // MinHook is already initialized. - MH_ERROR_ALREADY_INITIALIZED, + // The hook for the specified target function is already created. + MH_ERROR_ALREADY_CREATED, - // MinHook is not initialized yet, or already uninitialized. - MH_ERROR_NOT_INITIALIZED, + // The hook for the specified target function is not created yet. + MH_ERROR_NOT_CREATED, - // The hook for the specified target function is already created. - MH_ERROR_ALREADY_CREATED, + // The hook for the specified target function is already enabled. + MH_ERROR_ENABLED, - // The hook for the specified target function is not created yet. - MH_ERROR_NOT_CREATED, + // The hook for the specified target function is not enabled yet, or already + // disabled. + MH_ERROR_DISABLED, - // The hook for the specified target function is already enabled. - MH_ERROR_ENABLED, + // The specified pointer is invalid. It points the address of non-allocated + // and/or non-executable region. + MH_ERROR_NOT_EXECUTABLE, - // The hook for the specified target function is not enabled yet, or already disabled. - MH_ERROR_DISABLED, + // The specified target function cannot be hooked. + MH_ERROR_UNSUPPORTED_FUNCTION, - // The specified pointer is invalid. It points the address of non-allocated and/or non-executable region. - MH_ERROR_NOT_EXECUTABLE, + // Failed to allocate memory. + MH_ERROR_MEMORY_ALLOC, - // The specified target function cannot be hooked. - MH_ERROR_UNSUPPORTED_FUNCTION, + // Failed to change the memory protection. + MH_ERROR_MEMORY_PROTECT, - // Failed to allocate memory. - MH_ERROR_MEMORY_ALLOC, + // The specified module is not loaded. + MH_ERROR_MODULE_NOT_FOUND, - // Failed to change the memory protection. - MH_ERROR_MEMORY_PROTECT + // The specified function is not found. + MH_ERROR_FUNCTION_NOT_FOUND } MH_STATUS; -// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, MH_QueueEnableHook or MH_QueueDisableHook. +// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, +// MH_QueueEnableHook or MH_QueueDisableHook. #define MH_ALL_HOOKS NULL -#if defined __cplusplus +#ifdef __cplusplus extern "C" { #endif - // Initialize the MinHook library. - MH_STATUS WINAPI MH_Initialize(); - - // Uninitialize the MinHook library. - MH_STATUS WINAPI MH_Uninitialize(); - - // Creates the Hook for the specified target function, in disabled state. - // Parameters: - // pTarget [in] A pointer to the target function, which will be overridden by the detour function. - // pDetour [in] A pointer to the detour function, which will override the target function. - // ppOriginal [out] A pointer to the trampoline function, which will be used to call the original target function. - MH_STATUS WINAPI MH_CreateHook(void* pTarget, void* const pDetour, void** ppOriginal); - - // Removes the already created hook. - // Parameters: - // pTarget [in] A pointer to the target function. - MH_STATUS WINAPI MH_RemoveHook(void* pTarget); - - // Enables the already created hook. - // Parameters: - // pTarget [in] A pointer to the target function. - // If this parameter is MH_ALL_HOOKS, all created hooks are enabled in one go. - MH_STATUS WINAPI MH_EnableHook(void* pTarget); - - // Disables the already created hook. - // Parameters: - // pTarget [in] A pointer to the target function. - // If this parameter is MH_ALL_HOOKS, all created hooks are disabled in one go. - MH_STATUS WINAPI MH_DisableHook(void* pTarget); - - // Queues to enable the already created hook. - // Parameters: - // pTarget [in] A pointer to the target function. - // If this parameter is MH_ALL_HOOKS, all created hooks are queued to be enabled. - MH_STATUS WINAPI MH_QueueEnableHook(void* pTarget); - - // Queues to disable the already created hook. - // Parameters: - // pTarget [in] A pointer to the target function. - // If this parameter is MH_ALL_HOOKS, all created hooks are queued to be disabled. - MH_STATUS WINAPI MH_QueueDisableHook(void* pTarget); - - // Applies all queued changes in one go. - MH_STATUS WINAPI MH_ApplyQueued(); - -#if defined __cplusplus + // Initialize the MinHook library. You must call this function EXACTLY ONCE + // at the beginning of your program. + MH_STATUS WINAPI MH_Initialize(VOID); + + // Uninitialize the MinHook library. You must call this function EXACTLY + // ONCE at the end of your program. + MH_STATUS WINAPI MH_Uninitialize(VOID); + + // Creates a Hook for the specified target function, in disabled state. + // Parameters: + // pTarget [in] A pointer to the target function, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + // ppTarget [out] A pointer to the target function, which will be used + // with other functions. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); + + // Removes an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); + + // Enables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // enabled in one go. + MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); + + // Disables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // disabled in one go. + MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); + + // Queues to enable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be enabled. + MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); + + // Queues to disable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be disabled. + MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); + + // Applies all queued changes in one go. + MH_STATUS WINAPI MH_ApplyQueued(VOID); + + // Translates the MH_STATUS to its name as a string. + const char * WINAPI MH_StatusToString(MH_STATUS status); + +#ifdef __cplusplus } #endif diff --git a/libs/MinHook/src/HDE32/hde32.c b/libs/MinHook/src/HDE/hde32.c similarity index 98% rename from libs/MinHook/src/HDE32/hde32.c rename to libs/MinHook/src/HDE/hde32.c index 187c550..c3c62e8 100644 --- a/libs/MinHook/src/HDE32/hde32.c +++ b/libs/MinHook/src/HDE/hde32.c @@ -1,13 +1,10 @@ -/* +/* * Hacker Disassembler Engine 32 C * Copyright (c) 2008-2009, Vyacheslav Patkov. * All rights reserved. * */ -/* #include */ -#include - #include "hde32.h" #include "table32.h" @@ -16,7 +13,12 @@ unsigned int hde32_disasm(const void *code, hde32s *hs) uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0; - memset(hs,0,sizeof(hde32s)); + // Avoid using memset to reduce the footprint. +#ifndef _MSC_VER + memset((LPBYTE)hs, 0, sizeof(hde32s)); +#else + __stosb((LPBYTE)hs, 0, sizeof(hde32s)); +#endif for (x = 16; x; x--) switch (c = *p++) { diff --git a/libs/MinHook/src/HDE32/hde32.h b/libs/MinHook/src/HDE/hde32.h similarity index 98% rename from libs/MinHook/src/HDE32/hde32.h rename to libs/MinHook/src/HDE/hde32.h index 513f68b..1112450 100644 --- a/libs/MinHook/src/HDE32/hde32.h +++ b/libs/MinHook/src/HDE/hde32.h @@ -1,4 +1,4 @@ -/* +/* * Hacker Disassembler Engine 32 * Copyright (c) 2006-2009, Vyacheslav Patkov. * All rights reserved. @@ -19,7 +19,7 @@ * and change next line to: * #include "pstdint.h" */ - #include +#include "pstdint.h" #define F_MODRM 0x00000001 #define F_SIB 0x00000002 diff --git a/libs/MinHook/src/HDE64/src/hde64.c b/libs/MinHook/src/HDE/hde64.c similarity index 97% rename from libs/MinHook/src/HDE64/src/hde64.c rename to libs/MinHook/src/HDE/hde64.c index f43629d..72f9517 100644 --- a/libs/MinHook/src/HDE64/src/hde64.c +++ b/libs/MinHook/src/HDE/hde64.c @@ -1,14 +1,11 @@ -/* +/* * Hacker Disassembler Engine 64 C * Copyright (c) 2008-2009, Vyacheslav Patkov. * All rights reserved. * */ -/* #include */ -#include - -#include "../include/hde64.h" +#include "hde64.h" #include "table64.h" unsigned int hde64_disasm(const void *code, hde64s *hs) @@ -17,7 +14,12 @@ unsigned int hde64_disasm(const void *code, hde64s *hs) uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; uint8_t op64 = 0; - memset(hs,0,sizeof(hde64s)); + // Avoid using memset to reduce the footprint. +#ifndef _MSC_VER + memset((LPBYTE)hs, 0, sizeof(hde64s)); +#else + __stosb((LPBYTE)hs, 0, sizeof(hde64s)); +#endif for (x = 16; x; x--) switch (c = *p++) { diff --git a/libs/MinHook/src/HDE64/include/hde64.h b/libs/MinHook/src/HDE/hde64.h similarity index 98% rename from libs/MinHook/src/HDE64/include/hde64.h rename to libs/MinHook/src/HDE/hde64.h index 724c534..ecbf4df 100644 --- a/libs/MinHook/src/HDE64/include/hde64.h +++ b/libs/MinHook/src/HDE/hde64.h @@ -1,4 +1,4 @@ -/* +/* * Hacker Disassembler Engine 64 * Copyright (c) 2008-2009, Vyacheslav Patkov. * All rights reserved. @@ -19,7 +19,7 @@ * and change next line to: * #include "pstdint.h" */ -#include +#include "pstdint.h" #define F_MODRM 0x00000001 #define F_SIB 0x00000002 diff --git a/libs/MinHook/src/hook.h b/libs/MinHook/src/HDE/pstdint.h similarity index 61% rename from libs/MinHook/src/hook.h rename to libs/MinHook/src/HDE/pstdint.h index 0d843ce..5b7c5f0 100644 --- a/libs/MinHook/src/hook.h +++ b/libs/MinHook/src/HDE/pstdint.h @@ -1,20 +1,18 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, @@ -28,17 +26,14 @@ #pragma once -#include "MinHook.h" +#include -namespace MinHook -{ - MH_STATUS Initialize(); - MH_STATUS Uninitialize(); - MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal); - MH_STATUS RemoveHook(void* pTarget); - MH_STATUS EnableHook(void* pTarget); - MH_STATUS DisableHook(void* pTarget); - MH_STATUS QueueEnableHook(void* pTarget); - MH_STATUS QueueDisableHook(void* pTarget); - MH_STATUS ApplyQueued(); -} +// Integer types for HDE. +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; diff --git a/libs/MinHook/src/HDE32/table32.h b/libs/MinHook/src/HDE/table32.h similarity index 99% rename from libs/MinHook/src/HDE32/table32.h rename to libs/MinHook/src/HDE/table32.h index e1e1de6..7b3e12e 100644 --- a/libs/MinHook/src/HDE32/table32.h +++ b/libs/MinHook/src/HDE/table32.h @@ -1,4 +1,4 @@ -/* +/* * Hacker Disassembler Engine 32 C * Copyright (c) 2008-2009, Vyacheslav Patkov. * All rights reserved. diff --git a/libs/MinHook/src/HDE64/src/table64.h b/libs/MinHook/src/HDE/table64.h similarity index 99% rename from libs/MinHook/src/HDE64/src/table64.h rename to libs/MinHook/src/HDE/table64.h index 144f290..01d4541 100644 --- a/libs/MinHook/src/HDE64/src/table64.h +++ b/libs/MinHook/src/HDE/table64.h @@ -1,4 +1,4 @@ -/* +/* * Hacker Disassembler Engine 64 C * Copyright (c) 2008-2009, Vyacheslav Patkov. * All rights reserved. diff --git a/libs/MinHook/src/buffer.c b/libs/MinHook/src/buffer.c new file mode 100644 index 0000000..74f4709 --- /dev/null +++ b/libs/MinHook/src/buffer.c @@ -0,0 +1,315 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define STRICT +#define NOMINMAX +#define _WIN32_WINNT 0x0501 +#include +#include "buffer.h" + +// Size of each memory block. (= page size of VirtualAlloc) +#define MEMORY_BLOCK_SIZE 0x1000 + +// Max range for seeking a memory block. (= 1024MB) +#define MAX_MEMORY_RANGE 0x40000000 + +// Memory protection flags to check the executable address. +#define PAGE_EXECUTE_FLAGS \ + (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) + +// Memory slot. +typedef struct _MEMORY_SLOT +{ + union + { + struct _MEMORY_SLOT *pNext; + UINT8 buffer[MEMORY_SLOT_SIZE]; + }; +} MEMORY_SLOT, *PMEMORY_SLOT; + +// Memory block info. Placed at the head of each block. +typedef struct _MEMORY_BLOCK +{ + struct _MEMORY_BLOCK *pNext; + PMEMORY_SLOT pFree; // First element of the free slot list. + UINT usedCount; +} MEMORY_BLOCK, *PMEMORY_BLOCK; + +//------------------------------------------------------------------------- +// Global Variables: +//------------------------------------------------------------------------- + +// First element of the memory block list. +PMEMORY_BLOCK g_pMemoryBlocks; + +//------------------------------------------------------------------------- +VOID InitializeBuffer(VOID) +{ + // Nothing to do for now. +} + +//------------------------------------------------------------------------- +VOID UninitializeBuffer(VOID) +{ + PMEMORY_BLOCK pBlock = g_pMemoryBlocks; + g_pMemoryBlocks = NULL; + + while (pBlock) + { + PMEMORY_BLOCK pNext = pBlock->pNext; + VirtualFree(pBlock, 0, MEM_RELEASE); + pBlock = pNext; + } +} + +//------------------------------------------------------------------------- +#ifdef _M_X64 +static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity) +{ + ULONG_PTR tryAddr = (ULONG_PTR)pAddress; + + // Round down to the next allocation granularity. + tryAddr -= tryAddr % dwAllocationGranularity; + + // Start from the previous allocation granularity multiply. + tryAddr -= dwAllocationGranularity; + + while (tryAddr >= (ULONG_PTR)pMinAddr) + { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0) + break; + + if (mbi.State == MEM_FREE) + return (LPVOID)tryAddr; + + if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) + break; + + tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; + } + + return NULL; +} +#endif + +//------------------------------------------------------------------------- +#ifdef _M_X64 +static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity) +{ + ULONG_PTR tryAddr = (ULONG_PTR)pAddress; + + // Round down to the next allocation granularity. + tryAddr -= tryAddr % dwAllocationGranularity; + + // Start from the next allocation granularity multiply. + tryAddr += dwAllocationGranularity; + + while (tryAddr <= (ULONG_PTR)pMaxAddr) + { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0) + break; + + if (mbi.State == MEM_FREE) + return (LPVOID)tryAddr; + + tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; + + // Round up to the next allocation granularity. + tryAddr += dwAllocationGranularity - 1; + tryAddr -= tryAddr % dwAllocationGranularity; + } + + return NULL; +} +#endif + +//------------------------------------------------------------------------- +static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin) +{ + PMEMORY_BLOCK pBlock; +#ifdef _M_X64 + ULONG_PTR minAddr; + ULONG_PTR maxAddr; + + SYSTEM_INFO si; + GetSystemInfo(&si); + minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; + maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; + + // pOrigin ± 512MB + if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE) + minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE; + + if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE) + maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE; + + // Make room for MEMORY_BLOCK_SIZE bytes. + maxAddr -= MEMORY_BLOCK_SIZE - 1; +#endif + + // Look the registered blocks for a reachable one. + for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext) + { +#ifdef _M_X64 + // Ignore the blocks too far. + if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr) + continue; +#endif + // The block has at least one unused slot. + if (pBlock->pFree != NULL) + return pBlock; + } + +#ifdef _M_X64 + // Alloc a new block above if not found. + { + LPVOID pAlloc = pOrigin; + while ((ULONG_PTR)pAlloc >= minAddr) + { + pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity); + if (pAlloc == NULL) + break; + + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pBlock != NULL) + break; + } + } + + // Alloc a new block below if not found. + if (pBlock == NULL) + { + LPVOID pAlloc = pOrigin; + while ((ULONG_PTR)pAlloc <= maxAddr) + { + pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity); + if (pAlloc == NULL) + break; + + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pBlock != NULL) + break; + } + } +#else + // In x86 mode, a memory block can be placed anywhere. + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +#endif + + if (pBlock != NULL) + { + // Build a linked list of all the slots. + PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1; + pBlock->pFree = NULL; + pBlock->usedCount = 0; + do + { + pSlot->pNext = pBlock->pFree; + pBlock->pFree = pSlot; + pSlot++; + } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE); + + pBlock->pNext = g_pMemoryBlocks; + g_pMemoryBlocks = pBlock; + } + + return pBlock; +} + +//------------------------------------------------------------------------- +LPVOID AllocateBuffer(LPVOID pOrigin) +{ + PMEMORY_SLOT pSlot; + PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin); + if (pBlock == NULL) + return NULL; + + // Remove an unused slot from the list. + pSlot = pBlock->pFree; + pBlock->pFree = pSlot->pNext; + pBlock->usedCount++; +#ifdef _DEBUG + // Fill the slot with INT3 for debugging. + memset(pSlot, 0xCC, sizeof(MEMORY_SLOT)); +#endif + return pSlot; +} + +//------------------------------------------------------------------------- +VOID FreeBuffer(LPVOID pBuffer) +{ + PMEMORY_BLOCK pBlock = g_pMemoryBlocks; + PMEMORY_BLOCK pPrev = NULL; + ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE; + + while (pBlock != NULL) + { + if ((ULONG_PTR)pBlock == pTargetBlock) + { + PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer; +#ifdef _DEBUG + // Clear the released slot for debugging. + memset(pSlot, 0x00, sizeof(MEMORY_SLOT)); +#endif + // Restore the released slot to the list. + pSlot->pNext = pBlock->pFree; + pBlock->pFree = pSlot; + pBlock->usedCount--; + + // Free if unused. + if (pBlock->usedCount == 0) + { + if (pPrev) + pPrev->pNext = pBlock->pNext; + else + g_pMemoryBlocks = pBlock->pNext; + + VirtualFree(pBlock, 0, MEM_RELEASE); + } + + break; + } + + pPrev = pBlock; + pBlock = pBlock->pNext; + } +} + +//------------------------------------------------------------------------- +BOOL IsExecutableAddress(LPVOID pAddress) +{ + MEMORY_BASIC_INFORMATION mi; + VirtualQuery(pAddress, &mi, sizeof(MEMORY_BASIC_INFORMATION)); + + return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS)); +} diff --git a/libs/MinHook/src/buffer.cpp b/libs/MinHook/src/buffer.cpp deleted file mode 100644 index 87fca47..0000000 --- a/libs/MinHook/src/buffer.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include "buffer.h" - -namespace MinHook { namespace -{ - struct MEMORY_BLOCK - { - void* pAddress; - DWORD protect; - size_t uncommittedSize; - size_t uncommittedCount; - size_t fixedSize; - size_t fixedCount; - }; - - template - bool operator <(const MEMORY_BLOCK& lhs, const T& rhs); - template - bool operator <(const T& lhs, const MEMORY_BLOCK& rhs); - bool operator <(const MEMORY_BLOCK& lhs, const MEMORY_BLOCK& rhs); - - void* AllocateBuffer(void* const pOrigin, DWORD protect, size_t size); - MEMORY_BLOCK* GetMemoryBlock(void* const pOrigin, DWORD protect, size_t capacity); - - const size_t BlockSize = 0x10000; - -#if defined _M_X64 - intptr_t gMinAddress; - intptr_t gMaxAddress; -#endif - std::vector gMemoryBlocks; -}} - -namespace MinHook -{ - void InitializeBuffer() - { -#if defined _M_X64 - SYSTEM_INFO si; - GetSystemInfo(&si); - - gMinAddress = reinterpret_cast(si.lpMinimumApplicationAddress); - gMaxAddress = reinterpret_cast(si.lpMaximumApplicationAddress); -#endif - } - - void UninitializeBuffer() - { - for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i) - { - MEMORY_BLOCK& block = gMemoryBlocks[i]; - VirtualFree(block.pAddress, 0, MEM_RELEASE); - } - - std::vector v; - gMemoryBlocks.swap(v); - } - - void* AllocateCodeBuffer(void* const pOrigin, size_t size) - { - assert(("AllocateBuffer", (size > 0))); - - return AllocateBuffer(pOrigin, PAGE_EXECUTE_READ, size); - } - - void* AllocateDataBuffer(void* const pOrigin, size_t size) - { - assert(("AllocateBuffer", (size > 0))); - - return AllocateBuffer(pOrigin, PAGE_READONLY, size); - } - - void FreeBuffer(void* const pBuffer) - { - for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i) - { - MEMORY_BLOCK& block = gMemoryBlocks[i]; - void* pBlockEnd = reinterpret_cast(block.pAddress) + block.fixedSize; - - if (pBuffer >= block.pAddress && pBuffer < pBlockEnd) - { - assert(("FreeBuffer", (block.uncommittedSize == 0 && block.uncommittedCount == 0))); - - block.fixedCount--; - - if (block.fixedCount == 0) - { - VirtualFree(block.pAddress, 0, MEM_RELEASE); - gMemoryBlocks.erase(gMemoryBlocks.begin()+i); - } - - return; - } - } - - assert(("FreeBuffer", 0)); - } - - void RollbackBuffer() - { - for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i) - { - MEMORY_BLOCK& block = gMemoryBlocks[i]; - if (block.uncommittedSize == 0) - { - continue; - } - - block.uncommittedSize = 0; - block.uncommittedCount = 0; - - if (block.fixedCount == 0) - { - VirtualFree(block.pAddress, 0, MEM_RELEASE); - gMemoryBlocks.erase(gMemoryBlocks.begin()+i); - i--; - count--; - } - } - } - - void CommitBuffer() - { - for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i) - { - MEMORY_BLOCK& block = gMemoryBlocks[i]; - if (block.uncommittedSize == 0) - { - continue; - } - - void* pBuffer = reinterpret_cast(block.pAddress) + block.fixedSize; - size_t size = block.uncommittedSize; - DWORD op; - VirtualProtect(pBuffer, size, block.protect, &op); - - block.fixedSize += size; - block.uncommittedSize = 0; - - block.fixedCount += block.uncommittedCount; - block.uncommittedCount = 0; - } - } -} - -namespace MinHook { namespace -{ - void* AllocateBuffer(void* const pOrigin, DWORD protect, size_t size) - { - assert(("AllocateBuffer", (protect == PAGE_EXECUTE_READ || protect == PAGE_READONLY))); - assert(("AllocateBuffer", (size > 0))); - - // ƒAƒ‰ƒCƒƒ“ƒg‹«ŠE‚ÉØ‚èã‚° - size = (size + TYPE_ALIGNMENT(void*) - 1) & ~(TYPE_ALIGNMENT(void*) - 1); - - MEMORY_BLOCK* pBlock = GetMemoryBlock(pOrigin, protect, size); - if (pBlock == NULL) - { - return NULL; - } - - void* pBuffer = reinterpret_cast(pBlock->pAddress) + pBlock->fixedSize + pBlock->uncommittedSize; - if (VirtualAlloc(pBuffer, size, MEM_COMMIT, pBlock->protect) == NULL) - { - return NULL; - } - - DWORD oldProtect; - // PAGE_EXECUTE_READ -> PAGE_EXECUTE_READWRITE, PAGE_READONLY -> PAGE_READWRITE - if (!VirtualProtect(pBuffer, size, (pBlock->protect << 1), &oldProtect)) - { - return NULL; - } - - pBlock->uncommittedSize += size; - pBlock->uncommittedCount++; - return pBuffer; - } - - MEMORY_BLOCK* GetMemoryBlock(void* const pOrigin, DWORD protect, size_t capacity) - { - assert(("GetMemoryBlock", (protect == PAGE_EXECUTE_READ || protect == PAGE_READONLY))); - assert(("GetMemoryBlock", (capacity > 0))); - - typedef std::vector::iterator mb_iter; - -#if defined _M_X64 - intptr_t minAddr = gMinAddress; - intptr_t maxAddr = gMaxAddress; - if (pOrigin != NULL) - { - // pOrigin } 512MB ‚Ì”ÍˆÍ - minAddr = std::max(minAddr, reinterpret_cast(pOrigin) - 0x20000000); - maxAddr = std::min(maxAddr, reinterpret_cast(pOrigin) + 0x20000000); - } -#endif - - // ‚·‚łɓo˜^ς݂̗̈æ‚Ì’†‚©‚çŽg—p‰Â”\‚È‚à‚Ì‚ªŒ©‚‚©‚ê‚ÎA‚»‚ê‚ð•Ô‚· - MEMORY_BLOCK* pBlock = NULL; - { - mb_iter ib = gMemoryBlocks.begin(); - mb_iter ie = gMemoryBlocks.end(); -#if defined _M_X64 - if (pOrigin != NULL) - { - // ŒŸõ‘O‚ɃAƒhƒŒƒX”͈͂Åi‚èž‚Ý - ib = std::lower_bound(ib, ie, minAddr); - ie = std::lower_bound(ib, ie, maxAddr); - } -#endif - for (mb_iter i = ib; i != ie; ++i) - { - if (i->protect == protect && i->fixedSize + i->uncommittedSize + capacity <= BlockSize) - { - return &(*i); - } - } - } - - // Œ©‚‚©‚ç‚È‚¯‚ê‚ÎAV‚½‚ȃAƒhƒŒƒX—̈æ‚ðŠm•Û - void* pAlloc = NULL; -#if defined _M_X64 - if (pOrigin != NULL) - { - // ŒŸõ”͈͂̒†S‚©‚çŠO‘¤‚֋󂫗̈æ‚ð’T‚µ‚Ä‚¢‚­ - intptr_t min = minAddr / BlockSize; - intptr_t max = maxAddr / BlockSize; - int rel = 0; - MEMORY_BASIC_INFORMATION mi = { 0 }; - for (int i = 0; i < (max - min + 1); ++i) - { - rel = -rel + (i & 1); - void* pQuery = reinterpret_cast(((min + max) / 2 + rel) * BlockSize); - VirtualQuery(pQuery, &mi, sizeof(mi)); - if (mi.State == MEM_FREE) - { - pAlloc = VirtualAlloc(pQuery, BlockSize, MEM_RESERVE, protect); - if (pAlloc != NULL) - { - break; - } - } - } - } - else -#endif // X86ƒ‚[ƒh‚Å‚ÍAƒAƒhƒŒƒX‚Í–â‘è‚ɂȂç‚È‚¢ - { - pAlloc = VirtualAlloc(NULL, BlockSize, MEM_RESERVE, protect); - } - - if (pAlloc != NULL) - { - MEMORY_BLOCK block = { 0 }; - block.pAddress = pAlloc; - block.protect = protect; - -#if defined _M_X64 - mb_iter i = std::lower_bound(gMemoryBlocks.begin(), gMemoryBlocks.end(), pAlloc); -#elif defined _M_IX86 - mb_iter i = gMemoryBlocks.end(); -#endif - i = gMemoryBlocks.insert(i, block); - - return &(*i); - } - - return NULL; - } - - template - bool operator <(const MEMORY_BLOCK& lhs, const T& rhs) - { - return lhs.pAddress < reinterpret_cast(rhs); - } - - template - bool operator <(const T& lhs, const MEMORY_BLOCK& rhs) - { - return reinterpret_cast(lhs) < rhs.pAddress; - } - - bool operator <(const MEMORY_BLOCK& lhs, const MEMORY_BLOCK& rhs) - { - return lhs.pAddress < rhs.pAddress; - } -}} \ No newline at end of file diff --git a/libs/MinHook/src/buffer.h b/libs/MinHook/src/buffer.h index ce4dc2d..99cfebd 100644 --- a/libs/MinHook/src/buffer.h +++ b/libs/MinHook/src/buffer.h @@ -1,40 +1,42 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -namespace MinHook -{ - void InitializeBuffer(); - void UninitializeBuffer(); - void* AllocateCodeBuffer(void* const pOrigin, size_t size); - void* AllocateDataBuffer(void* const pOrigin, size_t size); - void FreeBuffer(void* const pBuffer); - void RollbackBuffer(); - void CommitBuffer(); -} +// Size of each memory slot. +#ifdef _M_X64 + #define MEMORY_SLOT_SIZE 64 +#else + #define MEMORY_SLOT_SIZE 32 +#endif + +VOID InitializeBuffer(VOID); +VOID UninitializeBuffer(VOID); +LPVOID AllocateBuffer(LPVOID pOrigin); +VOID FreeBuffer(LPVOID pBuffer); +BOOL IsExecutableAddress(LPVOID pAddress); diff --git a/libs/MinHook/src/export.cpp b/libs/MinHook/src/export.cpp deleted file mode 100644 index 08529f4..0000000 --- a/libs/MinHook/src/export.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "MinHook.h" -#include "hook.h" - -using namespace MinHook; - -MH_STATUS WINAPI MH_Initialize() -{ - return Initialize(); -} - -MH_STATUS WINAPI MH_Uninitialize() -{ - return Uninitialize(); -} - -MH_STATUS WINAPI MH_CreateHook(void* pTarget, void* const pDetour, void** ppOriginal) -{ - return CreateHook(pTarget, pDetour, ppOriginal); -} - -MH_STATUS WINAPI MH_RemoveHook(void* pTarget) -{ - return RemoveHook(pTarget); -} - -MH_STATUS WINAPI MH_EnableHook(void* pTarget) -{ - return EnableHook(pTarget); -} - -MH_STATUS WINAPI MH_DisableHook(void* pTarget) -{ - return DisableHook(pTarget); -} - -MH_STATUS WINAPI MH_QueueEnableHook(void* pTarget) -{ - return QueueEnableHook(pTarget); -} - -MH_STATUS WINAPI MH_QueueDisableHook(void* pTarget) -{ - return QueueDisableHook(pTarget); -} - -MH_STATUS WINAPI MH_ApplyQueued() -{ - return ApplyQueued(); -} diff --git a/libs/MinHook/src/hook.c b/libs/MinHook/src/hook.c new file mode 100644 index 0000000..b21b882 --- /dev/null +++ b/libs/MinHook/src/hook.c @@ -0,0 +1,891 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define STRICT +#define _WIN32_WINNT 0x0501 +#include +#include +#include + +#include "../include/MinHook.h" +#include "buffer.h" +#include "trampoline.h" + +#ifndef ARRAYSIZE + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +// Initial capacity of the HOOK_ENTRY buffer. +#define INITIAL_HOOK_CAPACITY 32 + +// Initial capacity of the thread IDs buffer. +#define INITIAL_THREAD_CAPACITY 128 + +// Special hook position values. +#define INVALID_HOOK_POS UINT_MAX +#define ALL_HOOKS_POS UINT_MAX + +// Freeze() action argument defines. +#define ACTION_DISABLE 0 +#define ACTION_ENABLE 1 +#define ACTION_APPLY_QUEUED 2 + +// Thread access rights for suspending/resuming threads. +#define THREAD_ACCESS \ + (THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT) + +// Hook information. +typedef struct _HOOK_ENTRY +{ + LPVOID pTarget; // Address of the target function. + LPVOID pDetour; // Address of the detour or relay function. + LPVOID pTrampoline; // Address of the trampoline function. + UINT8 backup[8]; // Original prologue of the target function. + + UINT8 patchAbove : 1; // Uses the hot patch area. + UINT8 isEnabled : 1; // Enabled. + UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled. + + UINT nIP : 4; // Count of the instruction boundaries. + UINT8 oldIPs[8]; // Instruction boundaries of the target function. + UINT8 newIPs[8]; // Instruction boundaries of the trampoline function. +} HOOK_ENTRY, *PHOOK_ENTRY; + +// Suspended threads for Freeze()/Unfreeze(). +typedef struct _FROZEN_THREADS +{ + LPDWORD pItems; // Data heap + UINT capacity; // Size of allocated data heap, items + UINT size; // Actual number of data items +} FROZEN_THREADS, *PFROZEN_THREADS; + +//------------------------------------------------------------------------- +// Global Variables: +//------------------------------------------------------------------------- + +// Spin lock flag for EnterSpinLock()/LeaveSpinLock(). +volatile LONG g_isLocked = FALSE; + +// Private heap handle. If not NULL, this library is initialized. +HANDLE g_hHeap = NULL; + +// Hook entries. +struct +{ + PHOOK_ENTRY pItems; // Data heap + UINT capacity; // Size of allocated data heap, items + UINT size; // Actual number of data items +} g_hooks; + +//------------------------------------------------------------------------- +// Returns INVALID_HOOK_POS if not found. +static UINT FindHookEntry(LPVOID pTarget) +{ + UINT i; + for (i = 0; i < g_hooks.size; ++i) + { + if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget) + return i; + } + + return INVALID_HOOK_POS; +} + +//------------------------------------------------------------------------- +static PHOOK_ENTRY AddHookEntry() +{ + if (g_hooks.pItems == NULL) + { + g_hooks.capacity = INITIAL_HOOK_CAPACITY; + g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc( + g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY)); + if (g_hooks.pItems == NULL) + return NULL; + } + else if (g_hooks.size >= g_hooks.capacity) + { + PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( + g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY)); + if (p == NULL) + return NULL; + + g_hooks.capacity *= 2; + g_hooks.pItems = p; + } + + return &g_hooks.pItems[g_hooks.size++]; +} + +//------------------------------------------------------------------------- +static void DeleteHookEntry(UINT pos) +{ + if (pos < g_hooks.size - 1) + g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1]; + + g_hooks.size--; + + if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size) + { + PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( + g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY)); + if (p == NULL) + return; + + g_hooks.capacity /= 2; + g_hooks.pItems = p; + } +} + +//------------------------------------------------------------------------- +static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip) +{ + UINT i; + + if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL))) + return (DWORD_PTR)pHook->pTarget; + + for (i = 0; i < pHook->nIP; ++i) + { + if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i])) + return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]; + } + +#ifdef _M_X64 + // Check relay function. + if (ip == (DWORD_PTR)pHook->pDetour) + return (DWORD_PTR)pHook->pTarget; +#endif + + return 0; +} + +//------------------------------------------------------------------------- +static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip) +{ + UINT i; + for (i = 0; i < pHook->nIP; ++i) + { + if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i])) + return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]; + } + + return 0; +} + +//------------------------------------------------------------------------- +static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action) +{ + // If the thread suspended in the overwritten area, + // move IP to the proper address. + + CONTEXT c; +#ifdef _M_X64 + DWORD64 *pIP = &c.Rip; +#else + DWORD *pIP = &c.Eip; +#endif + UINT count; + + c.ContextFlags = CONTEXT_CONTROL; + if (!GetThreadContext(hThread, &c)) + return; + + if (pos == ALL_HOOKS_POS) + { + pos = 0; + count = g_hooks.size; + } + else + { + count = pos + 1; + } + + for (; pos < count; ++pos) + { + PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; + BOOL enable; + DWORD_PTR ip; + + switch (action) + { + case ACTION_DISABLE: + enable = FALSE; + break; + + case ACTION_ENABLE: + enable = TRUE; + break; + + case ACTION_APPLY_QUEUED: + enable = pHook->queueEnable; + break; + } + if (pHook->isEnabled == enable) + continue; + + if (enable) + ip = FindNewIP(pHook, *pIP); + else + ip = FindOldIP(pHook, *pIP); + + if (ip != 0) + { + *pIP = ip; + SetThreadContext(hThread, &c); + } + } +} + +//------------------------------------------------------------------------- +static VOID EnumerateThreads(PFROZEN_THREADS pThreads) +{ + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) + { + THREADENTRY32 te; + te.dwSize = sizeof(THREADENTRY32); + if (Thread32First(hSnapshot, &te)) + { + do + { + if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD)) + && te.th32OwnerProcessID == GetCurrentProcessId() + && te.th32ThreadID != GetCurrentThreadId()) + { + if (pThreads->pItems == NULL) + { + pThreads->capacity = INITIAL_THREAD_CAPACITY; + pThreads->pItems + = (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD)); + if (pThreads->pItems == NULL) + break; + } + else if (pThreads->size >= pThreads->capacity) + { + LPDWORD p = (LPDWORD)HeapReAlloc( + g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD)); + if (p == NULL) + break; + + pThreads->capacity *= 2; + pThreads->pItems = p; + } + pThreads->pItems[pThreads->size++] = te.th32ThreadID; + } + + te.dwSize = sizeof(THREADENTRY32); + } while (Thread32Next(hSnapshot, &te)); + } + CloseHandle(hSnapshot); + } +} + +//------------------------------------------------------------------------- +static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action) +{ + pThreads->pItems = NULL; + pThreads->capacity = 0; + pThreads->size = 0; + EnumerateThreads(pThreads); + + if (pThreads->pItems != NULL) + { + UINT i; + for (i = 0; i < pThreads->size; ++i) + { + HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); + if (hThread != NULL) + { + SuspendThread(hThread); + ProcessThreadIPs(hThread, pos, action); + CloseHandle(hThread); + } + } + } +} + +//------------------------------------------------------------------------- +static VOID Unfreeze(PFROZEN_THREADS pThreads) +{ + if (pThreads->pItems != NULL) + { + UINT i; + for (i = 0; i < pThreads->size; ++i) + { + HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); + if (hThread != NULL) + { + ResumeThread(hThread); + CloseHandle(hThread); + } + } + + HeapFree(g_hHeap, 0, pThreads->pItems); + } +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableHookLL(UINT pos, BOOL enable) +{ + PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; + DWORD oldProtect; + SIZE_T patchSize = sizeof(JMP_REL); + LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget; + + if (pHook->patchAbove) + { + pPatchTarget -= sizeof(JMP_REL); + patchSize += sizeof(JMP_REL_SHORT); + } + + if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect)) + return MH_ERROR_MEMORY_PROTECT; + + if (enable) + { + PJMP_REL pJmp = (PJMP_REL)pPatchTarget; + pJmp->opcode = 0xE9; + pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL))); + + if (pHook->patchAbove) + { + PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget; + pShortJmp->opcode = 0xEB; + pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL))); + } + } + else + { + if (pHook->patchAbove) + memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); + else + memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL)); + } + + VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect); + + // Just-in-case measure. + FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize); + + pHook->isEnabled = enable; + pHook->queueEnable = enable; + + return MH_OK; +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableAllHooksLL(BOOL enable) +{ + MH_STATUS status = MH_OK; + UINT i, first = INVALID_HOOK_POS; + + for (i = 0; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != enable) + { + first = i; + break; + } + } + + if (first != INVALID_HOOK_POS) + { + FROZEN_THREADS threads; + Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE); + + for (i = first; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != enable) + { + status = EnableHookLL(i, enable); + if (status != MH_OK) + break; + } + } + + Unfreeze(&threads); + } + + return status; +} + +//------------------------------------------------------------------------- +static VOID EnterSpinLock(VOID) +{ + SIZE_T spinCount = 0; + + // Wait until the flag is FALSE. + while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE) + { + // No need to generate a memory barrier here, since InterlockedCompareExchange() + // generates a full memory barrier itself. + + // Prevent the loop from being too busy. + if (spinCount < 32) + Sleep(0); + else + Sleep(1); + + spinCount++; + } +} + +//------------------------------------------------------------------------- +static VOID LeaveSpinLock(VOID) +{ + // No need to generate a memory barrier here, since InterlockedExchange() + // generates a full memory barrier itself. + + InterlockedExchange(&g_isLocked, FALSE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_Initialize(VOID) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap == NULL) + { + g_hHeap = HeapCreate(0, 0, 0); + if (g_hHeap != NULL) + { + // Initialize the internal function buffer. + InitializeBuffer(); + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_ALREADY_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_Uninitialize(VOID) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + status = EnableAllHooksLL(FALSE); + if (status == MH_OK) + { + // Free the internal function buffer. + + // HeapFree is actually not required, but some tools detect a false + // memory leak without HeapFree. + + UninitializeBuffer(); + + HeapFree(g_hHeap, 0, g_hooks.pItems); + HeapDestroy(g_hHeap); + + g_hHeap = NULL; + + g_hooks.pItems = NULL; + g_hooks.capacity = 0; + g_hooks.size = 0; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour)) + { + UINT pos = FindHookEntry(pTarget); + if (pos == INVALID_HOOK_POS) + { + LPVOID pBuffer = AllocateBuffer(pTarget); + if (pBuffer != NULL) + { + TRAMPOLINE ct; + + ct.pTarget = pTarget; + ct.pDetour = pDetour; + ct.pTrampoline = pBuffer; + if (CreateTrampolineFunction(&ct)) + { + PHOOK_ENTRY pHook = AddHookEntry(); + if (pHook != NULL) + { + pHook->pTarget = ct.pTarget; +#ifdef _M_X64 + pHook->pDetour = ct.pRelay; +#else + pHook->pDetour = ct.pDetour; +#endif + pHook->pTrampoline = ct.pTrampoline; + pHook->patchAbove = ct.patchAbove; + pHook->isEnabled = FALSE; + pHook->queueEnable = FALSE; + pHook->nIP = ct.nIP; + memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs)); + memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs)); + + // Back up the target function. + + if (ct.patchAbove) + { + memcpy( + pHook->backup, + (LPBYTE)pTarget - sizeof(JMP_REL), + sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); + } + else + { + memcpy(pHook->backup, pTarget, sizeof(JMP_REL)); + } + + if (ppOriginal != NULL) + *ppOriginal = pHook->pTrampoline; + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_UNSUPPORTED_FUNCTION; + } + + if (status != MH_OK) + { + FreeBuffer(pBuffer); + } + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_ALREADY_CREATED; + } + } + else + { + status = MH_ERROR_NOT_EXECUTABLE; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + if (g_hooks.pItems[pos].isEnabled) + { + FROZEN_THREADS threads; + Freeze(&threads, pos, ACTION_DISABLE); + + status = EnableHookLL(pos, FALSE); + + Unfreeze(&threads); + } + + if (status == MH_OK) + { + FreeBuffer(g_hooks.pItems[pos].pTrampoline); + DeleteHookEntry(pos); + } + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (pTarget == MH_ALL_HOOKS) + { + status = EnableAllHooksLL(enable); + } + else + { + FROZEN_THREADS threads; + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + if (g_hooks.pItems[pos].isEnabled != enable) + { + Freeze(&threads, pos, ACTION_ENABLE); + + status = EnableHookLL(pos, enable); + + Unfreeze(&threads); + } + else + { + status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED; + } + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget) +{ + return EnableHook(pTarget, TRUE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget) +{ + return EnableHook(pTarget, FALSE); +} + +//------------------------------------------------------------------------- +static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (pTarget == MH_ALL_HOOKS) + { + UINT i; + for (i = 0; i < g_hooks.size; ++i) + g_hooks.pItems[i].queueEnable = queueEnable; + } + else + { + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + g_hooks.pItems[pos].queueEnable = queueEnable; + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget) +{ + return QueueHook(pTarget, TRUE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget) +{ + return QueueHook(pTarget, FALSE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_ApplyQueued(VOID) +{ + MH_STATUS status = MH_OK; + UINT i, first = INVALID_HOOK_POS; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + for (i = 0; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable) + { + first = i; + break; + } + } + + if (first != INVALID_HOOK_POS) + { + FROZEN_THREADS threads; + Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED); + + for (i = first; i < g_hooks.size; ++i) + { + PHOOK_ENTRY pHook = &g_hooks.pItems[i]; + if (pHook->isEnabled != pHook->queueEnable) + { + status = EnableHookLL(i, pHook->queueEnable); + if (status != MH_OK) + break; + } + } + + Unfreeze(&threads); + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, + LPVOID *ppOriginal, LPVOID *ppTarget) +{ + HMODULE hModule; + LPVOID pTarget; + + hModule = GetModuleHandleW(pszModule); + if (hModule == NULL) + return MH_ERROR_MODULE_NOT_FOUND; + + pTarget = (LPVOID)GetProcAddress(hModule, pszProcName); + if (pTarget == NULL) + return MH_ERROR_FUNCTION_NOT_FOUND; + + if(ppTarget != NULL) + *ppTarget = pTarget; + + return MH_CreateHook(pTarget, pDetour, ppOriginal); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal) +{ + return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL); +} + +//------------------------------------------------------------------------- +const char * WINAPI MH_StatusToString(MH_STATUS status) +{ +#define MH_ST2STR(x) \ + case x: \ + return #x; + + switch (status) { + MH_ST2STR(MH_UNKNOWN) + MH_ST2STR(MH_OK) + MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED) + MH_ST2STR(MH_ERROR_NOT_INITIALIZED) + MH_ST2STR(MH_ERROR_ALREADY_CREATED) + MH_ST2STR(MH_ERROR_NOT_CREATED) + MH_ST2STR(MH_ERROR_ENABLED) + MH_ST2STR(MH_ERROR_DISABLED) + MH_ST2STR(MH_ERROR_NOT_EXECUTABLE) + MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION) + MH_ST2STR(MH_ERROR_MEMORY_ALLOC) + MH_ST2STR(MH_ERROR_MEMORY_PROTECT) + MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND) + MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND) + } + +#undef MH_ST2STR + + return "(unknown)"; +} diff --git a/libs/MinHook/src/hook.cpp b/libs/MinHook/src/hook.cpp deleted file mode 100644 index 39c3970..0000000 --- a/libs/MinHook/src/hook.cpp +++ /dev/null @@ -1,727 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include "MinHook.h" -#include "hook.h" -#include "buffer.h" -#include "trampoline.h" -#include "thread.h" - -namespace MinHook { namespace -{ - struct HOOK_ENTRY - { - void* pTarget; - void* pDetour; -#if defined _M_X64 - void* pTable; - void* pRelay; -#endif - void* pTrampoline; - void* pBackup; - bool patchAbove; - bool isEnabled; - bool queueEnable; - std::vector oldIPs; - std::vector newIPs; - }; - - // –½—ß‘‚«ž‚Ý—p\‘¢‘Ì -#pragma pack(push, 1) - struct JMP_REL_SHORT - { - uint8_t opcode; - uint8_t operand; - }; - - struct JMP_REL - { - uint8_t opcode; - uint32_t operand; - }; - - struct JMP_ABS - { - uint16_t opcode; - uint32_t operand; - }; -#pragma pack(pop) - - MH_STATUS EnableHookLL(HOOK_ENTRY *pHook); - MH_STATUS DisableHookLL(HOOK_ENTRY *pHook); - MH_STATUS EnableAllHooksLL(); - MH_STATUS DisableAllHooksLL(); - HOOK_ENTRY* FindHook(void* const pTarget); - bool IsExecutableAddress(void* pAddress); - void WriteRelativeJump(void* pFrom, void* const pTo); - void WriteAbsoluteJump(void* pFrom, void* const pTo, void* pTable); - - template - bool operator <(const HOOK_ENTRY& lhs, const T& rhs) ; - template - bool operator <(const T& lhs, const HOOK_ENTRY& rhs) ; - bool operator <(const HOOK_ENTRY& lhs, const HOOK_ENTRY& rhs); - - CriticalSection gCS; - std::vector gHooks; - bool gIsInitialized = false; -}} - -namespace MinHook -{ - MH_STATUS Initialize() - { - CriticalSection::ScopedLock lock(gCS); - - if (gIsInitialized) - { - return MH_ERROR_ALREADY_INITIALIZED; - } - - // “à•”ŠÖ”ƒoƒbƒtƒ@‚̉Šú‰» - InitializeBuffer(); - - gIsInitialized = true; - return MH_OK; - } - - MH_STATUS Uninitialize() - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - // ‚·‚ׂẴtƒbƒN‚ð‰ðœ - MH_STATUS status = DisableAllHooksLL(); - if (status != MH_OK) - { - return status; - } - - std::vector v; - gHooks.swap(v); - - // “à•”ŠÖ”ƒoƒbƒtƒ@‚ÌŠJ•ú - UninitializeBuffer(); - - gIsInitialized = false; - return MH_OK; - } - - struct RollbackIfNotCommitted - { - bool* committed_; - RollbackIfNotCommitted(bool* committed) - : committed_(committed) - { - } - ~RollbackIfNotCommitted() - { - if (!*committed_) - { - RollbackBuffer(); - } - } - }; - - MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - HOOK_ENTRY *pHook = FindHook(pTarget); - if (pHook != NULL) - { - return MH_ERROR_ALREADY_CREATED; - } - - if (!IsExecutableAddress(pTarget) || !IsExecutableAddress(pDetour)) - { - return MH_ERROR_NOT_EXECUTABLE; - } - - { - bool committed = false; - RollbackIfNotCommitted scopedRollback(&committed); - - // ƒgƒ‰ƒ“ƒ|ƒŠƒ“ŠÖ”‚ð쬂·‚é - CREATE_TREMPOLINE_T ct = { 0 }; - ct.pTarget = pTarget; - if (!CreateTrampolineFunction(ct)) - { - return MH_ERROR_UNSUPPORTED_FUNCTION; - } - - void* pJmpPtr = pTarget; - if (ct.patchAbove) - { - pJmpPtr = reinterpret_cast(pJmpPtr) - sizeof(JMP_REL); - } - - void* pTrampoline = AllocateCodeBuffer(pJmpPtr, ct.trampoline.size()); - if (pTrampoline == NULL) - { - return MH_ERROR_MEMORY_ALLOC; - } -#if defined _M_X64 - void* pTable = AllocateDataBuffer(pTrampoline, (ct.table.size() + 1) * sizeof(uintptr_t)); - if (pTable == NULL) - { - return MH_ERROR_MEMORY_ALLOC; - } -#endif - - ct.pTrampoline = pTrampoline; -#if defined _M_X64 - ct.pTable = pTable; -#endif - if (!ResolveTemporaryAddresses(ct)) - { - return MH_ERROR_UNSUPPORTED_FUNCTION; - } - - memcpy(pTrampoline, &ct.trampoline[ 0 ], ct.trampoline.size()); -#if defined _M_X64 - if (ct.table.size() != 0) - { - memcpy(pTable, &ct.table[ 0 ], ct.table.size() * sizeof(uintptr_t)); - } -#endif - - // ƒ^[ƒQƒbƒgŠÖ”‚̃oƒbƒNƒAƒbƒv‚ð‚Æ‚é - size_t backupSize = sizeof(JMP_REL); - if (ct.patchAbove) - { - backupSize += sizeof(JMP_REL_SHORT); - } - - void* pBackup = AllocateDataBuffer(NULL, backupSize); - if (pBackup == NULL) - { - return MH_ERROR_MEMORY_ALLOC; - } - - memcpy(pBackup, pJmpPtr, backupSize); - - // ’†ŒpŠÖ”‚ð쬂·‚é -#if defined _M_X64 - void* pRelay = AllocateCodeBuffer(pJmpPtr, sizeof(JMP_ABS)); - if (pRelay == NULL) - { - return MH_ERROR_MEMORY_ALLOC; - } - - WriteAbsoluteJump(pRelay, pDetour, reinterpret_cast(pTable) + ct.table.size()); -#endif - CommitBuffer(); - committed = true; - - // ƒtƒbƒNî•ñ‚Ì“o˜^ - HOOK_ENTRY hook = { 0 }; - hook.pTarget = pTarget; - hook.pDetour = pDetour; -#if defined _M_X64 - hook.pTable = pTable; - hook.pRelay = pRelay; -#endif - hook.pTrampoline = pTrampoline; - hook.pBackup = pBackup; - hook.patchAbove = ct.patchAbove; - hook.isEnabled = false; - hook.queueEnable = false; - hook.oldIPs = ct.oldIPs; - hook.newIPs = ct.newIPs; - - std::vector::iterator i = std::lower_bound(gHooks.begin(), gHooks.end(), hook); - i = gHooks.insert(i, hook); - pHook = &(*i); - } - - // OUTˆø”‚̈— - *ppOriginal = pHook->pTrampoline; - - return MH_OK; - } - - MH_STATUS RemoveHook(void* pTarget) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - std::vector::iterator i - = std::lower_bound(gHooks.begin(), gHooks.end(), pTarget); - if (i == gHooks.end() || i->pTarget != pTarget) - return MH_ERROR_NOT_CREATED; - - HOOK_ENTRY *pHook = &(*i); - - if (pHook->isEnabled) - { - ScopedThreadExclusive tex(pHook->newIPs, pHook->oldIPs); - - MH_STATUS status = DisableHookLL(pHook); - if (status != MH_OK) - { - return status; - } - } - - FreeBuffer(pHook->pTrampoline); - -#if defined _M_X64 - FreeBuffer(pHook->pTable); -#endif - - FreeBuffer(pHook->pBackup); - -#if defined _M_X64 - FreeBuffer(pHook->pRelay); -#endif - - gHooks.erase(i); - - return MH_OK; - } - - MH_STATUS EnableHook(void* pTarget) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - if (pTarget == MH_ALL_HOOKS) - { - return EnableAllHooksLL(); - } - - HOOK_ENTRY *pHook = FindHook(pTarget); - if (pHook == NULL) - { - return MH_ERROR_NOT_CREATED; - } - - if (pHook->isEnabled) - { - return MH_ERROR_ENABLED; - } - - // ƒ^[ƒQƒbƒgŠÖ”‚Ì–`“ª‚ÉA’†ŒpŠÖ”‚Ü‚½‚̓tƒbƒNŠÖ”‚ւ̃Wƒƒƒ“ƒv‚ð‘‚«ž‚Þ - { - ScopedThreadExclusive tex(pHook->oldIPs, pHook->newIPs); - - MH_STATUS status = EnableHookLL(pHook); - if (status != MH_OK) - { - return status; - } - } - - return MH_OK; - } - - MH_STATUS DisableHook(void* pTarget) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - if (pTarget == MH_ALL_HOOKS) - { - return DisableAllHooksLL(); - } - - HOOK_ENTRY *pHook = FindHook(pTarget); - if (pHook == NULL) - { - return MH_ERROR_NOT_CREATED; - } - - if (!pHook->isEnabled) - { - return MH_ERROR_DISABLED; - } - - // ƒ^[ƒQƒbƒgŠÖ”‚Ì–`“ª‚ð‘‚«–ß‚·‚¾‚¯B‘¼‚ÍÄ—˜—p‚Ì‚½‚ߎc‚µ‚Ä‚¨‚­ - { - ScopedThreadExclusive tex(pHook->newIPs, pHook->oldIPs); - - MH_STATUS status = DisableHookLL(pHook); - if (status != MH_OK) - { - return status; - } - } - - return MH_OK; - } - - MH_STATUS QueueEnableHook(void* pTarget) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - if (pTarget == MH_ALL_HOOKS) - { - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - hook.queueEnable = true; - } - - return MH_OK; - } - - HOOK_ENTRY *pHook = FindHook(pTarget); - if (pHook == NULL) - { - return MH_ERROR_NOT_CREATED; - } - - pHook->queueEnable = true; - - return MH_OK; - } - - MH_STATUS QueueDisableHook(void* pTarget) - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - if (pTarget == MH_ALL_HOOKS) - { - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - hook.queueEnable = false; - } - - return MH_OK; - } - - HOOK_ENTRY *pHook = FindHook(pTarget); - if (pHook == NULL) - { - return MH_ERROR_NOT_CREATED; - } - - pHook->queueEnable = false; - - return MH_OK; - } - - MH_STATUS ApplyQueued() - { - CriticalSection::ScopedLock lock(gCS); - - if (!gIsInitialized) - { - return MH_ERROR_NOT_INITIALIZED; - } - - std::vector oldIPs; - std::vector newIPs; - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (hook.isEnabled != hook.queueEnable) - { - if (hook.queueEnable) - { - oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); - newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); - } - else - { - oldIPs.insert(oldIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); - newIPs.insert(newIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); - } - } - } - - if (oldIPs.size() > 0) - { - ScopedThreadExclusive tex(oldIPs, newIPs); - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (hook.isEnabled != hook.queueEnable) - { - MH_STATUS status; - if (hook.queueEnable) - { - status = EnableHookLL(&hook); - } - else - { - status = DisableHookLL(&hook); - } - - if (status != MH_OK) - { - return status; - } - } - } - } - - return MH_OK; - } - -} -namespace MinHook { namespace -{ - MH_STATUS EnableHookLL(HOOK_ENTRY *pHook) - { - void* pPatchTarget = pHook->pTarget; - size_t patchSize = sizeof(JMP_REL); - if (pHook->patchAbove) - { - pPatchTarget = reinterpret_cast(pPatchTarget) - sizeof(JMP_REL); - patchSize += sizeof(JMP_REL_SHORT); - } - - DWORD oldProtect; - if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect)) - { - return MH_ERROR_MEMORY_PROTECT; - } - -#if defined _M_X64 - WriteRelativeJump(pPatchTarget, pHook->pRelay); -#elif defined _M_IX86 - WriteRelativeJump(pPatchTarget, pHook->pDetour); -#endif - - if (pHook->patchAbove) - { - JMP_REL_SHORT jmpAbove; - jmpAbove.opcode = 0xEB; - jmpAbove.operand = 0 - static_cast(sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)); - - memcpy(pHook->pTarget, &jmpAbove, sizeof(jmpAbove)); - } - - VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect); - - pHook->isEnabled = true; - pHook->queueEnable = true; - - return MH_OK; - } - - MH_STATUS DisableHookLL(HOOK_ENTRY *pHook) - { - void* pPatchTarget = pHook->pTarget; - size_t patchSize = sizeof(JMP_REL); - if (pHook->patchAbove) - { - pPatchTarget = reinterpret_cast(pPatchTarget) - sizeof(JMP_REL); - patchSize += sizeof(JMP_REL_SHORT); - } - - DWORD oldProtect; - if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect)) - { - return MH_ERROR_MEMORY_PROTECT; - } - - memcpy(pPatchTarget, pHook->pBackup, patchSize); - - VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect); - - pHook->isEnabled = false; - pHook->queueEnable = false; - - return MH_OK; - } - - MH_STATUS EnableAllHooksLL() - { - std::vector oldIPs; - std::vector newIPs; - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (!hook.isEnabled) - { - oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); - newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); - } - } - - if (oldIPs.size() > 0) - { - ScopedThreadExclusive tex(oldIPs, newIPs); - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (!hook.isEnabled) - { - MH_STATUS status = EnableHookLL(&hook); - if (status != MH_OK) - { - return status; - } - } - } - } - - return MH_OK; - } - - MH_STATUS DisableAllHooksLL() - { - std::vector oldIPs; - std::vector newIPs; - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (hook.isEnabled) - { - oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); - newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); - } - } - - if (oldIPs.size() > 0) - { - ScopedThreadExclusive tex(newIPs, oldIPs); - - for (size_t i = 0, count = gHooks.size(); i < count; ++i) - { - HOOK_ENTRY& hook = gHooks[i]; - if (hook.isEnabled) - { - MH_STATUS status = DisableHookLL(&hook); - if (status != MH_OK) - { - return status; - } - } - } - } - - return MH_OK; - } - - HOOK_ENTRY* FindHook(void* const pTarget) - { - std::vector::iterator i - = std::lower_bound(gHooks.begin(), gHooks.end(), pTarget); - if (i != gHooks.end() && i->pTarget == pTarget) - { - return &(*i); - } - - return NULL; - } - - bool IsExecutableAddress(void* pAddress) - { - static const DWORD PageExecuteMask - = (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); - - // –¢Š„‚è“–‚Ä‚âŽÀs•s‰Â”\‚ȗ̈æ‚ðƒ`ƒFƒbƒN - MEMORY_BASIC_INFORMATION mi = { 0 }; - VirtualQuery(pAddress, &mi, sizeof(mi)); - - return ((mi.Protect & PageExecuteMask) != 0); - } - - void WriteRelativeJump(void* pFrom, void* const pTo) - { - JMP_REL jmp; - jmp.opcode = 0xE9; - jmp.operand = static_cast(reinterpret_cast(pTo) - (reinterpret_cast(pFrom) + sizeof(jmp))); - - memcpy(pFrom, &jmp, sizeof(jmp)); - } - - void WriteAbsoluteJump(void* pFrom, void* const pTo, void* pTable) - { - JMP_ABS jmp; - jmp.opcode = 0x25FF; - jmp.operand = static_cast(reinterpret_cast(pTable) - (reinterpret_cast(pFrom) + sizeof(jmp))); - - memcpy(pFrom, &jmp, sizeof(jmp)); - memcpy(pTable, &pTo, sizeof(pTo)); - } - - template - bool operator <(const HOOK_ENTRY& lhs, const T& rhs) - { - return lhs.pTarget < reinterpret_cast(rhs); - } - - template - bool operator <(const T& lhs, const HOOK_ENTRY& rhs) - { - return reinterpret_cast(lhs) < rhs.pTarget; - } - - bool operator <(const HOOK_ENTRY& lhs, const HOOK_ENTRY& rhs) - { - return lhs.pTarget < rhs.pTarget; - } -}} diff --git a/libs/MinHook/src/pstdint.h b/libs/MinHook/src/pstdint.h deleted file mode 100644 index 6a334ba..0000000 --- a/libs/MinHook/src/pstdint.h +++ /dev/null @@ -1,799 +0,0 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - **************************************************************************** - * - * Version 0.1.11 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * - */ - -#include -#include -#include - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED) -#include -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what will Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - -#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) - -/* - * Please compile with the maximum warning settings to make sure macros are not - * defined more than once. - */ - -#include -#include -#include - -#define glue3_aux(x,y,z) x ## y ## z -#define glue3(x,y,z) glue3_aux(x,y,z) - -#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); -#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); - -#define DECL(us,bits) glue3(DECL,us,) (bits) - -#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) - -int main () { - DECL(I,8) - DECL(U,8) - DECL(I,16) - DECL(U,16) - DECL(I,32) - DECL(U,32) -#ifdef INT64_MAX - DECL(I,64) - DECL(U,64) -#endif - intmax_t imax = INTMAX_C(0); - uintmax_t umax = UINTMAX_C(0); - char str0[256], str1[256]; - - sprintf (str0, "%d %x\n", 0, ~0); - - sprintf (str1, "%d %x\n", i8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); - sprintf (str1, "%u %x\n", u8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); - sprintf (str1, "%d %x\n", i16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); - sprintf (str1, "%u %x\n", u16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); -#ifdef INT64_MAX - sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); -#endif - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); - - TESTUMAX(8); - TESTUMAX(16); - TESTUMAX(32); -#ifdef INT64_MAX - TESTUMAX(64); -#endif - - return EXIT_SUCCESS; -} - -#endif diff --git a/libs/MinHook/src/thread.cpp b/libs/MinHook/src/thread.cpp deleted file mode 100644 index 2c33a4c..0000000 --- a/libs/MinHook/src/thread.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include "thread.h" - -namespace MinHook { namespace -{ - // Ž©“®“I‚ÉCloseHandle‚³‚ê‚éWindowsƒnƒ“ƒhƒ‹ - class ScopedHandle - { - ScopedHandle(const ScopedHandle&); - void operator=(const ScopedHandle&); - private: - HANDLE handle_; - public: - ScopedHandle(HANDLE handle) - : handle_(handle) - { - } - - ~ScopedHandle() - { - CloseHandle(handle_); - } - - operator HANDLE() const - { - return handle_; - } - }; - -}} - -// CriticalSection, CriticalSection::ScopedLock ‚ÌŽÀ‘• -namespace MinHook -{ - CriticalSection::CriticalSection() - { - InitializeCriticalSection(&cs_); - } - - CriticalSection::~CriticalSection() - { - DeleteCriticalSection(&cs_); - } - - void CriticalSection::enter() - { - EnterCriticalSection(&cs_); - } - - void CriticalSection::leave() - { - LeaveCriticalSection(&cs_); - } - - CriticalSection::ScopedLock::ScopedLock(CriticalSection& cs) - : cs_(cs) - { - cs_.enter(); - } - - CriticalSection::ScopedLock::~ScopedLock() - { - cs_.leave(); - } -} - -// ScopedThreadExclusive ‚ÌŽÀ‘• -namespace MinHook -{ - ScopedThreadExclusive::ScopedThreadExclusive(const std::vector& oldIPs, const std::vector& newIPs) - { - assert(("ScopedThreadExclusive::ctor", (oldIPs.size() == newIPs.size()))); - - GetThreads(threads_); - Freeze(threads_, oldIPs, newIPs); - } - - ScopedThreadExclusive::~ScopedThreadExclusive() - { - Unfreeze(threads_); - } - - void ScopedThreadExclusive::GetThreads(std::vector& threads) - { - ScopedHandle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hSnapshot == INVALID_HANDLE_VALUE) - { - return; - } - - THREADENTRY32 te = { sizeof(te) }; - if (Thread32First(hSnapshot, &te)) - { - do - { - if (te.th32OwnerProcessID == GetCurrentProcessId() - && te.th32ThreadID != GetCurrentThreadId()) - { - threads.push_back(te.th32ThreadID); - } - } - while (Thread32Next(hSnapshot, &te)); - } - } - - void ScopedThreadExclusive::Freeze( - const std::vector& threads, const std::vector& oldIPs, const std::vector& newIPs) - { - assert(("ScopedThreadExclusive::freeze", (oldIPs.size() == newIPs.size()))); - - static const DWORD ThreadAccess - = THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT; - - for (size_t i = 0, count = threads.size(); i < count; ++i) - { - DWORD tid = threads[i]; - ScopedHandle hThread = OpenThread(ThreadAccess, FALSE, tid); - SuspendThread(hThread); - - // ‘‚«Š·‚¦”͈͓à‚ŃXƒŒƒbƒh‚ª’âŽ~‚µ‚½ê‡‚ÍAƒgƒ‰ƒ“ƒ|ƒŠƒ“ŠÖ”‚ɧŒä‚ðˆÚ‚· - CONTEXT c = { 0 }; - c.ContextFlags = CONTEXT_CONTROL; - if (!GetThreadContext(hThread, &c)) - { - return; - } - -#if defined _M_X64 - DWORD64& ip = c.Rip; -#elif defined _M_IX86 - DWORD& ip = c.Eip; -#endif - for (size_t i = 0; i < oldIPs.size(); ++i) - { - if (ip == oldIPs[ i ]) - { - ip = newIPs[ i ]; - SetThreadContext(hThread, &c); - break; - } - } - } - } - - void ScopedThreadExclusive::Unfreeze(const std::vector& threads) - { - for (size_t i = 0, count = threads.size(); i < count; ++i) - { - DWORD tid = threads[i]; - ScopedHandle hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid); - ResumeThread(hThread); - } - } -} - diff --git a/libs/MinHook/src/thread.h b/libs/MinHook/src/thread.h deleted file mode 100644 index 4305d02..0000000 --- a/libs/MinHook/src/thread.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -#include "trampoline.h" - -namespace MinHook -{ - // ScopedLock •t‚«ƒNƒŠƒeƒBƒJƒ‹ƒZƒNƒVƒ‡ƒ“ - class CriticalSection - { - CriticalSection(const CriticalSection&); - void operator=(const CriticalSection&); - public: - class ScopedLock - { - ScopedLock(const ScopedLock&); - void operator=(const ScopedLock&); - private: - CriticalSection& cs_; - public: - ScopedLock(CriticalSection& cs); - ~ScopedLock(); - }; - - private: - CRITICAL_SECTION cs_; - public: - CriticalSection(); - ~CriticalSection(); - void enter(); - void leave(); - }; - - // “¯ˆêƒvƒƒZƒX“à‚Ì‘¼‚̃XƒŒƒbƒh‚ð‚·‚×‚Ä’âŽ~ - class ScopedThreadExclusive - { - private: - std::vector threads_; - public: - ScopedThreadExclusive(const std::vector& oldIPs, const std::vector& newIPs); - ~ScopedThreadExclusive(); - private: - static void GetThreads(std::vector& threads); - static void Freeze( - const std::vector& threads, const std::vector& oldIPs, const std::vector& newIPs); - static void Unfreeze(const std::vector& threads); - }; -} - diff --git a/libs/MinHook/src/trampoline.c b/libs/MinHook/src/trampoline.c new file mode 100644 index 0000000..209c94d --- /dev/null +++ b/libs/MinHook/src/trampoline.c @@ -0,0 +1,316 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#ifndef ARRAYSIZE + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +#ifdef _M_X64 + #include "./hde/hde64.h" + typedef hde64s HDE; + #define HDE_DISASM(code, hs) hde64_disasm(code, hs) +#else + #include "./hde/hde32.h" + typedef hde32s HDE; + #define HDE_DISASM(code, hs) hde32_disasm(code, hs) +#endif + +#include "trampoline.h" +#include "buffer.h" + +// Maximum size of a trampoline function. +#ifdef _M_X64 + #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS)) +#else + #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE +#endif + +//------------------------------------------------------------------------- +static BOOL IsCodePadding(LPBYTE pInst, UINT size) +{ + UINT i; + + if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC) + return FALSE; + + for (i = 1; i < size; ++i) + { + if (pInst[i] != pInst[0]) + return FALSE; + } + return TRUE; +} + +//------------------------------------------------------------------------- +BOOL CreateTrampolineFunction(PTRAMPOLINE ct) +{ +#ifdef _M_X64 + CALL_ABS call = { + 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8] + 0xEB, 0x08, // EB 08: JMP +10 + 0x0000000000000000ULL // Absolute destination address + }; + JMP_ABS jmp = { + 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] + 0x0000000000000000ULL // Absolute destination address + }; + JCC_ABS jcc = { + 0x70, 0x0E, // 7* 0E: J** +16 + 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] + 0x0000000000000000ULL // Absolute destination address + }; +#else + CALL_REL call = { + 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx + 0x00000000 // Relative destination address + }; + JMP_REL jmp = { + 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx + 0x00000000 // Relative destination address + }; + JCC_REL jcc = { + 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx + 0x00000000 // Relative destination address + }; +#endif + + UINT8 oldPos = 0; + UINT8 newPos = 0; + ULONG_PTR jmpDest = 0; // Destination address of an internal jump. + BOOL finished = FALSE; // Is the function completed? +#ifdef _M_X64 + UINT8 instBuf[16]; +#endif + + ct->patchAbove = FALSE; + ct->nIP = 0; + + do + { + HDE hs; + UINT copySize; + LPVOID pCopySrc; + ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos; + ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos; + + copySize = HDE_DISASM((LPVOID)pOldInst, &hs); + if (hs.flags & F_ERROR) + return FALSE; + + pCopySrc = (LPVOID)pOldInst; + if (oldPos >= sizeof(JMP_REL)) + { + // The trampoline function is long enough. + // Complete the function with the jump to the target function. +#ifdef _M_X64 + jmp.address = pOldInst; +#else + jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp))); +#endif + pCopySrc = &jmp; + copySize = sizeof(jmp); + + finished = TRUE; + } +#ifdef _M_X64 + else if ((hs.modrm & 0xC7) == 0x05) + { + // Instructions using RIP relative addressing. (ModR/M = 00???101B) + + // Modify the RIP relative address. + PUINT32 pRelAddr; + + // Avoid using memcpy to reduce the footprint. +#ifndef _MSC_VER + memcpy(instBuf, (LPBYTE)pOldInst, copySize); +#else + __movsb(instBuf, (LPBYTE)pOldInst, copySize); +#endif + pCopySrc = instBuf; + + // Relative address is stored at (instruction length - immediate value length - 4). + pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4); + *pRelAddr + = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len)); + + // Complete the function if JMP (FF /4). + if (hs.opcode == 0xFF && hs.modrm_reg == 4) + finished = TRUE; + } +#endif + else if (hs.opcode == 0xE8) + { + // Direct relative CALL + ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32; +#ifdef _M_X64 + call.address = dest; +#else + call.operand = (UINT32)(dest - (pNewInst + sizeof(call))); +#endif + pCopySrc = &call; + copySize = sizeof(call); + } + else if ((hs.opcode & 0xFD) == 0xE9) + { + // Direct relative JMP (EB or E9) + ULONG_PTR dest = pOldInst + hs.len; + + if (hs.opcode == 0xEB) // isShort jmp + dest += (INT8)hs.imm.imm8; + else + dest += (INT32)hs.imm.imm32; + + // Simply copy an internal jump. + if ((ULONG_PTR)ct->pTarget <= dest + && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) + { + if (jmpDest < dest) + jmpDest = dest; + } + else + { +#ifdef _M_X64 + jmp.address = dest; +#else + jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp))); +#endif + pCopySrc = &jmp; + copySize = sizeof(jmp); + + // Exit the function If it is not in the branch + finished = (pOldInst >= jmpDest); + } + } + else if ((hs.opcode & 0xF0) == 0x70 + || (hs.opcode & 0xFC) == 0xE0 + || (hs.opcode2 & 0xF0) == 0x80) + { + // Direct relative Jcc + ULONG_PTR dest = pOldInst + hs.len; + + if ((hs.opcode & 0xF0) == 0x70 // Jcc + || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ + dest += (INT8)hs.imm.imm8; + else + dest += (INT32)hs.imm.imm32; + + // Simply copy an internal jump. + if ((ULONG_PTR)ct->pTarget <= dest + && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) + { + if (jmpDest < dest) + jmpDest = dest; + } + else if ((hs.opcode & 0xFC) == 0xE0) + { + // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported. + return FALSE; + } + else + { + UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); +#ifdef _M_X64 + // Invert the condition in x64 mode to simplify the conditional jump logic. + jcc.opcode = 0x71 ^ cond; + jcc.address = dest; +#else + jcc.opcode1 = 0x80 | cond; + jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc))); +#endif + pCopySrc = &jcc; + copySize = sizeof(jcc); + } + } + else if ((hs.opcode & 0xFE) == 0xC2) + { + // RET (C2 or C3) + + // Complete the function if not in a branch. + finished = (pOldInst >= jmpDest); + } + + // Can't alter the instruction length in a branch. + if (pOldInst < jmpDest && copySize != hs.len) + return FALSE; + + // Trampoline function is too large. + if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE) + return FALSE; + + // Trampoline function has too many instructions. + if (ct->nIP >= ARRAYSIZE(ct->oldIPs)) + return FALSE; + + ct->oldIPs[ct->nIP] = oldPos; + ct->newIPs[ct->nIP] = newPos; + ct->nIP++; + + // Avoid using memcpy to reduce the footprint. +#ifndef _MSC_VER + memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); +#else + __movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); +#endif + newPos += copySize; + oldPos += hs.len; + } + while (!finished); + + // Is there enough place for a long jump? + if (oldPos < sizeof(JMP_REL) + && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos)) + { + // Is there enough place for a short jump? + if (oldPos < sizeof(JMP_REL_SHORT) + && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos)) + { + return FALSE; + } + + // Can we place the long jump above the function? + if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL))) + return FALSE; + + if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL))) + return FALSE; + + ct->patchAbove = TRUE; + } + +#ifdef _M_X64 + // Create a relay function. + jmp.address = (ULONG_PTR)ct->pDetour; + + ct->pRelay = (LPBYTE)ct->pTrampoline + newPos; + memcpy(ct->pRelay, &jmp, sizeof(jmp)); +#endif + + return TRUE; +} diff --git a/libs/MinHook/src/trampoline.cpp b/libs/MinHook/src/trampoline.cpp deleted file mode 100644 index ea62231..0000000 --- a/libs/MinHook/src/trampoline.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#if defined _M_X64 -#include "hde64/include/hde64.h" -#elif defined _M_IX86 -#include "hde32/hde32.h" -#endif - -#include "trampoline.h" - -namespace MinHook { namespace -{ -#if defined _M_X64 - typedef hde64s hde_t; - inline unsigned int hde_disasm(const void* code, hde_t* hs) { return hde64_disasm(code, hs); } -#elif defined _M_IX86 - typedef hde32s hde_t; - inline unsigned int hde_disasm(const void* code, hde_t* hs) { return hde32_disasm(code, hs); } -#endif - - // –½—ß‘‚«ž‚Ý—p\‘¢‘Ì -#pragma pack(push, 1) - struct JMP_REL_SHORT - { - uint8_t opcode; - uint8_t operand; - }; - - struct JMP_REL - { - uint8_t opcode; - uint32_t operand; - }; - typedef JMP_REL CALL_REL; - - struct JMP_ABS - { - uint16_t opcode; - uint32_t operand; - }; - typedef JMP_ABS CALL_ABS, JCC_REL; - - // ŠÔÚâ‘ÎNEAR Jcc‚ɑГ–‚·‚郃WƒbƒN - struct JCC_ABS - { - uint8_t opcode; // 7* 02 J** +4 - uint8_t dummy0; - uint8_t dummy1; // EB 06 JMP +8 - uint8_t dummy2; - uint16_t dummy3; // FF25 xxxxxxxx JMP [RIP+xxxxxxxx] - uint32_t operand; - }; -#pragma pack(pop) - - uintptr_t GetRelativeBranchDestination(uint8_t* pInst, const hde_t& hs, bool isShort); - inline bool IsInternalJump(void* pTarget, uintptr_t dest); - template - void AppendTempAddress(uintptr_t address, size_t pos, const T& inst, CREATE_TREMPOLINE_T& ct); -#if defined _M_X64 - void AppendRipRelativeAddress(uint8_t* pInst, size_t pos, const hde_t& hs, CREATE_TREMPOLINE_T& ct); -#endif - inline void SetJccOpcode(const hde_t& hs, JCC_REL& inst); - inline void SetJccOpcode(const hde_t& hs, JCC_ABS& inst); - bool IsCodePadding(uint8_t* pInst, size_t size); - bool IsExecutableAddress(void* pAddress); -}} - -namespace MinHook -{ - bool CreateTrampolineFunction(CREATE_TREMPOLINE_T& ct) - { - assert(("CreateTrampolineFunction", ct.pTarget != NULL)); - -#if defined _M_X64 - CALL_ABS call = { 0x15FF, 0x00000000 }; - JMP_ABS jmp = { 0x25FF, 0x00000000 }; - JCC_ABS jcc = { 0x70, 0x02, 0xEB, 0x06, 0x25FF, 0x00000000 }; -#elif defined _M_IX86 - CALL_REL call = { 0xE8, 0x00000000 }; - JMP_REL jmp = { 0xE9, 0x00000000 }; - JCC_REL jcc = { 0x800F, 0x00000000 }; -#endif - - size_t oldPos = 0; - size_t newPos = 0; - uintptr_t jmpDest = 0; // ŠÖ”“àƒWƒƒƒ“ƒv‚Ì”ò‚ÑæƒAƒhƒŒƒXi•ªŠò’†”»’è‚ÉŽg—pj - bool finished = false; // ŠÖ”I—¹ƒtƒ‰ƒO - while (!finished) - { - uint8_t *pInst = reinterpret_cast(ct.pTarget) + oldPos; - hde_t hs; - hde_disasm(pInst, &hs); - if ((hs.flags & F_ERROR) == F_ERROR) - { - return false; - } - - void* pCopySrc = pInst; - size_t copySize = hs.len; - - if (pInst - reinterpret_cast(ct.pTarget) >= sizeof(JMP_REL)) - { - // ƒ^[ƒQƒbƒgŠÖ”‚ւ̃Wƒƒƒ“ƒv‚ð‘‚«ž‚ÝAŠÖ”‚ðI—¹ - AppendTempAddress(reinterpret_cast(pInst), newPos, jmp, ct); - - pCopySrc = &jmp; - copySize = sizeof(jmp); - - finished = true; - } -#if defined _M_X64 - // RIP‘Š‘ÎƒAƒhƒŒƒbƒVƒ“ƒO‚ðŽg—p‚µ‚Ä‚¢‚é–½—ß (ModR/M = 00???101B) - else if ((hs.modrm & 0xC7) == 0x05) - { - // RIP‘Š‘ÎƒAƒhƒŒƒX‚̂ݑ‚«Š·‚¦ - AppendRipRelativeAddress(pInst, newPos, hs, ct); - - // JMP (FF /4)‚È‚çŠÖ”‚ðI—¹ - if (hs.opcode == 0xFF && hs.modrm_reg == 4) - { - finished = true; - } - } -#endif - // ‘Š‘Î’¼ÚCALL - else if (hs.opcode == 0xE8) - { - AppendTempAddress(GetRelativeBranchDestination(pInst, hs, false), newPos, call, ct); - pCopySrc = &call; - copySize = sizeof(call); - } - // ‘Š‘Î’¼ÚJMP (EB or E9) - else if ((hs.opcode & 0xFD) == 0xE9) - { - uintptr_t dest = GetRelativeBranchDestination(pInst, hs, hs.opcode == 0xEB); - - // ŠÖ”“à‚ւ̃Wƒƒƒ“ƒv‚Í‚»‚̂܂܃Rƒs[iƒWƒƒƒ“ƒv’†‚Í–½—ß’·‚ª•Ï‚í‚邿‚¤‚È‘€ì‚Í•s‰Âj - if (IsInternalJump(ct.pTarget, dest)) - { - jmpDest = std::max(jmpDest, dest); - } - else - { - AppendTempAddress(dest, newPos, jmp, ct); - pCopySrc = &jmp; - copySize = sizeof(jmp); - - // •ªŠò’†‚łȂ¯‚ê‚Ί֔‚ðI—¹ - finished = (reinterpret_cast(pInst) >= jmpDest); - } - } - // ‘Š‘Î’¼ÚJcc - else if ((hs.opcode & 0xF0) == 0x70 || (hs.opcode & 0xFC) == 0xE0 || (hs.opcode2 & 0xF0) == 0x80) - { - uintptr_t dest = GetRelativeBranchDestination(pInst, hs, (hs.opcode & 0xF0) == 0x70 || (hs.opcode & 0xFC) == 0xE0); - - // ŠÖ”“à‚ւ̃Wƒƒƒ“ƒv‚Í‚»‚̂܂܃Rƒs[i•ªŠò’†‚Í–½—ß’·‚ª•Ï‚í‚邿‚¤‚È‘€ì‚Í•s‰Âj - if (IsInternalJump(ct.pTarget, dest)) - { - jmpDest = std::max(jmpDest, dest); - } - else if ((hs.opcode & 0xFC) == 0xE0) // ŠÖ”ŠO‚Ö‚ÌJCXZ, JECXZ ‚ɂ͑Ήž‚µ‚È‚¢ - { - return false; - } - else - { - AppendTempAddress(dest, newPos, jcc, ct); - SetJccOpcode(hs, jcc); - pCopySrc = &jcc; - copySize = sizeof(jcc); - } - } - // RET (C2 or C3) - else if ((hs.opcode & 0xFE) == 0xC2) - { - // •ªŠò’†‚łȂ¯‚ê‚΃gƒ‰ƒ“ƒ|ƒŠƒ“ŠÖ”‚ðI—¹ - finished = (reinterpret_cast(pInst) >= jmpDest); - } - - // •ªŠò’†‚Í–½—ß’·‚ª•Ï‚í‚邿‚¤‚È‘€ì‚Í•s‰Â - if (reinterpret_cast(pInst) < jmpDest && copySize != hs.len) - { - return false; - } - - ct.trampoline.resize(newPos + copySize); - memcpy(&ct.trampoline[ newPos ], pCopySrc, copySize); - - ct.oldIPs.push_back(oldPos); - oldPos += hs.len; - ct.newIPs.push_back(newPos); - newPos += copySize; - } - - // Is there enough place for a long jump? - if (oldPos < sizeof(JMP_REL) && !IsCodePadding(reinterpret_cast(ct.pTarget) + oldPos, sizeof(JMP_REL) - oldPos)) - { - // Is there enough place for a short jump? - if (oldPos < sizeof(JMP_REL_SHORT) && !IsCodePadding(reinterpret_cast(ct.pTarget) + oldPos, sizeof(JMP_REL_SHORT) - oldPos)) - { - return false; - } - - // Can we place the long jump above the function? - if (!IsExecutableAddress(reinterpret_cast(ct.pTarget) - sizeof(JMP_REL))) - { - return false; - } - - if (!IsCodePadding(reinterpret_cast(ct.pTarget) - sizeof(JMP_REL), sizeof(JMP_REL))) - { - return false; - } - - ct.patchAbove = true; - } - - return true; - } - - bool ResolveTemporaryAddresses(CREATE_TREMPOLINE_T& ct) - { - assert(("ResolveTemporaryAddresses", ct.pTrampoline != NULL)); -#if defined _M_X64 - assert(("ResolveTemporaryAddresses", (ct.table.empty() || ct.pTable != NULL))); -#endif - -#if defined _M_X64 - uintptr_t* pt = reinterpret_cast(ct.pTable); -#endif - for (size_t i = 0, count = ct.tempAddr.size(); i < count; ++i) - { - const TEMP_ADDR& ta = ct.tempAddr[i]; - if (ta.position > ct.trampoline.size() - sizeof(uint32_t)) - { - return false; - } - - uintptr_t addr; -#if defined _M_X64 - if (ta.address < 0x10000) // 0x10000–¢–ž‚̓e[ƒuƒ‹‚̃Cƒ“ƒfƒbƒNƒXA0x10000ˆÈã‚ÍRIP‘Š‘ÎƒAƒhƒŒƒX - { - addr = reinterpret_cast(pt++); - } - else -#endif - { - addr = ta.address; - } - - *reinterpret_cast(&ct.trampoline[ ta.position ]) - = static_cast(addr - (reinterpret_cast(ct.pTrampoline) + ta.pc)); - } - - for (size_t i = 0; i < ct.oldIPs.size(); ++i) - { - ct.oldIPs[ i ] += reinterpret_cast(ct.pTarget); - ct.newIPs[ i ] += reinterpret_cast(ct.pTrampoline); - } - - if (ct.patchAbove) - { - ct.oldIPs.push_back(reinterpret_cast(ct.pTarget)); - ct.newIPs.push_back(reinterpret_cast(ct.pTarget) - sizeof(JMP_REL)); - } - - return true; - } -} - -namespace MinHook { namespace -{ - inline uintptr_t GetRelativeBranchDestination(uint8_t* pInst, const hde_t& hs, bool isShort) - { - int32_t imm = isShort ? static_cast(hs.imm.imm8) : static_cast(hs.imm.imm32); - return reinterpret_cast(pInst) + hs.len + imm; - } - - inline bool IsInternalJump(void* pTarget, uintptr_t dest) - { - uintptr_t pt = reinterpret_cast(pTarget); - return (pt <= dest && dest <= pt + sizeof(JMP_REL)); - } - - template - void AppendTempAddress(uintptr_t address, size_t pos, const T& inst, CREATE_TREMPOLINE_T& ct) - { - TEMP_ADDR ta; -#if defined _M_X64 - ta.address = ct.table.size(); - ct.table.push_back(address); -#elif defined _M_IX86 - ta.address = address; -#endif - ta.position = pos + (reinterpret_cast(&inst.operand) - reinterpret_cast(&inst)); - ta.pc = pos + sizeof(inst); - - ct.tempAddr.push_back(ta); - } - -#if defined _M_X64 - void AppendRipRelativeAddress(uint8_t* pInst, size_t pos, const hde_t& hs, CREATE_TREMPOLINE_T& ct) - { - TEMP_ADDR ta; - ta.address = reinterpret_cast(pInst) + hs.len + static_cast(hs.disp.disp32); - ta.position = pos + hs.len - ((hs.flags & 0x3C) >> 2) - 4; // pos + –½—ß’· - ‘¦’lƒTƒCƒY - 4 - ta.pc = pos + hs.len; - - ct.tempAddr.push_back(ta); - } -#endif - - inline void SetJccOpcode(const hde_t& hs, JCC_REL& inst) - { - uint8_t n = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); - inst.opcode = 0x800F | (n << 8); - } - - inline void SetJccOpcode(const hde_t& hs, JCC_ABS& inst) - { - uint8_t n = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); - inst.opcode = 0x70 | n; - } - - bool IsCodePadding(uint8_t* pInst, size_t size) - { - uint8_t paddingByte = pInst[0]; - switch (paddingByte) - { - case 0x00: - case 0x90: // NOP - case 0xCC: // INT3 - for (size_t i = 1; i < size; ++i) - { - if (pInst[i] != paddingByte) - { - return false; - } - } - return true; - - default: - return false; - } - } - - bool IsExecutableAddress(void* pAddress) - { - static const DWORD PageExecuteMask - = (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); - - // –¢Š„‚è“–‚Ä‚âŽÀs•s‰Â”\‚ȗ̈æ‚ðƒ`ƒFƒbƒN - MEMORY_BASIC_INFORMATION mi = { 0 }; - VirtualQuery(pAddress, &mi, sizeof(mi)); - - return ((mi.Protect & PageExecuteMask) != 0); - } -}} - - diff --git a/libs/MinHook/src/trampoline.h b/libs/MinHook/src/trampoline.h index 9081040..885c6ed 100644 --- a/libs/MinHook/src/trampoline.h +++ b/libs/MinHook/src/trampoline.h @@ -1,59 +1,105 @@ -/* - * MinHook - Minimalistic API Hook Library - * Copyright (C) 2009 Tsuda Kageyu. All rights reserved. - * +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2015 Tsuda Kageyu. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#pragma pack(push, 1) -namespace MinHook +// Structs for writing x86/x64 instructions. + +// 8-bit relative jump. +typedef struct _JMP_REL_SHORT +{ + UINT8 opcode; // EB xx: JMP +2+xx + UINT8 operand; +} JMP_REL_SHORT, *PJMP_REL_SHORT; + +// 32-bit direct relative jump/call. +typedef struct _JMP_REL +{ + UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx + UINT32 operand; // Relative destination address +} JMP_REL, *PJMP_REL, CALL_REL; + +// 64-bit indirect absolute jump. +typedef struct _JMP_ABS +{ + UINT8 opcode0; // FF25 00000000: JMP [+6] + UINT8 opcode1; + UINT32 dummy; + UINT64 address; // Absolute destination address +} JMP_ABS, *PJMP_ABS; + +// 64-bit indirect absolute call. +typedef struct _CALL_ABS { - struct TEMP_ADDR - { - uintptr_t address; - size_t position; - size_t pc; - }; - - struct CREATE_TREMPOLINE_T - { - void* pTarget; - void* pTrampoline; - bool patchAbove; - std::vector trampoline; - std::vector tempAddr; -#if defined _M_X64 - void* pTable; - std::vector table; + UINT8 opcode0; // FF15 00000002: CALL [+6] + UINT8 opcode1; + UINT32 dummy0; + UINT8 dummy1; // EB 08: JMP +10 + UINT8 dummy2; + UINT64 address; // Absolute destination address +} CALL_ABS; + +// 32-bit direct relative conditional jumps. +typedef struct _JCC_REL +{ + UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx + UINT8 opcode1; + UINT32 operand; // Relative destination address +} JCC_REL; + +// 64bit indirect absolute conditional jumps that x64 lacks. +typedef struct _JCC_ABS +{ + UINT8 opcode; // 7* 0E: J** +16 + UINT8 dummy0; + UINT8 dummy1; // FF25 00000000: JMP [+6] + UINT8 dummy2; + UINT32 dummy3; + UINT64 address; // Absolute destination address +} JCC_ABS; + +#pragma pack(pop) + +typedef struct _TRAMPOLINE +{ + LPVOID pTarget; // [In] Address of the target function. + LPVOID pDetour; // [In] Address of the detour function. + LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function. + +#ifdef _M_X64 + LPVOID pRelay; // [Out] Address of the relay function. #endif - std::vector oldIPs; - std::vector newIPs; - }; + BOOL patchAbove; // [Out] Should use the hot patch area? + UINT nIP; // [Out] Number of the instruction boundaries. + UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function. + UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function. +} TRAMPOLINE, *PTRAMPOLINE; - bool CreateTrampolineFunction(CREATE_TREMPOLINE_T& ct); - bool ResolveTemporaryAddresses(CREATE_TREMPOLINE_T& ct); -} \ No newline at end of file +BOOL CreateTrampolineFunction(PTRAMPOLINE ct); diff --git a/libs/Where these are from.txt b/libs/Where these are from.txt index c9e1860..4e2d80d 100644 --- a/libs/Where these are from.txt +++ b/libs/Where these are from.txt @@ -4,7 +4,7 @@ MinHook This guys MinHook fork: -https://github.com/RaMMicHaeL/minhook commit 4141fefb4445d41e8506d8f72801a27e1b8874c6 +https://github.com/TsudaKageyu/minhook.git commit 0740da73c50a7e735b9ff1d1660dac18aeb16e5d MinHook is originally from codeproject.com: http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x86-x64-API-Hooking-Libra