Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Kolyah35 committed Jan 7, 2025
2 parents 4e18c9b + be4ddf8 commit 763688b
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 39 deletions.
34 changes: 17 additions & 17 deletions api/stringPatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ namespace gdl {
#if defined(GEODE_IS_WINDOWS64)
bool patchCString(uintptr_t srcAddr, const char* str) {
uint8_t* arr = (uint8_t*)srcAddr;
if(arr[1] != 0x8D) {
if (arr[1] != 0x8D) {
log::error("0x{:X}: instruction isn't lea!", srcAddr);
return false;
}

uint8_t reg = arr[2] >> 3;

// clang-format off
std::array<uint8_t, 11> patch = {
static_cast<uint8_t>(0x48 | (reg > 0x07)), // prefix 64 bit operation
static_cast<uint8_t>(0xB8 | (reg & 0xF7)), // mov <reg>,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <64-bit value>
0xC3 // ret
};
// clang-format on

*(uintptr_t*)(patch.data() + 2) = (uintptr_t)str;

Expand All @@ -35,7 +37,7 @@ namespace gdl {
std::copy(patch.begin(), patch.end(), tramp);

std::array<uint8_t, 7> callBytes = {0xE8, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90}; // call <tramp> and 2 NOPs
auto relAddr = (uintptr_t)tramp - ((uintptr_t)srcAddr + 5); // call is 5 bytes long
auto relAddr = (uintptr_t)tramp - ((uintptr_t)srcAddr + 5); // call is 5 bytes long
*(int32_t*)(callBytes.data() + 1) = (int32_t)relAddr;

if (Mod::get()->patch((void*)srcAddr, ByteVector(callBytes.begin(), callBytes.end())).isErr()) {
Expand All @@ -46,7 +48,7 @@ namespace gdl {
return true;
}

bool patchStdString(uintptr_t srcAddr, std::string const& str) {
bool patchStdString(uintptr_t srcAddr, const std::string& str) {
// clang-format off
// 1. patch the alloc_data function
// 1. patch `lea rcx/ecx, [...]` OR `mov ecx/rcx ...` to the correct string size (with \0).
Expand Down Expand Up @@ -76,55 +78,53 @@ namespace gdl {
uint8_t reg = 0;


// check for 64-bit operation
if(*arr == 0x48 || *arr == 0x49) {
// check for 64-bit or 16-bit operation
if (*arr == 0x48 || *arr == 0x49 || *arr == 0x66) {
arr++;
availableSize++;
}

if(*arr == 0x8D) { // lea
if (*arr == 0x8D) { // lea
auto modrm = gdlutils::decodeModRM(*arr);
availableSize += modrm.size;
reg = modrm.reg;
} else if(*arr == 0x89 || *arr == 0x8B) { // mov <reg>, <reg> || mov <reg>, [mem]
} else if (*arr == 0x89 || *arr == 0x8B) { // mov <reg>, <reg> || mov <reg>, [mem]
auto modrm = gdlutils::decodeModRM(*arr);
availableSize += modrm.size;
reg = modrm.reg;
} else if(*arr >= 0xB8 && *arr <= 0xBF) { // mov <reg>, <imm>
} else if (*arr >= 0xB8 && *arr <= 0xBF) { // mov <reg>, <imm>
availableSize += 5;
reg = (*arr - 0xB8) & 0xF7;
} else {
log::error("0x{:X}: Unknown operand {}!", srcAddr, arr[0]);
return false;
}

bool strTooLong =
(availableSize <= 3 && str.size() > 0x7F) ||
(availableSize == 4 && str.size() > 0x7FFF);
bool strTooLong = (availableSize <= 3 && str.size() > 0x7F) || (availableSize == 4 && str.size() > 0x7FFF);

if(strTooLong) {
if (strTooLong) {
log::error("0x{:X}: String too long!", srcAddr, str.size());
return false;
}

std::vector<uint8_t> patch(availableSize, 0x90);

if(availableSize <= 3) {
if (availableSize <= 3) {
patch[0] = 0xB0 | (reg & 0xF7);
patch[1] = static_cast<int8_t>(str.size());
}

if(availableSize == 4) {
if (availableSize == 4) {
int16_t size = static_cast<int16_t>(str.size());
patch[0] = 0x66;
patch[1] = 0xB0 | (reg & 0xF7);
std::copy(&patch[3], (uint8_t*)(&size), (uint8_t*)(&size) + sizeof(size));
std::copy(&patch[3], (uint8_t*)(&size), (uint8_t*)(&size) + sizeof(size));
}

if(availableSize >= 5) {
if (availableSize >= 5) {
int32_t size = static_cast<int32_t>(str.size());
patch[0] = 0xB8 | (reg & 0xF7);
std::copy(&patch[1], (uint8_t*)(&size), (uint8_t*)(&size) + sizeof(size));
std::copy(&patch[1], (uint8_t*)(&size), (uint8_t*)(&size) + sizeof(size));
}

if (Mod::get()->patch((void*)srcAddr, ByteVector(patch.begin(), patch.end())).isErr()) {
Expand Down
2 changes: 1 addition & 1 deletion libs/utf8
14 changes: 7 additions & 7 deletions src/hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,13 @@ void gd_string_assign_hk(void* self, char* src, size_t len) {
$execute {
#ifdef GEODE_IS_WINDOWS
// constexpr auto GD_STR_ASSIGN_ADDR = 0x3BE50; // OLD (2.206?)
// constexpr auto GD_STR_ASSIGN_ADDR = 0x3cca0;
// gd_string_assign_o = reinterpret_cast<void (__thiscall*)(void* self, char* src, size_t len)>(base::get() + GD_STR_ASSIGN_ADDR);
// auto res2 = Mod::get()->hook((void*)(base::get() + GD_STR_ASSIGN_ADDR), gd_string_assign_hk, "gd::string::assign", tulip::hook::TulipConvention::Thiscall).err();
// if (res2 != std::nullopt) {
// log::error("Failed to hook gd::string::assign because of: {}", res2);
// }
constexpr auto GD_STR_ASSIGN_ADDR = 0x3cca0;
gd_string_assign_o = reinterpret_cast<void(__thiscall*)(void* self, char* src, size_t len)>(base::get() + GD_STR_ASSIGN_ADDR);
auto res2 = Mod::get()->hook((void*)(base::get() + GD_STR_ASSIGN_ADDR), gd_string_assign_hk, "gd::string::assign", tulip::hook::TulipConvention::Thiscall).err();
if (res2 != std::nullopt) {
log::error("Failed to hook gd::string::assign because of: {}", res2);
}

// constexpr auto GD_STR_APPEND_ADDR = 0x21DE0;
// gd_string_append_o = reinterpret_cast<void (__thiscall*)(void*, char*, size_t)>(base::get() + GD_STR_APPEND_ADDR);
// auto res3 = Mod::get()->hook((void*)(base::get() + GD_STR_APPEND_ADDR), gd_string_append_hk, "gd::string::append", tulip::hook::TulipConvention::Thiscall).err();
Expand Down
32 changes: 20 additions & 12 deletions src/patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ void patches::patchStrings() {
patches::fixCyrillicP();

#ifdef GEODE_IS_WINDOWS64
bool res3;
res3 = gdl::patchCString(base::get() + 0x320CB5, "Настройки");
// log::debug("{}", res3);
// res3 = gdl::patchCString(base::get() + 0x350598, "Привет, мир 2!");
// log::debug("{}", res3);
// res3 = gdl::patchCString(base::get() + 0x3505F1, "Привет, мир 3!");
// log::debug("{}", res3);

// bool res2;
// res2 = gdl::patchStdStringRel("hi", 0x31561F, 0x31562F, 0x315638, {0x315641, 0x315648, 0x31564B, 0x315652, 0x315656, 0x31565C, 0x31565F, 0x315666, 0x31566A});
// // res2 = gdl::patchStdStringRel("This is a very very long string1!This is a very very long string2!This is a very very long string3!This is a very very long string4!This is a very very long string5!", 0x31561F, 0x31562F, 0x315638, {0x315641, 0x315648, 0x31564B, 0x315652, 0x315656, 0x31565C, 0x31565F, 0x315666, 0x31566A});
// log::debug("res {}", res2);
bool res3;
res3 = gdl::patchCString(base::get() + 0x320CB5, "Настройки");

///////////// OLD /////////////
// log::debug("{}", res3);
// res3 = gdl::patchCString(base::get() + 0x350598, "Привет, мир 2!");
// log::debug("{}", res3);
// res3 = gdl::patchCString(base::get() + 0x3505F1, "Привет, мир 3!");
// log::debug("{}", res3);

// bool res2;
// res2 = gdl::patchStdStringRel("hi", 0x31561F, 0x31562F, 0x315638, {0x315641, 0x315648, 0x31564B, 0x315652, 0x315656, 0x31565C, 0x31565F, 0x315666, 0x31566A});
// // res2 = gdl::patchStdStringRel("This is a very very long string1!This is a very very long string2!This is a very very long string3!This is a very very long string4!This is a very very long string5!", 0x31561F, 0x31562F, 0x315638, {0x315641, 0x315648, 0x31564B, 0x315652, 0x315656, 0x31565C, 0x31565F, 0x315666, 0x31566A});
// log::debug("res {}", res2);

// bool res2;
// res2 = gdl::patchStdString2("Hello world! This is a long enough string!", {{base::get() + 0x31561F, 0x4F}}, base::get() + 0x31562A); // quit text
Expand All @@ -59,6 +61,12 @@ void patches::patchStrings() {
// log::debug("res {}", res2);
// res2 = gdl::patchStdString2("Hello!", {{base::get() + 0x67032, 0x2a}}, base::get() + 0x67052); // "Ease Out" which is inlined
// log::debug("res {}", res2);
///////////////////////////////

// bool res;
// res = gdl::patchCString(base::get() + 0x35C17A, "Привет GDL!"); // yay it works


#endif

auto languageID = gdl::getCurrentLanguage();
Expand Down
2 changes: 1 addition & 1 deletion src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,5 @@ ModRM gdlutils::decodeModRM(uint8_t modrm){

ret.reg = (modrm >> 2) & 0b00000111;

return ret
return ret;
}

0 comments on commit 763688b

Please sign in to comment.