commit e2f4d891a3360eec1fd8fafc8161c9af374a2eb7 Author: Abheek Dhawan Date: Tue Dec 28 13:05:44 2021 -0600 Initial commit 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 0000000..b5383ff Binary files /dev/null and b/modlimitfix.ico differ diff --git a/modlimitfix.rc b/modlimitfix.rc new file mode 100644 index 0000000..236aacf --- /dev/null +++ b/modlimitfix.rc @@ -0,0 +1 @@ +id ICON "./modlimitfix.ico" diff --git a/modlimitfix.res b/modlimitfix.res new file mode 100644 index 0000000..01a3795 Binary files /dev/null and b/modlimitfix.res differ