2024-01-23 01:45:59 -05:00
|
|
|
#include <ctype.h>
|
2023-07-19 19:39:50 +02:00
|
|
|
#include <stdio.h>
|
2023-07-20 01:29:11 +02:00
|
|
|
#include <dlfcn.h>
|
2025-04-04 16:51:40 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
2023-07-20 01:29:11 +02:00
|
|
|
|
|
|
|
|
#include "include/main.h"
|
|
|
|
|
#include "include/sdk.h"
|
2023-07-20 17:44:35 +02:00
|
|
|
#include "include/globals.h"
|
2025-04-04 16:51:40 -04:00
|
|
|
#include "include/settings.h"
|
2023-07-20 17:44:35 +02:00
|
|
|
#include "include/hooks.h"
|
2023-07-28 15:44:31 +02:00
|
|
|
#include "include/util.h"
|
2023-09-19 13:16:13 -04:00
|
|
|
#include "include/game_detection.h"
|
2023-07-19 19:39:50 +02:00
|
|
|
|
2023-07-21 07:02:38 +02:00
|
|
|
static bool loaded = false;
|
|
|
|
|
|
2025-04-04 16:51:40 -04:00
|
|
|
void debug_log(const char* message) {
|
|
|
|
|
FILE* logfile = fopen("/tmp/cheat-unload-debug.log", "a");
|
|
|
|
|
if (logfile) {
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
char timestamp[64];
|
|
|
|
|
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
|
|
|
|
|
fprintf(logfile, "[%s] %s\n", timestamp, message);
|
|
|
|
|
fclose(logfile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void safe_unload_with_debug(void) {
|
|
|
|
|
debug_log("Starting safe unload with debug logging");
|
|
|
|
|
|
|
|
|
|
char buf[256];
|
|
|
|
|
snprintf(buf, sizeof(buf), "Function addresses - self_unload: %p, unload: %p, hooks_restore: %p",
|
|
|
|
|
(void*)self_unload, (void*)unload, (void*)hooks_restore);
|
|
|
|
|
debug_log(buf);
|
|
|
|
|
|
|
|
|
|
debug_log("Resetting all settings to default values");
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Step 0: Resetting all settings...\"");
|
|
|
|
|
settings_reset();
|
|
|
|
|
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Step 1: Unhooking functions...\"");
|
|
|
|
|
debug_log("Unhooking all functions");
|
|
|
|
|
|
|
|
|
|
debug_log("Restoring OpenGL hooks");
|
|
|
|
|
|
|
|
|
|
debug_log("Restoring VMT hooks");
|
|
|
|
|
hooks_restore();
|
|
|
|
|
|
|
|
|
|
debug_log("Restoring globals");
|
|
|
|
|
globals_restore();
|
|
|
|
|
|
|
|
|
|
debug_log("Removing custom commands");
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Step 2: Removing custom commands...\"");
|
|
|
|
|
|
|
|
|
|
debug_log("Waiting for hooks to settle");
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Step 3: Waiting for hooks to settle...\"");
|
2025-04-04 17:07:54 -04:00
|
|
|
usleep(250000);
|
2025-04-04 16:51:40 -04:00
|
|
|
|
|
|
|
|
debug_log("Beginning library unload sequence");
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Step 4: Unloading library...\"");
|
2025-04-04 17:07:54 -04:00
|
|
|
|
2025-04-04 16:51:40 -04:00
|
|
|
void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD);
|
|
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "dlopen result: %p", self);
|
|
|
|
|
debug_log(buf);
|
|
|
|
|
|
|
|
|
|
if (self) {
|
|
|
|
|
/* Close the call we just made to dlopen() */
|
|
|
|
|
debug_log("Closing first dlopen reference");
|
|
|
|
|
int result = dlclose(self);
|
|
|
|
|
snprintf(buf, sizeof(buf), "First dlclose result: %d", result);
|
|
|
|
|
debug_log(buf);
|
|
|
|
|
|
|
|
|
|
/* Close the call our injector made */
|
|
|
|
|
debug_log("Closing second dlopen reference");
|
|
|
|
|
result = dlclose(self);
|
|
|
|
|
snprintf(buf, sizeof(buf), "Second dlclose result: %d", result);
|
|
|
|
|
debug_log(buf);
|
|
|
|
|
} else {
|
|
|
|
|
debug_log("ERROR: Failed to get handle to library");
|
|
|
|
|
const char* error = dlerror();
|
|
|
|
|
if (error) {
|
|
|
|
|
debug_log(error);
|
|
|
|
|
i_engine->pfnClientCmd("echo \"ERROR: Failed to get handle to library\"");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_log("Safe unload completed");
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Unload procedure completed\"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UNINJECT_CommandHandler(void) {
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Uninjecting goldsource-cheat with debug logging...\"");
|
|
|
|
|
|
|
|
|
|
safe_unload_with_debug();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MENU_CommandHandler(void) {
|
|
|
|
|
extern bool g_menu_open;
|
|
|
|
|
g_menu_open = !g_menu_open;
|
|
|
|
|
i_engine->Con_Printf("Menu toggled to %s\n", g_menu_open ? "open" : "closed");
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-04 17:07:54 -04:00
|
|
|
__attribute__((constructor))
|
2023-07-21 13:59:38 +02:00
|
|
|
void load(void) {
|
2023-09-19 10:38:01 -04:00
|
|
|
printf("goldsource-cheat injected!\n");
|
2023-07-20 01:29:11 +02:00
|
|
|
|
|
|
|
|
if (!globals_init()) {
|
2023-09-19 10:38:01 -04:00
|
|
|
fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n");
|
2023-07-20 01:29:11 +02:00
|
|
|
self_unload();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-04 16:51:40 -04:00
|
|
|
settings_init();
|
2023-07-21 13:44:53 +02:00
|
|
|
|
2023-07-20 17:44:35 +02:00
|
|
|
if (!hooks_init()) {
|
2023-09-19 10:38:01 -04:00
|
|
|
fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n");
|
2023-07-20 17:44:35 +02:00
|
|
|
self_unload();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-07-20 01:29:11 +02:00
|
|
|
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnAddCommand("dz_uninject", UNINJECT_CommandHandler);
|
|
|
|
|
i_engine->pfnAddCommand("dz_menu", MENU_CommandHandler);
|
|
|
|
|
|
|
|
|
|
i_engine->pfnClientCmd("bind INS dz_menu");
|
|
|
|
|
i_engine->Con_Printf("Bound INSERT key to menu toggle\n");
|
2023-07-28 15:44:31 +02:00
|
|
|
|
2023-09-19 18:54:15 -04:00
|
|
|
if (IsCS16()) {
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnClientCmd("play weapons/knife_deploy1.wav");
|
|
|
|
|
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
|
2023-09-19 18:54:15 -04:00
|
|
|
}
|
|
|
|
|
else if (IsDayOfDefeat()) {
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnClientCmd("play weapons/kar_cock.wav");
|
|
|
|
|
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
|
2023-09-19 18:54:15 -04:00
|
|
|
}
|
|
|
|
|
else if (IsTFC()) {
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnClientCmd("play misc/party2.wav");
|
|
|
|
|
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
|
2023-09-19 18:54:15 -04:00
|
|
|
}
|
2023-09-20 08:46:08 -04:00
|
|
|
else if (IsDeathmatchClassic()) {
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnClientCmd("play items/r_item1.wav");
|
|
|
|
|
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
|
2024-01-23 01:45:59 -05:00
|
|
|
}
|
2023-09-19 18:54:15 -04:00
|
|
|
else
|
|
|
|
|
{
|
2025-04-04 16:51:40 -04:00
|
|
|
i_engine->pfnClientCmd("play weapons/cbar_hit1.wav");
|
|
|
|
|
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
|
2023-09-19 18:54:15 -04:00
|
|
|
}
|
|
|
|
|
|
2023-09-19 10:38:01 -04:00
|
|
|
i_engine->pfnClientCmd("echo \"goldsource-cheat loaded successfully!\"");
|
2023-09-19 13:16:13 -04:00
|
|
|
i_engine->pfnClientCmd("echo \"Deadzone rulez!\"");
|
2023-09-21 15:08:13 -04:00
|
|
|
i_engine->pfnClientCmd("echo \"https://git.deadzone.lol/Wizzard/goldsrc-cheat\"");
|
2023-09-19 13:16:13 -04:00
|
|
|
|
|
|
|
|
GameType game = get_current_game();
|
|
|
|
|
switch(game) {
|
|
|
|
|
case GAME_HALFLIFE:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Half-Life 1\"");
|
|
|
|
|
break;
|
|
|
|
|
case GAME_CS16:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Counter-Strike 1.6\"");
|
|
|
|
|
break;
|
|
|
|
|
case GAME_DAY_OF_DEFEAT:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Day of Defeat\"");
|
|
|
|
|
break;
|
|
|
|
|
case GAME_TFC:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Team Fortress Classic\"");
|
|
|
|
|
break;
|
2023-09-20 08:46:08 -04:00
|
|
|
case GAME_DMC:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Deathmatch Classic\"");
|
|
|
|
|
break;
|
2024-01-23 01:45:59 -05:00
|
|
|
case GAME_SL:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Space Life: Finley's Revenge\"");
|
|
|
|
|
break;
|
2023-09-19 13:16:13 -04:00
|
|
|
default:
|
|
|
|
|
i_engine->pfnClientCmd("echo \"Detected Game: Unknown Game\"");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-21 07:02:38 +02:00
|
|
|
loaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-04 17:07:54 -04:00
|
|
|
__attribute__((destructor))
|
2023-08-01 19:53:43 +02:00
|
|
|
void unload(void) {
|
2023-07-21 13:58:47 +02:00
|
|
|
if (loaded) {
|
2025-04-04 16:51:40 -04:00
|
|
|
settings_reset();
|
|
|
|
|
|
2023-07-21 07:02:38 +02:00
|
|
|
globals_restore();
|
2023-07-25 20:37:52 +02:00
|
|
|
hooks_restore();
|
2023-07-25 14:28:03 +02:00
|
|
|
|
2023-07-21 13:58:47 +02:00
|
|
|
}
|
2023-07-21 07:02:38 +02:00
|
|
|
|
2023-09-19 10:38:01 -04:00
|
|
|
printf("goldsource-cheat unloaded.\n\n");
|
2023-07-20 01:29:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void self_unload(void) {
|
|
|
|
|
void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD);
|
2025-04-04 17:07:54 -04:00
|
|
|
|
|
|
|
|
if (self) {
|
|
|
|
|
dlclose(self);
|
|
|
|
|
dlclose(self);
|
|
|
|
|
}
|
2023-07-19 19:39:50 +02:00
|
|
|
}
|