Skip to content

Commit

Permalink
add AOB signature scanning, more font size tweaks
Browse files Browse the repository at this point in the history
SomeCrazyGuy committed May 16, 2024
1 parent d0790c6 commit 0d52008
Showing 6 changed files with 136 additions and 19 deletions.
3 changes: 3 additions & 0 deletions betterapi.h
Original file line number Diff line number Diff line change
@@ -195,6 +195,9 @@ struct hook_api_t {

// hook a function in the Import Address Table of starfield
FUNC_PTR(*HookFunctionIAT)(const char* dll_name, const char* func_name, const FUNC_PTR new_function);

// !EXPERIMENTAL API! AOB scan the exe memory and return the first match
void* (*AOBScanEXE)(const char* signature);
};

// This API allows you to create a basic mod menu without linking to imgui
44 changes: 33 additions & 11 deletions src/console.cpp
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
#include <vector>
#include <ctype.h>

//48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 57 b8 30 10 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 49 - new sig with 1 match
//48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 57 b8 30 10 -- the 0x1030 stack size might be too unique
/*
undefined4 uVar1;
@@ -252,17 +253,38 @@ extern void setup_console(const BetterAPI* api) {
OutputHandle = LogBuffer->Create("Console Output", OUTPUT_FILE_PATH);
HistoryHandle = LogBuffer->Restore("Command History", HISTORY_FILE_PATH);

DEBUG("HookFunction: ConsolePrintV");
OLD_ConsolePrintV = (decltype(OLD_ConsolePrintV))HookAPI->HookFunction(
(FUNC_PTR)HookAPI->Relocate(OFFSET_console_vprint),
(FUNC_PTR)console_print
);

DEBUG("HookFunction: ConsoleRun");
OLD_ConsoleRun = (decltype(OLD_ConsoleRun))HookAPI->HookFunction(
(FUNC_PTR)HookAPI->Relocate(OFFSET_console_run),
(FUNC_PTR)console_run
);
const auto hook_print_aob = HookAPI->AOBScanEXE("48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 57 b8 30 10 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 49");

if (hook_print_aob) {
DEBUG("Hooking print function using AOB method");
OLD_ConsolePrintV = (decltype(OLD_ConsolePrintV))HookAPI->HookFunction(
(FUNC_PTR)hook_print_aob,
(FUNC_PTR)console_print
);
}
else {
DEBUG("Hooking print function using offset method");
OLD_ConsolePrintV = (decltype(OLD_ConsolePrintV))HookAPI->HookFunction(
(FUNC_PTR)HookAPI->Relocate(OFFSET_console_vprint),
(FUNC_PTR)console_print
);
}

const auto hook_run_aob = HookAPI->AOBScanEXE("48 8b c4 48 89 50 ?? 4c 89 40 ?? 4c 89 48 ?? 55 53 56 57 41 55 41 56 41 57 48 8d");
if (hook_run_aob) {
DEBUG("Hooking run function using AOB method");
OLD_ConsoleRun = (decltype(OLD_ConsoleRun))HookAPI->HookFunction(
(FUNC_PTR)hook_run_aob,
(FUNC_PTR)console_run
);
}
else {
DEBUG("Hooking run function using offset method");
OLD_ConsoleRun = (decltype(OLD_ConsoleRun))HookAPI->HookFunction(
(FUNC_PTR)HookAPI->Relocate(OFFSET_console_run),
(FUNC_PTR)console_run
);
}

IOBuffer[0] = 0;
}
4 changes: 4 additions & 0 deletions src/gui.cpp
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@ extern void draw_gui() {
size_t infos_count = 0;
auto infos = GetModInfo(&infos_count);

if (GetSettings()->FontScaleOverride == 0) {
GetSettingsMutable()->FontScaleOverride = 100;
}

//todo: make the help text always visible with font size override?
ImGui::SetWindowFontScale(1);
if (ImGui::TabItemButton("Help", ImGuiTabItemFlags_Leading)) {
89 changes: 88 additions & 1 deletion src/hook_api.cpp
Original file line number Diff line number Diff line change
@@ -162,13 +162,100 @@ static FUNC_PTR HookFunctionIAT(const char* dll_name, const char* func_name, con
return ret;
}


static void* AOBScanEXE(const char* signature) {
constexpr uint16_t sig_end = 0xFFFF;
const auto siglen = strlen(signature);

//compile signature
uint16_t* sig = (uint16_t*)malloc((siglen + 1) * 2);
ASSERT(sig != NULL);

static const auto unhex = [](char upper, char lower) -> uint16_t {
uint16_t ret = 0xFF00;

upper = (char)::toupper(upper);
lower = (char)::toupper(lower);

if (upper == '?') {
ret &= 0x0FFF;
}
else if ((upper >= '0') && (upper <= '9')) {
ret |= (upper - '0') << 4;
}
else if ((upper >= 'A') && (upper <= 'F')) {
ret |= (10 + (upper - 'A')) << 4;
}
else {
ASSERT(false && "invalid character in signature");
}

if (lower == '?') {
ret &= 0xF0FF;
}
else if ((lower >= '0') && (lower <= '9')) {
ret |= (lower - '0');
}
else if ((lower >= 'A') && (lower <= 'F')) {
ret |= (10 + (lower - 'A'));
}
else {
ASSERT(false && "invalid character in signature");
}

return ret;
};

auto matchcount = 0;
for (auto i = 0; i < siglen; ) {
char upper = signature[i++];
char lower = signature[i++];
char test = signature[i++];

ASSERT(matchcount < siglen);
sig[matchcount++] = unhex(upper, lower);

if ((test != ' ') && (test != '\0')) {
DEBUG("signature-bad format: %s", &signature[i - 3]);
free(sig);
return NULL;
}
}

sig[matchcount] = sig_end;

const auto hdr1 = (const IMAGE_DOS_HEADER*)Relocate(0);
const auto hdr2 = (const IMAGE_NT_HEADERS64*)Relocate(hdr1->e_lfanew);
const unsigned char* haystack = (const unsigned char*)Relocate(0);
const unsigned count = hdr2->OptionalHeader.SizeOfImage;


for (unsigned i = 0; i < count; ++i) {
auto match = 0;

while ((haystack[i] & (sig[match] >> 8)) == (sig[match] & 0xFF)) {
++i;
++match;
if (sig[match] == sig_end) {
free(sig);
return Relocate(i - match);
}
}
}

return NULL;
}



static constexpr struct hook_api_t HookAPI {
&HookFunction,
&HookVirtualTable,
&Relocate,
&SafeWriteMemory,
&GetProcAddressFromIAT,
&HookFunctionIAT
&HookFunctionIAT,
&AOBScanEXE
};

extern constexpr const struct hook_api_t* GetHookAPI() {
11 changes: 6 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -48,14 +48,14 @@ static void write_log(const char* const str) noexcept {
static HANDLE debugfile = INVALID_HANDLE_VALUE;
logging_mutex.lock();
if (debugfile == INVALID_HANDLE_VALUE) {
debugfile = CreateFileW(L"debuglog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
debugfile = CreateFileW(L"BetterConsoleLog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (debugfile != INVALID_HANDLE_VALUE) {
WriteFile(debugfile, str, (DWORD)strnlen(str, 4096), NULL, NULL);
FlushFileBuffers(debugfile);
}
else {
MessageBoxA(NULL, "Could not write to 'debuglog.txt'", "ASSERTION FAILURE", 0);
MessageBoxA(NULL, "Could not write to 'BetterConsoleLog.txt'", "ASSERTION FAILURE", 0);
}
logging_mutex.unlock();
}
@@ -323,13 +323,14 @@ static void SetupModMenu() {
ImGui::StyleColorsDark();
DEBUG("ImGui one time init completed!");

// the modmenu UI is internally imlpemented using the plugin api, it gets coupled here
RegisterInternalPlugin(&API);
// the modmenu UI is internally implemented using the plugin api, it gets coupled here
DEBUG("RegisterInternalPlugin");
RegisterInternalPlugin(&API);


// The console part of better console is now minimally coupled to the mod menu
DEBUG("Console setup - crashing here is AOB or offset issue");
setup_console(&API);
DEBUG("Console setup");
}

extern "C" __declspec(dllexport) void SFSEPlugin_Load(const SFSEInterface * sfse) {
4 changes: 2 additions & 2 deletions src/main.h
Original file line number Diff line number Diff line change
@@ -48,13 +48,13 @@ inline constexpr auto file_name_only(const char* const in) noexcept -> const cha
#include "../imgui/imgui.h"


#define BETTERCONSOLE_VERSION "1.2.18"
#define BETTERCONSOLE_VERSION "1.2.19"


// --------------------------------------------------------------------
// ---- Change these offsets for each game update ----
// --------------------------------------------------------------------
constexpr uint32_t GAME_VERSION = MAKE_VERSION(1, 10, 32);
constexpr uint32_t GAME_VERSION = MAKE_VERSION(1, 11, 36);



0 comments on commit 0d52008

Please sign in to comment.