From e161a8ffb4a1eda6dff2554d4dcbb953e1b36001 Mon Sep 17 00:00:00 2001 From: Joseph Blackman Date: Sun, 26 Sep 2021 01:12:11 -0700 Subject: [PATCH 1/2] Improve findGlobals by using a sigscan --- App/Main.cpp | 2 +- Source/Memory.cpp | 38 +++++++++++++++++++++++++++++++++----- Source/Memory.h | 1 + Source/Special.cpp | 28 ---------------------------- Source/Special.h | 2 -- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/App/Main.cpp b/App/Main.cpp index d2681bd0..4fbac660 100644 --- a/App/Main.cpp +++ b/App/Main.cpp @@ -408,7 +408,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance else { std::string str = "Globals ptr not found. Press OK to search for globals ptr (may take a minute or two). Please keep The Witness open during this time."; if (MessageBox(GetActiveWindow(), std::wstring(str.begin(), str.end()).c_str(), NULL, MB_OK) != IDOK) return 0; - int address = Special::findGlobals(); + int address = memory.findGlobals(); if (address) { std::stringstream ss; ss << std::hex << "Address found: 0x" << address << ". This address wil be automatically loaded next time. Please post an issue on Github with this address so that it can be added in the future."; std::string str = ss.str(); diff --git a/Source/Memory.cpp b/Source/Memory.cpp index ff8e1442..7021d7b8 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp @@ -50,21 +50,49 @@ Memory::~Memory() { CloseHandle(_handle); } -int find(const std::vector &data, const std::vector& search, size_t startIndex = 0) { - for (size_t i=startIndex; i &data, const std::vector &search) { + const byte* dataBegin = &data[0]; + const byte* searchBegin = &search[0]; + size_t maxI = data.size() - search.size(); + size_t maxJ = search.size(); + + for (int i=0; i(i); + if (match) return i; } return -1; } +int Memory::findGlobals() { + const std::vector scanBytes = {0x74, 0x41, 0x48, 0x85, 0xC0, 0x74, 0x04, 0x48, 0x8B, 0x48, 0x10}; + #define BUFFER_SIZE 0x10000 // 10 KB + std::vector buff; + buff.resize(BUFFER_SIZE + 0x100); // padding in case the sigscan is past the end of the buffer + + for (uintptr_t i = 0; i < 0x500000; i += BUFFER_SIZE) { + SIZE_T numBytesWritten; + if (!ReadProcessMemory(_handle, reinterpret_cast(_baseAddress + i), &buff[0], buff.size(), &numBytesWritten)) continue; + buff.resize(numBytesWritten); + int index = find(buff, scanBytes); + if (index == -1) continue; + + index = index + 0x14; // This scan targets a line slightly before the key instruction + // (address of next line) + (index interpreted as 4byte int) + Memory::GLOBALS = (int)(i + index + 4) + *(int*)&buff[index]; + break; + } + + return Memory::GLOBALS; +} + void Memory::ThrowError(std::string message) { if (!showMsg) throw std::exception(message.c_str()); DWORD exitCode; diff --git a/Source/Memory.h b/Source/Memory.h index cf5e877e..4d4a0156 100644 --- a/Source/Memory.h +++ b/Source/Memory.h @@ -14,6 +14,7 @@ class Memory { public: Memory(const std::string& processName); + int findGlobals(); ~Memory(); Memory(const Memory& memory) = delete; diff --git a/Source/Special.cpp b/Source/Special.cpp index 6e3288ac..6e9db003 100644 --- a/Source/Special.cpp +++ b/Source/Special.cpp @@ -1522,34 +1522,6 @@ void Special::drawGoodLuckPanel(int id) drawText(id, intersections, connectionsA, connectionsB, { 0.66f, 0.62f, 0.66f, 0.69f, 0.32f, 0.69f, 0.51f, 0.51f, 0.32f, 0.32f, 0.66f, 0.32f, 0.66f, 0.39f }); } -int Special::findGlobals() { - Panel panel; - panel._memory->retryOnFail = false; //Too slow to retry every read - int address = 0; - for (int j = 0; j < 10; j++) { //Do several passes through memory, in case of memory faults - for (int i = 0x600000; i < 0x800000; i += 4) { - Memory::GLOBALS = i; - try { - if ((address = panel._memory->ReadPanelData(0x17E52, STYLE_FLAGS, 1)[0]) == 0x0000A040) { - return i; - } - } - catch (std::exception) {} - } - for (int i = 0x400000; i < 0x600000; i += 4) { - Memory::GLOBALS = i; - try { - if ((address = panel._memory->ReadPanelData(0x17E52, STYLE_FLAGS, 1)[0]) == 0x0000A040) { - return i; - } - } - catch (std::exception) {} - } - Sleep(10); - } - return 0; -} - //For testing/debugging purposes only void Special::test() { diff --git a/Source/Special.h b/Source/Special.h index ff802b63..b5dca3c8 100644 --- a/Source/Special.h +++ b/Source/Special.h @@ -196,8 +196,6 @@ class Special { return -1; } - static int findGlobals(); - private: std::shared_ptr generator; From 67ebc729987aa3cc6f927cdd46b092e09a33379d Mon Sep 17 00:00:00 2001 From: Joseph Blackman Date: Sun, 26 Sep 2021 01:12:45 -0700 Subject: [PATCH 2/2] Various other small cleanups Mostly avoiding string and object copies. --- App/Main.cpp | 13 ++++++------- App/Version.h | 4 ++-- Source/Memory.cpp | 2 +- Source/Special.cpp | 6 +++--- Source/Watchdog.cpp | 6 +++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/App/Main.cpp b/App/Main.cpp index 4fbac660..e81b8649 100644 --- a/App/Main.cpp +++ b/App/Main.cpp @@ -406,20 +406,19 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance file.close(); } else { - std::string str = "Globals ptr not found. Press OK to search for globals ptr (may take a minute or two). Please keep The Witness open during this time."; - if (MessageBox(GetActiveWindow(), std::wstring(str.begin(), str.end()).c_str(), NULL, MB_OK) != IDOK) return 0; + std::wstring str = L"Globals ptr not found. Press OK to search for globals ptr (may take a minute or two). Please keep The Witness open during this time."; + if (MessageBox(GetActiveWindow(), str.c_str(), NULL, MB_OK) != IDOK) return 0; int address = memory.findGlobals(); if (address) { - std::stringstream ss; ss << std::hex << "Address found: 0x" << address << ". This address wil be automatically loaded next time. Please post an issue on Github with this address so that it can be added in the future."; - std::string str = ss.str(); - MessageBox(GetActiveWindow(), std::wstring(str.begin(), str.end()).c_str(), NULL, MB_OK); + std::wstringstream ss; ss << std::hex << "Address found: 0x" << address << ". This address wil be automatically loaded next time. Please post an issue on Github with this address so that it can be added in the future."; + MessageBox(GetActiveWindow(), ss.str().c_str(), NULL, MB_OK); std::ofstream ofile("WRPGglobals.txt", std::ofstream::app); ofile << std::hex << address << std::endl; ofile.close(); } else { - str = "Address could not be found. Please post an issue on the Github page."; - MessageBox(GetActiveWindow(), std::wstring(str.begin(), str.end()).c_str(), NULL, MB_OK); + str = L"Address could not be found. Please post an issue on the Github page."; + MessageBox(GetActiveWindow(), str.c_str(), NULL, MB_OK); return 0; } } diff --git a/App/Version.h b/App/Version.h index 33b245a6..dd2bcb9d 100644 --- a/App/Version.h +++ b/App/Version.h @@ -1,13 +1,13 @@ #pragma once -#define TO_STRING2(s) L#s +#define TO_STRING2(s) #s #define TO_STRING(s) TO_STRING2(s) #define MAJOR 1 #define MINOR 2 #define PATCH 3 -#define VERSION_STR TO_STRING(MAJOR) L"." TO_STRING(MINOR) L"." TO_STRING(PATCH) +#define VERSION_STR TO_STRING(MAJOR) "." TO_STRING(MINOR) "." TO_STRING(PATCH) #define VERSION MAJOR, MINOR, PATCH #define PRODUCT_NAME L"Witness Random Puzzle Generator" diff --git a/Source/Memory.cpp b/Source/Memory.cpp index 7021d7b8..9a8c455f 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp @@ -99,7 +99,7 @@ void Memory::ThrowError(std::string message) { GetExitCodeProcess(_handle, &exitCode); if (exitCode != STILL_ACTIVE) throw std::exception(message.c_str()); message += "\nPlease close The Witness and try again. If the error persists, please report the issue on the Github Issues page."; - MessageBox(GetActiveWindow(), std::wstring(message.begin(), message.end()).c_str(), NULL, MB_OK); + MessageBoxA(GetActiveWindow(), message.c_str(), NULL, MB_OK); throw std::exception(message.c_str()); } diff --git a/Source/Special.cpp b/Source/Special.cpp index 6e9db003..1dccf5b7 100644 --- a/Source/Special.cpp +++ b/Source/Special.cpp @@ -146,7 +146,7 @@ void Special::generateColorFilterPuzzle(int id, Point size, const std::vectorReadPanelData(id, NUM_DOTS); std::vector intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); std::vector edges = _memory->ReadArray(id, TRACED_EDGE_DATA, length); - for (SolutionPoint sp : edges) if (intersectionFlags[sp.pointA] == Decoration::Dot_Intersection || intersectionFlags[sp.pointB] == Decoration::Dot_Intersection) return true; + for (const SolutionPoint& sp : edges) if (intersectionFlags[sp.pointA] == Decoration::Dot_Intersection || intersectionFlags[sp.pointB] == Decoration::Dot_Intersection) return true; return false; } @@ -220,7 +220,7 @@ void JungleWatchdog::action() if (!tracedptr) return; std::vector traced = ReadArray(id, TRACED_EDGE_DATA, numTraced); int seqIndex = 0; - for (SolutionPoint p : traced) { + for (const SolutionPoint& p : traced) { if ((sizes[p.pointA] & IntersectionFlags::DOT) == 0) continue; if (sizes[p.pointA] & (0x1000 << (state ? correctSeq1[seqIndex] : correctSeq2[seqIndex]))) seqIndex++;