diff --git a/src/main.cpp b/src/main.cpp index 5f975b63..c297fad9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) g_main_thread = CreateThread(nullptr, 0, [](PVOID) -> DWORD { while (!FindWindow("grcWindow", "Grand Theft Auto V")) - std::this_thread::sleep_for(1s); + std::this_thread::sleep_for(100ms); std::filesystem::path base_dir = std::getenv("appdata"); base_dir /= "BigBaseV2"; diff --git a/src/memory/module.cpp b/src/memory/module.cpp index fe98977a..2706a7ad 100644 --- a/src/memory/module.cpp +++ b/src/memory/module.cpp @@ -3,31 +3,75 @@ namespace memory { - module::module(HMODULE mod) : - range(mod, 0) - { - auto dosHeader = m_base.as(); - auto ntHeader = m_base.add(dosHeader->e_lfanew).as(); - m_size = ntHeader->OptionalHeader.SizeOfImage; - } - - module::module(std::nullptr_t) : - module(GetModuleHandle(nullptr)) - { - } - - module::module(std::string_view name) : - module(GetModuleHandleA(name.data())) - { - } - - module::module(std::wstring_view name) : - module(GetModuleHandleW(name.data())) + module::module(const std::string_view name) : + range(nullptr, 0), + m_name(name), + m_loaded(false) { + try_get_module(); } handle module::get_export(std::string_view symbol_name) { - return GetProcAddress(m_base.as(), symbol_name.data()); + if (!m_loaded) + return nullptr; + + const auto dosHeader = m_base.as(); + const auto ntHeader = m_base.add(dosHeader->e_lfanew).as(); + const auto imageDataDirectory = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + const auto exportDirectory = m_base.add(imageDataDirectory.VirtualAddress).as(); + + const auto nameOffsetArray = m_base.add(exportDirectory->AddressOfNames).as(); + const auto ordinalArray = m_base.add(exportDirectory->AddressOfNameOrdinals).as(); + const auto functionOffsetArray = m_base.add(exportDirectory->AddressOfFunctions).as(); + + for (std::size_t i = 0; i < exportDirectory->NumberOfFunctions; i++) + { + const auto functionName = m_base.add(nameOffsetArray[i]).as(); + if (strcmp(functionName, symbol_name.data())) + continue; + + return functionOffsetArray + ordinalArray[i]; + } + return nullptr; + } + + bool module::loaded() const + { + return m_loaded; + } + + bool module::wait_for_module(std::optional time) + { + const auto giveup_time = time.has_value() + ? std::make_optional(std::chrono::high_resolution_clock::now() + time.value()) + : std::nullopt; + LOG(G3LOG_DEBUG) << "Waiting for " << m_name << "..."; + while (!try_get_module()) + { + if (giveup_time.has_value() && giveup_time <= std::chrono::high_resolution_clock::now()) + break; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + return m_loaded; + } + + bool module::try_get_module() + { + if (m_loaded) + return m_loaded; + + const auto mod = GetModuleHandleA(m_name.data()); + if (!mod) + return false; + m_loaded = true; + + m_base = mod; + const auto dosHeader = m_base.as(); + const auto ntHeader = m_base.add(dosHeader->e_lfanew).as(); + + m_size = ntHeader->OptionalHeader.SizeOfImage; + + return m_loaded; } } diff --git a/src/memory/module.hpp b/src/memory/module.hpp index a71f8624..8fb6a6d5 100644 --- a/src/memory/module.hpp +++ b/src/memory/module.hpp @@ -6,11 +6,32 @@ namespace memory class module : public range { public: - module(HMODULE mod); - explicit module(std::nullptr_t); - explicit module(std::string_view name); - explicit module(std::wstring_view name); + explicit module(const std::string_view name); + /** + * @brief Get the export address of the current module given a symbol name + * + * @param symbol_name + * @return memory::handle + */ memory::handle get_export(std::string_view symbol_name); + + bool loaded() const; + /** + * @brief Waits till the given module is loaded. + * + * @param time Time to wait before giving up. + * @return true + * @return false + */ + bool wait_for_module(std::optional time = std::nullopt); + + protected: + bool try_get_module(); + + private: + const std::string_view m_name; + bool m_loaded; + }; } diff --git a/src/pointers.cpp b/src/pointers.cpp index d7000dc6..468e2142 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -482,7 +482,7 @@ namespace big m_communications = ptr.add(3).rip().as(); }); - auto mem_region = memory::module(nullptr); + auto mem_region = memory::module("GTA5.exe"); main_batch.run(mem_region); memory::batch socialclub_batch; @@ -495,7 +495,12 @@ namespace big m_update_presence_attribute_string = presence_data_vft[3]; }); - socialclub_batch.run(memory::module("socialclub.dll")); + auto sc_module = memory::module("socialclub.dll"); + if (sc_module.wait_for_module()) + { + socialclub_batch.run(sc_module); + } + else LOG(WARNING) << "socialclub.dll module was not loaded within the time limit."; if (auto pat = mem_region.scan("41 80 78 28 ? 0F 85 F5 01 00 00")) { diff --git a/src/util/system.hpp b/src/util/system.hpp index bae6642d..4d7395fa 100644 --- a/src/util/system.hpp +++ b/src/util/system.hpp @@ -1,5 +1,6 @@ #pragma once #include "crossmap.hpp" +#include "file_manager.hpp" #include "pointers.hpp" #include "memory/module.hpp" @@ -7,13 +8,10 @@ namespace big::system { inline void dump_entry_points() { - DWORD64 base_address = memory::module(nullptr).begin().as(); + DWORD64 base_address = memory::module("GTA5.exe").begin().as(); - std::string path = std::getenv("appdata"); - path += "\\BigBaseV2\\entrypoints.txt"; - - std::ofstream file; - file.open(path, std::ios::out |std::ios::trunc); + const auto file_path = g_file_manager->get_project_file("./entrypoints.txt"); + auto file = std::ofstream(file_path.get_path(), std::ios::out | std::ios::trunc); for (auto &map : g_crossmap) { @@ -27,7 +25,7 @@ namespace big::system inline uintptr_t get_relative_address(void* ptr) { - uintptr_t base_address = memory::module(nullptr).begin().as(); + uintptr_t base_address = memory::module("GTA5.exe").begin().as(); return (uintptr_t)ptr - base_address; }