From e2f4d891a3360eec1fd8fafc8161c9af374a2eb7 Mon Sep 17 00:00:00 2001 From: Abheek Dhawan Date: Tue, 28 Dec 2021 13:05:44 -0600 Subject: [PATCH] Initial commit --- main.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ modlimitfix.ico | Bin 0 -> 2462 bytes modlimitfix.rc | 1 + modlimitfix.res | Bin 0 -> 2734 bytes 4 files changed, 136 insertions(+) create mode 100644 main.cpp create mode 100644 modlimitfix.ico create mode 100644 modlimitfix.rc create mode 100644 modlimitfix.res diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9d00146 --- /dev/null +++ b/main.cpp @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +namespace fs = std::filesystem; + +static const uint64_t address_not_found = 0; +static const uint64_t address_already_patched = 1; +static const uint64_t check_range_start = 0xB94000; +static const uint64_t check_range_end = 0xB98000; +static const uint64_t patch_offset_in_sequence = 1; +static const uint32_t patched_limit = 500; + +static const std::vector known_candidates{0xB95CF6, 0xB96366, + 0xB967A6, 0xB95E56}; +static const std::vector unpatched_sequence{0xBA, 0xC0, 0x00, 0x00, + 0x00, 0x48, 0x8D, 0x4B}; +static const std::vector patched_sequence{0xBA, 0xF4, 0x01, 0x00, + 0x00, 0x48, 0x8D, 0x4B}; + +uint64_t find_patch_address(const std::vector &search_buffer) { + for (auto candidate : known_candidates) { + size_t candidate_range_start = + candidate - check_range_start - patch_offset_in_sequence; + std::vector checked_bytes( + &search_buffer[candidate_range_start], + &search_buffer[candidate_range_start + unpatched_sequence.size()]); + + if (checked_bytes == unpatched_sequence) { + return candidate; + } else if (checked_bytes == patched_sequence) { + return address_already_patched; + } + } + + for (size_t i = 0; i < search_buffer.size() - unpatched_sequence.size(); + i++) { + std::vector checked_bytes( + &search_buffer[i], &search_buffer[i + unpatched_sequence.size()]); + + if (checked_bytes == unpatched_sequence) { + return i + check_range_start + patch_offset_in_sequence; + } + } + + for (size_t i = 0; i < search_buffer.size() - patched_sequence.size(); i++) { + std::vector checked_bytes( + &search_buffer[i], &search_buffer[i + patched_sequence.size()]); + + if (checked_bytes == patched_sequence) { + return address_already_patched; + } + } + + return address_not_found; +} + +int main() { + auto path = fs::absolute(fs::current_path() / "witcher3.exe"); + + if (!fs::exists(path)) { + cout << "Could not find witcher3.exe file, make sure you are running this " + << "in the bin/x64 directory." << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } + + size_t read_size = check_range_end - check_range_start; + std::vector search_buffer(read_size); + + { + std::ifstream file(path.c_str(), std::ios::binary); + file.seekg(check_range_start); + + if (file.eof() || + !file.read(reinterpret_cast(search_buffer.data()), read_size)) { + cout << "witcher3.exe is unexpectedly small, aborting patching." << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } + } + + uint64_t patch_address = find_patch_address(search_buffer); + + if (patch_address == address_not_found) { + cout << "Did not find the address to patch, possibly an unexpected version " + "of executable. Contact sedmelluq and give him your exe." << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } else if (patch_address == address_already_patched) { + cout << "It seems the executable is already patched" << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } + + auto backup_path = fs::absolute(fs::current_path() / "witcher3.exe.orig"); + + if (fs::exists(backup_path)) { + cout << "Backup file witcher3.exe.orig already exists. Rename it or delete " + "it (might be left over from previous patch attempt)." << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } else if (!fs::copy_file(path, backup_path)) { + cout << "Failed to create backup file, try running as administrator." << endl; + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; + } + + { + std::fstream file(path.c_str(), std::fstream::binary | std::fstream::in | + std::fstream::out); + file.seekp(patch_address); + + if (file.eof()) { + cout << "Unexpectedly encountered file end when writing patch." << endl; + } else if (!file.write((char *)&patched_limit, sizeof(patched_limit))) { + cout << "Failed to write patch" << endl; + } else { + cout << "Successfully patched." << endl; + } + } + cout << "Please press ENTER or close the window to terminate the program" << endl; + cin.get(); + return 0; +} diff --git a/modlimitfix.ico b/modlimitfix.ico new file mode 100644 index 0000000000000000000000000000000000000000..b5383ffca7a8ee419a6047db5cbfe5efa34b172a GIT binary patch literal 2462 zcmds1yG{a85FJ8-F^Gv4h7KAZrC*?y5@Xaqu~ic&Ec6d3`4yB7Q9Hp>@CS^N*vNX$ z-5qni-n(qD(jjN(&Y3f_!|s4c4xe&aaIMPayvT}(YyhBS6CiI4xz1vYnD{@}D2i&p z2(WG7`-Tua+9I5Xz^+fL9P(~&w)g;6RYQ+>J>lWL+0fRxXH_bXxS4Pd@LNC;*a7+g zt!Zfup|Q^!0WO-uaT&N(-tjkxmn^MGYwYt@J?A#H@Fk!D41h7f+3Uc9-2<^Pn{&?) z@SX8_(>Pzr)r4YG5nsA+`zboUJAJ5sVaK=JdFQi3| z&zv?6X+k_|wDvVcv(4tPS>`{DOa1dBx5mDSrV*OK!jU?gQ-vC<40Q-7NLfH0XB(aG!1S?)S7_p*$KN0(Zb0z~6;;zeDwZoyYg( zUP$}BBJJaf^l~kO>wHVDq6>M7&gCWQ03+iWlkY?=xlh2lcC{jtd}M$vGd?m!8_0;hp$R4M2Mj9wZ&FoN7wm&jc2nOI!l#ggy$2RjTpuGJ_g0Ia z;G*Y9<6o}hsAIAh@?zUFeH?$ij(tSm0MlR|>;TDnz;yxdr?ew*@j1-%;GK_0dJF$t zz;$Wwr*u%Sxm_)K2CRTxZ~!#>GB^|Vz;_bHVjF_qnVz>q^UcJZobM`zmrc~25j?#+ z|9qEoyf_~8mw5|i<-?x@&s2zP=eXqb%q0goPA*Q3ul+WHb5qTclg$5g zSel-n+$Hs`IV-st;&{#XO3(jpf}6>q}H z)inBcaFrf8M6%OQKGpN!