diff --git a/README.md b/README.md index 5e3f98a..6ebcb83 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,15 @@ A Dynamic-Link Library which exports the same methods as version.dll (winver.h) Usage ----- -Rename VersionShim.dll to `version.dll` and place it in the target application'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. Lines beginning with `#` will be skipped. +Rename VersionShim.dll to `version.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. -Libraries.txt *MUST* use CRLF line endings and be encoded in UTF-8 with *no* BOM. +You can optionally select the target process(es) by listing its path or filename, each on a new line preceded by `*`. These must come before the library paths. + +Lines beginning with `#` will be skipped. + +libraries.txt *MUST* be encoded in UTF-8. License ------- diff --git a/VersionShim/dllmain.c b/VersionShim/dllmain.c index 08782f8..33cb002 100644 --- a/VersionShim/dllmain.c +++ b/VersionShim/dllmain.c @@ -1,4 +1,4 @@ -// 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 @@ -7,48 +7,73 @@ #include "pch.h" #include "util.h" -#pragma region Forward functions to version.dll -#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=C:\\Windows\\System32\\version.GetFileVersionInfoA,@1") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=C:\\Windows\\System32\\version.GetFileVersionInfoByHandle,@2") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=C:\\Windows\\System32\\version.GetFileVersionInfoExA,@3") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=C:\\Windows\\System32\\version.GetFileVersionInfoExW,@4") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeA,@5") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExA,@6") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExW,@7") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeW,@8") -#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=C:\\Windows\\System32\\version.GetFileVersionInfoW,@9") -#pragma comment(linker, "/EXPORT:VerFindFileA=C:\\Windows\\System32\\version.VerFindFileA,@10") -#pragma comment(linker, "/EXPORT:VerFindFileW=C:\\Windows\\System32\\version.VerFindFileW,@11") -#pragma comment(linker, "/EXPORT:VerInstallFileA=C:\\Windows\\System32\\version.VerInstallFileA,@12") -#pragma comment(linker, "/EXPORT:VerInstallFileW=C:\\Windows\\System32\\version.VerInstallFileW,@13") -#pragma comment(linker, "/EXPORT:VerLanguageNameA=C:\\Windows\\System32\\version.VerLanguageNameA,@14") -#pragma comment(linker, "/EXPORT:VerLanguageNameW=C:\\Windows\\System32\\version.VerLanguageNameW,@15") -#pragma comment(linker, "/EXPORT:VerQueryValueA=C:\\Windows\\System32\\version.VerQueryValueA,@16") -#pragma comment(linker, "/EXPORT:VerQueryValueW=C:\\Windows\\System32\\version.VerQueryValueW,@17") +#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, LPCVOID lpReserved) +BOOL APIENTRY DllMain(CONST HMODULE hModule, CONST DWORD fdwReason, CONST LPVOID lpvReserved) { if (fdwReason != DLL_PROCESS_ATTACH) return TRUE; - LPCH fileStr = NULL; + LPSTR fileStr = NULL; DWORD fileLen = 0; - if (!OpenReadFileUtf8("Libraries.txt", &fileStr, &fileLen)) + if (!OpenReadFileUtf8("libraries.txt", &fileStr, &fileLen)) { - MessageBoxA(NULL, "Failed to read Libraries.txt", PROJECT_NAME, ErrBoxType); + MessageBoxA(NULL, "Failed to read libraries.txt", PROJECT_NAME, ErrBoxType); return TRUE; } - int charsInLine; - for (LPCH line = fileStr, fileEnd = fileStr + fileLen; line < fileEnd; line += charsInLine + 2) + LPSTR callerPath[MAX_PATH + 1]; + if (!GetModuleFileNameA(NULL, callerPath, MAX_PATH + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types) { - charsInLine = TerminateLineCrlf(line); + 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); diff --git a/VersionShim/util.c b/VersionShim/util.c index c0bbe93..aab6d5c 100644 --- a/VersionShim/util.c +++ b/VersionShim/util.c @@ -6,22 +6,22 @@ #include "pch.h" -BOOL OpenFileRead(const LPCSTR lpFileName, HANDLE* fileHandle) +static BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle) { - OFSTRUCT ofStruct = { 0 }; + OFSTRUCT ofStruct; HFILE hFile = OpenFile(lpFileName, &ofStruct, OF_READ | OF_PROMPT); - *fileHandle = (HANDLE)(INT_PTR)hFile; + *fileHandle = (HANDLE)(INT_PTR)hFile; // NOLINT(performance-no-int-to-ptr) return hFile != HFILE_ERROR; } -BOOL ReadFileUtf8(const HANDLE fileHandle, LPCH* fileString, DWORD* fileLength) +static BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWORD fileLength) { DWORD fileLen = GetFileSize(fileHandle, NULL); *fileLength = fileLen; HANDLE heap = GetProcessHeap(); - LPCH buffer = HeapAlloc(heap, 0, fileLen + 1); + LPSTR buffer = HeapAlloc(heap, 0, fileLen + 1); if (!buffer) return FALSE; @@ -37,7 +37,7 @@ BOOL ReadFileUtf8(const HANDLE fileHandle, LPCH* fileString, DWORD* fileLength) return TRUE; } -BOOL OpenReadFileUtf8(const LPCSTR lpFileName, LPCH* fileString, DWORD* fileLength) +BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength) { HANDLE hFile = NULL; if (!OpenFileRead(lpFileName, &hFile)) @@ -49,19 +49,45 @@ BOOL OpenReadFileUtf8(const LPCSTR lpFileName, LPCH* fileString, DWORD* fileLeng return success; } -INT TerminateLineCrlf(const LPCH fileString) +BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target) { - for (INT i = 0; ; i++) - { - if (fileString[i] == '\r' && - fileString[i + 1] == '\n') - { - fileString[i] = fileString[i + 1] = '\0'; - } + DWORD strLen = lstrlenA(str), targetLen = lstrlenA(target); - if (fileString[i] == '\0') + if (strLen < targetLen) + return FALSE; + + return lstrcmpA(str + strLen - targetLen, target) == 0; +} + +LPSTR SkipBomUtf8(CONST LPSTR str) +{ + if (str[0] == (char)0xEF + && str[1] == (char)0xBB + && str[2] == (char)0xBF) + { + return str + 3; + } + + return str; +} + +INT TerminateLine(CONST LPSTR str) +{ + for (INT i = 0;; i++) + { + if (str[i] == '\0') + return i + 1; + + if (str[i] == '\r' || str[i] == '\n') { - return i; + str[i] = '\0'; + + if (str[i + 1] == '\n') + { + str[++i] = '\0'; + } + + return i + 1; } } } \ No newline at end of file diff --git a/VersionShim/util.h b/VersionShim/util.h index d4ec6dd..58c527f 100644 --- a/VersionShim/util.h +++ b/VersionShim/util.h @@ -2,5 +2,7 @@ UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST; -BOOL OpenReadFileUtf8(LPCSTR lpFileName, LPCH* fileBuffer, DWORD* fileLength); -INT TerminateLineCrlf(LPCH fileString); \ No newline at end of file +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