Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Injector redux #89

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 49 additions & 41 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,54 @@
name: Build

on:
push:
branches:
- main
pull_request:
branches:
- main
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:
strategy:
matrix:
game_version: ['official', 'steam']
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: 'recursive'

- name: Download SDK
run: |
$sdk_link = "${{ secrets.SDK_LINK }}"
Invoke-WebRequest -Uri $sdk_link -OutFile sdk.zip
Expand-Archive -Path sdk.zip -DestinationPath CppSDK

- name: Set up MSVC environment
uses: microsoft/setup-msbuild@v2

- uses: lukka/get-cmake@latest

- name: Configure CMake
run: cmake -B build -S . -DBUILD_STEAM_VERSION=${{ matrix.game_version == 'steam' && 'ON' || 'OFF' }}

- name: Build project
run: cmake --build build --config Release

- name: Archive artifacts
uses: actions/upload-artifact@v4
with:
name: TOFInternal-${{ matrix.game_version }}
path: |
build/bin/Release/TOFInternal.dll
build/bin/Release/Injector.exe
build:
strategy:
matrix:
game_version: ["official", "steam"]
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: "recursive"

- name: Download SDK
run: |
$sdk_link = "${{ secrets.SDK_LINK }}"
Invoke-WebRequest -Uri $sdk_link -OutFile sdk.zip
Expand-Archive -Path sdk.zip -DestinationPath CppSDK

- name: Set up MSVC environment
uses: microsoft/setup-msbuild@v2

- uses: lukka/get-cmake@latest

- name: Configure TOF-SIH
run: cmake -B build -S . -DBUILD_STEAM_VERSION=${{ matrix.game_version == 'steam' && 'ON' || 'OFF' }}

- name: Build TOF-SIH
run: cmake --build build --config Release

- name: Configure Injector
run: cmake -B injector/build -S injector

- name: Build Injector
run: cmake --build injector/build --config Release

- name: Archive artifacts
uses: actions/upload-artifact@v4
with:
name: TOFInternal-${{ matrix.game_version }}
path: |
build/bin/Release/TOFInternal.dll
build/bin/Release/proc.exe
injector/build/bin/Release/injector.exe
injector/build/bin/Release/_aux.dll
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,10 @@
},
"cmake.preferredGenerators": [
"Visual Studio 17 2022"
]
],
"cmake.sourceDirectory": [
"${workspaceFolder}",
"${workspaceFolder}/injector"
],
"cmake.buildDirectory": "${sourceDirectory}/build"
}
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,8 @@ if (BUILD_STEAM_VERSION)
add_definitions(-DIS_STEAM_VERSION)
endif()

include(FetchContent)
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
FetchContent_MakeAvailable(json)

add_subdirectory(src)
add_subdirectory(CppSDK)
add_subdirectory(cfg)
add_subdirectory(injector)
add_subdirectory(tools)
add_subdirectory(kiero/minhook)
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
> This is for educational purposes only!
> **The safety of your account is entirely your responsibility. If it gets banned by using this, it's your own fault! (You have been warned.)**

## How to Use

Simply run the provided injector and select the game launcher executable.
If you're playing the Steam version, start the launcher via Steam, then run the injector.

## External Library Credits

- [Dear ImGui](https://github.com/ocornut/imgui)
Expand Down
4 changes: 4 additions & 0 deletions cfg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
include(FetchContent)
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
FetchContent_MakeAvailable(json)

add_library(Config STATIC
config.cpp
)
Expand Down
5 changes: 4 additions & 1 deletion cfg/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,8 @@ namespace Config {
saveThreadStarted = true;
}

void shutdown() { shuttingDown = true; }
void shutdown() {
actualSave();
shuttingDown = true;
}
} // namespace Config
18 changes: 18 additions & 0 deletions injector/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
cmake_minimum_required(VERSION 3.20)

project(TOFInjector VERSION 0.0.1)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_definitions(-DUNICODE -D_UNICODE)

add_executable(Injector main.cpp)
add_library(_aux SHARED _aux.cpp)
add_subdirectory(../cfg ${CMAKE_BINARY_DIR}/cfg)
add_subdirectory(../kiero/minhook ${CMAKE_BINARY_DIR}/kiero/minhook)
target_precompile_headers(Injector PRIVATE pch.hpp)
target_include_directories(Injector PRIVATE
../cfg
)
target_include_directories(_aux PRIVATE
../kiero/minhook/include
)
target_link_libraries(Injector Config ntdll.lib)
target_link_libraries(_aux minhook ntdll.lib)
92 changes: 92 additions & 0 deletions injector/_aux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include "MinHook.h"

void *createProcAddr = nullptr;
bool isSteam = false;
HANDLE gameThread = nullptr;

void rehook() {
// For some reason immediate rehook (or not removing the hook at all) will cause
// a crash for the Steam version of the game.
Sleep(1);
MH_EnableHook(createProcAddr);
}

typedef BOOL(WINAPI *createProcessW_t)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
createProcessW_t oCreateProcessW = nullptr;
BOOL WINAPI createProcess(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation) {
const auto isGame = wcsstr(lpApplicationName, L"QRSL.exe") != nullptr;
const auto isLauncher = wcsstr(lpApplicationName, L"x64launcher.exe") != nullptr;

if (isGame) {
dwCreationFlags |= CREATE_SUSPENDED;
SetEnvironmentVariable(L"__COMPAT_LAYER", L"RUNASINVOKER");
}

const auto result =
oCreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);

if (result) {
if (isGame) {
SetEnvironmentVariable(L"__COMPAT_LAYER", L"");
// Wait for main injector to do its thing
Sleep(250);
MH_DisableHook(createProcAddr);

if (isSteam) {
gameThread = lpProcessInformation->hThread;
} else {
ResumeThread(lpProcessInformation->hThread);
}

// Call rehook to re-enable the hook.
// This is important because for some reason Steam will try to use
// thread hijacking DLL injection via a remote process and we want to make sure
// to only resume the main game thread after that injection is finished.
CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)rehook, nullptr, 0, nullptr);
}

if (isLauncher) {
ResumeThread(gameThread);
}
}

return result;
}

WNDPROC oWndProc = nullptr;
LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_USER + 0x420) {
createProcAddr = (void *)wParam;
MH_Initialize();

MH_CreateHook(createProcAddr, createProcess, (void **)&oCreateProcessW);
MH_EnableHook(createProcAddr);

isSteam = GetModuleHandle(L"gameoverlayrenderer.dll") != nullptr;

return true;
}

return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam);
}

BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hInstDLL);
oWndProc =
(WNDPROC)SetWindowLongPtr(FindWindow(L"TWINCONTROL", L"Tower of Fantasy"), GWLP_WNDPROC, (LONG_PTR)wndProc);
}

return true;
}
Loading