optionally select target process(es)
also improve config reading
This commit is contained in:
parent
2935e88ed9
commit
1bca5e9272
12
README.md
12
README.md
|
@ -4,11 +4,15 @@ A Dynamic-Link Library which exports the same methods as version.dll (winver.h)
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
Rename VersionShim.dll to `version.dll` and place it in the target application's search location,
|
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,
|
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.
|
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
|
License
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright © 2023 Xpl0itR
|
// Copyright © 2023 Xpl0itR
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
@ -7,48 +7,73 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#pragma region Forward functions to version.dll
|
#pragma region Forward functions to system version.dll
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=C:\\Windows\\System32\\version.GetFileVersionInfoA,@1")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=c:\\windows\\system32\\version.GetFileVersionInfoA")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=C:\\Windows\\System32\\version.GetFileVersionInfoByHandle,@2")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=c:\\windows\\system32\\version.GetFileVersionInfoByHandle")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=C:\\Windows\\System32\\version.GetFileVersionInfoExA,@3")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=c:\\windows\\system32\\version.GetFileVersionInfoExA")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=C:\\Windows\\System32\\version.GetFileVersionInfoExW,@4")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=c:\\windows\\system32\\version.GetFileVersionInfoExW")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeA,@5")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=c:\\windows\\system32\\version.GetFileVersionInfoSizeA")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExA,@6")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=c:\\windows\\system32\\version.GetFileVersionInfoSizeExA")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExW,@7")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=c:\\windows\\system32\\version.GetFileVersionInfoSizeExW")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeW,@8")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=c:\\windows\\system32\\version.GetFileVersionInfoSizeW")
|
||||||
#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=C:\\Windows\\System32\\version.GetFileVersionInfoW,@9")
|
#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=c:\\windows\\system32\\version.GetFileVersionInfoW")
|
||||||
#pragma comment(linker, "/EXPORT:VerFindFileA=C:\\Windows\\System32\\version.VerFindFileA,@10")
|
#pragma comment(linker, "/EXPORT:VerFindFileA=c:\\windows\\system32\\version.VerFindFileA")
|
||||||
#pragma comment(linker, "/EXPORT:VerFindFileW=C:\\Windows\\System32\\version.VerFindFileW,@11")
|
#pragma comment(linker, "/EXPORT:VerFindFileW=c:\\windows\\system32\\version.VerFindFileW")
|
||||||
#pragma comment(linker, "/EXPORT:VerInstallFileA=C:\\Windows\\System32\\version.VerInstallFileA,@12")
|
#pragma comment(linker, "/EXPORT:VerInstallFileA=c:\\windows\\system32\\version.VerInstallFileA")
|
||||||
#pragma comment(linker, "/EXPORT:VerInstallFileW=C:\\Windows\\System32\\version.VerInstallFileW,@13")
|
#pragma comment(linker, "/EXPORT:VerInstallFileW=c:\\windows\\system32\\version.VerInstallFileW")
|
||||||
#pragma comment(linker, "/EXPORT:VerLanguageNameA=C:\\Windows\\System32\\version.VerLanguageNameA,@14")
|
#pragma comment(linker, "/EXPORT:VerLanguageNameA=c:\\windows\\system32\\version.VerLanguageNameA")
|
||||||
#pragma comment(linker, "/EXPORT:VerLanguageNameW=C:\\Windows\\System32\\version.VerLanguageNameW,@15")
|
#pragma comment(linker, "/EXPORT:VerLanguageNameW=c:\\windows\\system32\\version.VerLanguageNameW")
|
||||||
#pragma comment(linker, "/EXPORT:VerQueryValueA=C:\\Windows\\System32\\version.VerQueryValueA,@16")
|
#pragma comment(linker, "/EXPORT:VerQueryValueA=c:\\windows\\system32\\version.VerQueryValueA")
|
||||||
#pragma comment(linker, "/EXPORT:VerQueryValueW=C:\\Windows\\System32\\version.VerQueryValueW,@17")
|
#pragma comment(linker, "/EXPORT:VerQueryValueW=c:\\windows\\system32\\version.VerQueryValueW")
|
||||||
#pragma endregion
|
#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)
|
if (fdwReason != DLL_PROCESS_ATTACH)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
LPCH fileStr = NULL;
|
LPSTR fileStr = NULL;
|
||||||
DWORD fileLen = 0;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int charsInLine;
|
LPSTR callerPath[MAX_PATH + 1];
|
||||||
for (LPCH line = fileStr, fileEnd = fileStr + fileLen; line < fileEnd; line += charsInLine + 2)
|
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 == '#')
|
if (*line == '#')
|
||||||
continue;
|
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))
|
if (!LoadLibraryA(line))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType);
|
MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType);
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#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);
|
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;
|
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);
|
DWORD fileLen = GetFileSize(fileHandle, NULL);
|
||||||
*fileLength = fileLen;
|
*fileLength = fileLen;
|
||||||
|
|
||||||
HANDLE heap = GetProcessHeap();
|
HANDLE heap = GetProcessHeap();
|
||||||
LPCH buffer = HeapAlloc(heap, 0, fileLen + 1);
|
LPSTR buffer = HeapAlloc(heap, 0, fileLen + 1);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ BOOL ReadFileUtf8(const HANDLE fileHandle, LPCH* fileString, DWORD* fileLength)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL OpenReadFileUtf8(const LPCSTR lpFileName, LPCH* fileString, DWORD* fileLength)
|
BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength)
|
||||||
{
|
{
|
||||||
HANDLE hFile = NULL;
|
HANDLE hFile = NULL;
|
||||||
if (!OpenFileRead(lpFileName, &hFile))
|
if (!OpenFileRead(lpFileName, &hFile))
|
||||||
|
@ -49,19 +49,45 @@ BOOL OpenReadFileUtf8(const LPCSTR lpFileName, LPCH* fileString, DWORD* fileLeng
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
INT TerminateLineCrlf(const LPCH fileString)
|
BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target)
|
||||||
|
{
|
||||||
|
DWORD strLen = lstrlenA(str), targetLen = lstrlenA(target);
|
||||||
|
|
||||||
|
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++)
|
for (INT i = 0;; i++)
|
||||||
{
|
{
|
||||||
if (fileString[i] == '\r' &&
|
if (str[i] == '\0')
|
||||||
fileString[i + 1] == '\n')
|
return i + 1;
|
||||||
|
|
||||||
|
if (str[i] == '\r' || str[i] == '\n')
|
||||||
{
|
{
|
||||||
fileString[i] = fileString[i + 1] = '\0';
|
str[i] = '\0';
|
||||||
|
|
||||||
|
if (str[i + 1] == '\n')
|
||||||
|
{
|
||||||
|
str[++i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileString[i] == '\0')
|
return i + 1;
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,5 +2,7 @@
|
||||||
|
|
||||||
UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST;
|
UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST;
|
||||||
|
|
||||||
BOOL OpenReadFileUtf8(LPCSTR lpFileName, LPCH* fileBuffer, DWORD* fileLength);
|
BOOL OpenReadFileUtf8(LPCSTR lpFileName, LPSTR* fileBuffer, LPDWORD fileLength);
|
||||||
INT TerminateLineCrlf(LPCH fileString);
|
BOOL StrEndsWith(LPSTR str, LPSTR target);
|
||||||
|
LPSTR SkipBomUtf8(LPSTR str);
|
||||||
|
INT TerminateLine(LPSTR str);
|
Loading…
Reference in New Issue