mirror of
https://github.com/kurikomoe/L4D2Fix.git
synced 2026-10-10 04:43:07 +08:00
fix(*):
switch to exe loader method to make sure the dll is properly injected
This commit is contained in:
+10
@@ -85,3 +85,13 @@ _deps
|
|||||||
*.app
|
*.app
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/c++
|
# End of https://www.toptal.com/developers/gitignore/api/c++
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/xmake
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=xmake
|
||||||
|
|
||||||
|
### xmake ###
|
||||||
|
# Xmake cache
|
||||||
|
.xmake/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/xmake
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.25.0)
|
|
||||||
|
|
||||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "")
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|
||||||
|
|
||||||
include(AutoCCache)
|
|
||||||
|
|
||||||
project(KProject)
|
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
||||||
|
|
||||||
find_package(minhook CONFIG REQUIRED)
|
|
||||||
find_package(spdlog CONFIG REQUIRED)
|
|
||||||
|
|
||||||
set(TARGET "kpatch")
|
|
||||||
set(TARGET_SRC src/dllmain.cpp)
|
|
||||||
set(TARGET_OUTPUT_NAME "kpatch")
|
|
||||||
add_library(${TARGET} SHARED ${TARGET_SRC})
|
|
||||||
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET_OUTPUT_NAME})
|
|
||||||
target_include_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
|
||||||
target_link_libraries(${TARGET} PRIVATE spdlog::spdlog_header_only)
|
|
||||||
# target_link_libraries(${TARGET} PUBLIC minhook::minhook)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------ post build ------------
|
|
||||||
# copy compile_commands.json for clangd
|
|
||||||
if(EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json")
|
|
||||||
file(COPY "${CMAKE_BINARY_DIR}/compile_commands.json" DESTINATION "${CMAKE_SOURCE_DIR}")
|
|
||||||
endif()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 6,
|
|
||||||
"cmakeMinimumRequired": {
|
|
||||||
"major": 3,
|
|
||||||
"minor": 25,
|
|
||||||
"patch": 0
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"cmake/presets/linux.json",
|
|
||||||
"cmake/presets/windows.json"
|
|
||||||
],
|
|
||||||
"configurePresets": [ ],
|
|
||||||
"buildPresets": [ ],
|
|
||||||
"testPresets": [ ]
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 303 KiB |
@@ -0,0 +1 @@
|
|||||||
|
IDI_APP_ICON ICON "app.ico"
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# From https://gist.github.com/cgmb/c48bfa77da6c825a27bf05d25001d321
|
|
||||||
|
|
||||||
option(AUTO_CCACHE "Use ccache to speed up rebuilds" ON)
|
|
||||||
find_program(CCACHE_PROGRAM ccache)
|
|
||||||
if(CCACHE_PROGRAM AND ${AUTO_CCACHE})
|
|
||||||
message(STATUS "Using ${CCACHE_PROGRAM} as compiler launcher")
|
|
||||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
|
|
||||||
# requires at least CMake 3.9 to be any use
|
|
||||||
set(CMAKE_CUDA_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
|
|
||||||
endif()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 6,
|
|
||||||
"configurePresets": [
|
|
||||||
{
|
|
||||||
"name": "config-base",
|
|
||||||
"displayName": "base Configuration",
|
|
||||||
"hidden": true,
|
|
||||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/install/${presetName}",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 6,
|
|
||||||
"include": [ "base.json" ],
|
|
||||||
"configurePresets": [
|
|
||||||
{
|
|
||||||
"name": "config-base-linux",
|
|
||||||
"displayName": "base Configuration for linux",
|
|
||||||
"inherits": "config-base",
|
|
||||||
"hidden": true,
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Linux"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-debug",
|
|
||||||
"inherits": "config-base-linux",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"architecture":{
|
|
||||||
"value": "x64",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Debug"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-release",
|
|
||||||
"inherits": "x64-debug",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Release"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-debug",
|
|
||||||
"inherits": "config-base-linux",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"architecture":{
|
|
||||||
"value": "x86",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Debug",
|
|
||||||
"CMAKE_C_FLAGS": "-m32",
|
|
||||||
"CMAKE_CXX_FLAGS": "-m32",
|
|
||||||
"CMAKE_SYSTEM_PROCESSOR": "x86"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-release",
|
|
||||||
"inherits": "x86-debug",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Release"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildPresets": [
|
|
||||||
{
|
|
||||||
"name": "x64-debug",
|
|
||||||
"configurePreset": "x64-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-release",
|
|
||||||
"configurePreset": "x64-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-debug",
|
|
||||||
"configurePreset": "x86-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-release",
|
|
||||||
"configurePreset": "x86-release"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"testPresets": [ ]
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 6,
|
|
||||||
"include": ["base.json"],
|
|
||||||
"configurePresets": [
|
|
||||||
{
|
|
||||||
"name": "config-base-windows",
|
|
||||||
"displayName": "base Configuration for windows",
|
|
||||||
"inherits": "config-base",
|
|
||||||
"hidden": true,
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Windows"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-debug-msvc",
|
|
||||||
"inherits": "config-base-windows",
|
|
||||||
"generator": "",
|
|
||||||
"architecture":{
|
|
||||||
"value": "x64",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Debug",
|
|
||||||
"CMAKE_GENERATOR_PLATFORM": "x64"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-release-msvc",
|
|
||||||
"inherits": "x64-debug-msvc",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Release"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-debug-msvc",
|
|
||||||
"inherits": "config-base-windows",
|
|
||||||
"generator": "",
|
|
||||||
"architecture":{
|
|
||||||
"value": "x86",
|
|
||||||
"strategy": "external"
|
|
||||||
},
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Debug",
|
|
||||||
"CMAKE_GENERATOR_PLATFORM": "Win32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-release-msvc",
|
|
||||||
"inherits": "x86-debug-msvc",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE" : "Release"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildPresets": [
|
|
||||||
{
|
|
||||||
"name": "x64-debug-msvc",
|
|
||||||
"configurePreset": "x64-debug-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x64-release-msvc",
|
|
||||||
"configurePreset": "x64-release-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-debug-msvc",
|
|
||||||
"configurePreset": "x86-debug-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-release-msvc",
|
|
||||||
"configurePreset": "x86-release-msvc"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"testPresets": [ ]
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
TEMPLATE_VER := "v1.0.0"
|
TEMPLATE_VER := "v1.0.0"
|
||||||
TARGET := "F:/Games/SteamLibrary/steamapps/common/Left 4 Dead 2"
|
TARGET := "D:\\Games\\GamePlatforms\\SteamLibrary\\steamapps\\common\\Left 4 Dead 2"
|
||||||
|
|
||||||
# use `just preset=x64-release config build` to override this
|
# use `just preset=x64-release config build` to override this
|
||||||
preset := "x86-release-msvc"
|
preset := "x86-release-msvc"
|
||||||
@@ -12,17 +12,24 @@ init:
|
|||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
||||||
config:
|
# config:
|
||||||
cmake --preset {{preset}}
|
# # cmake --preset {{preset}} -DBUILD_SHARED_LIBS=OFF
|
||||||
|
# xmake
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cmake --build --preset {{preset}} --config Release
|
# cmake --build --preset {{preset}} --config Release
|
||||||
|
xmake
|
||||||
|
|
||||||
copy: build
|
copy: build
|
||||||
cd ./build/x86-release-msvc/bin/Release && \
|
# cd ./build/x86-release-msvc/bin/Release && \
|
||||||
cp -f kpatch.dll "{{TARGET}}/kpatch.asi" && \
|
# cp -f kpatch.dll "{{TARGET}}/kpatch.asi" && \
|
||||||
cp -f fmt.dll "{{TARGET}}/"
|
# cp -f fmt.dll "{{TARGET}}/"
|
||||||
cp -f third/version.dll "{{TARGET}}/"
|
# cp -f third/version.dll "{{TARGET}}/"
|
||||||
|
|
||||||
|
# cp build/windows/x86/release/version.dll "{{TARGET}}"
|
||||||
|
|
||||||
|
cp build/windows/x86/release/kpatch.dll "{{TARGET}}"
|
||||||
|
cp build/windows/x86/release/left4dead2_fix.exe "{{TARGET}}"
|
||||||
|
|
||||||
@run:
|
@run:
|
||||||
./build/{{preset}}/bin/{{target}}
|
./build/{{preset}}/bin/{{target}}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//#pragma comment(linker, "/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")
|
||||||
|
#include <windows.h>
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
#include <detours/detours.h>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
const wchar_t* game_name = L"left4dead2.exe";
|
||||||
|
|
||||||
|
int WINAPI wWinMain(
|
||||||
|
_In_ HINSTANCE hInstance,
|
||||||
|
_In_opt_ HINSTANCE hPrevInstance,
|
||||||
|
_In_ LPWSTR lpwCmdLine,
|
||||||
|
_In_ int nShowCmd
|
||||||
|
) {
|
||||||
|
WCHAR working_path[MAX_PATH];
|
||||||
|
GetModuleFileNameW(nullptr, working_path, MAX_PATH);
|
||||||
|
|
||||||
|
// Change the working directory to the directory containing the DLL.
|
||||||
|
fs::path path(working_path);
|
||||||
|
SetCurrentDirectoryW(path.parent_path().wstring().c_str());
|
||||||
|
|
||||||
|
LPCSTR dll_path = "kpatch.dll";
|
||||||
|
|
||||||
|
LPCWSTR target_exe_path = game_name;
|
||||||
|
|
||||||
|
// if (std::filesystem::exists(L"left4dead2.exe.orig")) {
|
||||||
|
// target_exe_path = L"left4dead2.exe.orig";
|
||||||
|
// } else {
|
||||||
|
// target_exe_path = game_name;
|
||||||
|
// }
|
||||||
|
|
||||||
|
STARTUPINFOW si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
ZeroMemory(&si, sizeof(si));
|
||||||
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
|
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
|
DWORD dwFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED;
|
||||||
|
|
||||||
|
SetLastError(0);
|
||||||
|
if (TRUE != DetourCreateProcessWithDllExW(
|
||||||
|
target_exe_path,
|
||||||
|
lpwCmdLine,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
TRUE,
|
||||||
|
dwFlags,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&si,
|
||||||
|
&pi,
|
||||||
|
dll_path,
|
||||||
|
nullptr)) {
|
||||||
|
auto dwError = GetLastError();
|
||||||
|
printf("DetourCreateProcessWithDllEx failed with error %ld\n", dwError);
|
||||||
|
|
||||||
|
ExitProcess(9009);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResumeThread(pi.hThread);
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
git clone https://github.com/microsoft/vcpkg.git --depth 1
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
|
||||||
|
|
||||||
./vcpkg/vcpkg new --application
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!nu
|
|
||||||
|
|
||||||
echo "init vcpkg"
|
|
||||||
git clone https://github.com/microsoft/vcpkg.git --depth 1
|
|
||||||
./vcpkg/bootstrap-vcpkg.bat
|
|
||||||
|
|
||||||
./vcpkg/vcpkg new --application
|
|
||||||
|
|
||||||
echo "Retarget from linux preset `x64-debug` to windows preset `x64-debug-msvc`"
|
|
||||||
open justfile | str replace r#'"x64-debug"'# r#'"x64-debug-msvc"'# | save justfile -f
|
|
||||||
+103
-29
@@ -2,11 +2,22 @@
|
|||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <spdlog/sinks/basic_file_sink.h>
|
#include <spdlog/sinks/basic_file_sink.h>
|
||||||
|
|
||||||
#include <cctype>
|
#include <windows.h>
|
||||||
|
#include <libloaderapi.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iostream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <detours/detours.h>
|
||||||
|
|
||||||
#include "helper.hpp"
|
#include "helper.hpp"
|
||||||
|
|
||||||
|
constexpr bool isDebug = true;
|
||||||
|
constexpr bool isTesting = true;
|
||||||
|
|
||||||
HMODULE baseModule = GetModuleHandle(NULL);
|
HMODULE baseModule = GetModuleHandle(NULL);
|
||||||
HMODULE thisModule; // Fix DLL
|
HMODULE thisModule; // Fix DLL
|
||||||
|
|
||||||
@@ -21,7 +32,16 @@ std::filesystem::path sExePath;
|
|||||||
std::string sExeName;
|
std::string sExeName;
|
||||||
std::filesystem::path sThisModulePath;
|
std::filesystem::path sThisModulePath;
|
||||||
|
|
||||||
|
void InitConsole() {
|
||||||
|
AllocConsole();
|
||||||
|
FILE *dummy;
|
||||||
|
freopen_s(&dummy, "CONOUT$", "w", stdout);
|
||||||
|
}
|
||||||
|
|
||||||
void Logging() {
|
void Logging() {
|
||||||
|
if constexpr (isDebug) {
|
||||||
|
InitConsole();
|
||||||
|
}
|
||||||
// Get this module path
|
// Get this module path
|
||||||
WCHAR thisModulePath[_MAX_PATH] = { 0 };
|
WCHAR thisModulePath[_MAX_PATH] = { 0 };
|
||||||
GetModuleFileNameW(thisModule, thisModulePath, MAX_PATH);
|
GetModuleFileNameW(thisModule, thisModulePath, MAX_PATH);
|
||||||
@@ -57,18 +77,18 @@ void Logging() {
|
|||||||
spdlog::info("Module Timestamp: {0:d}", Memory::ModuleTimestamp(baseModule));
|
spdlog::info("Module Timestamp: {0:d}", Memory::ModuleTimestamp(baseModule));
|
||||||
spdlog::info("----------");
|
spdlog::info("----------");
|
||||||
} catch (const spdlog::spdlog_ex &ex) {
|
} catch (const spdlog::spdlog_ex &ex) {
|
||||||
AllocConsole();
|
InitConsole();
|
||||||
FILE *dummy;
|
|
||||||
freopen_s(&dummy, "CONOUT$", "w", stdout);
|
|
||||||
std::cout << "Log initialisation failed: " << ex.what() << std::endl;
|
|
||||||
FreeLibraryAndExitThread(baseModule, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD __stdcall Main(void*) {
|
DWORD __stdcall Main(void*) {
|
||||||
Logging();
|
Logging();
|
||||||
|
|
||||||
|
if constexpr (isTesting) {
|
||||||
|
MessageBoxW(NULL, L"警告:这是测试版补丁,设定为必定会炸,用于检测补丁是否正确应用。", L"L4D2 Fix", MB_OK|MB_SYSTEMMODAL|MB_ICONWARNING);
|
||||||
|
}
|
||||||
|
|
||||||
std::filesystem::path startup_check = L"success.txt";
|
std::filesystem::path startup_check = L"success.txt";
|
||||||
// MessageBoxW(NULL, L"警告:这是测试版补丁,设定为必定会炸,用于检测补丁是否正确应用。", L"L4D2 Fix", MB_OK|MB_SYSTEMMODAL|MB_ICONWARNING);
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(startup_check)) {
|
if (!std::filesystem::exists(startup_check)) {
|
||||||
MessageBoxW(
|
MessageBoxW(
|
||||||
@@ -80,31 +100,51 @@ DWORD __stdcall Main(void*) {
|
|||||||
std::wstring cmdline = GetCommandLineW();
|
std::wstring cmdline = GetCommandLineW();
|
||||||
spdlog::info(L"Startup commandline: {}", cmdline.c_str());
|
spdlog::info(L"Startup commandline: {}", cmdline.c_str());
|
||||||
|
|
||||||
std::wstring dllName;
|
std::wstring dllName = L"shaderapidx9.dll";
|
||||||
std::transform(cmdline.cbegin(), cmdline.cend(), cmdline.begin(), ::tolower);
|
bool isVulkan = false;
|
||||||
|
|
||||||
|
std::transform(cmdline.cbegin(), cmdline.cend(), cmdline.begin(), ::tolower);
|
||||||
if (cmdline.find(L"-vulkan") != std::wstring::npos) {
|
if (cmdline.find(L"-vulkan") != std::wstring::npos) {
|
||||||
dllName = L"shaderapivk.dll";
|
dllName = L"shaderapivk.dll";
|
||||||
spdlog::info(L"Detected Vulkan: using {}", dllName);
|
spdlog::info(L"Detected Vulkan: using {}", dllName);
|
||||||
|
isVulkan = true;
|
||||||
} else {
|
} else {
|
||||||
dllName = L"shaderapidx9.dll";
|
spdlog::info(L"Detected DirectX9: using {}", dllName);
|
||||||
}
|
}
|
||||||
auto hDll = LoadLibraryW(dllName.c_str());
|
|
||||||
|
auto relPath = std::filesystem::path(L"bin") / dllName;
|
||||||
|
auto absPath = std::filesystem::absolute(relPath);
|
||||||
|
|
||||||
|
std::wcout << absPath << std::endl;
|
||||||
|
spdlog::info(L"Loading Dll fromg {}", absPath.wstring());
|
||||||
|
|
||||||
|
HMODULE hDll = LoadLibraryExW(absPath.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||||
|
|
||||||
if (hDll == nullptr) {
|
if (hDll == nullptr) {
|
||||||
MessageBoxW(NULL, std::format(L"Failed to load {}!", dllName).c_str(), L"L4D2 Fix", MB_OK|MB_SYSTEMMODAL|MB_ICONSTOP);
|
auto errCode = GetLastError();
|
||||||
|
wchar_t buf[255];
|
||||||
|
FormatMessageW(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
|
||||||
|
std::wcout << errCode << std::endl;
|
||||||
|
std::wcout << buf << std::endl;
|
||||||
|
MessageBoxW(NULL, std::format(L"Failed to load {}!", dllName).c_str(), L"L4D2 Fix", MB_OK | MB_SYSTEMMODAL | MB_ICONSTOP);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tag, pattern, start_search_path, write_offset
|
||||||
auto f = [&](const wchar_t* tag, const char* pattern, size_t offset, size_t w_offset) {
|
auto f = [&](const wchar_t* tag, const char* pattern, size_t offset, size_t w_offset) {
|
||||||
std::uint8_t* ptr = Memory::PatternScan(hDll, pattern);
|
std::uint8_t* ptr = Memory::PatternScan(hDll, pattern, offset);
|
||||||
|
|
||||||
constexpr uint32_t new_buffer_size = 0x020000;
|
uint32_t new_buffer_size = 0x020000;
|
||||||
// constexpr uint32_t new_buffer_size = 32;
|
if constexpr (isTesting) {
|
||||||
|
new_buffer_size = 32;
|
||||||
|
}
|
||||||
|
|
||||||
if (ptr != nullptr) {
|
if (ptr != nullptr) {
|
||||||
Memory::Write((uintptr_t)(ptr + w_offset), new_buffer_size);
|
Memory::Write((uintptr_t)(ptr + w_offset), new_buffer_size);
|
||||||
spdlog::info(L"Modified the vertex max buffer {}: {}", dllName, tag);
|
spdlog::info(L"Modified the vertex max buffer {}: {} @ 0x{:0x}", dllName, tag, (intptr_t)(ptr) - (intptr_t)hDll);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,24 +152,58 @@ DWORD __stdcall Main(void*) {
|
|||||||
return (uint8_t*)nullptr;
|
return (uint8_t*)nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CreateEmptyColorMesh
|
|
||||||
auto ptr1 = f(L"CreateEmptyColorMesh", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", 0, 6);
|
|
||||||
|
|
||||||
auto ptr1_1 = f(L"CreateEmptyColorMesh Later", "68 00 80 00 00 50 8B", (size_t)ptr1, 1);
|
std::vector<void*> ptr_cache;
|
||||||
|
std::string pattern;
|
||||||
|
// CreateEmptyColorMesh
|
||||||
|
|
||||||
|
pattern = "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04";
|
||||||
|
auto* ptr1 = f(
|
||||||
|
L"CreateEmptyColorMesh",
|
||||||
|
pattern.c_str(),
|
||||||
|
0,
|
||||||
|
6
|
||||||
|
);
|
||||||
|
ptr_cache.push_back(ptr1);
|
||||||
|
|
||||||
|
pattern = "68 00 80 00 00 50 8B";
|
||||||
|
auto* ptr1_1 = f(
|
||||||
|
L"CreateEmptyColorMesh Later",
|
||||||
|
pattern.c_str(),
|
||||||
|
(size_t)ptr1,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
ptr_cache.push_back(ptr1_1);
|
||||||
|
|
||||||
// CreateVertexIDBuffer
|
// CreateVertexIDBuffer
|
||||||
auto ptr2 = f(L"CreateVertexIDBuffer", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", (size_t)ptr1_1, 6);
|
pattern = "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04";
|
||||||
auto ptr2_1 = f(L"CreateVertexIDBuffer Later", "68 00 80 00 00 50 8B", (size_t)ptr2, 1);
|
auto* ptr2 = f(
|
||||||
|
L"CreateVertexIDBuffer",
|
||||||
|
pattern.c_str(),
|
||||||
|
(size_t)ptr1_1,
|
||||||
|
6
|
||||||
|
);
|
||||||
|
ptr_cache.push_back(ptr2);
|
||||||
|
|
||||||
|
pattern = "68 00 80 00 00 50 8B";
|
||||||
|
auto* ptr2_1 = f(
|
||||||
|
L"CreateVertexIDBuffer Later",
|
||||||
|
pattern.c_str(),
|
||||||
|
(size_t)ptr2,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
ptr_cache.push_back(ptr2_1);
|
||||||
|
|
||||||
|
auto* ptr3 = f(
|
||||||
|
L"Unknown",
|
||||||
|
"0F B6 C0 50 68 00 80 00 00 53 8B CF E8 ?? ?? ?? ??",
|
||||||
|
(size_t)ptr2,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
ptr_cache.push_back(ptr3);
|
||||||
// Not known
|
// Not known
|
||||||
auto ptr3 = f(L"Unknown", "0F B6 C0 50 68 00 80 00 00 53 8B CF E8 ?? ?? ?? ??", (size_t)ptr1, 5);
|
|
||||||
|
|
||||||
if (ptr1 == nullptr
|
if (std::ranges::any_of(ptr_cache, [](void* ptr) { return ptr == nullptr; })) {
|
||||||
|| ptr1_1 == nullptr
|
|
||||||
|| ptr2 == nullptr
|
|
||||||
|| ptr2_1 == nullptr
|
|
||||||
|| ptr3 == nullptr
|
|
||||||
) {
|
|
||||||
MessageBoxW(NULL, L"未能正常应用补丁,patch 未生效,请联系开发者\n这只是一个警告,可能不影响游戏运行", L"L4D2 Fix", MB_OK);
|
MessageBoxW(NULL, L"未能正常应用补丁,patch 未生效,请联系开发者\n这只是一个警告,可能不影响游戏运行", L"L4D2 Fix", MB_OK);
|
||||||
} else {
|
} else {
|
||||||
std::fstream file(startup_check, std::ios::out);
|
std::fstream file(startup_check, std::ios::out);
|
||||||
@@ -150,5 +224,5 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detour needs at least on exported function
|
||||||
void __declspec(dllexport) kuriko_export() {}
|
void __declspec(dllexport) kuriko_export() {}
|
||||||
|
|||||||
+11
-20
@@ -1,4 +1,8 @@
|
|||||||
#include "stdafx.h"
|
#include <cassert>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
@@ -52,7 +56,12 @@ namespace Memory
|
|||||||
auto s = patternBytes.size();
|
auto s = patternBytes.size();
|
||||||
auto d = patternBytes.data();
|
auto d = patternBytes.data();
|
||||||
|
|
||||||
for (auto i = offset; i < sizeOfImage - s; ++i) {
|
auto new_offset = 0;
|
||||||
|
if (offset != 0) {
|
||||||
|
assert((intptr_t)offset > (intptr_t)&scanBytes[0]);
|
||||||
|
new_offset = offset - (intptr_t)&scanBytes[0];
|
||||||
|
}
|
||||||
|
for (auto i = new_offset; i < sizeOfImage - s; ++i) {
|
||||||
bool found = true;
|
bool found = true;
|
||||||
for (auto j = 0ul; j < s; ++j) {
|
for (auto j = 0ul; j < s; ++j) {
|
||||||
if (scanBytes[i + j] != d[j] && d[j] != -1) {
|
if (scanBytes[i + j] != d[j] && d[j] != -1) {
|
||||||
@@ -87,21 +96,3 @@ namespace Memory
|
|||||||
return (address + 4 + *reinterpret_cast<std::int32_t*>(address));
|
return (address + 4 + *reinterpret_cast<std::int32_t*>(address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// namespace Util
|
|
||||||
// {
|
|
||||||
// std::pair<int, int> GetPhysicalDesktopDimensions() {
|
|
||||||
// if (DEVMODE devMode{ .dmSize = sizeof(DEVMODE) }; EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &devMode))
|
|
||||||
// return { devMode.dmPelsWidth, devMode.dmPelsHeight };
|
|
||||||
|
|
||||||
// return {};
|
|
||||||
// }
|
|
||||||
|
|
||||||
// int HexStringToInt(const std::string& hexString) {
|
|
||||||
// int num;
|
|
||||||
// std::stringstream ss;
|
|
||||||
// ss << std::hex << hexString;
|
|
||||||
// ss >> num;
|
|
||||||
// return num;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cassert>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstddef>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"default-registry": {
|
|
||||||
"kind": "git",
|
|
||||||
"baseline": "f523208df4ae467436dc2d2eeab594fed240d552",
|
|
||||||
"repository": "https://github.com/microsoft/vcpkg"
|
|
||||||
},
|
|
||||||
"registries": [
|
|
||||||
{
|
|
||||||
"kind": "artifact",
|
|
||||||
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
|
|
||||||
"name": "microsoft"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": [
|
|
||||||
"spdlog",
|
|
||||||
"minhook"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-- add_requires("microsoft-proxy 2.4.0")
|
||||||
|
add_rules("mode.debug", "mode.release")
|
||||||
|
add_rules("plugin.compile_commands.autoupdate")
|
||||||
|
|
||||||
|
set_languages("cxx20", "c++20")
|
||||||
|
|
||||||
|
set_plat("windows")
|
||||||
|
set_arch("x86") -- Use "x64" for 64-bit builds
|
||||||
|
|
||||||
|
add_requires("spdlog")
|
||||||
|
add_requires("vcpkg::detours")
|
||||||
|
|
||||||
|
-- local name = "version"
|
||||||
|
-- target(name)
|
||||||
|
-- set_kind("shared")
|
||||||
|
-- add_files("src/dllmain.cpp")
|
||||||
|
-- add_packages("spdlog")
|
||||||
|
-- add_links("user32", "gdi32")
|
||||||
|
-- add_linkdirs("$(projectdir)/lib")
|
||||||
|
-- -- add_files(string.format("lib/%s.def", name), string.format("lib/%s.asm", name))
|
||||||
|
-- add_files(string.format("lib/%s.def", name))
|
||||||
|
|
||||||
|
local name = "kpatch"
|
||||||
|
target(name)
|
||||||
|
set_kind("shared")
|
||||||
|
add_files("src/dllmain.cpp")
|
||||||
|
add_packages("spdlog", "vcpkg::detours")
|
||||||
|
add_links("user32", "gdi32")
|
||||||
|
|
||||||
|
local name = "left4dead2_fix"
|
||||||
|
target(name)
|
||||||
|
set_kind("binary")
|
||||||
|
add_files("launcher/main.cpp")
|
||||||
|
add_files("assets/app.rc")
|
||||||
|
add_links("user32", "gdi32")
|
||||||
|
add_packages("vcpkg::detours")
|
||||||
Reference in New Issue
Block a user