diff options
author | BDKPlayer <fabian.stotz@yahoo.de> | 2020-03-27 22:09:57 +0100 |
---|---|---|
committer | BDKPlayer <fabian.stotz@yahoo.de> | 2020-03-27 22:09:57 +0100 |
commit | 78ddf8f82467c64d8653cea199e1f435afe41b76 (patch) | |
tree | 39d6eb7d140d19efa572e63fdd1006f047a2e3ad | |
parent | e95f90c028b40f39a41f18533f7cc921f4f37dd3 (diff) |
Added: Custom Loading Screen
Fixed: Minimaphook now works in release/debug
-rw-r--r-- | AoE_imgui_DE.vcxproj | 19 | ||||
-rw-r--r-- | AoE_imgui_DE.vcxproj.filters | 24 | ||||
-rw-r--r-- | Classes.h | 10 | ||||
-rw-r--r-- | Core.cpp | 25 | ||||
-rw-r--r-- | CustomLoadingScreen.cpp | 32 | ||||
-rw-r--r-- | CustomLoadingScreen.h | 20 | ||||
-rw-r--r-- | ESP.cpp | 19 | ||||
-rw-r--r-- | Engine.cpp | 4 | ||||
-rw-r--r-- | MidfunctionHook.cpp | 210 | ||||
-rw-r--r-- | MidfunctionHook.h | 84 | ||||
-rw-r--r-- | MinimapText.cpp | 121 | ||||
-rw-r--r-- | Offsets.cpp | 28 | ||||
-rw-r--r-- | Offsets.h | 27 | ||||
-rw-r--r-- | Patcher.cpp | 112 | ||||
-rw-r--r-- | Patcher.h | 20 | ||||
-rw-r--r-- | RelicManager.cpp | 4 | ||||
-rw-r--r-- | ResourceInformation.cpp | 1 | ||||
-rw-r--r-- | Resources.h | 43 | ||||
-rw-r--r-- | SDK.h | 3 |
19 files changed, 672 insertions, 134 deletions
diff --git a/AoE_imgui_DE.vcxproj b/AoE_imgui_DE.vcxproj index bc4b41c..81ce97e 100644 --- a/AoE_imgui_DE.vcxproj +++ b/AoE_imgui_DE.vcxproj @@ -30,6 +30,7 @@ <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <CharacterSet>Unicode</CharacterSet> + <InterproceduralOptimization>false</InterproceduralOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -37,12 +38,14 @@ <PlatformToolset>v142</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> + <InterproceduralOptimization>false</InterproceduralOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <ConfigurationType>DynamicLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <CharacterSet>Unicode</CharacterSet> + <InterproceduralOptimization>false</InterproceduralOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -50,6 +53,7 @@ <PlatformToolset>v142</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>NotSet</CharacterSet> + <InterproceduralOptimization>false</InterproceduralOptimization> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -86,7 +90,7 @@ <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> + <Optimization>MinSpace</Optimization> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;AoE_imgui_DE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> <Link> @@ -101,6 +105,7 @@ <WarningLevel>Level3</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;AoE_imgui_DE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <BasicRuntimeChecks>Default</BasicRuntimeChecks> </ClCompile> <Link> <SubSystem>Windows</SubSystem> @@ -112,7 +117,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> + <Optimization>MinSpace</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;AoE_imgui_DE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -129,7 +134,7 @@ <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> + <Optimization>MinSpace</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;AoE_imgui_DE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -144,6 +149,7 @@ <ItemGroup> <ClInclude Include="Classes.h" /> <ClInclude Include="Core.h" /> + <ClInclude Include="CustomLoadingScreen.h" /> <ClInclude Include="DetourHook64.h" /> <ClInclude Include="detours.h" /> <ClInclude Include="Engine.h" /> @@ -159,17 +165,19 @@ <ClInclude Include="imgui\imstb_textedit.h" /> <ClInclude Include="imgui\imstb_truetype.h" /> <ClInclude Include="main.h" /> + <ClInclude Include="MidfunctionHook.h" /> <ClInclude Include="MinimapText.h" /> <ClInclude Include="Offsets.h" /> + <ClInclude Include="Patcher.h" /> <ClInclude Include="RelicManager.h" /> <ClInclude Include="Renderer.h" /> <ClInclude Include="ResourceInformation.h" /> - <ClInclude Include="Resources.h" /> <ClInclude Include="SDK.h" /> <ClInclude Include="Utility.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="Core.cpp" /> + <ClCompile Include="CustomLoadingScreen.cpp" /> <ClCompile Include="DetourHook64.cpp" /> <ClCompile Include="Engine.cpp" /> <ClCompile Include="ESP.cpp" /> @@ -181,7 +189,10 @@ <ClCompile Include="imgui\imgui_impl_dx11.cpp" /> <ClCompile Include="imgui\imgui_impl_win32.cpp" /> <ClCompile Include="imgui\imgui_widgets.cpp" /> + <ClCompile Include="MidfunctionHook.cpp" /> <ClCompile Include="MinimapText.cpp" /> + <ClCompile Include="Offsets.cpp" /> + <ClCompile Include="Patcher.cpp" /> <ClCompile Include="RelicManager.cpp" /> <ClCompile Include="Renderer.cpp" /> <ClCompile Include="ResourceInformation.cpp" /> diff --git a/AoE_imgui_DE.vcxproj.filters b/AoE_imgui_DE.vcxproj.filters index ec3121a..abb66d8 100644 --- a/AoE_imgui_DE.vcxproj.filters +++ b/AoE_imgui_DE.vcxproj.filters @@ -96,9 +96,6 @@ <ClInclude Include="Classes.h"> <Filter>Header Files\SDK</Filter> </ClInclude> - <ClInclude Include="Resources.h"> - <Filter>Header Files\SDK</Filter> - </ClInclude> <ClInclude Include="ESP.h"> <Filter>Header Files\Feature</Filter> </ClInclude> @@ -111,6 +108,15 @@ <ClInclude Include="RelicManager.h"> <Filter>Header Files\Feature</Filter> </ClInclude> + <ClInclude Include="MidfunctionHook.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Patcher.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="CustomLoadingScreen.h"> + <Filter>Header Files\Feature</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="imgui\imgui.cpp"> @@ -164,5 +170,17 @@ <ClCompile Include="RelicManager.cpp"> <Filter>Source Files\Feature</Filter> </ClCompile> + <ClCompile Include="MidfunctionHook.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Offsets.cpp"> + <Filter>Source Files\SDK</Filter> + </ClCompile> + <ClCompile Include="Patcher.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="CustomLoadingScreen.cpp"> + <Filter>Source Files\Feature</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file @@ -155,8 +155,14 @@ public: float stone; //0x0008 float gold; //0x000C float popSpaceLeft; //0x0010 - -}; //Size=0x00C8 + char pad_0x0014[0x4]; //0x0014 + float age; //0x0018 + char pad_0x001C[0x10]; //0x001C + float currentPop; //0x002C + char pad_0x0030[0x64]; //0x0030 + float villagerCount; //0x0094 + +}; //Size=0x0098 class Player { @@ -17,14 +17,18 @@ #include "ESP.h" #include "MinimapText.h" #include "RelicManager.h" +#include "CustomLoadingScreen.h" Core::Core() { + FeatureManager* featureManager = FeatureManager::Get(); //Register Features here - FeatureManager::Get()->registerFeature(new ResourceInformation()); - FeatureManager::Get()->registerFeature(new ESP()); - //FeatureManager::Get()->registerFeature(new MinimapText()); - FeatureManager::Get()->registerFeature(new RelicManager()); + featureManager->registerFeature(new ResourceInformation()); + featureManager->registerFeature(new ESP()); + featureManager->registerFeature(new MinimapText()); + featureManager->registerFeature(new RelicManager()); + featureManager->registerFeature(new CustomLoadingScreen("C:\\wallpaper.jpg")); + FeatureManager::Get()->OnInitialise(); } @@ -37,11 +41,6 @@ void createPlayerTreeNode(Player* player, int playerIndex) { ImGui::PushStyleColor(ImGuiCol_Text, 0xffffffff); ImGui::Text("Player %p (%f, %f)", player, player->xScreenPos, player->yScreenPos); - if (ImGui::Button("Set camera to 0")) - { - player->xScreenPos = 0; - player->yScreenPos = 0; - } FeatureManager::Get()->OnMenuPlayerTreenode(player, playerIndex); if (ImGui::TreeNode("Units")) { @@ -89,26 +88,26 @@ void Core::OnPresent() { __try { - printf("Valid: "); + //printf("Valid: "); MainScreen* mainScreen = Engine::Get()->GetMainScreen(); if (!mainScreen) { return; } - printf("mainScreen %p", mainScreen); + //printf("mainScreen %p", mainScreen); World* world = Engine::Get()->GetWorld(); if (!world) { return; } - printf(" world %p", world); + //printf(" world %p", world); PlayerArray* playerArray = world->pPlayerArray; if (!playerArray) { return; } - printf(" playerArray %p", playerArray); + //printf(" playerArray %p", playerArray); int totalPlayers = Engine::Get()->GetTotalPlayers(); static bool openOverlay = true; diff --git a/CustomLoadingScreen.cpp b/CustomLoadingScreen.cpp new file mode 100644 index 0000000..a3c0c44 --- /dev/null +++ b/CustomLoadingScreen.cpp @@ -0,0 +1,32 @@ +#include "CustomLoadingScreen.h" + +#include "Patcher.h" + + +CustomLoadingScreen::CustomLoadingScreen(char* imagePath) +{ + this->imagePath = imagePath; +} + +void CustomLoadingScreen::OnInitialise() +{ + //char* newLoadScreen = "C:\\Users\\Fahersto\\Pictures\\wallpaper.jpg"; + //char* newLoadScreen = "C:\\Users\\Fahersto\\Pictures\\wallpaper.jpg"; + + //original string "/resources/loading_slash.png" + Patcher().Patch((BYTE*)GetModuleHandle(NULL) + 0x2088328,(int64_t)this->imagePath); + + //change LEA to MOV by changing 0x8d to 0x8b + //E8 ? ? ? ? 4C 89 A5 ? ? ? ? 48 8D 15 ? ? ? ? 48 + 0xC (location where string is loaded) + Patcher().Patch((BYTE*)GetModuleHandle(NULL) + 0xD10DDA + 1, (int8_t)0x8b); +} + +void CustomLoadingScreen::OnMenuMainWindow() +{ + +} + +void CustomLoadingScreen::OnShutdown() +{ + //Restart the game +}
\ No newline at end of file diff --git a/CustomLoadingScreen.h b/CustomLoadingScreen.h new file mode 100644 index 0000000..66737b0 --- /dev/null +++ b/CustomLoadingScreen.h @@ -0,0 +1,20 @@ +#pragma once +#pragma once +#include "Feature.h" + +class CustomLoadingScreen : public Feature +{ +private: + CustomLoadingScreen(); + + char* imagePath; + +public: + //Supports .gif, .bmp, .jpg, .png + CustomLoadingScreen(char* imagePath); + + //Callbacks + void OnInitialise(); + void OnMenuMainWindow(); + void OnShutdown(); +};
\ No newline at end of file @@ -146,6 +146,12 @@ void ESP::OnUnitIteration(Unit* unit, Player* player, int playerIndex) return; } + if (strcmp(unit->pUnitData->name, "CSTL") == 0) + { + DrawBox(unit, colors_hex[*player->pColor], true); + return; + } + DrawBox(unit, colors_hex[*player->pColor], playerUnitNameEsp[playerIndex]); if (trebuchetESP && (std::string(unit->pUnitData->name).find("TREBU") != std::string::npos || std::string(unit->pUnitData->name).find("PTREB") != std::string::npos)) @@ -259,12 +265,15 @@ void ESP::OnNeutralUnit(Unit* unit) void ESP::OnMenuMainWindow() { ImGui::Separator(); - ImGui::Checkbox("Siege Impact ESP", &siegeImpactLocation); - ImGui::Checkbox("Trebuchet range ESP", &trebuchetESP); + ImGui::Text("Siege ESP"); + ImGui::Checkbox("Siege Impact", &siegeImpactLocation); + ImGui::Checkbox("Trebuchet range", &trebuchetESP); ImGui::Separator(); ImGui::Text("Resource ESP"); - ImGui::Checkbox("GaiaESP", &gaiaEsp); - ImGui::Checkbox("GoldESP", &goldESP); - ImGui::Checkbox("StoneESP", &stoneESP); + ImGui::Checkbox("Gaia##ESP", &gaiaEsp); + ImGui::SameLine(); + ImGui::Checkbox("Gold##ESP", &goldESP); + ImGui::SameLine(); + ImGui::Checkbox("Stone##ESP", &stoneESP); ImGui::Separator(); }
\ No newline at end of file @@ -25,7 +25,7 @@ Engine* Engine::Get() World* Engine::GetWorld() { PathfindingSystem* pathfindingSystem = reinterpret_cast<PathfindingSystem*>(base + Offsets::pathfindingSystem); - printf("pathfindingSystem: %p\n", pathfindingSystem); + //printf("pathfindingSystem: %p\n", pathfindingSystem); if (!pathfindingSystem) { return NULL; @@ -147,7 +147,7 @@ Player* Engine::GetPlayerByName(char* playerName) int totalPlayers = GetTotalPlayers(); - for (int i = 0; i < totalPlayers; i++) + for (int i = 0; i <= totalPlayers; i++) { Player* player = playerArray->playerData[i].player; if (!player) diff --git a/MidfunctionHook.cpp b/MidfunctionHook.cpp new file mode 100644 index 0000000..4b5daea --- /dev/null +++ b/MidfunctionHook.cpp @@ -0,0 +1,210 @@ +#include "MidfunctionHook.h" + +#include <cassert> + + +// +//Hooks a function anywhere by placing jumping to a trampoline. The trampoline saves all registers and then calls the proxy function +//0xff, 0x25, 0x0, 0x0, 0x0, 0x0 JMP[rip + 0] +//0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 absolute address of jump +//The proxy functions signature is expected to be: void __fastcall proxyFunction(registers* registers) +//Important: the overwritten bytes are NOT relocated meaning only position independet instructions can be overwritten +// +//TODO: +//When hooking within prologe or epicloge of a function the stack by not be aligned +//use BTR RSP, 3 to align stack and save RSP to then later restore it +void MidfunctionHook::Hook(BYTE* sourceAddress, BYTE* targetAddress, const int hookLength) +{ + const int stubLength = 375; + const int stubJumpBackLength = 14; + const int proxyFunctionAddressIndex = 185; + + //14 bytes are required to place JMP[rip+0x] 0x1122334455667788 + assert(hookLength >= stubJumpBackLength); + + //1. save xmm registers + //2. save general purpose registers + //3. call proxy function + //4. restore all registers + //5. jump back to orignal function + BYTE stub[stubLength] = { + 0x9C, //pushfq + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x3C, 0x24, //movdqu XMMWORD PTR [rsp],xmm15 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x34, 0x24, //movdqu XMMWORD PTR [rsp],xmm14 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x2C, 0x24, //movdqu XMMWORD PTR [rsp],xmm13 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x24, 0x24, //movdqu XMMWORD PTR [rsp],xmm12 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x1C, 0x24, //movdqu XMMWORD PTR [rsp],xmm11 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x14, 0x24, //movdqu XMMWORD PTR [rsp],xmm10 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x0C, 0x24, //movdqu XMMWORD PTR [rsp],xmm9 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x44, 0x0F, 0x7F, 0x04, 0x24, //movdqu XMMWORD PTR [rsp],xmm8 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x3C, 0x24, //movdqu XMMWORD PTR [rsp],xmm7 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x34, 0x24, //movdqu XMMWORD PTR [rsp],xmm6 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x2C, 0x24, //movdqu XMMWORD PTR [rsp],xmm5 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x24, 0x24, //movdqu XMMWORD PTR [rsp],xmm4 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x1C, 0x24, //movdqu XMMWORD PTR [rsp],xmm3 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x14, 0x24, //movdqu XMMWORD PTR [rsp],xmm2 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x0C, 0x24, //movdqu XMMWORD PTR [rsp],xmm1 + 0x48, 0x83, 0xEC, 0x10, //sub rsp,0x10 + 0xF3, 0x0F, 0x7F, 0x04, 0x24, //movdqu XMMWORD PTR [rsp],xmm0 + 0x41, 0x57, //push r15 + 0x41, 0x56, //push r14 + 0x41, 0x55, //push r13 + 0x41, 0x54, //push r12 + 0x41, 0x53, //push r11 + 0x41, 0x52, //push r10 + 0x41, 0x51, //push r9 + 0x41, 0x50, //push r8 + 0x57, //push rdi + 0x56, //push rsi + 0x55, //push rbp + 0x53, //push rbx + 0x52, //push rdx + 0x51, //push rcx + 0x50, //push rax + 0x48, 0x89, 0xE1, //mov rcx,rsp + 0x48, 0x83, 0xEC, 0x20, //sub rsp,0x20 (allocate shadow space) + 0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, //movabs rax,0x1122334455667788 (use register to have an absolute 8 byte call) + 0xFF, 0xD0, //call rax (call proxy function) + 0x48, 0x83, 0xC4, 0x20, //add rsp,0x20 (deallocate shadow space) + 0x58, //pop rax + 0x59, //pop rcx + 0x5A, //pop rdx + 0x5B, //pop rbx + 0x5D, //pop rbp + 0x5E, //pop rsi + 0x5F, //pop rdi + 0x41, 0x58, //pop r8 + 0x41, 0x59, //pop r9 + 0x41, 0x5A, //pop r10 + 0x41, 0x5B, //pop r11 + 0x41, 0x5C, //pop r12 + 0x41, 0x5D, //pop r13 + 0x41, 0x5E, //pop r14 + 0x41, 0x5F, //pop r15 + 0xF3, 0x0F, 0x6F, 0x04, 0x24, //movdqu xmm0,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x0C, 0x24, //movdqu xmm1,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x14, 0x24, //movdqu xmm2,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x1C, 0x24, //movdqu xmm3,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x24, 0x24, //movdqu xmm4,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x2C, 0x24, //movdqu xmm5,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x34, 0x24, //movdqu xmm6,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x0F, 0x6F, 0x3C, 0x24, //movdqu xmm7,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x04, 0x24, //movdqu xmm8,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x0C, 0x24, //movdqu xmm9,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x14, 0x24, //movdqu xmm10,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x1C, 0x24, //movdqu xmm11,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x24, 0x24, //movdqu xmm12,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x2C, 0x24, //movdqu xmm13,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x34, 0x24, //movdqu xmm14,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0xF3, 0x44, 0x0F, 0x6F, 0x3C, 0x24, //movdqu xmm15,XMMWORD PTR[rsp] + 0x48, 0x83, 0xC4, 0x10, //add rsp,0x10 + 0x9D //popfq + }; + + + + BYTE stubJumpBack[stubJumpBackLength] = { + 0xff, 0x25, 0x0, 0x0, 0x0,0x0, //JMP[rip + 0] + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 //absolute address of jump + }; + + //remember for unhooking + this->hookLength = hookLength; + this->sourceAddress = sourceAddress; + + //save original bytes + originalBytes = new BYTE[hookLength]; + memcpy(originalBytes, sourceAddress, hookLength); + + //allocate space for stub + space for overwritten bytes + jumpback + trampoline = (BYTE*)VirtualAlloc(NULL, stubLength + hookLength + stubJumpBackLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + //copy stub to trampoline + memcpy(trampoline, stub, stubLength); + + //copy original bytes to trampoline + memcpy(&trampoline[stubLength], originalBytes, hookLength); + + //copy jump back to original code + memcpy(&trampoline[stubLength + hookLength], stubJumpBack, hookLength); + + //insert address of proxy function to call instruction + *(int64_t*)&trampoline[proxyFunctionAddressIndex] = (int64_t)targetAddress; + + //write jump from trampoline to original code + *(int64_t*)&trampoline[stubLength + hookLength + 6] = (int64_t)&sourceAddress[hookLength]; + + //make trampoline executable + //DWORD pageProtection; + //VirtualProtect(trampoline, stubLength + hookLength + stubJumpBackLength, PAGE_EXECUTE_READWRITE, &pageProtection); + + //make page of original code writeable + DWORD pageProtection; + VirtualProtect(sourceAddress, hookLength, PAGE_READWRITE, &pageProtection); + + //write JMP from original code to trampoline + sourceAddress[0] = 0xFF; //opcodes = JMP [rip+0] + sourceAddress[1] = 0x25; //opcodes = JMP [rip+0] + *(uint32_t*)(&sourceAddress[2]) = 0; //relative distance from RIP (+0) + *(uint64_t*)(&sourceAddress[2 + 4]) = (uint64_t)(trampoline); //destination to jump to + + //NOP left over bytes + for (int i = stubJumpBackLength; i < hookLength; i++) + { + sourceAddress[i] = 0x90; + } + + //restore page protection of original code + VirtualProtect(sourceAddress, hookLength, pageProtection, &pageProtection); +} + +// +//Unhooks a previously hooked function by copying back the original bytes +void MidfunctionHook::Unhook() +{ + //make page writeable + DWORD dwback; + VirtualProtect(sourceAddress, hookLength, PAGE_READWRITE, &dwback); + + //copy back original bytes + memcpy(sourceAddress, originalBytes, hookLength); + + //restore page protection + VirtualProtect(sourceAddress, hookLength, dwback, &dwback); + + //clean up allocated memory + delete[] originalBytes; + + //memory leak but enables unhooking inside hooked function and makes it threadsafe? + //delete[] trampoline; +} diff --git a/MidfunctionHook.h b/MidfunctionHook.h new file mode 100644 index 0000000..76ce1ee --- /dev/null +++ b/MidfunctionHook.h @@ -0,0 +1,84 @@ +#pragma once + +#include <Windows.h> +#include <cstdint> +#include <iostream> +#include <xmmintrin.h> + + +struct registers +{ + int64_t rax; + int64_t rcx; + int64_t rdx; + int64_t rbx; + int64_t rbp; + int64_t rsi; + int64_t rdi; + int64_t r8; + int64_t r9; + int64_t r10; + int64_t r11; + int64_t r12; + int64_t r13; + int64_t r14; + int64_t r15; + + __m128 xmm0; + __m128 xmm1; + __m128 xmm2; + __m128 xmm3; + __m128 xmm4; + __m128 xmm5; + __m128 xmm6; + __m128 xmm7; + __m128 xmm8; + __m128 xmm9; + __m128 xmm10; + __m128 xmm11; + __m128 xmm12; + __m128 xmm13; + __m128 xmm14; + __m128 xmm15; + + void print() + { + printf("rax = %llx\nrcx = %llx\nrdx = %llx\nrbx = %llx\nrbp = %llx\nrsi = %llx\nrdi = %llx\nr8 = %llx\nr9 = %llx\nr10 = %llx\nr11 = %llx\nr12 = %llx\nr13 = %llx\nr14 = %llx\nr15 = %llx\n", + rax, + rcx, + rdx, + rbx, + rbp, + rsi, + rdi, + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15); + } +}; + + +class MidfunctionHook +{ + //bytes overwritten by placing the detour + BYTE* originalBytes; + + //location where hook is placed + BYTE* sourceAddress; + + //runs overwritten instructions + BYTE* trampoline; + + //number of bytes to overwrite (don't cut instructions in half) + int hookLength; + +public: + void Hook(BYTE* sourceAddress, BYTE* targetAddress, const int length); + void Unhook(); +}; + diff --git a/MinimapText.cpp b/MinimapText.cpp index 1d13635..a596d04 100644 --- a/MinimapText.cpp +++ b/MinimapText.cpp @@ -7,70 +7,113 @@ #include "Sdk.h" #include "Renderer.h" #include "Utility.h" +#include "Offsets.h" #include "DetourHook64.h" +#include "MidfunctionHook.h" +#include "Patcher.h" #include <map> #pragma warning( disable : 4244 ) +MidfunctionHook minimapHook; +bool* hookEnabled; +bool displayWood = false; +bool displayFood = false; +bool displayGold = true; +bool displayStone = false; +bool displayPopulation = false; -char* name = "NewName"; - -typedef int(__fastcall* printMinimap)(void* that, char* format, ...); -printMinimap oPrintMinimap; - -int __fastcall hookedWrapper(void* that, char* format, char* playername, int currentPoints, int maxPoints) +void __fastcall minimapProxy(registers* registers) { - printf("In da Hook\n"); - - return oPrintMinimap(that, format, playername, currentPoints, maxPoints); //call original call + if (!*hookEnabled) + { + return; + } + if (!displayWood && !displayFood && !displayGold && !displayStone && !displayPopulation) + { + return; + } + + Player* player = Engine::Get()->GetPlayerByName((char*)registers->rdi); + if (!player) + { + return; + } + + if (!player->pResources) + { + return; + } + + std::string woodString = std::to_string((int)player->pResources->wood); + std::string foodString = std::to_string((int)player->pResources->food); + std::string goldString = std::to_string((int)player->pResources->gold); + std::string stoneString = std::to_string((int)player->pResources->stone); + std::string populationString = std::to_string((int)player->pResources->currentPop) + "/" + std::to_string((int)player->pResources->currentPop + (int)player->pResources->popSpaceLeft); + + std::string newName = std::string(player->name) + " -"; + if (displayWood) + { + newName += " Wood: " + woodString; + } + if (displayFood) + { + newName += " Food: " + foodString; + } + if (displayGold) + { + newName += " Gold: " + goldString; + } + if (displayStone) + { + newName += " Stone: " + stoneString; + } + if (displayPopulation) + { + newName += " Pop: " + populationString; + } + strcpy((char*)registers->rdi, newName.c_str()); } void MinimapText::OnInitialise() { - //Working - //const int shellcodeSize = 29; - //BYTE shellcode[shellcodeSize] = { 0x8B, 0x84, 0xF5, 0x24, 0x1, 0x0, 0x0, // mov eax, [rbp+rsi*8+5F8h+var_4D4] <-- orginal code - // 0x89, 0x44, 0x24, 0x20, // mov dword ptr[rsp + 6D0h + var_6B0], eax <-- orginal code - // 0x44, 0x8B, 0x8C, 0xF5, 0x20, 0x1, 0x0, 0x0, // mov r9d, dword ptr[rbp + rsi * 8 + 5F8h + var_4DC + 4] <-- orginal code - // 0x49, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }; //MOV R8, 0x1122334455667788 <-- new code (replaces string to print) - //*(uint64_t*)(&shellcode[21]) = (uint64_t)name; - - ////8B 84 F5 ? ? ? ? 89 - //BYTE* hookAddress = (BYTE*)Utility::Scan("\x8B\x84\xF5\x00\x00\x00\x00\x89", "xxx????x", (char*)0x7ff000000000, 0x800000000000 - 0x7ff000000000); - //printf("hookAddress: %p\n", hookAddress); - //minimapTextDetour = new DetourHook64(); - //minimapTextDetour->Hook(hookAddress, shellcode, shellcodeSize, (uint64_t)(hookAddress + 23), 19); - - BYTE* callAddress = (BYTE*)Utility::Scan("\xE8\x00\x00\x00\x00\x49\x8B\x9D\x00\x00\x00\x00\x33\xD2\x44", "x????xxx????xxx", (char*)0x7ff000000000, 0x800000000000 - 0x7ff000000000); - - BYTE* function = (BYTE*)Utility::Scan("\xFF\x15\x00\x00\x00\x00\x85\xC0\x0F\x48", "xx????xxxx", (char*)0x7ff000000000, 0x800000000000 - 0x7ff000000000); - - function = function - 0x4b; - printf("callAddress: %p\n", callAddress); - printf("function: %p\n", function); - printf("hookedWrapper: %p\n", hookedWrapper); - + hookEnabled = &enabled; - oPrintMinimap = (printMinimap)(function); + int64_t base = (int64_t)GetModuleHandle(NULL); - int32_t callRelativeOffset = (int64_t)hookedWrapper - (int64_t)callAddress - 5; + Patcher patcher; + //74 7F 48 8D 4B 01 48 85 C9 74 59 + 14 + //Patch usage of short string optimizaation (playernames <= 15) + patcher.NOPBytes((BYTE*)(base + 0xA426EE), 6); - getchar(); - //*(int32_t*)(callAddress + 1) = callRelativeOffset; //override original call + //74 7F 48 8D 4B 01 48 85 C9 74 59 + 18 + //Increase space allocated for playernames to 0x120 bytes so we can write as much as we want to on screen + Patcher().Patch((BYTE*)(base + 0xA426F5), (int32_t)0x120); - //TO CALL E8 ? ? ? ? 49 8B 9D ? ? ? ? 33 D2 44 + minimapHook.Hook((BYTE*)(int64_t)GetModuleHandle(NULL) + Offsets::minimapHookOffset, (BYTE*)minimapProxy, 17); } void MinimapText::OnShutdown() { - //minimapTextDetour->Unhook(); + minimapHook.Unhook(); } void MinimapText::OnMenuMainWindow() { - //ImGui::Checkbox("Minimap Ressource Information", &hookEnabled); + ImGui::Separator(); + ImGui::Checkbox("Minimap Ressource Information", &enabled); + ImGui::Checkbox("Wood##Minimap", &displayWood); + ImGui::SameLine(); + ImGui::Checkbox("Food##Minimap", &displayFood); + ImGui::SameLine(); + ImGui::Checkbox("Gold##Minimap", &displayGold); + ImGui::SameLine(); + ImGui::Checkbox("Stone##Minimap", &displayStone); + ImGui::SameLine(); + ImGui::Checkbox("Population##Minimap", &displayPopulation); + ImGui::Separator(); }
\ No newline at end of file diff --git a/Offsets.cpp b/Offsets.cpp new file mode 100644 index 0000000..be54037 --- /dev/null +++ b/Offsets.cpp @@ -0,0 +1,28 @@ +#include "Offsets.h" + +namespace Offsets +{ + //48 8D 0D ? ? ? ? 41 B8 ? ? ? ? E8 ? ? ? ? 33 C0 + //48 8D 0D ? ? ? ? E8 ? ? ? ? 0F B6 C0 + int64_t pathfindingSystem = 0x2A070F0; //PathingSystem, World and map correct + + //48 8B 0D ? ? ? ? E8 ? ? ? ? C6 85 + //48 83 3D ? ? ? ? ? 0F 84 ? ? ? ? 45 0F + int64_t mainScreen = 0x29C50F8; //MainScreenCorrect, MainView COrrect + + //44 89 25 ? ? ? ? 2B + //41 8B 45 28 99 + int64_t totalPlayers = 0x28900D4; //correct + + //48 8B 0D ? ? ? ? 48 85 C9 74 0C 45 + int64_t tribePanelInven = 0x29c5110; + + //48 8B 83 ? ? ? ? 48 8B 48 70 F3 0F 10 + int64_t tribePanelInven_localPlayer = 0x208; + + //Pattern + int64_t unit_actionlist = 0x278; //48 8B 8B ? ? ? ? E8 ? ? ? ? 48 85 FF + + //88 85 ? ? ? ? 8B 84 + int64_t minimapHookOffset = 0xA429F7; +}
\ No newline at end of file @@ -3,25 +3,14 @@ namespace Offsets { - //48 8D 0D ? ? ? ? 41 B8 ? ? ? ? E8 ? ? ? ? 33 C0 - //48 8D 0D ? ? ? ? E8 ? ? ? ? 0F B6 C0 - int64_t pathfindingSystem = 0x2A070F0; //PathingSystem, World and map correct + extern int64_t pathfindingSystem; + extern int64_t mainScreen; + extern int64_t totalPlayers; - //48 8B 0D ? ? ? ? E8 ? ? ? ? C6 85 - //48 83 3D ? ? ? ? ? 0F 84 ? ? ? ? 45 0F - int64_t mainScreen = 0x29C50F8; //MainScreenCorrect, MainView COrrect + extern int64_t tribePanelInven; + extern int64_t tribePanelInven_localPlayer; - //44 89 25 ? ? ? ? 2B - //41 8B 45 28 99 - int64_t totalPlayers = 0x28900D4; //correct - - //48 8B 0D ? ? ? ? 48 85 C9 74 0C 45 - int64_t tribePanelInven = 0x29c5110; - - //48 8B 83 ? ? ? ? 48 8B 48 70 F3 0F 10 - int64_t tribePanelInven_localPlayer = 0x208; - - - //Pattern - int64_t unit_actionlist = 0x278; //48 8B 8B ? ? ? ? E8 ? ? ? ? 48 85 FF + extern int64_t unit_actionlist ; + + extern int64_t minimapHookOffset; }
\ No newline at end of file diff --git a/Patcher.cpp b/Patcher.cpp new file mode 100644 index 0000000..cefeeb1 --- /dev/null +++ b/Patcher.cpp @@ -0,0 +1,112 @@ +#include "Patcher.h" + +void Patcher::PatchBytes(BYTE* address, BYTE* shellcode, const int shellCodeSize, bool modifyPageProtection, DWORD newPageProtection, bool restorePageProtection) +{ + DWORD oldProtection; + if (modifyPageProtection) + { + //apply new page protection + VirtualProtect(address, shellCodeSize, newPageProtection, &oldProtection); + } + else + { + //there is nothing to restore if page protection wasn't changed + restorePageProtection = false; + } + + //apply patch + memcpy(address, shellcode, shellCodeSize); + + if (restorePageProtection) + { + //restore page protection + VirtualProtect(address, shellCodeSize, oldProtection, &oldProtection); + } +} + +void Patcher::NOPBytes(BYTE* address, const int amount, bool modifyPageProtection, DWORD newPageProtection, bool restorePageProtection) +{ + DWORD oldProtection; + if (modifyPageProtection) + { + //apply new page protection + VirtualProtect(address, amount, newPageProtection, &oldProtection); + } + else + { + //there is nothing to restore if page protection wasn't changed + restorePageProtection = false; + } + + //apply patch + for (int i = 0; i < amount; i++) + { + address[i] = 0x90; //NOP + } + + if (restorePageProtection) + { + //restore page protection + VirtualProtect(address, amount, oldProtection, &oldProtection); + } +} + +//Writes a 1 byte value using local endianess +void Patcher::Patch(BYTE* address, int8_t value) +{ + DWORD oldProtection; + + //apply new page protection + VirtualProtect(address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtection); + + //write value + *(int8_t*)address = value; + + //restore page protection + VirtualProtect(address, sizeof(value), oldProtection, &oldProtection); +} + +//Writes a 2 byte value using local endianess +void Patcher::Patch(BYTE* address, int16_t value) +{ + DWORD oldProtection; + + //apply new page protection + VirtualProtect(address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtection); + + //write value + *(int16_t*)address = value; + + //restore page protection + VirtualProtect(address, sizeof(value), oldProtection, &oldProtection); +} + +//Writes a 4 byte value using local endianess +void Patcher::Patch(BYTE* address, int32_t value) +{ + DWORD oldProtection; + + //apply new page protection + VirtualProtect(address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtection); + + //write value + *(int32_t*)address = value; + + //restore page protection + VirtualProtect(address, sizeof(value), oldProtection, &oldProtection); +} + +//Writes a 8 byte value using local endianess +void Patcher::Patch(BYTE* address, int64_t value) +{ + DWORD oldProtection; + + //apply new page protection + VirtualProtect(address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtection); + + //write value + *(int64_t*)address = value; + + //restore page protection + VirtualProtect(address, sizeof(value), oldProtection, &oldProtection); +}
\ No newline at end of file diff --git a/Patcher.h b/Patcher.h new file mode 100644 index 0000000..706c9ba --- /dev/null +++ b/Patcher.h @@ -0,0 +1,20 @@ +#pragma once + +#include <Windows.h> +#include <cstdint> + +class Patcher +{ +public: + + void PatchBytes(BYTE* address, BYTE* shellcode, const int shellCodeSize, bool modifyPageProtection = true, DWORD newPageProtection = PAGE_EXECUTE_READWRITE, bool restorePageProtection = true); + + void NOPBytes(BYTE* address, const int amount, bool modifyPageProtection = true, DWORD newPageProtection = PAGE_EXECUTE_READWRITE, bool restorePageProtection = true); + + + //TODO: template? + void Patch(BYTE* address, int8_t value); + void Patch(BYTE* address, int16_t value); + void Patch(BYTE* address, int32_t value); + void Patch(BYTE* address, int64_t value); +}; diff --git a/RelicManager.cpp b/RelicManager.cpp index 10f41d2..1075c0e 100644 --- a/RelicManager.cpp +++ b/RelicManager.cpp @@ -37,9 +37,9 @@ void RelicManager::OnMenuMainWindow() currentRelic = (currentRelic - 1) % relics.size(); Engine::Get()->GetLocalPlayer()->SetCameraPosition(relics[currentRelic]->position); } - ImGui::SameLine(24); + ImGui::SameLine(); ImGui::Text("%d/%d", currentRelic + 1, relics.size()); - ImGui::SameLine(48); + ImGui::SameLine(); if (ImGui::Button(">")) { currentRelic = (currentRelic + 1) % relics.size(); diff --git a/ResourceInformation.cpp b/ResourceInformation.cpp index 57ff2d0..dcaf470 100644 --- a/ResourceInformation.cpp +++ b/ResourceInformation.cpp @@ -8,6 +8,7 @@ void ResourceInformation::OnMenuPlayerTreenode(Player* player, int playerIndex) { + ImGui::Text("Resources: %p", player->pResources); ImGui::Text("Wood: %.f", player->pResources->wood); ImGui::Text("Food: %.f", player->pResources->food); ImGui::Text("Gold: %.f", player->pResources->gold); diff --git a/Resources.h b/Resources.h deleted file mode 100644 index 3acbc85..0000000 --- a/Resources.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - - -class Ressources -{ -public: - float food; //0x0000 - float wood; //0x0004 - float stone; //0x0008 - float gold; //0x000C - float popSpaceLeft; //0x0010 - char pad_0014[4]; //0x0014 - float age; //0x0018 - char pad_001C[16]; //0x001C - float CurrentPop; //0x002C - char pad_0030[28]; //0x0030 - float unitProduced; //0x004C - char pad_0050[4]; //0x0050 - float techUpgradeCount; //0x0054 - float percentExplored; //0x0058 - char pad_005C[36]; //0x005C - float gameMaxPop; //0x0080 - char pad_0084[12]; //0x0084 - float farmFoodAmount; //0x0090 - float villagerCount; //0x0094 - char pad_0098[8]; //0x0098 - float infantryCount; //0x00A0 - char pad_00A4[24]; //0x00A4 - float goldRate; //0x00BC - char pad_00C0[124]; //0x00C0 - float stoneRate; //0x013C - float unitsQueueCount; //0x0140 - float builingProducingCount; //0x0144 - char pad_0148[24]; //0x0148 - float fishTrapAmount; //0x0160 - char pad_0164[400]; //0x0164 - float chopRate; //0x02F4 - float foodRate; //0x02F8 - float relicGoldRate; //0x02FC - char pad_0300[12]; //0x0300 - float construcRateMaybe; //0x030C - char pad_0310[48]; //0x0310 -}; //Size: 0x0340 @@ -2,6 +2,5 @@ #include <Windows.h> #include <vector> -#include "Resources.h" #include "Classes.h" -#pragma once + |