diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4693cc1..e723fbf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,5 +23,5 @@ jobs: - name: Release uses: softprops/action-gh-release@v1 with: - files: x64/Release/VersionShim.dll - fail_on_unmatched_files: true + files: bin/x64/Release/VersionShim.dll + fail_on_unmatched_files: true \ No newline at end of file diff --git a/README.md b/README.md index 6ebcb83..574bd83 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ VersionShim =========== -A Dynamic-Link Library which exports the same methods as version.dll (winver.h) in addition to chainloading additional user defined libraries. +A Dynamic-Link Library which exports the same methods as version.dll (winver.h) and winhttp.dll in addition to chainloading additional user defined libraries. Usage ----- -Rename VersionShim.dll to `version.dll` and place it in the target process's search location, +Rename VersionShim.dll to `version.dll` or `winhttp.dll` and place it in the target process's search location, then create a file named `libraries.txt` in the same directory and list the paths to all the libraries you'd like to load, each on a new line. diff --git a/VersionShim.sln b/VersionShim.sln index 30935ab..3bc9eb9 100644 --- a/VersionShim.sln +++ b/VersionShim.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33209.295 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VersionShim", "VersionShim\VersionShim.vcxproj", "{7D2E1375-BF0B-49EF-BBA8-C134A347F1C7}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VersionShim", "src\VersionShim.vcxproj", "{7D2E1375-BF0B-49EF-BBA8-C134A347F1C7}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39DCA191-5807-42D8-A66A-373FBE7F5EA9}" ProjectSection(SolutionItems) = preProject diff --git a/VersionShim/dllmain.c b/VersionShim/dllmain.c deleted file mode 100644 index 33cb002..0000000 --- a/VersionShim/dllmain.c +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright © 2023 Xpl0itR -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "pch.h" -#include "util.h" - -#pragma region Forward functions to system version.dll -#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=c:\\windows\\system32\\version.GetFileVersionInfoA") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=c:\\windows\\system32\\version.GetFileVersionInfoByHandle") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=c:\\windows\\system32\\version.GetFileVersionInfoExA") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=c:\\windows\\system32\\version.GetFileVersionInfoExW") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=c:\\windows\\system32\\version.GetFileVersionInfoSizeA") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=c:\\windows\\system32\\version.GetFileVersionInfoSizeExA") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=c:\\windows\\system32\\version.GetFileVersionInfoSizeExW") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=c:\\windows\\system32\\version.GetFileVersionInfoSizeW") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=c:\\windows\\system32\\version.GetFileVersionInfoW") -#pragma comment(linker, "/EXPORT:VerFindFileA=c:\\windows\\system32\\version.VerFindFileA") -#pragma comment(linker, "/EXPORT:VerFindFileW=c:\\windows\\system32\\version.VerFindFileW") -#pragma comment(linker, "/EXPORT:VerInstallFileA=c:\\windows\\system32\\version.VerInstallFileA") -#pragma comment(linker, "/EXPORT:VerInstallFileW=c:\\windows\\system32\\version.VerInstallFileW") -#pragma comment(linker, "/EXPORT:VerLanguageNameA=c:\\windows\\system32\\version.VerLanguageNameA") -#pragma comment(linker, "/EXPORT:VerLanguageNameW=c:\\windows\\system32\\version.VerLanguageNameW") -#pragma comment(linker, "/EXPORT:VerQueryValueA=c:\\windows\\system32\\version.VerQueryValueA") -#pragma comment(linker, "/EXPORT:VerQueryValueW=c:\\windows\\system32\\version.VerQueryValueW") -#pragma endregion - -BOOL APIENTRY DllMain(CONST HMODULE hModule, CONST DWORD fdwReason, CONST LPVOID lpvReserved) -{ - if (fdwReason != DLL_PROCESS_ATTACH) - return TRUE; - - LPSTR fileStr = NULL; - DWORD fileLen = 0; - - if (!OpenReadFileUtf8("libraries.txt", &fileStr, &fileLen)) - { - MessageBoxA(NULL, "Failed to read libraries.txt", PROJECT_NAME, ErrBoxType); - return TRUE; - } - - LPSTR callerPath[MAX_PATH + 1]; - if (!GetModuleFileNameA(NULL, callerPath, MAX_PATH + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types) - { - MessageBoxA(NULL, "Failed to read caller path", PROJECT_NAME, ErrBoxType); - return TRUE; - } - - int read, hasTarget = FALSE, targetMatched = FALSE; - for (LPSTR line = SkipBomUtf8(fileStr), fileEnd = fileStr + fileLen; line < fileEnd; line += read) - { - read = TerminateLine(line); - - if (*line == '#') - continue; - - if (*line == '*') - { - if (!targetMatched) - { - hasTarget = TRUE; - - if (StrEndsWith(callerPath, line + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types) - { - targetMatched = TRUE; - } - } - - continue; - } - - if (hasTarget && !targetMatched) - return TRUE; - - if (!LoadLibraryA(line)) - { - MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType); - } - } - - HeapFree(GetProcessHeap(), 0, fileStr); - return TRUE; -} \ No newline at end of file diff --git a/VersionShim/pch.c b/VersionShim/pch.c deleted file mode 100644 index 4c048fe..0000000 --- a/VersionShim/pch.c +++ /dev/null @@ -1,3 +0,0 @@ -// pch.c: source file corresponding to the pre-compiled header -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. -#include "pch.h" \ No newline at end of file diff --git a/VersionShim/pch.h b/VersionShim/pch.h deleted file mode 100644 index 5aa60e2..0000000 --- a/VersionShim/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include \ No newline at end of file diff --git a/VersionShim/util.h b/VersionShim/util.h deleted file mode 100644 index 58c527f..0000000 --- a/VersionShim/util.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST; - -BOOL OpenReadFileUtf8(LPCSTR lpFileName, LPSTR* fileBuffer, LPDWORD fileLength); -BOOL StrEndsWith(LPSTR str, LPSTR target); -LPSTR SkipBomUtf8(LPSTR str); -INT TerminateLine(LPSTR str); \ No newline at end of file diff --git a/VersionShim/VersionShim.vcxproj b/src/VersionShim.vcxproj similarity index 72% rename from VersionShim/VersionShim.vcxproj rename to src/VersionShim.vcxproj index 3648205..2063ab4 100644 --- a/VersionShim/VersionShim.vcxproj +++ b/src/VersionShim.vcxproj @@ -39,18 +39,27 @@ + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + false + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + false + Level3 true _DEBUG;VERSIONSHIM_EXPORTS;_WINDOWS;_USRDLL;PROJECT_NAME="$(ProjectName)";%(PreprocessorDefinitions) true - Create - pch.h + NotUsing Windows true + DllMain + true @@ -58,27 +67,32 @@ Level3 true true - true + false NDEBUG;VERSIONSHIM_EXPORTS;_WINDOWS;_USRDLL;PROJECT_NAME="$(ProjectName)";%(PreprocessorDefinitions) true - Create - pch.h + NotUsing + MinSpace + Size + false + true Windows true true - true + false + DllMain + true + /EMITPOGOPHASEINFO %(AdditionalOptions) + UseLinkTimeCodeGeneration - + - - \ No newline at end of file diff --git a/VersionShim/VersionShim.vcxproj.filters b/src/VersionShim.vcxproj.filters similarity index 82% rename from VersionShim/VersionShim.vcxproj.filters rename to src/VersionShim.vcxproj.filters index 0db1bb8..12f962e 100644 --- a/VersionShim/VersionShim.vcxproj.filters +++ b/src/VersionShim.vcxproj.filters @@ -15,10 +15,10 @@ - + Header Files - + Header Files @@ -26,11 +26,5 @@ Source Files - - Source Files - - - Source Files - \ No newline at end of file diff --git a/src/dllmain.c b/src/dllmain.c new file mode 100644 index 0000000..cbc8dc9 --- /dev/null +++ b/src/dllmain.c @@ -0,0 +1,67 @@ +// Copyright © 2023 Xpl0itR +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// ReSharper disable once CppUnusedIncludeDirective +#include "exports.h" +#include "util.h" + +BOOL APIENTRY DllMain(CONST HMODULE hModule, CONST DWORD fdwReason, CONST LPVOID lpvReserved) +{ + if (fdwReason != DLL_PROCESS_ATTACH) + return TRUE; + + LPSTR fileStr = NULL; + DWORD fileLen = 0; + + if (!OpenReadFileUtf8("libraries.txt", &fileStr, &fileLen)) + { + MessageBoxA(NULL, "Failed to read libraries.txt", PROJECT_NAME, ErrBoxType); + return TRUE; + } + + LPSTR callerPath[MAX_PATH + 1]; + if (!GetModuleFileNameA(NULL, callerPath, MAX_PATH + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types) + { + MessageBoxA(NULL, "Failed to read caller path", PROJECT_NAME, ErrBoxType); + return TRUE; + } + + int read, hasTarget = FALSE, targetMatched = FALSE; + for (LPSTR line = SkipBomUtf8(fileStr), fileEnd = fileStr + fileLen; line < fileEnd; line += read) + { + read = TerminateLine(line); + + if (*line == '#') + continue; + + if (*line == '*') + { + if (!targetMatched) + { + hasTarget = TRUE; + + if (StrEndsWith(callerPath, line + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types) + { + targetMatched = TRUE; + } + } + + continue; + } + + if (hasTarget && !targetMatched) + return TRUE; + + // ReSharper disable once CppPointerToIntegralConversion + if (!LoadLibraryA(line)) + { + MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType); + } + } + + HeapFree(GetProcessHeap(), 0, fileStr); + return TRUE; +} \ No newline at end of file diff --git a/src/exports.h b/src/exports.h new file mode 100644 index 0000000..3491224 --- /dev/null +++ b/src/exports.h @@ -0,0 +1,109 @@ +// Copyright © 2024 Xpl0itR +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once +#define FORWARD(dll, method) __pragma(comment(linker, "/EXPORT:"method"=c:\\windows\\system32\\"dll"."method)) + +FORWARD("version", "GetFileVersionInfoA") +FORWARD("version", "GetFileVersionInfoByHandle") +FORWARD("version", "GetFileVersionInfoExA") +FORWARD("version", "GetFileVersionInfoExW") +FORWARD("version", "GetFileVersionInfoSizeA") +FORWARD("version", "GetFileVersionInfoSizeExA") +FORWARD("version", "GetFileVersionInfoSizeExW") +FORWARD("version", "GetFileVersionInfoSizeW") +FORWARD("version", "GetFileVersionInfoW") +FORWARD("version", "VerFindFileA") +FORWARD("version", "VerFindFileW") +FORWARD("version", "VerInstallFileA") +FORWARD("version", "VerInstallFileW") +FORWARD("version", "VerLanguageNameA") +FORWARD("version", "VerLanguageNameW") +FORWARD("version", "VerQueryValueA") +FORWARD("version", "VerQueryValueW") + +FORWARD("winhttp", "DllCanUnloadNow") +FORWARD("winhttp", "DllGetClassObject") +FORWARD("winhttp", "Private1") +FORWARD("winhttp", "SvchostPushServiceGlobals") +FORWARD("winhttp", "WinHttpAddRequestHeaders") +FORWARD("winhttp", "WinHttpAddRequestHeadersEx") +FORWARD("winhttp", "WinHttpAutoProxySvcMain") +FORWARD("winhttp", "WinHttpCheckPlatform") +FORWARD("winhttp", "WinHttpCloseHandle") +FORWARD("winhttp", "WinHttpConnect") +FORWARD("winhttp", "WinHttpConnectionDeletePolicyEntries") +FORWARD("winhttp", "WinHttpConnectionDeleteProxyInfo") +FORWARD("winhttp", "WinHttpConnectionFreeNameList") +FORWARD("winhttp", "WinHttpConnectionFreeProxyInfo") +FORWARD("winhttp", "WinHttpConnectionFreeProxyList") +FORWARD("winhttp", "WinHttpConnectionGetNameList") +FORWARD("winhttp", "WinHttpConnectionGetProxyInfo") +FORWARD("winhttp", "WinHttpConnectionGetProxyList") +FORWARD("winhttp", "WinHttpConnectionOnlyConvert") +FORWARD("winhttp", "WinHttpConnectionOnlyReceive") +FORWARD("winhttp", "WinHttpConnectionOnlySend") +FORWARD("winhttp", "WinHttpConnectionSetPolicyEntries") +FORWARD("winhttp", "WinHttpConnectionSetProxyInfo") +FORWARD("winhttp", "WinHttpConnectionUpdateIfIndexTable") +FORWARD("winhttp", "WinHttpCrackUrl") +FORWARD("winhttp", "WinHttpCreateProxyResolver") +FORWARD("winhttp", "WinHttpCreateUrl") +FORWARD("winhttp", "WinHttpDetectAutoProxyConfigUrl") +FORWARD("winhttp", "WinHttpFreeProxyResult") +FORWARD("winhttp", "WinHttpFreeProxyResultEx") +FORWARD("winhttp", "WinHttpFreeProxySettings") +FORWARD("winhttp", "WinHttpFreeProxySettingsEx") +FORWARD("winhttp", "WinHttpFreeQueryConnectionGroupResult") +FORWARD("winhttp", "WinHttpGetDefaultProxyConfiguration") +FORWARD("winhttp", "WinHttpGetIEProxyConfigForCurrentUser") +FORWARD("winhttp", "WinHttpGetProxyForUrl") +FORWARD("winhttp", "WinHttpGetProxyForUrlEx") +FORWARD("winhttp", "WinHttpGetProxyForUrlEx2") +FORWARD("winhttp", "WinHttpGetProxyForUrlHvsi") +FORWARD("winhttp", "WinHttpGetProxyResult") +FORWARD("winhttp", "WinHttpGetProxyResultEx") +FORWARD("winhttp", "WinHttpGetProxySettingsEx") +FORWARD("winhttp", "WinHttpGetProxySettingsResultEx") +FORWARD("winhttp", "WinHttpGetProxySettingsVersion") +FORWARD("winhttp", "WinHttpGetTunnelSocket") +FORWARD("winhttp", "WinHttpOpen") +FORWARD("winhttp", "WinHttpOpenRequest") +FORWARD("winhttp", "WinHttpPacJsWorkerMain") +FORWARD("winhttp", "WinHttpProbeConnectivity") +FORWARD("winhttp", "WinHttpQueryAuthSchemes") +FORWARD("winhttp", "WinHttpQueryConnectionGroup") +FORWARD("winhttp", "WinHttpQueryDataAvailable") +FORWARD("winhttp", "WinHttpQueryHeaders") +FORWARD("winhttp", "WinHttpQueryHeadersEx") +FORWARD("winhttp", "WinHttpQueryOption") +FORWARD("winhttp", "WinHttpReadData") +FORWARD("winhttp", "WinHttpReadDataEx") +FORWARD("winhttp", "WinHttpReadProxySettings") +FORWARD("winhttp", "WinHttpReadProxySettingsHvsi") +FORWARD("winhttp", "WinHttpReceiveResponse") +FORWARD("winhttp", "WinHttpRegisterProxyChangeNotification") +FORWARD("winhttp", "WinHttpResetAutoProxy") +FORWARD("winhttp", "WinHttpSaveProxyCredentials") +FORWARD("winhttp", "WinHttpSendRequest") +FORWARD("winhttp", "WinHttpSetCredentials") +FORWARD("winhttp", "WinHttpSetDefaultProxyConfiguration") +FORWARD("winhttp", "WinHttpSetOption") +FORWARD("winhttp", "WinHttpSetProxySettingsPerUser") +FORWARD("winhttp", "WinHttpSetSecureLegacyServersAppCompat") +FORWARD("winhttp", "WinHttpSetStatusCallback") +FORWARD("winhttp", "WinHttpSetTimeouts") +FORWARD("winhttp", "WinHttpTimeFromSystemTime") +FORWARD("winhttp", "WinHttpTimeToSystemTime") +FORWARD("winhttp", "WinHttpUnregisterProxyChangeNotification") +FORWARD("winhttp", "WinHttpWebSocketClose") +FORWARD("winhttp", "WinHttpWebSocketCompleteUpgrade") +FORWARD("winhttp", "WinHttpWebSocketQueryCloseStatus") +FORWARD("winhttp", "WinHttpWebSocketReceive") +FORWARD("winhttp", "WinHttpWebSocketSend") +FORWARD("winhttp", "WinHttpWebSocketShutdown") +FORWARD("winhttp", "WinHttpWriteData") +FORWARD("winhttp", "WinHttpWriteProxySettings") \ No newline at end of file diff --git a/VersionShim/util.c b/src/util.h similarity index 69% rename from VersionShim/util.c rename to src/util.h index aab6d5c..6b1d816 100644 --- a/VersionShim/util.c +++ b/src/util.h @@ -1,12 +1,17 @@ -// Copyright © 2023 Xpl0itR +// Copyright © 2023 Xpl0itR // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include "pch.h" +#pragma once -static BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle) +#define WIN32_LEAN_AND_MEAN +#include + +UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST; + +inline BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle) { OFSTRUCT ofStruct; HFILE hFile = OpenFile(lpFileName, &ofStruct, OF_READ | OF_PROMPT); @@ -15,13 +20,14 @@ static BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle) return hFile != HFILE_ERROR; } -static BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWORD fileLength) +inline BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWORD fileLength) { DWORD fileLen = GetFileSize(fileHandle, NULL); *fileLength = fileLen; HANDLE heap = GetProcessHeap(); LPSTR buffer = HeapAlloc(heap, 0, fileLen + 1); + // ReSharper disable once CppPointerToIntegralConversion if (!buffer) return FALSE; @@ -37,7 +43,7 @@ static BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWO return TRUE; } -BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength) +inline BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength) { HANDLE hFile = NULL; if (!OpenFileRead(lpFileName, &hFile)) @@ -49,7 +55,7 @@ BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD return success; } -BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target) +inline BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target) { DWORD strLen = lstrlenA(str), targetLen = lstrlenA(target); @@ -59,11 +65,11 @@ BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target) return lstrcmpA(str + strLen - targetLen, target) == 0; } -LPSTR SkipBomUtf8(CONST LPSTR str) +inline LPSTR SkipBomUtf8(CONST LPSTR str) { if (str[0] == (char)0xEF - && str[1] == (char)0xBB - && str[2] == (char)0xBF) + && str[1] == (char)0xBB + && str[2] == (char)0xBF) { return str + 3; } @@ -71,7 +77,7 @@ LPSTR SkipBomUtf8(CONST LPSTR str) return str; } -INT TerminateLine(CONST LPSTR str) +inline INT TerminateLine(CONST LPSTR str) { for (INT i = 0;; i++) {