From 0f3f10f376c94dbde1bf4284582d3b275ca80156 Mon Sep 17 00:00:00 2001 From: Gynt Date: Wed, 24 Sep 2025 14:26:00 +0200 Subject: [PATCH 1/2] feat(seh): basic implementation, for some reason __except not being hit --- CodeFunctions.cpp | 358 ++++++++++++-------------- CodeFunctions.h | 3 - Exceptions.cpp | 22 ++ Exceptions.h | 13 + MemoryFunctions.cpp | 228 +++++++++++----- MemoryFunctions.h | 1 - RuntimePatchingSystem.cpp | 2 +- RuntimePatchingSystem.vcxproj | 10 +- RuntimePatchingSystem.vcxproj.filters | 8 +- UtilityFunctions.cpp | 48 +++- UtilityFunctions.h | 13 - UtilityFunctions.hpp | 22 ++ 12 files changed, 455 insertions(+), 273 deletions(-) create mode 100644 Exceptions.cpp create mode 100644 Exceptions.h delete mode 100644 UtilityFunctions.h create mode 100644 UtilityFunctions.hpp diff --git a/CodeFunctions.cpp b/CodeFunctions.cpp index 0760900..dc708f3 100644 --- a/CodeFunctions.cpp +++ b/CodeFunctions.cpp @@ -1,5 +1,7 @@ #include "CodeFunctions.h" #include +#include "Exceptions.h" +#include "UtilityFunctions.hpp" #define RPS_ARGUMENT_LIMIT 20 @@ -357,7 +359,10 @@ DWORD fakeStack[RPS_ARGUMENT_LIMIT + 1]; // The user has called the luaOriginalFunctionName int luaCallMachineCode(lua_State* L) { + + DWORD address = lua_tointeger(L, lua_upvalueindex(1)); + int argumentCount = lua_tointeger(L, lua_upvalueindex(2)); int callingConvention = lua_tointeger(L, lua_upvalueindex(3)); @@ -371,7 +376,7 @@ int luaCallMachineCode(lua_State* L) { for (int i = 0; i < argumentCount; i++) { if (lua_type(L, i + 1 + 1) != LUA_TNUMBER) { - return luaL_error(L, ("[RPS]: calling function " + std::to_string(functionLocation) + " argument #" + std::to_string(i + 1 + 1) + " is not an integer (or pointer);").c_str()); + return luaL_error(L, "[RPS]: calling function 0x%X argument #%d is not an integer (or pointer);", functionLocation, i + 1 + 1); } fakeStack[i] = lua_tointeger(L, i + 1 + 1); // i+1+1 (1 to offset 0-base and 1 because this-parameter is ignored } @@ -397,155 +402,164 @@ int luaCallMachineCode(lua_State* L) { } - __asm { - mov ecx, argumentCount; - loopbegin: - cmp ecx, 0; - jle done; - dec ecx; - mov eax, fakeStack[ecx * 4]; - push eax; - jmp loopbegin; - done: - mov ecx, callingConvention; - cmp ecx, 0; - je caller; - jmp callee; - caller: - mov ecx, argumentCount; - mov eax, address; - cmp ecx, 0; - je add0x00; - cmp ecx, 1; - je add0x04; - cmp ecx, 2; - je add0x08; - cmp ecx, 3; - je add0x0C; - cmp ecx, 4; - je add0x10; - cmp ecx, 5; - je add0x14; - cmp ecx, 6; - je add0x18; - cmp ecx, 7; - je add0x1C; - cmp ecx, 8; - je add0x20; - cmp ecx, 9; - je add0x24; - cmp ecx, 10; - je add0x28; - cmp ecx, 11; - je add0x2C; - cmp ecx, 12; - je add0x30; - cmp ecx, 13; - je add0x34; - cmp ecx, 14; - je add0x38; - cmp ecx, 15; - je add0x3C; - cmp ecx, 16; - je add0x40; - cmp ecx, 17; - je add0x44; - cmp ecx, 18; - je add0x48; - cmp ecx, 19; - je add0x4C; - cmp ecx, 20; - je add0x50; - add0x00: - call eax; - add esp, 0x00; - jmp eor; - add0x04: - call eax; - add esp, 0x04; - jmp eor; - add0x08: - call eax; - add esp, 0x08; - jmp eor; - add0x0C: - call eax; - add esp, 0x0C; - jmp eor; - add0x10: - call eax; - add esp, 0x10; - jmp eor; - add0x14: - call eax; - add esp, 0x14; - jmp eor; - add0x18: - call eax; - add esp, 0x18; - jmp eor; - add0x1c: - call eax; - add esp, 0x1c; - jmp eor; - add0x20: - call eax; - add esp, 0x20; - jmp eor; - add0x24: - call eax; - add esp, 0x24; - jmp eor; - add0x28: - call eax; - add esp, 0x28; - jmp eor; - add0x2C: - call eax; - add esp, 0x2C; - jmp eor; - add0x30: - call eax; - add esp, 0x30; - jmp eor; - add0x34: - call eax; - add esp, 0x34; - jmp eor; - add0x38: - call eax; - add esp, 0x38; - jmp eor; - add0x3C: - call eax; - add esp, 0x3C; - jmp eor; - add0x40: - call eax; - add esp, 0x40; - jmp eor; - add0x44: - call eax; - add esp, 0x44; - jmp eor; - add0x48: - call eax; - add esp, 0x48; - jmp eor; - add0x4C: - call eax; - add esp, 0x4C; - jmp eor; - add0x50: - call eax; - add esp, 0x50; - jmp eor; - callee: - mov eax, address; - mov ecx, currentECXValue; - call eax; - eor: +#ifdef EH_GUARDRAILS + __try { +#endif + __asm { + mov ecx, argumentCount; + loopbegin: + cmp ecx, 0; + jle done; + dec ecx; + mov eax, fakeStack[ecx * 4]; + push eax; + jmp loopbegin; + done: + mov ecx, callingConvention; + cmp ecx, 0; + je caller; + jmp callee; + caller: + mov ecx, argumentCount; + mov eax, address; + cmp ecx, 0; + je add0x00; + cmp ecx, 1; + je add0x04; + cmp ecx, 2; + je add0x08; + cmp ecx, 3; + je add0x0C; + cmp ecx, 4; + je add0x10; + cmp ecx, 5; + je add0x14; + cmp ecx, 6; + je add0x18; + cmp ecx, 7; + je add0x1C; + cmp ecx, 8; + je add0x20; + cmp ecx, 9; + je add0x24; + cmp ecx, 10; + je add0x28; + cmp ecx, 11; + je add0x2C; + cmp ecx, 12; + je add0x30; + cmp ecx, 13; + je add0x34; + cmp ecx, 14; + je add0x38; + cmp ecx, 15; + je add0x3C; + cmp ecx, 16; + je add0x40; + cmp ecx, 17; + je add0x44; + cmp ecx, 18; + je add0x48; + cmp ecx, 19; + je add0x4C; + cmp ecx, 20; + je add0x50; + add0x00: + call eax; + add esp, 0x00; + jmp eor; + add0x04: + call eax; + add esp, 0x04; + jmp eor; + add0x08: + call eax; + add esp, 0x08; + jmp eor; + add0x0C: + call eax; + add esp, 0x0C; + jmp eor; + add0x10: + call eax; + add esp, 0x10; + jmp eor; + add0x14: + call eax; + add esp, 0x14; + jmp eor; + add0x18: + call eax; + add esp, 0x18; + jmp eor; + add0x1c: + call eax; + add esp, 0x1c; + jmp eor; + add0x20: + call eax; + add esp, 0x20; + jmp eor; + add0x24: + call eax; + add esp, 0x24; + jmp eor; + add0x28: + call eax; + add esp, 0x28; + jmp eor; + add0x2C: + call eax; + add esp, 0x2C; + jmp eor; + add0x30: + call eax; + add esp, 0x30; + jmp eor; + add0x34: + call eax; + add esp, 0x34; + jmp eor; + add0x38: + call eax; + add esp, 0x38; + jmp eor; + add0x3C: + call eax; + add esp, 0x3C; + jmp eor; + add0x40: + call eax; + add esp, 0x40; + jmp eor; + add0x44: + call eax; + add esp, 0x44; + jmp eor; + add0x48: + call eax; + add esp, 0x48; + jmp eor; + add0x4C: + call eax; + add esp, 0x4C; + jmp eor; + add0x50: + call eax; + add esp, 0x50; + jmp eor; + callee: + mov eax, address; + mov ecx, currentECXValue; + call eax; + eor: + } +#ifdef EH_GUARDRAILS } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif DWORD result; __asm { @@ -916,36 +930,6 @@ void __declspec(naked) detourLandingFunction() { -int convertTableToByteStream(lua_State* L, std::stringstream* s) { - - for (int i = 1; ; i++) { - lua_geti(L, -1, i); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - - if (!lua_isinteger(L, -1)) { - lua_pop(L, 1); - return -1; - } - - unsigned int value = lua_tointeger(L, -1); - - if (value <= 0xff && value >= 0x00) { - s->write(reinterpret_cast(&value), 1); - } - else { - s->write(reinterpret_cast(&value), 4); - } - - /* removes 'value' */ - lua_pop(L, 1); - } - - return 0; -} int luaWriteCode(lua_State* L) { if (lua_gettop(L) != 2) { @@ -963,8 +947,8 @@ int luaWriteCode(lua_State* L) { // and that converts integers to 4 bytes in big endian order. // // Makes use the of the table at -1 (2) - std::stringstream bytes; - int returnCode = convertTableToByteStream(L, &bytes); + ByteStream stream; + int returnCode = convertTableToByteStream(L, &stream); if (returnCode == -1) { return luaL_error(L, "The return value table must have integer values"); @@ -973,16 +957,14 @@ int luaWriteCode(lua_State* L) { return luaL_error(L, "The values must all be positive"); } - bytes.seekg(0, bytes.end); - int size = bytes.tellg(); - bytes.seekg(0, bytes.beg); - DWORD oldProtect; - VirtualProtect((LPVOID)address, size, PAGE_EXECUTE_READWRITE, &oldProtect); + VirtualProtect((LPVOID)address, stream.len, PAGE_EXECUTE_READWRITE, &oldProtect); + + memcpy((void*)address, stream.address, stream.len); - memcpy((void*)address, bytes.str().data(), size); + VirtualProtect((LPVOID)address, stream.len, oldProtect, &oldProtect); - VirtualProtect((LPVOID)address, size, oldProtect, &oldProtect); + free(stream.address); return 0; } diff --git a/CodeFunctions.h b/CodeFunctions.h index 5fa97a0..7a01cdf 100644 --- a/CodeFunctions.h +++ b/CodeFunctions.h @@ -9,7 +9,6 @@ #include #include #include "AOB.h" -#include "UtilityFunctions.h" #include "Memory.h" extern HANDLE codeHeap; @@ -29,5 +28,3 @@ int luaExposeCode(lua_State* L); int luaHookCode(lua_State* L); int luaCallMachineCode(lua_State* L); - -int convertTableToByteStream(lua_State* L, std::stringstream* s); \ No newline at end of file diff --git a/Exceptions.cpp b/Exceptions.cpp new file mode 100644 index 0000000..ade6189 --- /dev/null +++ b/Exceptions.cpp @@ -0,0 +1,22 @@ +#include "Exceptions.h" + + +const char errorReport[1000] = {}; +static const char* const errorReportTooLong = "error report is too longer, longer than 1000 characters"; + +int errorFilterAndReporter(unsigned int code, struct _EXCEPTION_POINTERS* ep) +{ + std::stringstream errorReportBuilder; + errorReportBuilder << "Exception occurred: code: 0x" << std::hex << code << " at 0x" << std::hex << ep->ExceptionRecord->ExceptionAddress; + std::string r = errorReportBuilder.str(); + const char* data = r.c_str(); + size_t size = strnlen_s(data, 1000); + if (size < 1000) { + // memset((void*)errorReport, 0, 1000); + memcpy((void*)errorReport, data, size + 1); + } + else { + memcpy((void*)errorReport, (void*)errorReportTooLong, strnlen_s(errorReportTooLong, 1000)); + } + return EXCEPTION_EXECUTE_HANDLER; +} \ No newline at end of file diff --git a/Exceptions.h b/Exceptions.h new file mode 100644 index 0000000..741b882 --- /dev/null +++ b/Exceptions.h @@ -0,0 +1,13 @@ +#pragma once + +#include "framework.h" +#include +#include + +#define RPS_HANDLE_SEH errorFilterAndReporter(GetExceptionCode(), GetExceptionInformation()) +#define RPS_LUA_SEH luaL_error(L, "%s", errorReport) +#define RPS_LUA_SEH_X(x) luaL_error(L, "%s while executing 0x%X", errorReport, x) +#define RPS_LUA_SEH_ADDRESS luaL_error(L, "%s while executing 0x%X", errorReport, address) + +extern const char errorReport[1000]; +int errorFilterAndReporter(unsigned int code, struct _EXCEPTION_POINTERS* ep); \ No newline at end of file diff --git a/MemoryFunctions.cpp b/MemoryFunctions.cpp index 75ef152..1f53dd7 100644 --- a/MemoryFunctions.cpp +++ b/MemoryFunctions.cpp @@ -2,6 +2,8 @@ #include "MemoryFunctions.h" #include "CodeFunctions.h" +#include "Exceptions.h" +#include "UtilityFunctions.hpp" int luaReadByte(lua_State* L) { if (lua_gettop(L) != 1) { @@ -11,7 +13,17 @@ int luaReadByte(lua_State* L) { if (address == 0) { return luaL_error(L, "argument 1 must be a valid address"); } - lua_pushinteger(L, *((BYTE*)address)); + +#ifdef EH_GUARDRAILS + __try { +#endif + lua_pushinteger(L, *((BYTE*)address)); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif return 1; } @@ -24,7 +36,16 @@ int luaReadSmallInteger(lua_State* L) { return luaL_error(L, "argument 1 must be a valid address"); } - lua_pushinteger(L, *((SHORT*)address)); +#ifdef EH_GUARDRAILS + __try { +#endif + lua_pushinteger(L, *((SHORT*)address)); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif return 1; } @@ -37,7 +58,16 @@ int luaReadInteger(lua_State* L) { return luaL_error(L, "argument 1 must be a valid address"); } - lua_pushinteger(L, *((int*)address)); +#ifdef EH_GUARDRAILS + __try { +#endif + lua_pushinteger(L, *((int*)address)); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif return 1; } @@ -66,14 +96,24 @@ int luaReadString(lua_State* L) { return luaL_error(L, "sorry, wide string is not supported yet."); } - if (length > 0) { - lua_pushlstring(L, (const char*)address, length); +#ifdef EH_GUARDRAILS + __try { +#endif + if (length > 0) { + lua_pushlstring(L, (const char*)address, length); + + } + else { + // Finds the first \0 byte and terminates + lua_pushlstring(L, (const char *)address, strlen((const char*) address)); + } +#ifdef EH_GUARDRAILS } - else { - // Finds the first \0 byte and terminates - std::string result((const char*)address); - lua_pushstring(L, result.c_str()); + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; } +#endif + return 1; } @@ -92,12 +132,26 @@ int luaReadBytes(lua_State* L) { lua_createtable(L, size, 0); - for (int i = 0; i < size; i++) { - unsigned char value = *((BYTE*)(address + i)); - lua_pushinteger(L, (lua_Integer)i + 1); - lua_pushinteger(L, value); - lua_settable(L, -3); /* 3rd element from the stack top */ +#ifdef EH_GUARDRAILS + __try { +#endif + for (int i = 0; i < size; i++) { + unsigned char value = *((BYTE*)(address + i)); + + + lua_pushinteger(L, (lua_Integer)i + 1); + lua_pushinteger(L, value); + lua_settable(L, -3); /* 3rd element from the stack top */ + } +#ifdef EH_GUARDRAILS } + __except (RPS_HANDLE_SEH) { + // address is technically not entirely correct, but will probably point + // in the right direction to fix the underlying cause + return RPS_LUA_SEH_ADDRESS; + } +#endif + // we pass the table back; @@ -116,13 +170,18 @@ int luaWriteString(lua_State* L) { size_t size = 0; const char* value = lua_tolstring(L, 2, &size); -#ifdef _DEBUG - if (!canWrite(address, size)) { - return luaL_error(L, "cannot write %d string to location: 0x%X", 1, address); +#ifdef EH_GUARDRAILS + __try { +#endif + memcpy((void*)address, value, size); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; } #endif - memcpy((void*)address, value, size); + return 0; } @@ -138,13 +197,17 @@ int luaWriteByte(lua_State* L) { BYTE value = lua_tointeger(L, 2); -#ifdef _DEBUG - if (!canWrite(address, 1)) { - return luaL_error(L, "cannot write 1 bytes to location: 0x%X", address); +#ifdef EH_GUARDRAILS + __try { +#endif + * ((BYTE*)address) = value; +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; } #endif - * ((BYTE*)address) = value; return 0; } @@ -159,13 +222,18 @@ int luaWriteSmallInteger(lua_State* L) { SHORT value = lua_tointeger(L, 2); -#ifdef _DEBUG - if (!canWrite(address, 2)) { - return luaL_error(L, "cannot write 2 bytes to location: 0x%X", address); +#ifdef EH_GUARDRAILS + __try { +#endif + * ((SHORT*)address) = value; +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; } #endif - * ((SHORT*)address) = value; + return 0; } @@ -180,16 +248,23 @@ int luaWriteInteger(lua_State* L) { int value = lua_tointeger(L, 2); -#ifdef _DEBUG - if (!canWrite(address, 4)) { - return luaL_error(L, "cannot write 4 bytes to location: 0x%X", address); +#ifdef EH_GUARDRAILS + __try { +#endif + * ((int*)address) = value; +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; } #endif - * ((int*)address) = value; + return 0; } + + int luaWriteBytes(lua_State* L) { if (lua_gettop(L) != 2) { return luaL_error(L, "expected exactly 2 arguments"); @@ -203,16 +278,10 @@ int luaWriteBytes(lua_State* L) { return luaL_error(L, "the second argument should be a table"); } -#ifdef _DEBUG - int length = lua_rawlen(L, 2); - if (!canWrite(address, length)) { - return luaL_error(L, "cannot write %d bytes to location: 0x%X", length, address); - } -#endif // Makes use the of the table at -1 (2) - std::stringstream bytes; - int returnCode = convertTableToByteStream(L, &bytes); + ByteStream stream; + int returnCode = convertTableToByteStream(L, &stream); if (returnCode == -1) { return luaL_error(L, "The return value table must have integer values"); @@ -221,12 +290,19 @@ int luaWriteBytes(lua_State* L) { return luaL_error(L, "The values must all be positive"); } - bytes.seekg(0, bytes.end); - int size = bytes.tellg(); - bytes.seekg(0, bytes.beg); +#ifdef EH_GUARDRAILS + __try { +#endif + // str() is null-terminated, but size is the size without the final null byte, which makes this correct + memcpy((void*)address, stream.address, stream.len); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif - // str() is null-terminated, but size is the size without the final null byte, which makes this correct - memcpy((void*)address, bytes.str().data(), size); + free(stream.address); return 0; } @@ -252,13 +328,17 @@ int luaMemCpy(lua_State* L) { return luaL_error(L, "argument 3 must be a valid size higher than 0"); } -#ifdef _DEBUG - if (!canWrite(dst, size)) { - return luaL_error(L, "cannot write %d bytes to location: 0x%X", size, dst); +#ifdef EH_GUARDRAILS + __try { +#endif + memcpy((void*)dst, (void*)src, size); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_X(dst); } #endif - - memcpy((void*)dst, (void*)src, size); + return 0; } @@ -286,13 +366,18 @@ int luaMemSet(lua_State* L) { return luaL_error(L, "argument 3 must be a valid size higher than 0"); } -#ifdef _DEBUG - if (!canWrite(dst, size)) { - return luaL_error(L, "cannot write %d bytes to location: 0x%X", size, dst); + +#ifdef EH_GUARDRAILS + __try { +#endif + memset((void*)dst, val, size); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_X(dst); } #endif - - memset((void*)dst, val, size); + return 0; } @@ -324,12 +409,22 @@ int luaAllocate(lua_State* L) { void* memory; int size = lua_tonumber(L, 1); - if (lua_gettop(L) == 2 && lua_toboolean(L, 2)) { - memory = calloc(size, sizeof(BYTE)); +#ifdef EH_GUARDRAILS + __try { +#endif + if (lua_gettop(L) == 2 && lua_toboolean(L, 2)) { + memory = calloc(size, sizeof(BYTE)); + } + else { + memory = malloc(size); + } +#ifdef EH_GUARDRAILS } - else { - memory = malloc(size); + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH; } +#endif + lua_pushinteger(L, (DWORD_PTR)memory); @@ -341,13 +436,24 @@ int luaDeallocate(lua_State* L) { return luaL_error(L, "Expected one argument"); } - int addr = luaL_checkinteger(L, 1); - if (addr == 0) { + int address = luaL_checkinteger(L, 1); + if (address == 0) { return luaL_error(L, "Address is 0"); } - void* memory = (void* )((DWORD_PTR) addr); - free(memory); + void* memory = (void* )((DWORD_PTR) address); + +#ifdef EH_GUARDRAILS + __try { +#endif + free(memory); +#ifdef EH_GUARDRAILS + } + __except (RPS_HANDLE_SEH) { + return RPS_LUA_SEH_ADDRESS; + } +#endif + return 0; } diff --git a/MemoryFunctions.h b/MemoryFunctions.h index d4dfb58..c4284cc 100644 --- a/MemoryFunctions.h +++ b/MemoryFunctions.h @@ -3,7 +3,6 @@ #include "framework.h" #include "lua.hpp" #include -#include "UtilityFunctions.h" #include #include diff --git a/RuntimePatchingSystem.cpp b/RuntimePatchingSystem.cpp index cf7c7d4..6ca31ba 100644 --- a/RuntimePatchingSystem.cpp +++ b/RuntimePatchingSystem.cpp @@ -10,7 +10,7 @@ #include "RuntimePatchingSystem.h" #include "CodeFunctions.h" #include "MemoryFunctions.h" -#include "UtilityFunctions.h" +#include "UtilityFunctions.hpp" #include "LibraryFunctions.h" diff --git a/RuntimePatchingSystem.vcxproj b/RuntimePatchingSystem.vcxproj index 40ba310..9373838 100644 --- a/RuntimePatchingSystem.vcxproj +++ b/RuntimePatchingSystem.vcxproj @@ -57,9 +57,10 @@ Level3 Disabled true - WIN32;_DEBUG;RUNTIMEPATCHINGLIBRARY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;EH_GUARDRAILS;_DEBUG;RUNTIMEPATCHINGLIBRARY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h + Async Windows @@ -75,9 +76,10 @@ true true true - WIN32;NDEBUG;RUNTIMEPATCHINGLIBRARY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;EH_GUARDRAILS;NDEBUG;RUNTIMEPATCHINGLIBRARY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h + Async Windows @@ -99,17 +101,19 @@ + - + + diff --git a/RuntimePatchingSystem.vcxproj.filters b/RuntimePatchingSystem.vcxproj.filters index cd84368..f2ca7ee 100644 --- a/RuntimePatchingSystem.vcxproj.filters +++ b/RuntimePatchingSystem.vcxproj.filters @@ -36,7 +36,7 @@ Header Files - + Header Files @@ -48,6 +48,9 @@ Header Files + + Header Files + @@ -71,6 +74,9 @@ Source Files + + Source Files + diff --git a/UtilityFunctions.cpp b/UtilityFunctions.cpp index 745e07d..c28cb0b 100644 --- a/UtilityFunctions.cpp +++ b/UtilityFunctions.cpp @@ -1,4 +1,4 @@ -#include "UtilityFunctions.h" +#include "UtilityFunctions.hpp" lua_State* LC = 0; @@ -17,4 +17,48 @@ bool canWrite(DWORD address, int length) { return mi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_WRITECOMBINE | PAGE_WRITECOPY | PAGE_READWRITE); } -#endif \ No newline at end of file +#endif + + +int convertTableToByteStream(lua_State* L, ByteStream * stream) { + std::stringstream s; + + for (int i = 1; ; i++) { + lua_geti(L, -1, i); + + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + break; + } + + if (!lua_isinteger(L, -1)) { + lua_pop(L, 1); + return -1; + } + + unsigned int value = lua_tointeger(L, -1); + + if (value <= 0xff && value >= 0x00) { + s.write(reinterpret_cast(&value), 1); + } + else { + s.write(reinterpret_cast(&value), 4); + } + + /* removes 'value' */ + lua_pop(L, 1); + } + + s.seekg(0, s.end); + int size = s.tellg (); + s.seekg(0, s.beg); + + stream->address = calloc(size, 1); + if (stream->address == NULL) { + return -1; + } + stream->len = size; + memcpy(stream->address, s.str().data(), size); + + return 0; +} \ No newline at end of file diff --git a/UtilityFunctions.h b/UtilityFunctions.h deleted file mode 100644 index 5c59338..0000000 --- a/UtilityFunctions.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "framework.h" -#include -#include "lua.hpp" - -extern lua_State* LC; - -#ifdef _DEBUG - -bool canWrite(DWORD address, int length); - -#endif diff --git a/UtilityFunctions.hpp b/UtilityFunctions.hpp new file mode 100644 index 0000000..f091212 --- /dev/null +++ b/UtilityFunctions.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "framework.h" +#include +#include "lua.hpp" +#include +#include + +extern lua_State* LC; + +#ifdef _DEBUG + +bool canWrite(DWORD address, int length); + +#endif + +typedef struct ByteStream { + void* address; + size_t len; +} ByteStream; + +int convertTableToByteStream(lua_State* L, ByteStream * stream); \ No newline at end of file From 9899e198ac21218da259fb00bf2160ead0310402 Mon Sep 17 00:00:00 2001 From: Gynt Date: Thu, 25 Sep 2025 22:04:52 +0200 Subject: [PATCH 2/2] feat(seh): fix errors in seh code --- Exceptions.cpp | 3 ++- Exceptions.h | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Exceptions.cpp b/Exceptions.cpp index ade6189..bd467d9 100644 --- a/Exceptions.cpp +++ b/Exceptions.cpp @@ -1,7 +1,8 @@ #include "Exceptions.h" -const char errorReport[1000] = {}; +char errorReport[1000] = {}; +char intHex[4 + 1] = {}; static const char* const errorReportTooLong = "error report is too longer, longer than 1000 characters"; int errorFilterAndReporter(unsigned int code, struct _EXCEPTION_POINTERS* ep) diff --git a/Exceptions.h b/Exceptions.h index 741b882..23d8c95 100644 --- a/Exceptions.h +++ b/Exceptions.h @@ -5,9 +5,10 @@ #include #define RPS_HANDLE_SEH errorFilterAndReporter(GetExceptionCode(), GetExceptionInformation()) -#define RPS_LUA_SEH luaL_error(L, "%s", errorReport) -#define RPS_LUA_SEH_X(x) luaL_error(L, "%s while executing 0x%X", errorReport, x) -#define RPS_LUA_SEH_ADDRESS luaL_error(L, "%s while executing 0x%X", errorReport, address) +#define RPS_LUA_SEH luaL_error(L, "%s", errorReport); +#define RPS_LUA_SEH_X(x) (sprintf_s(intHex, "%X", x), luaL_error(L, "%s address: 0x%s", errorReport, intHex)); +#define RPS_LUA_SEH_ADDRESS (sprintf_s(intHex, "%X", address), luaL_error(L, "%s address: 0x%s", errorReport, intHex)); -extern const char errorReport[1000]; +extern char intHex[4 + 1]; +extern char errorReport[1000]; int errorFilterAndReporter(unsigned int code, struct _EXCEPTION_POINTERS* ep); \ No newline at end of file