Skip to content

Commit

Permalink
0.2.0: Hooking HavokScript
Browse files Browse the repository at this point in the history
  • Loading branch information
Surasia committed Aug 12, 2024
1 parent f27815c commit 8e43db9
Show file tree
Hide file tree
Showing 19 changed files with 354 additions and 659 deletions.
3 changes: 1 addition & 2 deletions InfExt/InfExt.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,18 @@
<ClInclude Include="src\Client.hpp" />
<ClInclude Include="src\Exports.hpp" />
<ClInclude Include="src\HavokScript\HavokScript.hpp" />
<ClInclude Include="src\HavokScript\HksCompilerSettings.hpp" />
<ClInclude Include="src\ImGuiHook\stdafx.h" />
<ClInclude Include="src\Lua\LuaHook.hpp" />
<ClInclude Include="src\Memory.hpp" />
<ClInclude Include="src\Misc\ChromaSDK.hpp" />
<ClInclude Include="src\Variant\Variant.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Client.cpp" />
<ClCompile Include="src\HavokScript\HavokScript.cpp" />
<ClCompile Include="src\Lua\LuaHook.cpp" />
<ClCompile Include="src\Memory.cpp" />
<ClCompile Include="src\Misc\ChromaSDK.cpp" />
<ClCompile Include="src\Variant\Variant.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
9 changes: 3 additions & 6 deletions InfExt/InfExt.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
<ClInclude Include="src\Misc\ChromaSDK.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Variant\Variant.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\ImGuiHook\stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Lua\LuaHook.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\HavokScript\HksCompilerSettings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Client.cpp">
Expand All @@ -49,9 +49,6 @@
<ClCompile Include="src\Misc\ChromaSDK.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Variant\Variant.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Lua\LuaHook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down
193 changes: 98 additions & 95 deletions InfExt/src/Client.cpp
Original file line number Diff line number Diff line change
@@ -1,117 +1,120 @@
#include "Client.hpp"
#include "Exports.hpp"
#include "./HavokScript/HavokScript.hpp"
#include "./Lua/LuaHook.hpp"
#include "./Misc/ChromaSDK.hpp"
#include "./Variant/Variant.hpp"

std::mutex consoleMutex;
std::condition_variable cv;
std::atomic<bool> stopThread(false);
std::thread mainThread;

DWORD WINAPI CreateConsole()
{
FILE *dummy = nullptr;
AllocConsole();
AttachConsole(GetCurrentProcessId());
{
std::lock_guard<std::mutex> lock(consoleMutex);
if (freopen_s(&dummy, "CONIN$", "r", stdin) != 0 || freopen_s(&dummy, "CONOUT$", "w", stdout) != 0 ||
freopen_s(&dummy, "CONOUT$", "w", stderr) != 0) {
std::cerr << "Failed to redirect console streams !" << std::endl;
return 1;
}
}
return 0;
#include "Exports.hpp"

DWORD WINAPI CreateConsole() {
FILE* dummy = nullptr;
AllocConsole();
AttachConsole(GetCurrentProcessId());
{
std::lock_guard<std::mutex> lock(consoleMutex);
if (freopen_s(&dummy, "CONIN$", "r", stdin) != 0 ||
freopen_s(&dummy, "CONOUT$", "w", stdout) != 0 ||
freopen_s(&dummy, "CONOUT$", "w", stderr) != 0) {
std::cerr << "Failed to redirect console streams !" << std::endl;
return 1;
}
}
return 0;
}

DWORD WINAPI DestroyConsole()
{
if (FreeConsole() == 0) {
std::cerr << "Console failed to close!" << std::endl;
}

{
std::lock_guard<std::mutex> lock(consoleMutex);
freopen_s(reinterpret_cast<FILE **>(stdin), "NUL:", "r", stdin);
freopen_s(reinterpret_cast<FILE **>(stdout), "NUL:", "r", stdout);
freopen_s(reinterpret_cast<FILE **>(stderr), "NUL:", "r", stderr);
}

std::cin.clear();
std::cout.clear();
std::cerr.clear();
return 0;
DWORD WINAPI DestroyConsole() {
if (FreeConsole() == 0) {
std::cerr << "Console failed to close!" << std::endl;
}

{
std::lock_guard<std::mutex> lock(consoleMutex);
freopen_s(reinterpret_cast<FILE**>(stdin), "NUL:", "r", stdin);
freopen_s(reinterpret_cast<FILE**>(stdout), "NUL:", "r", stdout);
freopen_s(reinterpret_cast<FILE**>(stderr), "NUL:", "r", stderr);
}

std::cin.clear();
std::cout.clear();
std::cerr.clear();
return 0;
}

DWORD WINAPI DestroyHook()
{
stopThread = true;
cv.notify_all();
DWORD WINAPI DestroyHook() {
stopThread = true;
cv.notify_all();

if (mainThread.joinable()) {
mainThread.join();
}
if (mainThread.joinable()) {
mainThread.join();
}

MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
return 0;
}
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();

void ProcessCommands()
{
while (!stopThread) {
LuaVM::ProcessCommand();
}
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
hMutex = NULL;
}

return 0;
}

void ProcessCommands() {
{
std::unique_lock<std::mutex> lock(consoleMutex);
if (cv.wait_for(lock, std::chrono::seconds(10),
[] { return stopThread.load(); })) {
return; // Wait after Steam prints debug info.
}
}
while (!stopThread) {
LuaVM::ProcessCommand();
}
}

static DWORD SetupHook()
{
uintptr_t ModuleBase = 0;
static DWORD SetupHook() {
uintptr_t ModuleBase = 0;

LPCSTR moduleName = "HaloInfinite.exe";
ModuleBase = reinterpret_cast<uintptr_t>(GetModuleHandleA(moduleName));
if (ModuleBase == 0) {
std::cerr << "Failed to get module handle for " << moduleName << std::endl;
return 1;
}
LPCSTR moduleName = "HaloInfinite.exe";
ModuleBase = reinterpret_cast<uintptr_t>(GetModuleHandleA(moduleName));
if (ModuleBase == 0) {
std::cerr << "Failed to get module handle for " << moduleName << std::endl;
return 1;
}

ChromaSDK::HookChroma(ModuleBase);
Hks::HookHavokScript(ModuleBase);
Variant::HookVariant(ModuleBase);
ChromaSDK::HookChroma(ModuleBase);
Hks::HookHavokScript(ModuleBase);

LuaVM::InitializeLua();
LuaVM::HookVariantFunctions();
mainThread = std::thread(ProcessCommands);
return 0;
mainThread = std::thread(ProcessCommands);
return 0;
}


DWORD WINAPI MainThread(LPVOID lpParameter)
{
SetupHook();
return 0;
DWORD WINAPI MainThread(LPVOID lpParameter) {
SetupHook();
return 0;
}


BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
CreateConsole();
DisableThreadLibraryCalls(hModule);
CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
break;
case DLL_PROCESS_DETACH:
DestroyHook();
LuaVM::CleanLua();
DestroyConsole();
FreeLibraryAndExitThread(hModule, TRUE);
break;
default:
break;
}
return TRUE;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
hMutex = CreateMutexA(NULL, TRUE, "UniqueDLLInstanceMutex");
if (hMutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) {
if (hMutex) {
CloseHandle(hMutex);
hMutex = NULL;
}
return FALSE; // DLL is already loaded
}
CreateConsole();
DisableThreadLibraryCalls(hModule);
CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
break;
case DLL_PROCESS_DETACH:
DestroyHook();
DestroyConsole();
FreeLibraryAndExitThread(hModule, TRUE);
break;
default:
break;
}
return TRUE;
}
9 changes: 6 additions & 3 deletions InfExt/src/Client.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
#ifndef CLIENT_HPP
#define CLIENT_HPP


#include "../include/MinHook.h" // IWYU pragma: keep
#include <Minhook.h>
#include <array> // IWYU pragma: keep
#include <consoleapi.h>
#include <cstring> // IWYU pragma: keep
#include <fstream> // IWYU pragma: keep
#include <functional> // IWYU pragma: keep
#include <iostream> // IWYU pragma: keep
#include <lua.hpp>
#include <map> // IWYU pragma: keep
#include <psapi.h>
#include <sstream> // IWYU pragma: keep
Expand All @@ -20,5 +18,10 @@
#include <windows.h>
#include <mutex>

std::mutex consoleMutex;
std::condition_variable cv;
std::atomic<bool> stopThread(false);
std::thread mainThread;
HANDLE hMutex = NULL;

#endif
71 changes: 61 additions & 10 deletions InfExt/src/HavokScript/HavokScript.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,69 @@
#include "HavokScript.hpp"
#include "../Memory.hpp"
#include "HksCompilerSettings.hpp"

int Hks::GetGlobalHook(uintptr_t state, char* string) {
LuaState = state;
return GetGlobalA(state, string);
}

uint64_t Hks::PCallHook(uintptr_t state, int function, uint32_t i, int u) {
__int64 result = PCallA(state, function, i, u);
return result;
}

/* Declare private variables. */
Hks::GetGlobal Hks::GetGlobalH = nullptr;
Hks::GetGlobal Hks::GetGlobalA = nullptr;

int Hks::GetGlobalHook(lua_State *state, char *string)
{
return GetGlobalA(state, string);
uint64_t Hks::LoadBufferHook(uintptr_t state,
const struct HksCompilerSettings* compilerSettings,
const char* buffer, __int64 length,
const char* unknown1) {
__int64 result =
LoadBufferA(state, compilerSettings, buffer, length, unknown1);
return result;
}


void Hks::HookHavokScript(uintptr_t ModuleBase)
{
const uintptr_t GetGlobalOffset = 0x80CB4C;
GetGlobalH = hook_function<GetGlobal>(ModuleBase, GetGlobalOffset, &GetGlobalHook, &GetGlobalA);
uint64_t Hks::DoString(const char* string) {

size_t stringLength = std::strlen(string);
if (Hks::LoadBufferHook(
LuaState,
(const struct HksCompilerSettings*)(*((uintptr_t*)LuaState + 2) +
1368),
string, stringLength, string)) {
return 1;
}

uint64_t call_result = PCallHook(LuaState, 0, 0xFFFFFFFF, 0);
if (call_result) {
return 1;
}
return call_result;
}


uint64_t Hks::DoFile(const char* filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Failed to open file: " << filename << std::endl;
return 1;
}

std::stringstream buffer;
buffer << file.rdbuf();
std::string fileContents = buffer.str();
file.close();

return DoString(fileContents.c_str());
}

void Hks::HookHavokScript(uintptr_t ModuleBase) {
const uintptr_t GetGlobalOffset = 0x80CB4C;
GetGlobalH = hook_function<GetGlobal>(ModuleBase, GetGlobalOffset,
&GetGlobalHook, &GetGlobalA);
const uintptr_t PCallOffset = 0x764304;
PCallH = hook_function<PCall>(ModuleBase, PCallOffset, &PCallHook, &PCallA);
const uintptr_t LoadBufferOffset = 0xA484C0;
LoadBufferH = hook_function<LoadBuffer>(ModuleBase, LoadBufferOffset,
&LoadBufferHook, &LoadBufferA);
}
Loading

0 comments on commit 8e43db9

Please sign in to comment.