diff --git a/akebi-gc.sln b/akebi-gc.sln index 1915763..f0de0a1 100644 --- a/akebi-gc.sln +++ b/akebi-gc.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32014.148 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "injector", "injector\injector.vcxproj", "{F578B30C-8DE6-4741-99E4-1D30D2ACDAC4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cheat-library", "cheat-library\cheat-library.vcxproj", "{CE178784-CB96-45CA-AE16-FC0DA1126970}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cheat-base", "cheat-base\cheat-base.vcxproj", "{ADB35022-823B-4DC0-B495-3EFEFBD3A82F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cheat-library", "cheat-library\cheat-library.vcxproj", "{CE178784-CB96-45CA-AE16-FC0DA1126970}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "injector", "injector\injector.vcxproj", "{F578B30C-8DE6-4741-99E4-1D30D2ACDAC4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/cheat-base/cheat-base.vcxproj b/cheat-base/cheat-base.vcxproj index f755db3..10266a0 100644 --- a/cheat-base/cheat-base.vcxproj +++ b/cheat-base/cheat-base.vcxproj @@ -1,14 +1,26 @@  + + Debug + Win32 + Debug x64 + + Release_WS + Win32 + Release_WS x64 + + Release + Win32 + Release x64 @@ -43,6 +55,24 @@ true MultiByte + + v143 + StaticLibrary + true + MultiByte + + + v143 + StaticLibrary + MultiByte + true + + + v143 + StaticLibrary + MultiByte + true + @@ -60,18 +90,30 @@ true - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ false - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ false - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ + + + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ + + + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ + + + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ @@ -81,8 +123,9 @@ true Use pch.h - stdcpp17 + stdcpp20 $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ + stdc17 @@ -94,26 +137,28 @@ - detours-x64.lib;%(AdditionalDependencies) + detours-$(PlatformShortName).lib - $(ProjectDir)/vendor/detours/;%(AdditionalLibraryDirectories) + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) Level3 true - false + true true _AMD64_;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h - stdcpp17 + stdcpp20 $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ - Disabled - false + MaxSpeed + true + false + stdc17 @@ -127,26 +172,28 @@ - detours-x64.lib;%(AdditionalDependencies) + detours-$(PlatformShortName).lib - $(ProjectDir)/vendor/detours/;%(AdditionalLibraryDirectories) + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) Level3 true - false + true true _AMD64_;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h - stdcpp17 + stdcpp20 $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ - Disabled - false + MaxSpeed + true + false + stdc17 @@ -160,10 +207,63 @@ - detours-x64.lib;%(AdditionalDependencies) + detours-$(PlatformShortName).lib - $(ProjectDir)/vendor/detours/;%(AdditionalLibraryDirectories) + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) + + + + + stdcpp20 + true + Level3 + $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ + _DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) + Use + pch.h + stdc17 + ProgramDatabase + false + false + + + detours-$(PlatformShortName).lib + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) + + + + + stdcpp20 + true + Level3 + $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ + true + _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) + Use + pch.h + stdc17 + + + detours-$(PlatformShortName).lib + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) + + + + + stdcpp20 + true + Level3 + $(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\ + true + _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) + Use + pch.h + stdc17 + + + detours-$(PlatformShortName).lib + $(ProjectDir)vendor\detours\;%(AdditionalLibraryDirectories) @@ -196,6 +296,8 @@ + + @@ -208,6 +310,8 @@ + + @@ -247,12 +351,20 @@ NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h + + @@ -269,57 +381,90 @@ Create Create Create + Create + Create + Create NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h NotUsing NotUsing NotUsing + NotUsing + pch.h + pch.h diff --git a/cheat-base/cheat-base.vcxproj.filters b/cheat-base/cheat-base.vcxproj.filters index 95f3a92..c8e131f 100644 --- a/cheat-base/cheat-base.vcxproj.filters +++ b/cheat-base/cheat-base.vcxproj.filters @@ -231,6 +231,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -317,5 +329,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/cheat-base/framework/pch.h b/cheat-base/framework/pch.h index 2cfc048..45f6c66 100644 --- a/cheat-base/framework/pch.h +++ b/cheat-base/framework/pch.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/cheat-base/src/cheat-base/Logger.cpp b/cheat-base/src/cheat-base/Logger.cpp index a2ca152..96ba53c 100644 --- a/cheat-base/src/cheat-base/Logger.cpp +++ b/cheat-base/src/cheat-base/Logger.cpp @@ -88,11 +88,6 @@ Prefix GetLevelPrefix(Logger::Level level) void Logger::Log(Logger::Level logLevel, const char* filepath, int line, const char* fmt, ...) { - if (Logger::s_ConsoleLogLevel == Logger::Level::None && Logger::s_FileLogLevel == Logger::Level::None) - return; - - auto filename = std::filesystem::path(filepath).filename().string(); - auto prefix = GetLevelPrefix(logLevel); char buffer[1024]; va_list args; @@ -100,6 +95,13 @@ void Logger::Log(Logger::Level logLevel, const char* filepath, int line, const c vsprintf_s(buffer, fmt, args); va_end(args); + LogEvent(logLevel, filepath, line, buffer); + if (Logger::s_ConsoleLogLevel == Logger::Level::None && Logger::s_FileLogLevel == Logger::Level::None) + return; + + auto filename = std::filesystem::path(filepath).filename().string(); + auto prefix = GetLevelPrefix(logLevel); + if (Logger::s_ConsoleLogLevel != Logger::Level::None && Logger::s_ConsoleLogLevel >= logLevel) { const std::lock_guard lock(_mutex); @@ -140,4 +142,4 @@ void Logger::PrepareFileLogging(std::string directory) Logger::logfilepath = util::string_format("%s\\log_%04d-%02d-%02d_%02d-%02d.txt", directory.c_str(), 1900 + gmtm.tm_year, gmtm.tm_mon, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min); -} +} \ No newline at end of file diff --git a/cheat-base/src/cheat-base/Logger.h b/cheat-base/src/cheat-base/Logger.h index 37fc6e9..d2fe3c7 100644 --- a/cheat-base/src/cheat-base/Logger.h +++ b/cheat-base/src/cheat-base/Logger.h @@ -1,6 +1,8 @@ #pragma once #include #include +#include + #define EXTLOG(level, fmt, ...) Logger::Log(level, __FILE__, __LINE__, fmt, __VA_ARGS__) #define LOG_CRIT(fmt, ...) EXTLOG(Logger::Level::Critical, fmt, __VA_ARGS__) #define LOG_ERROR(fmt, ...) EXTLOG(Logger::Level::Error, fmt, __VA_ARGS__) @@ -37,6 +39,8 @@ public: static void PrepareFileLogging(std::string directory); + static inline TEvent LogEvent; + private: static Level s_FileLogLevel; static Level s_ConsoleLogLevel; diff --git a/cheat-base/src/cheat-base/PatternScanner.h b/cheat-base/src/cheat-base/PatternScanner.h index e6801bc..a5a318a 100644 --- a/cheat-base/src/cheat-base/PatternScanner.h +++ b/cheat-base/src/cheat-base/PatternScanner.h @@ -33,6 +33,9 @@ public: int64_t GetModuleTimestamp(const std::string& moduleName); int64_t GetModuleTimestamp(HMODULE hModule); + + uintptr_t SearchInModule(const std::string& moduleName, const std::string& pattern); + uintptr_t SearchInModule(HMODULE hModule, const std::string& pattern); protected: @@ -97,9 +100,6 @@ protected: uintptr_t SearchXref(const std::string& moduleName, const OffsetSignature& xrefPattern); uintptr_t SearchXref(HMODULE hModule, const OffsetSignature& xrefPattern); - - uintptr_t SearchInModule(const std::string& moduleName, const std::string& pattern); - uintptr_t SearchInModule(HMODULE hModule, const std::string& pattern); uintptr_t GetOffsetInt(const nlohmann::json& value); std::string GetOffsetStr(uintptr_t offset); diff --git a/cheat-base/src/cheat-base/PipeTransfer.cpp b/cheat-base/src/cheat-base/PipeTransfer.cpp index 1dfa028..b4f616f 100644 --- a/cheat-base/src/cheat-base/PipeTransfer.cpp +++ b/cheat-base/src/cheat-base/PipeTransfer.cpp @@ -45,7 +45,7 @@ bool PipeTransfer::Connect() bool PipeTransfer::WaitForConnection() { - return ConnectNamedPipe(m_Pipe, nullptr); + return ConnectNamedPipe(m_Pipe, nullptr) || GetLastError() == ERROR_PIPE_CONNECTED; } void PipeTransfer::ReadBytes(void* buffer, size_t size) diff --git a/cheat-base/src/cheat-base/inject/load-library.cpp b/cheat-base/src/cheat-base/inject/load-library.cpp new file mode 100644 index 0000000..771fc75 --- /dev/null +++ b/cheat-base/src/cheat-base/inject/load-library.cpp @@ -0,0 +1,55 @@ +#include +#include "load-library.h" +#include + +#if defined(DISABLE_OUTPUT) +#define ILog(data, ...) +#define IPrintError(text, ...) +#else +#define ILog(text, ...) printf(text, __VA_ARGS__) +#define ILogError(text, ...) ILog(text, __VA_ARGS__); std::cout << "Error: " << util::GetLastErrorAsString() << std::endl +#endif + +bool LoadLibraryDLL(HANDLE hProc, const std::string& dllpath) +{ + HMODULE hKernel = GetModuleHandle("kernel32.dll"); + if (hKernel == NULL) + { + ILogError("[DLL Injection] Failed to get kernel32.dll module address.\n"); + return false; + } + + LPVOID pLoadLibrary = (LPVOID)GetProcAddress(hKernel, "LoadLibraryA"); + if (pLoadLibrary == NULL) { + ILogError("[DLL Injection] Failed to get LoadLibraryA address.\n"); + return false; + } + + LPVOID pDLLPath = VirtualAllocEx(hProc, NULL, strlen(dllpath.c_str()) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (pDLLPath == NULL) { + ILogError("[DLL Injection] Failed to allocate memory for DLLPath in target process.\n"); + return false; + } + + // Write the string name of our DLL in the memory allocated + BOOL writeResult = WriteProcessMemory(hProc, pDLLPath, dllpath.c_str(), strlen(dllpath.c_str()), NULL); + if (writeResult == FALSE) { + ILogError("[DLL Injection] Failed to write remote process memory.\n"); + return false; + } + + // Load our DLL by calling loadlibrary in the other process and passing our dll name + HANDLE hThread = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)pLoadLibrary, (LPVOID)pDLLPath, NULL, NULL); + if (hThread == NULL) { + ILogError("[DLL Injection] Failed to create remote thread.\n"); + VirtualFreeEx(hProc, pDLLPath, 0, MEM_RELEASE); + return false; + } + CloseHandle(hThread); + + // TODO: Add waiting for thread end and release unneccessary data. + // VirtualFreeEx(hProc, pDLLPath, 0, MEM_RELEASE); + + ILog("[DLL Injection] Successfully LoadLibraryA injection.\n"); + return true; +} \ No newline at end of file diff --git a/cheat-base/src/cheat-base/inject/load-library.h b/cheat-base/src/cheat-base/inject/load-library.h new file mode 100644 index 0000000..95fc16d --- /dev/null +++ b/cheat-base/src/cheat-base/inject/load-library.h @@ -0,0 +1,3 @@ +#pragma once + +bool LoadLibraryDLL(HANDLE hProc, const std::string& dllpath); \ No newline at end of file diff --git a/cheat-base/src/cheat-base/inject/manual-map.cpp b/cheat-base/src/cheat-base/inject/manual-map.cpp new file mode 100644 index 0000000..2fb11b9 --- /dev/null +++ b/cheat-base/src/cheat-base/inject/manual-map.cpp @@ -0,0 +1,385 @@ +#include +#include "manual-map.h" +#include + +#if defined(DISABLE_OUTPUT) +#define ILog(data, ...) +#define IPrintError(text, ...) +#else +#define ILog(text, ...) printf(text, __VA_ARGS__) +#define ILogError(text, ...) ILog(text, __VA_ARGS__); std::cout << "Error: " << util::GetLastErrorAsString() << std::endl +#endif + +#ifdef _WIN64 +#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64 +#else +#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386 +#endif + +using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename); +using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName); +using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReserved); + +#ifdef _WIN64 +using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress); +#endif + +struct MANUAL_MAPPING_DATA +{ + f_LoadLibraryA pLoadLibraryA; + f_GetProcAddress pGetProcAddress; +#ifdef _WIN64 + f_RtlAddFunctionTable pRtlAddFunctionTable; +#endif + BYTE* pbase; + HINSTANCE hMod; + DWORD fdwReasonParam; + LPVOID reservedParam; + BOOL SEHSupport; +}; + + +bool ManualMapDLL(HANDLE hProc, const std::string& filepath) +{ + std::ifstream file(filepath, std::ios::in | std::ios::binary | std::ios::ate); + if (!file.is_open()) + { + std::cout << "Error while reading DLL file!" << std::endl; + return false; + } + + std::streampos size = file.tellg(); + auto memblock = new char[size]; + file.seekg(0, std::ios::beg); + file.read(memblock, size); + file.close(); + + BYTE* fileContent = (BYTE*)memblock; + + // Manual map injection will help us to be like a assasin + bool result = ManualMapDLL(hProc, fileContent, size); + + delete[] memblock; + + return result; +} + +void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData); + +bool ManualMapDLL(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason) { + IMAGE_NT_HEADERS* pOldNtHeader = nullptr; + IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr; + IMAGE_FILE_HEADER* pOldFileHeader = nullptr; + BYTE* pTargetBase = nullptr; + + if (reinterpret_cast(pSrcData)->e_magic != 0x5A4D) { //"MZ" + ILog("[DLL injection] Invalid file\n"); + return false; + } + + pOldNtHeader = reinterpret_cast(pSrcData + reinterpret_cast(pSrcData)->e_lfanew); + pOldOptHeader = &pOldNtHeader->OptionalHeader; + pOldFileHeader = &pOldNtHeader->FileHeader; + + if (pOldFileHeader->Machine != CURRENT_ARCH) { + ILog("[DLL injection] Invalid platform.\n"); + return false; + } + + ILog("[DLL injection] File ok\n"); + + pTargetBase = reinterpret_cast(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); + if (!pTargetBase) { + ILogError("[DLL injection] Target process memory allocation failed (ex)\n"); + return false; + } + + DWORD oldp = 0; + VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp); + + MANUAL_MAPPING_DATA data{ 0 }; + data.pLoadLibraryA = LoadLibraryA; + data.pGetProcAddress = GetProcAddress; +#ifdef _WIN64 + data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable; +#else + SEHExceptionSupport = false; +#endif + data.pbase = pTargetBase; + data.fdwReasonParam = fdwReason; + data.SEHSupport = SEHExceptionSupport; + + //File header + if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) { //only first 0x1000 bytes for the header + ILogError("[DLL injection] Can't write file header.\n"); + + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + return false; + } + + IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); + for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { + if (pSectionHeader->SizeOfRawData) { + if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr)) { + ILogError("[DLL injection] Can't map sections.\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + return false; + } + } + } + + //Mapping params + BYTE* MappingDataAlloc = reinterpret_cast(VirtualAllocEx(hProc, nullptr, sizeof(MANUAL_MAPPING_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); + if (!MappingDataAlloc) { + ILogError("[DLL injection] Target process mapping allocation failed (ex).\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + return false; + } + + if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr)) { + ILogError("[DLL injection] Can't write mapping.\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); + return false; + } + + //Shell code + void* pShellcode = VirtualAllocEx(hProc, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!pShellcode) { + ILogError("[DLL injection] Memory shellcode allocation failed (ex).\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); + return false; + } + + if (!WriteProcessMemory(hProc, pShellcode, Shellcode, 0x1000, nullptr)) { + ILogError("[DLL injection] Can't write shellcode.\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); + VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); + return false; + } + + ILog("[DLL injection] Mapped DLL at %p\n", pTargetBase); + ILog("[DLL injection] Mapping info at %p\n", MappingDataAlloc); + ILog("[DLL injection] Shell code at %p\n", pShellcode); + + ILog("[DLL injection] Data allocated\n"); + +#ifdef _DEBUG + ILog("[DLL injection] My shellcode pointer %p\n", Shellcode); + ILog("[DLL injection] Target point %p\n", pShellcode); +#endif + + HANDLE hThread = CreateRemoteThread(hProc, nullptr, 0, reinterpret_cast(pShellcode), MappingDataAlloc, 0, nullptr); + if (!hThread) { + ILogError("[DLL injection] Thread creation failed.\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); + VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); + return false; + } + CloseHandle(hThread); + + ILog("[DLL injection] Thread created at: %p, waiting for return...\n", pShellcode); + + HINSTANCE hCheck = NULL; + while (!hCheck) { + DWORD exitcode = 0; + GetExitCodeProcess(hProc, &exitcode); + if (exitcode != STILL_ACTIVE) { + ILog("[DLL injection] Process crashed, exit code: 0x%x\n", exitcode); + return false; + } + + MANUAL_MAPPING_DATA data_checked{ 0 }; + ReadProcessMemory(hProc, MappingDataAlloc, &data_checked, sizeof(data_checked), nullptr); + hCheck = data_checked.hMod; + + if (hCheck == (HINSTANCE)0x404040) { + ILog("[DLL injection] Wrong mapping ptr.\n"); + VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); + VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); + VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); + return false; + } + else if (hCheck == (HINSTANCE)0x505050) { + ILog("[DLL injection] WARNING: Exception support failed!\n"); + } + + Sleep(10); + } + + BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20); + if (emptyBuffer == nullptr) { + ILog("[DLL injection] Unable to allocate memory\n"); + return false; + } + memset(emptyBuffer, 0, 1024 * 1024 * 20); + + //CLEAR PE HEAD + if (ClearHeader) { + if (!WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr)) { + ILogError("[DLL injection] WARNING!: Can't clear HEADER\n"); + } + } + //END CLEAR PE HEAD + + + if (ClearNonNeededSections) { + pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); + for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { + if (pSectionHeader->Misc.VirtualSize) { + if ((SEHExceptionSupport ? 0 : strcmp((char*)pSectionHeader->Name, ".pdata") == 0) || + strcmp((char*)pSectionHeader->Name, ".rsrc") == 0 || + strcmp((char*)pSectionHeader->Name, ".reloc") == 0) { + ILog("[DLL injection] Processing %s removal\n", pSectionHeader->Name); + if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, emptyBuffer, pSectionHeader->Misc.VirtualSize, nullptr)) { + ILogError("[DLL injection] Can't clear section %s.\n", pSectionHeader->Name); + } + } + } + } + } + + if (AdjustProtections) { + pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); + for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { + if (pSectionHeader->Misc.VirtualSize) { + DWORD old = 0; + DWORD newP = PAGE_READONLY; + + if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) > 0) { + newP = PAGE_READWRITE; + } + else if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) > 0) { + newP = PAGE_EXECUTE_READ; + } + if (VirtualProtectEx(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSectionHeader->Misc.VirtualSize, newP, &old)) { + ILog("[DLL injection] Section %s set as %lX\n", (char*)pSectionHeader->Name, newP); + } + else { + ILog("[DLL injection] FAIL: section %s not set as %lX\n", (char*)pSectionHeader->Name, newP); + } + } + } + DWORD old = 0; + VirtualProtectEx(hProc, pTargetBase, IMAGE_FIRST_SECTION(pOldNtHeader)->VirtualAddress, PAGE_READONLY, &old); + } + + if (!WriteProcessMemory(hProc, pShellcode, emptyBuffer, 0x1000, nullptr)) { + ILog("[DLL injection] WARNING: Can't clear shellcode\n"); + } + if (!VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE)) { + ILog("[DLL injection] WARNING: can't release shell code memory\n"); + } + if (!VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE)) { + ILog("[DLL injection] WARNING: can't release mapping data memory\n"); + } + + return true; +} + +#define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW) +#define RELOC_FLAG64(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_DIR64) + +#ifdef _WIN64 +#define RELOC_FLAG RELOC_FLAG64 +#else +#define RELOC_FLAG RELOC_FLAG32 +#endif + +#pragma runtime_checks( "", off ) +#pragma optimize( "", off ) +void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData) { + if (!pData) { + pData->hMod = (HINSTANCE)0x404040; + return; + } + + BYTE* pBase = pData->pbase; + auto* pOpt = &reinterpret_cast(pBase + reinterpret_cast((uintptr_t)pBase)->e_lfanew)->OptionalHeader; + + auto _LoadLibraryA = pData->pLoadLibraryA; + auto _GetProcAddress = pData->pGetProcAddress; +#ifdef _WIN64 + auto _RtlAddFunctionTable = pData->pRtlAddFunctionTable; +#endif + auto _DllMain = reinterpret_cast(pBase + pOpt->AddressOfEntryPoint); + + BYTE* LocationDelta = pBase - pOpt->ImageBase; + if (LocationDelta) { + if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) { + auto* pRelocData = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); + const auto* pRelocEnd = reinterpret_cast(reinterpret_cast(pRelocData) + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); + while (pRelocData < pRelocEnd && pRelocData->SizeOfBlock) { + UINT AmountOfEntries = (pRelocData->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD* pRelativeInfo = reinterpret_cast(pRelocData + 1); + + for (UINT i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo) { + if (RELOC_FLAG(*pRelativeInfo)) { + UINT_PTR* pPatch = reinterpret_cast(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF)); + *pPatch += reinterpret_cast(LocationDelta); + } + } + pRelocData = reinterpret_cast(reinterpret_cast(pRelocData) + pRelocData->SizeOfBlock); + } + } + } + + if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) { + auto* pImportDescr = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + while (pImportDescr->Name) { + char* szMod = reinterpret_cast(pBase + pImportDescr->Name); + HINSTANCE hDll = _LoadLibraryA(szMod); + + ULONG_PTR* pThunkRef = reinterpret_cast(pBase + pImportDescr->OriginalFirstThunk); + ULONG_PTR* pFuncRef = reinterpret_cast(pBase + pImportDescr->FirstThunk); + + if (!pThunkRef) + pThunkRef = pFuncRef; + + for (; *pThunkRef; ++pThunkRef, ++pFuncRef) { + if (IMAGE_SNAP_BY_ORDINAL(*pThunkRef)) { + *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, reinterpret_cast(*pThunkRef & 0xFFFF)); + } + else { + auto* pImport = reinterpret_cast(pBase + (*pThunkRef)); + *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, pImport->Name); + } + } + ++pImportDescr; + } + } + + if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) { + auto* pTLS = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); + auto* pCallback = reinterpret_cast(pTLS->AddressOfCallBacks); + for (; pCallback && *pCallback; ++pCallback) + (*pCallback)(pBase, DLL_PROCESS_ATTACH, nullptr); + } + + bool ExceptionSupportFailed = false; + +#ifdef _WIN64 + + if (pData->SEHSupport) { + auto excep = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + if (excep.Size) { + if (!_RtlAddFunctionTable( + reinterpret_cast(pBase + excep.VirtualAddress), + excep.Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY), (DWORD64)pBase)) { + ExceptionSupportFailed = true; + } + } + } + +#endif + + _DllMain(pBase, pData->fdwReasonParam, nullptr); + + if (ExceptionSupportFailed) + pData->hMod = reinterpret_cast(0x505050); + else + pData->hMod = reinterpret_cast(pBase); +} \ No newline at end of file diff --git a/cheat-base/src/cheat-base/inject/manual-map.h b/cheat-base/src/cheat-base/inject/manual-map.h new file mode 100644 index 0000000..3f4d133 --- /dev/null +++ b/cheat-base/src/cheat-base/inject/manual-map.h @@ -0,0 +1,4 @@ +#pragma once + +bool ManualMapDLL(HANDLE hProc, const std::string& filepath); +bool ManualMapDLL(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = false, bool ClearNonNeededSections = false, bool AdjustProtections = true, bool SEHExceptionSupport = false, DWORD fdwReason = DLL_PROCESS_ATTACH); \ No newline at end of file diff --git a/cheat-base/vendor/detours/detours-x64.lib b/cheat-base/vendor/detours/detours-x64.lib index 7fda12a..49a767c 100644 Binary files a/cheat-base/vendor/detours/detours-x64.lib and b/cheat-base/vendor/detours/detours-x64.lib differ diff --git a/cheat-base/vendor/detours/detours-x86.lib b/cheat-base/vendor/detours/detours-x86.lib new file mode 100644 index 0000000..f638091 Binary files /dev/null and b/cheat-base/vendor/detours/detours-x86.lib differ diff --git a/cheat-library/cheat-library.vcxproj b/cheat-library/cheat-library.vcxproj index 51c3fc4..3d1fd77 100644 --- a/cheat-library/cheat-library.vcxproj +++ b/cheat-library/cheat-library.vcxproj @@ -40,15 +40,7 @@ false true - - true - true - - - true - true - @@ -93,18 +85,10 @@ - - true - true - false true - - true - true - @@ -154,14 +138,6 @@ false true - - true - true - - - true - true - @@ -204,18 +180,10 @@ - - true - true - false true - - true - true - @@ -871,8 +839,8 @@ true CLibrary - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ Run false FinalizeBuildStatus @@ -880,8 +848,8 @@ false CLibrary - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ Run true FinalizeBuildStatus @@ -889,8 +857,8 @@ false CLibrary - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ Run false FinalizeBuildStatus @@ -911,6 +879,7 @@ false false ProgramDatabase + stdc17 Windows @@ -949,6 +918,7 @@ powershell -nop -c "& {sleep 15}" false Async Speed + stdc17 Windows @@ -986,6 +956,7 @@ powershell -nop -c "& {sleep 15}" Async Speed Classic + stdc17 Windows diff --git a/cheat-library/cheat-library.vcxproj.filters b/cheat-library/cheat-library.vcxproj.filters index 20245a6..3803464 100644 --- a/cheat-library/cheat-library.vcxproj.filters +++ b/cheat-library/cheat-library.vcxproj.filters @@ -48,15 +48,9 @@ Header Files - - Header Files - Header Files - - Header Files - Header Files @@ -195,12 +189,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -255,15 +243,9 @@ Source Files - - Source Files - Source Files - - Source Files - Source Files @@ -390,12 +372,6 @@ Source Files - - Source Files - - - Source Files - Source Files diff --git a/cheat-library/src/appdata/il2cpp-types.h b/cheat-library/src/appdata/il2cpp-types.h index ae47281..5c6567f 100644 --- a/cheat-library/src/appdata/il2cpp-types.h +++ b/cheat-library/src/appdata/il2cpp-types.h @@ -11651,6 +11651,16 @@ namespace app { struct Browser__Fields fields; }; + struct Button_1 { + struct Button_1__Class* klass; + MonitorData* monitor; + }; + + struct Slider_1 { + struct Slider_1__Class* klass; + MonitorData* monitor; + }; + #if !defined(_GHIDRA_) && !defined(_IDA_) } #endif diff --git a/cheat-library/src/user/cheat/misc/sniffer/MessageManager.h b/cheat-library/src/user/cheat/misc/sniffer/MessageManager.h index 6f9e448..660a0f6 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/MessageManager.h +++ b/cheat-library/src/user/cheat/misc/sniffer/MessageManager.h @@ -45,6 +45,9 @@ namespace sniffer while (true) { auto messagePtr = ReceiveMessage(); + if (messagePtr == nullptr) + return {}; + if (GetMessageIDByType() != messagePtr->messageID()) { delete messagePtr; diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.cpp b/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.cpp deleted file mode 100644 index d7c346a..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "pch-il2cpp.h" -#include "PacketInfo.h" - -#include - -namespace sniffer -{ - PacketInfo::PacketInfo(PacketData packetData) - : m_Data(packetData), - m_JObject(nlohmann::json::parse(packetData.messageJson)), - m_Time(util::GetCurrentTimeMillisec()), - m_DrawBeauty(false) - { - - } - - PacketIOType PacketInfo::type() const - { - return m_Data.ioType; - } - - uint32_t PacketInfo::id() const - { - return m_Data.messageID; - } - - size_t PacketInfo::size() const - { - return m_Data.messageRawData.size(); - } - - int64_t PacketInfo::time() const - { - return m_Time; - } - - std::string PacketInfo::name() const - { - return m_Data.name; - } - - nlohmann::json PacketInfo::object() const - { - return m_JObject; - } - - void DrawPrimitive(const std::string& key, nlohmann::json& jsonPrimitive) - { - if (jsonPrimitive.is_boolean()) - { - bool primitive = jsonPrimitive; - ImGui::Checkbox(key.c_str(), &primitive); - } - else if (jsonPrimitive.is_number_integer() || jsonPrimitive.is_number_unsigned()) - { - int primitive = jsonPrimitive; - ImGui::InputInt(key.c_str(), &primitive); - } - else if (jsonPrimitive.is_number_float()) - { - float primitive = jsonPrimitive; - ImGui::InputFloat(key.c_str(), &primitive); - } - else if (jsonPrimitive.is_string()) - { - std::string primitive = jsonPrimitive; - ImGui::InputText(key.c_str(), &primitive); - } - else if (jsonPrimitive.is_null()) - { - ImGui::Text("%s: ", key.c_str()); - } - } - - void DrawObject(const std::string& key, nlohmann::json& jsonObject); - - void DrawArray(const std::string& key, nlohmann::json& jsonArray) - { - ImGui::PushID(key.c_str()); - - if (ImGui::TreeNode(key.c_str())) - { - int i = 0; - for (auto& el : jsonArray) - { - DrawObject(std::to_string(i), el); - i++; - } - ImGui::TreePop(); - } - - ImGui::PopID(); - } - - void DrawObject(const std::string& key, nlohmann::json& jsonObject) - { - if (jsonObject.is_array()) - DrawArray(key, jsonObject); - else if (jsonObject.is_primitive()) - DrawPrimitive(key, jsonObject); - else - { - ImGui::PushID(key.c_str()); - - if (ImGui::TreeNode(key.c_str())) - { - for (auto& el : jsonObject.items()) - DrawObject(el.key(), el.value()); - - ImGui::TreePop(); - } - - ImGui::PopID(); - } - } - - void PacketInfo::Draw() - { - ImGui::PushID(this); - - if (m_Header.empty()) - m_Header = fmt::format("[{}] {} | {}. Size: {}", magic_enum::enum_name(type()), id(), name(), size()); - - if (ImGui::TreeNode(m_Header.c_str())) - { - if (ImGui::Checkbox("## Beauty", &m_DrawBeauty) && m_DrawBeauty && m_JsonMessageBeauty.empty()) - { - m_JsonMessageBeauty = m_JObject.dump(2); - } - ImGui::SameLine(); - - if (m_DrawBeauty) - ImGui::InputTextMultiline("JSON Message", &m_JsonMessageBeauty); - else - ImGui::InputText("JSON Message", &m_Data.messageJson); - - - DrawObject("Data", m_JObject); - ImGui::TreePop(); - } - - ImGui::PopID(); - } -} - diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.h b/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.h deleted file mode 100644 index 0434814..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketInfo.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -#include "messages/PacketData.h" - -namespace sniffer -{ - class PacketInfo - { - public: - PacketInfo(PacketData packetData); - - PacketIOType type() const; - uint32_t id() const; - size_t size() const; - int64_t time() const; - std::string name() const; - nlohmann::json object() const; - - void Draw(); - - private: - nlohmann::json m_JObject; - int64_t m_Time; - - bool m_DrawBeauty; - std::string m_JsonMessageBeauty; - std::string m_Header; - - PacketData m_Data; - }; -} - - diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketParser.cpp b/cheat-library/src/user/cheat/misc/sniffer/PacketParser.cpp deleted file mode 100644 index ca0cdf4..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketParser.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include "pch-il2cpp.h" -#include "PacketParser.h" - -#include "MessageManager.h" -namespace sniffer -{ - - PacketParser::PacketParser(const std::string& protoDirPath, const std::string& protoIDPath) - : m_ProtoManager() - { - m_ProtoManager.Load(protoIDPath, protoDirPath); - UpdateUnionPacketIDs(); - } - - void PacketParser::SetProtoDir(const std::string& protoDir) - { - m_ProtoManager.LoadProtoDir(protoDir); - UpdateUnionPacketIDs(); - } - - void PacketParser::SetProtoIDPath(const std::string& protoIDPath) - { - m_ProtoManager.LoadProtoDir(protoIDPath); - UpdateUnionPacketIDs(); - } - - bool PacketParser::Parse(PacketData& data) - { - auto name = m_ProtoManager.GetName(data.messageID); - if (!name) - return false; - - auto head = m_ProtoManager.GetJson("PacketHead", data.headRawData); - if (!head) - return false; - - auto message = m_ProtoManager.GetJson(data.messageID, data.messageRawData); - if (!message) - return false; - - data.name = *name; - data.headJson = *head; - data.messageJson = *message; - return true; - } - - bool PacketParser::IsUnionPacket(const PacketData& data) - { - return m_UnionPacketIds.count(data.messageID) > 0; - } - - std::vector PacketParser::ParseUnionPacket(const PacketData& data) - { - if (!IsUnionPacket(data)) - return {}; - - auto parseFunction = m_UnionPacketIds[data.messageID]; - return (this->*parseFunction)(data); - } - - PacketData PacketParser::CreateNestedPacket(const PacketData& parent, std::string bodyEncoded, int16_t packetID) - { - PacketData nestedPacketData = MessageManager::CreateMessage(); - nestedPacketData.headRawData = parent.headRawData; - nestedPacketData.headJson = parent.headJson; - nestedPacketData.messageRawData = util::base64_decode(bodyEncoded); - nestedPacketData.messageID = packetID; - nestedPacketData.valid = true; - nestedPacketData.ioType = parent.ioType; - nestedPacketData.parentPacketID = parent.sequenceID(); - - if (packetID != 0) - Parse(nestedPacketData); - - return nestedPacketData; - } - - std::vector PacketParser::ParseUnionCmdNotify(const PacketData& data) - { - nlohmann::json cmdListObject = nlohmann::json::parse(data.messageJson); - - std::vector packets; - for (auto& cmd : cmdListObject["cmdList"]) - { - auto nestedPacketData = CreateNestedPacket(data, cmd["body"], cmd["messageId"]); - packets.push_back(nestedPacketData); - - if (IsUnionPacket(nestedPacketData)) - { - auto nestedNestedPackets = ParseUnionPacket(nestedPacketData); - packets.insert(packets.end(), nestedNestedPackets.begin(), nestedNestedPackets.end()); - } - continue; - } - return packets; - } - - std::optional PacketParser::ParseAbilityInvokeEntry(const PacketData& parent, const nlohmann::json& entry) - { - static std::map abilityArgument2Proto = - { - { "ABILITY_META_MODIFIER_CHANGE", "AbilityMetaModifierChange" }, - { "ABILITY_META_COMMAND_MODIFIER_CHANGE_REQUEST", "AbilityMetaCommandModifierChangeRequest" }, - { "ABILITY_META_SPECIAL_FLOAT_ARGUMENT", "AbilityMetaSpecialFloatArgument" }, - { "ABILITY_META_OVERRIDE_PARAM", "AbilityMetaOverrideParam" }, - { "ABILITY_META_CLEAR_OVERRIDE_PARAM", "AbilityMetaClearOverrideParam" }, - { "ABILITY_META_REINIT_OVERRIDEMAP", "AbilityMetaReinitOverridemap" }, - { "ABILITY_META_GLOBAL_FLOAT_VALUE", "AbilityMetaGlobalFloatValue" }, - { "ABILITY_META_CLEAR_GLOBAL_FLOAT_VALUE", "AbilityMetaClearGlobalFloatValue" }, - { "ABILITY_META_ABILITY_ELEMENT_STRENGTH", "AbilityMetaAbilityElementStrength" }, - { "ABILITY_META_ADD_OR_GET_ABILITY_AND_TRIGGER", "AbilityMetaAddOrGetAbilityAndTrigger" }, - { "ABILITY_META_SET_KILLED_SETATE", "AbilityMetaSetKilledSetate" }, - { "ABILITY_META_SET_ABILITY_TRIGGER", "AbilityMetaSetAbilityTrigger" }, - { "ABILITY_META_ADD_NEW_ABILITY", "AbilityMetaAddNewAbility" }, - { "ABILITY_META_REMOVE_ABILITY", "AbilityMetaRemoveAbility" }, - { "ABILITY_META_SET_MODIFIER_APPLY_ENTITY", "AbilityMetaSetModifierApplyEntity" }, - { "ABILITY_META_MODIFIER_DURABILITY_CHANGE", "AbilityMetaModifierDurabilityChange" }, - { "ABILITY_META_ELEMENT_REACTION_VISUAL", "AbilityMetaElementReactionVisual" }, - { "ABILITY_META_SET_POSE_PARAMETER", "AbilityMetaSetPoseParameter" }, - { "ABILITY_META_UPDATE_BASE_REACTION_DAMAGE", "AbilityMetaUpdateBaseReactionDamage" }, - { "ABILITY_META_TRIGGER_ELEMENT_REACTION", "AbilityMetaTriggerElementReaction" }, - { "ABILITY_META_LOSE_HP", "AbilityMetaLoseHp" }, - { "ABILITY_ACTION_TRIGGER_ABILITY", "AbilityActionTriggerAbility" }, - { "ABILITY_ACTION_SET_CRASH_DAMAGE", "AbilityActionSetCrashDamage" }, - { "ABILITY_ACTION_EFFECT", "AbilityActionEffect" }, - { "ABILITY_ACTION_SUMMON", "AbilityActionSummon" }, - { "ABILITY_ACTION_BLINK", "AbilityActionBlink" }, - { "ABILITY_ACTION_CREATE_GADGET", "AbilityActionCreateGadget" }, - { "ABILITY_ACTION_APPLY_LEVEL_MODIFIER", "AbilityActionApplyLevelModifier" }, - { "ABILITY_ACTION_GENERATE_ELEM_BALL", "AbilityActionGenerateElemBall" }, - { "ABILITY_ACTION_SET_RANDOM_OVERRIDE_MAP_VALUE", "AbilityActionSetRandomOverrideMapValue" }, - { "ABILITY_ACTION_SERVER_MONSTER_LOG", "AbilityActionServerMonsterLog" }, - { "ABILITY_ACTION_CREATE_TILE", "AbilityActionCreateTile" }, - { "ABILITY_ACTION_DESTROY_TILE", "AbilityActionDestroyTile" }, - { "ABILITY_ACTION_FIRE_AFTER_IMAGE", "AbilityActionFireAfterImage" }, - { "ABILITY_MIXIN_AVATAR_STEER_BY_CAMERA", "AbilityMixinAvatarSteerByCamera" }, - { "ABILITY_MIXIN_MONSTER_DEFEND", "AbilityMixinMonsterDefend" }, - { "ABILITY_MIXIN_WIND_ZONE", "AbilityMixinWindZone" }, - { "ABILITY_MIXIN_COST_STAMINA", "AbilityMixinCostStamina" }, - { "ABILITY_MIXIN_ELITE_SHIELD", "AbilityMixinEliteShield" }, - { "ABILITY_MIXIN_ELEMENT_SHIELD", "AbilityMixinElementShield" }, - { "ABILITY_MIXIN_GLOBAL_SHIELD", "AbilityMixinGlobalShield" }, - { "ABILITY_MIXIN_SHIELD_BAR", "AbilityMixinShieldBar" }, - { "ABILITY_MIXIN_WIND_SEED_SPAWNER", "AbilityMixinWindSeedSpawner" }, - { "ABILITY_MIXIN_DO_ACTION_BY_ELEMENT_REACTION", "AbilityMixinDoActionByElementReaction" }, - { "ABILITY_MIXIN_FIELD_ENTITY_COUNT_CHANGE", "AbilityMixinFieldEntityCountChange" }, - { "ABILITY_MIXIN_SCENE_PROP_SYNC", "AbilityMixinScenePropSync" }, - { "ABILITY_MIXIN_WIDGET_MP_SUPPORT", "AbilityMixinWidgetMpSupport" } - }; - - if (entry.count("abilityData") == 0 || entry.count("argumentType") == 0) - return {}; - - std::string argumentType = entry["argumentType"]; - if (abilityArgument2Proto.count(argumentType) == 0) - return {}; - - PacketData nestedPacketData = CreateNestedPacket(parent, entry["abilityData"]); - nestedPacketData.name = abilityArgument2Proto[argumentType]; - - auto jsonData = m_ProtoManager.GetJson(nestedPacketData.name, nestedPacketData.messageRawData); - nestedPacketData.messageJson = jsonData ? *jsonData : "{}"; - return nestedPacketData; - } - - std::vector PacketParser::ParseAbilityInvocationsNotify(const PacketData& data) - { - auto combatJsonObject = nlohmann::json::parse(data.messageJson); - std::vector packets = {}; - for (auto& invokeEntry : combatJsonObject["invokes"]) - { - auto abilityPacketData = ParseAbilityInvokeEntry(data, invokeEntry); - if (abilityPacketData) - packets.push_back(*abilityPacketData); - } - return packets; - } - - std::optional PacketParser::ParseCombatInvokeEntry(const PacketData& parent, const nlohmann::json& entry) - { - static std::map combateTypeProtos = { - { "ENTITY_MOVE", "EntityMoveInfo" }, - { "COMBAT_EVT_BEING_HIT", "EvtBeingHitInfo" }, - { "COMBAT_ANIMATOR_STATE_CHANGED", "EvtAnimatorStateChangedInfo" }, - { "COMBAT_FACE_TO_DIR", "EvtFaceToDirInfo" }, - { "COMBAT_SET_ATTACK_TARGET", "EvtSetAttackTargetInfo" }, - { "COMBAT_RUSH_MOVE", "EvtRushMoveInfo" }, - { "COMBAT_ANIMATOR_PARAMETER_CHANGED", "EvtAnimatorParameterInfo" }, - { "SYNC_ENTITY_POSITION", "EvtSyncEntityPositionInfo" }, - { "COMBAT_STEER_MOTION_INFO", "EvtCombatSteerMotionInfo" }, - { "COMBAT_FORCE_SET_POSITION_INFO", "EvtCombatForceSetPosInfo" }, - { "COMBAT_FORCE_SET_POS_INFO", "EvtCombatForceSetPosInfo" }, - { "COMBAT_COMPENSATE_POS_DIFF", "EvtCompensatePosDiffInfo" }, - { "COMBAT_MONSTER_DO_BLINK", "EvtMonsterDoBlink" }, - { "COMBAT_FIXED_RUSH_MOVE", "EvtFixedRushMove" }, - { "COMBAT_SYNC_TRANSFORM", "EvtSyncTransform" }, - { "COMBAT_LIGHT_CORE_MOVE", "EvtLightCoreMove" } - }; - - if (!entry["argumentType"].is_string()) - return {}; - - std::string argumentType = entry["argumentType"]; - - if (combateTypeProtos.count(argumentType) == 0) - { - LOG_WARNING("Failed to find argument type %s", argumentType.c_str()); - return {}; - } - - PacketData nestedPacketData = CreateNestedPacket(parent, entry["combatData"]); - nestedPacketData.name = combateTypeProtos[argumentType]; - - auto jsonData = m_ProtoManager.GetJson(nestedPacketData.name, nestedPacketData.messageRawData); - nestedPacketData.messageJson = jsonData ? *jsonData : "{}"; - return nestedPacketData; - } - - std::vector PacketParser::ParseCombatInvocationsNotify(const PacketData& data) - { - auto combatJsonObject = nlohmann::json::parse(data.messageJson); - std::vector packets = {}; - for (auto& invokeEntry : combatJsonObject["invokeList"]) - { - auto combatPacketData = ParseCombatInvokeEntry(data, invokeEntry); - if (combatPacketData) - packets.push_back(*combatPacketData); - } - return packets; - } - - void PacketParser::UpdateUnionPacketIDs() - { - m_UnionPacketIds.clear(); - for (auto& [unionPacketName, parserFunc] : s_UnionPacketNames) - { - m_UnionPacketIds[m_ProtoManager.GetId(unionPacketName)] = parserFunc; - } - } -} \ No newline at end of file diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketParser.h b/cheat-library/src/user/cheat/misc/sniffer/PacketParser.h deleted file mode 100644 index 700a623..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketParser.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include "messages/PacketData.h" -#include "ProtoManager.h" - -namespace sniffer -{ - class PacketParser - { - public: - PacketParser(const std::string& protoDirPath, const std::string& protoIDPath); - - void SetProtoDir(const std::string& protoDir); - void SetProtoIDPath(const std::string& protoIDPath); - - bool Parse(PacketData& data); - bool IsUnionPacket(const PacketData& data); - std::vector ParseUnionPacket(const PacketData& data); - - private: - PacketData CreateNestedPacket(const PacketData& parent, std::string bodyEncoded, int16_t packetID = 0); - std::vector ParseUnionCmdNotify(const PacketData& data); - - std::optional ParseAbilityInvokeEntry(const PacketData& parent, const nlohmann::json& entry); - std::vector ParseAbilityInvocationsNotify(const PacketData& data); - - std::optional ParseCombatInvokeEntry(const PacketData& parent, const nlohmann::json& entry); - std::vector ParseCombatInvocationsNotify(const PacketData& data); - - using UnionPacketParserFunc = std::vector(PacketParser::*)(const PacketData& data); - inline static std::map s_UnionPacketNames = - { - { "UnionCmdNotify", &ParseUnionCmdNotify}, - - { "EntityAbilityInvokeEntry", &ParseAbilityInvocationsNotify }, - { "ClientAbilityInitFinishNotify", &ParseAbilityInvocationsNotify }, - { "ClientAbilityChangeNotify", &ParseAbilityInvocationsNotify }, - { "AbilityInvocationsNotify", &ParseAbilityInvocationsNotify }, - - { "CombatInvocationsNotify", &ParseCombatInvocationsNotify} - }; - - sniffer::ProtoManager m_ProtoManager; - std::map m_UnionPacketIds; - - void UpdateUnionPacketIDs(); - }; -} - - diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp index 534f669..c8f1771 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp +++ b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp @@ -11,18 +11,12 @@ namespace cheat::feature { PacketSniffer::PacketSniffer() : Feature(), - NF(m_CapturingEnabled, "Capturing", "PacketSniffer", false), - NF(m_ManipulationEnabled, "Manipulation", "PacketSniffer", false), - NF(m_PipeEnabled, "Pipe", "PacketSniffer", false) - -#ifdef _PACKET_SNIFFER - , NF(m_ProtoDirPath, "Proto Dir Path", "PacketSniffer", ""), - NF(m_ProtoIDFilePath, "Proto ID File Path", "PacketSniffer", ""), - m_PacketParser(m_ProtoDirPath, m_ProtoIDFilePath) -#endif + NF(f_CaptureEnabled, "Capturing", "PacketSniffer", false), + NF(f_ManipulationEnabled, "Manipulation", "PacketSniffer", false), + NF(f_PipeName, "Pipe name", "PacketSniffer", "genshin_packet_pipe") { - sniffer::MessageManager::Connect("genshin_packet_pipe"); + sniffer::MessageManager::Connect(f_PipeName.value()); HookManager::install(app::Kcp_KcpNative_kcp_client_send_packet, KcpNative_kcp_client_send_packet_Hook); HookManager::install(app::MoleMole_KcpClient_TryDequeueEvent, KcpClient_TryDequeueEvent_Hook); @@ -34,80 +28,14 @@ namespace cheat::feature return info; } - bool PacketSniffer::OnCapturingChanged() - { -#ifdef _PACKET_SNIFFER - if (!m_CapturingEnabled) - return true; - - if (!m_ProtoDirPath.value().empty() && !m_ProtoIDFilePath.value().empty()) - { - m_PacketParser.SetProtoIDPath(m_ProtoIDFilePath); - m_PacketParser.SetProtoDir(m_ProtoDirPath); - return true; - } - - return false; -#endif - - return true; - } - void PacketSniffer::DrawMain() { - - //ImGui::Text("Dev: for working needs server for named pipe 'genshin_packet_pipe'.\nCheck 'packet-handler' project like example."); - if (ConfigWidget(m_CapturingEnabled, "Enabling capturing of packet info and sending to pipe, if it exists.")) - { - bool result = OnCapturingChanged(); - if (!result) - { - m_CapturingEnabled = false; - ImGui::OpenPopup("Error"); - } - } - - if (ImGui::BeginPopup("Error")) - { - ImGui::Text("Please fill 'Proto Dir Path' and 'Proto ID File Path' before enabling capture."); - ImGui::EndPopup(); - } - -#ifdef _PACKET_SNIFFER - auto& window = sniffer::SnifferWindow::GetInstance(); - ConfigWidget(window.m_Show, "Show capturing window."); - - ConfigWidget(m_PipeEnabled, "Enable sending of packet data to pipe with name 'genshin_packet_pipe'.\n"\ - "This feature can be used with external monitoring tools."); - //ConfigWidget(m_ManipulationEnabled, "Enabling manipulation packet feature, that allows to replace, block incoming/outcoming packets." \ - // "\nThis feature often needs, to read-write pipe operation, so can decrease network bandwidth."); - - if (m_CapturingEnabled) - { - ImGui::Text("These parameters can only be changed when 'Capturing' is disabled."); - ImGui::BeginDisabled(); - } - - ConfigWidget(m_ProtoDirPath, "Path to directory containing Genshin .proto files."); - ConfigWidget(m_ProtoIDFilePath, "Path to JSON file containing packet id->packet name info."); - - if (m_CapturingEnabled) - ImGui::EndDisabled(); -#else - ImGui::Text("When capture is enabled, raw packet data will be send to named pipe: 'genshin_packet_pipe'."); - ImGui::Text("'Raw' means that you should to parse protobuf structure by yourself."); -#endif + ImGui::Text("Dev: for working needs server for named pipe with specified name.\nCheck 'packet-handler' project like example."); + ConfigWidget(f_PipeName, "Pipe name for connecting. Changes will apply after next game launch."); + ConfigWidget(f_CaptureEnabled, "Enable capturing of packet info and sending to pipe, if it exists."); + ConfigWidget(f_ManipulationEnabled, "Enable blocking and modifying packets by sniffer, can cause network lags."); } - void PacketSniffer::DrawExternal() - { -#ifdef _PACKET_SNIFFER - auto& window = sniffer::SnifferWindow::GetInstance(); - if (window.m_Show) - window.Draw(); -#endif - } - PacketSniffer& PacketSniffer::GetInstance() { static PacketSniffer instance; @@ -141,7 +69,10 @@ namespace cheat::feature bool PacketSniffer::OnPacketIO(app::KcpPacket_1* packet, PacketIOType type) { - if (!m_CapturingEnabled) + if (!sniffer::MessageManager::IsConnected()) + return true; + + if (!f_CaptureEnabled) return true; PacketData packetData = ParseRawPacketData((char*)packet->data, packet->dataLen); @@ -149,30 +80,10 @@ namespace cheat::feature return true; packetData.ioType = type; - packetData.blockModeEnabled = m_ManipulationEnabled; - -#ifdef _PACKET_SNIFFER - bool parsed = m_PacketParser.Parse(packetData); - if (!parsed) - return true; - - sniffer::SnifferWindow::GetInstance().OnPacketIO({packetData}); -#endif - + packetData.blockModeEnabled = f_ManipulationEnabled; sniffer::MessageManager::Send(packetData); - bool canceled = m_ManipulationEnabled && ProcessModifiedData(packet); - -#ifdef _PACKET_SNIFFER - if (m_PacketParser.IsUnionPacket(packetData)) - { - for (auto& nestedPacketData : m_PacketParser.ParseUnionPacket(packetData)) - { - sniffer::SnifferWindow::GetInstance().OnPacketIO({ nestedPacketData }); - sniffer::MessageManager::Send(nestedPacketData); - } - } -#endif + bool canceled = f_ManipulationEnabled && ProcessModifiedData(packet); return !canceled; } diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h index 890130b..68a9934 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h +++ b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h @@ -12,41 +12,25 @@ #include "MessageManager.h" -#ifdef _PACKET_SNIFFER -#include "PacketParser.h" -#include "PacketInfo.h" -#endif - namespace cheat::feature { class PacketSniffer : public Feature { public: - config::Field m_CapturingEnabled; - config::Field m_ManipulationEnabled; - config::Field m_PipeEnabled; - -#ifdef _PACKET_SNIFFER - config::Field m_ProtoDirPath; - config::Field m_ProtoIDFilePath; -#endif + config::Field f_CaptureEnabled; + config::Field f_ManipulationEnabled; + config::Field f_PipeName; static PacketSniffer& GetInstance(); const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; - void DrawExternal() final; - private: -#ifdef _PACKET_SNIFFER - sniffer::PacketParser m_PacketParser; -#endif PacketSniffer(); - PacketData ParseRawPacketData(char* encryptedData, uint32_t length); - bool OnCapturingChanged(); + PacketData ParseRawPacketData(char* encryptedData, uint32_t length); static char* EncryptXor(void* content, uint32_t length); static bool KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method); static int32_t KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method); diff --git a/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.cpp b/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.cpp deleted file mode 100644 index 3a82161..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "pch-il2cpp.h" -#include "ProtoManager.h" - -#include - -namespace sniffer -{ - - class ErrorCollector : public google::protobuf::compiler::MultiFileErrorCollector - { - // Inherited via MultiFileErrorCollector - virtual void AddError(const std::string& filename, int line, int column, const std::string& message) override - { - LOG_ERROR("Error while parsing %s file, line %d, column %d, error: %s\n", filename.c_str(), line, column, message.c_str()); - } - }; - - void ProtoManager::LoadProtoDir(const std::string& dirPath) - { - const std::lock_guard lock(_mutex); - - diskTree = std::shared_ptr(new google::protobuf::compiler::DiskSourceTree()); - if (!dirPath.empty()) - diskTree->MapPath("", dirPath); - - auto errorCollector = new ErrorCollector(); - importer = std::shared_ptr(new google::protobuf::compiler::Importer(diskTree.get(), errorCollector)); - factory = std::shared_ptr(new google::protobuf::DynamicMessageFactory(importer->pool())); - } - - void ProtoManager::LoadIDFile(const std::string& filepath) - { - if (filepath.empty()) - return; - - const std::lock_guard lock(_mutex); - - nameMap.clear(); - - std::ifstream file; - file.open(filepath); - if (!file.is_open()) - { - LOG_WARNING("Failed to load proto id file."); - return; - } - - auto content = nlohmann::json::parse(file); - for (nlohmann::json::iterator it = content.begin(); it != content.end(); ++it) - { - auto id = std::stoi(it.key().c_str()); - nameMap[id] = it.value(); - idMap[it.value()] = id; - } - file.close(); - } - - google::protobuf::Message* ProtoManager::ParseMessage(const std::string& name, std::vector data) - { - const std::lock_guard lock(_mutex); - - auto fileDescriptor = importer->Import(name + ".proto"); - if (fileDescriptor == nullptr || fileDescriptor->message_type_count() == 0) - return nullptr; - - auto message = factory->GetPrototype(fileDescriptor->message_type(0))->New(); - - std::string stringData((char*)data.data(), data.size()); - message->ParseFromString(stringData); - return message; - } - - ProtoManager::ProtoManager() {} - - void ProtoManager::Load(const std::string& idFilePath, const std::string& protoDir) - { - LoadIDFile(idFilePath); - LoadProtoDir(protoDir); - } - - std::optional ProtoManager::GetJson(const std::string& name, std::vector& data) - { - auto message = ParseMessage(name, data); - if (message == nullptr) - { - LOG_ERROR("Failed to parse message with name %s.", name.c_str()); - return {}; - } - - std::string jsonMessage = {}; - google::protobuf::util::MessageToJsonString(*message, &jsonMessage); - - delete message; - - return jsonMessage; - } - - std::optional ProtoManager::GetJson(uint32_t id, std::vector& data) - { - auto name = GetName(id); - if (!name) - return {}; - - return GetJson(*name, data); - } - - std::optional ProtoManager::GetName(uint32_t id) - { - const std::lock_guard lock(_mutex); - - if (nameMap.count(id) == 0) - { - LOG_WARNING("Failed to find proto with id %u", id); - return {}; - } - - return nameMap[id]; - } - - uint16_t ProtoManager::GetId(const std::string& name) - { - return idMap.count(name) == 0 ? 0 : idMap[name]; - } - -} \ No newline at end of file diff --git a/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.h b/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.h deleted file mode 100644 index 0809acf..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/ProtoManager.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include - -namespace sniffer -{ - class ProtoManager - { - public: - ProtoManager(); - - std::optional GetJson(uint32_t id, std::vector& data); - std::optional GetJson(const std::string& name, std::vector& byte); - std::optional GetName(uint32_t id); - uint16_t GetId(const std::string& name); - - void Load(const std::string& idFilePath, const std::string& protoDir); - void LoadIDFile(const std::string& filepath); - void LoadProtoDir(const std::string& dirPath); - - private: - std::mutex _mutex; - std::shared_ptr importer; - std::shared_ptr factory; - std::shared_ptr diskTree; - - std::map nameMap; - std::map idMap; - - google::protobuf::Message* ParseMessage(const std::string& name, std::vector data); - - }; -} - - diff --git a/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.cpp b/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.cpp deleted file mode 100644 index 604ee5c..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.cpp +++ /dev/null @@ -1,547 +0,0 @@ -#include "pch-il2cpp.h" -#include "SnifferWindow.h" -#include -#include -#include - -namespace sniffer -{ - SnifferWindow& SnifferWindow::GetInstance() - { - static SnifferWindow instance; - return instance; - } - - static auto nameCompare = [](const PacketInfo& a, const PacketInfo& b) { return a.name() < b.name(); }; - static auto sizeCompare = [](const PacketInfo& a, const PacketInfo& b) { return a.size() < b.size(); }; - static auto idCompare = [](const PacketInfo& a, const PacketInfo& b) { return a.id() < b.id(); }; - static auto typeCompare = [](const PacketInfo& a, const PacketInfo& b) { return a.type() < b.type(); }; - static auto timeCompare = [](const PacketInfo& a, const PacketInfo& b) { return a.time() < b.time(); }; - - void SnifferWindow::OnPacketIO(const PacketInfo& info) - { - const std::lock_guard lock(m_CapturePacketLock); - - if (m_SortValue == SortValue::Time) - { - m_CapturedPackets.push_back(info); - if (m_FilterGroup.Execute(info)) - m_CachedPackets.push_back(info); - return; - } - - switch (m_SortValue) - { - case sniffer::SnifferWindow::SortValue::Name: - m_CapturedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, nameCompare), info); - if (m_FilterGroup.Execute(info)) - m_CachedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, nameCompare), info); - break; - case sniffer::SnifferWindow::SortValue::Size: - m_CapturedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, sizeCompare), info); - if (m_FilterGroup.Execute(info)) - m_CachedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, nameCompare), info); - break; - case sniffer::SnifferWindow::SortValue::Id: - m_CapturedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, idCompare), info); - if (m_FilterGroup.Execute(info)) - m_CachedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, nameCompare), info); - break; - case sniffer::SnifferWindow::SortValue::Type: - m_CapturedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, typeCompare), info); - if (m_FilterGroup.Execute(info)) - m_CachedPackets.insert(std::lower_bound(m_CapturedPackets.begin(), m_CapturedPackets.end(), info, nameCompare), info); - break; - default: - break; - } - } - -#undef min -#undef max - - void SnifferWindow::Draw() - { - - const std::lock_guard lock(m_CapturePacketLock); - - bool showPrev = m_Show; - bool windowShowed = ImGui::Begin("Packet sniffer", m_Show); - - if (showPrev != m_Show) - m_Show.FireChanged(); - - if (!windowShowed) - { - ImGui::End(); - return; - } - - if (ComboEnum("## SortValue", &m_SortValue)) - { - switch (m_SortValue) - { - case sniffer::SnifferWindow::SortValue::Name: - m_CapturedPackets.sort(nameCompare); - m_CachedPackets.sort(nameCompare); - break; - case sniffer::SnifferWindow::SortValue::Size: - m_CapturedPackets.sort(sizeCompare); - m_CachedPackets.sort(sizeCompare); - break; - case sniffer::SnifferWindow::SortValue::Id: - m_CapturedPackets.sort(idCompare); - m_CachedPackets.sort(idCompare); - break; - case sniffer::SnifferWindow::SortValue::Type: - m_CapturedPackets.sort(typeCompare); - m_CachedPackets.sort(typeCompare); - break; - case sniffer::SnifferWindow::SortValue::Time: - m_CapturedPackets.sort(timeCompare); - m_CachedPackets.sort(timeCompare); - break; - default: - break; - } - } - ImGui::SameLine(); - ComboEnum("Sort ## SortType", &m_SortType); - - m_FilterGroup.Draw(false); - - if (ImGui::Button("Apply filter")) - { - m_CachedPackets.clear(); - for (auto& info : m_CapturedPackets) - { - if (m_FilterGroup.Execute(info)) - { - m_CachedPackets.push_back(info); - } - } - } - ImGui::SameLine(); - - if (ImGui::Button("Clear history")) - { - m_CapturedPackets.clear(); - m_CachedPackets.clear(); - } - - ImGui::BeginChild("Packets"); - - if (m_SortType == SortType::Asc) - { - for (auto& info : m_CachedPackets) - info.Draw(); - } - else - { - for (auto it = m_CachedPackets.rbegin(); it != m_CachedPackets.rend(); it++) - it->Draw(); - } - - ImGui::EndChild(); - - ImGui::End(); - } - - SnifferWindow::SnifferWindow() : - NF(m_Show, "Show capturing window", "SnifferWindow", false), - m_SortType(SortType::Desc), - m_SortValue(SortValue::Time) - { - - } - - bool Filter::Draw(bool canBeRemoved) -{ - ImGui::PushID(this); - ComboEnum("## ObjectType", &m_ObjectType); ImGui::SameLine(); - ComboEnum("## CompareType", &m_CompareType); ImGui::SameLine(); - - if (m_ObjectType != ObjectType::AnyValue) - { - ImGui::SetNextItemWidth(200); - ImGui::InputText("## Key", &m_KeyPattern); ImGui::SameLine(); - } - - if (m_ObjectType == ObjectType::AnyValue || m_ObjectType == ObjectType::KeyValue) - { - ImGui::SetNextItemWidth(200); - ImGui::InputText("## Value", &m_ObjectPattern); ImGui::SameLine(); - } - - bool removed = false; - if (canBeRemoved && ImGui::Button("Remove")) - removed = true; - - ImGui::PopID(); - return removed; - } - - static std::vector StringSplit(const std::string& delimiter, const std::string& content) - { - std::vector tokens; - size_t pos = 0; - size_t prevPos = 0; - std::string token; - while ((pos = content.find(delimiter, prevPos)) != std::string::npos) { - token = content.substr(prevPos, pos - prevPos); - tokens.push_back(token); - prevPos = pos + delimiter.length(); - } - tokens.push_back(content.substr(prevPos)); - return tokens; - } - - static bool ApplyCompareString(const std::string& value, const std::string& pattern, Filter::CompareType compare) - { - std::string lowerValue = value; - std::transform(lowerValue.begin(), lowerValue.end(), lowerValue.begin(), - [](unsigned char c) { return std::tolower(c); }); - - std::string lowerPattern = pattern; - std::transform(lowerPattern.begin(), lowerPattern.end(), lowerPattern.begin(), - [](unsigned char c) { return std::tolower(c); }); - - switch (compare) - { - case sniffer::Filter::CompareType::Regex: - { - std::regex _regex(lowerPattern.c_str()); - return std::regex_match(lowerValue, _regex); - } - case sniffer::Filter::CompareType::Equal: - return lowerValue == lowerPattern; - case sniffer::Filter::CompareType::Contains: - return lowerValue.find(lowerPattern) != std::string::npos; - default: - return false; - } - } - - template - static bool ApplyCompareAnyType(const nlohmann::json& object, const T& value, Filter::CompareType compare) - { - switch (compare) - { - case sniffer::Filter::CompareType::Equal: - return object == value; - case sniffer::Filter::CompareType::Less: - return object < value; - case sniffer::Filter::CompareType::LessEqual: - return object <= value; - case sniffer::Filter::CompareType::More: - return object > value; - case sniffer::Filter::CompareType::MoreEqual: - return object >= value; - default: - return false; - } - } - - static bool ApplyCompareValue(const nlohmann::json& object, const std::string& pattern, Filter::CompareType compare) - { - if (object.is_string()) - return ApplyCompareString(object, pattern, compare); - - if (object.is_boolean()) - { - if (compare != Filter::CompareType::Equal) - return false; - - bool value = pattern == "true" || pattern == "1"; - return object == value; - } - - if (!object.is_number()) - return false; - - if (object.is_number_float()) - { - auto value = std::stof(pattern); - return ApplyCompareAnyType(object, value, compare); - } - - if (object.is_number_integer()) - { - auto value = std::stoi(pattern); - return ApplyCompareAnyType(object, value, compare); - } - - if (object.is_number_unsigned()) - { - auto value = std::stoul(pattern); - return ApplyCompareAnyType(object, value, compare); - } - - return false; - } - - static bool HasValue(const nlohmann::json& object, const std::string& pattern, Filter::CompareType compare) - { - if (object.is_array()) - { - for (auto& nested : object) - { - if (HasValue(nested, pattern, compare)) - return true; - } - return false; - } - - - if (object.is_object()) - { - for (auto& item : object.items()) - { - if (HasValue(item.value(), pattern, compare)) - return true; - } - return false; - } - - return ApplyCompareValue(object, pattern, compare); - } - - bool Filter::FindAnyValue(const sniffer::PacketInfo& info) - { - if (m_ObjectPattern.empty()) - return true; - - return HasValue(info.object(), m_ObjectPattern, m_CompareType); - } - - bool Filter::FindAnyKey(const sniffer::PacketInfo& info) - { - if (m_KeyPattern.empty()) - return true; - - return !FindKeys(info, true).empty(); - } - - bool Filter::FindKeyValue(const sniffer::PacketInfo& info) - { - if (m_KeyPattern.empty()) - return true; - - auto objects = FindKeys(info); - for (auto& obj : objects) - { - if (ApplyCompareValue(info.object(), m_ObjectPattern, m_CompareType)) - return true; - } - return false; - } - - static std::vector FindKey(const nlohmann::json& object, const std::string& pattern, Filter::CompareType compareType, bool onlyFirst, bool recursive) - { - std::vector objects; - - if (object.is_array()) - { - if (!recursive) - return objects; - - for (auto& nested : object) - { - auto nestedResult = FindKey(nested, pattern, compareType, onlyFirst, recursive); - if (nestedResult.size() > 0) - { - objects.insert(objects.end(), nestedResult.begin(), nestedResult.end()); - if (onlyFirst) - return objects; - } - - } - } - else if (object.is_object()) - { - for (auto& item : object.items()) - { - bool correct = ApplyCompareString(item.key(), pattern, compareType); - if (!correct) - { - if (recursive) - { - auto nestedResult = FindKey(item.value(), pattern, compareType, onlyFirst, recursive); - if (nestedResult.size() > 0) - { - objects.insert(objects.end(), nestedResult.begin(), nestedResult.end()); - if (onlyFirst) - return objects; - } - } - continue; - } - - objects.push_back(item.value()); - if (onlyFirst) - return objects; - } - } - return objects; - - } - - std::vector Filter::FindKeys(const sniffer::PacketInfo& info, bool onlyFirst) - { - auto equalType = m_ObjectType == ObjectType::KeyValue ? CompareType::Regex : m_CompareType; - auto tokens = StringSplit("::", m_KeyPattern); - - std::string& mainToken = tokens[0]; - if (tokens.size() == 1) - { - auto mainObjects = FindKey(info.object(), mainToken, equalType, onlyFirst, true); - return mainObjects; - } - - auto objects = FindKey(info.object(), m_KeyPattern, equalType, false, true); - - for (auto it = tokens.begin() + 1; it != tokens.end(); it++) - { - if (objects.empty()) - return {}; - - bool last_token = (tokens.end() - 1) == it; - bool _onlyFirst = onlyFirst && last_token; - - objects = FindKey(objects, *it, equalType, _onlyFirst, false); - } - - return objects; - } - - - bool Filter::Execute(const sniffer::PacketInfo& info) - { - try - { - switch (m_ObjectType) - { - case sniffer::Filter::ObjectType::KeyValue: - return FindKeyValue(info); - case sniffer::Filter::ObjectType::AnyKey: - return FindAnyKey(info); - case sniffer::Filter::ObjectType::AnyValue: - return FindAnyValue(info); - case sniffer::Filter::ObjectType::Name: - return ApplyCompareString(info.name(), m_KeyPattern, m_CompareType); - case sniffer::Filter::ObjectType::PacketId: - return ApplyCompareString(std::to_string(info.id()), m_KeyPattern, m_CompareType); - default: - return true; - } - } - catch (const std::regex_error& e) - { - UNREFERENCED_PARAMETER(e); - return false; - } - } - - nlohmann::json Filter::Serialize() - { - return {}; - } - - Filter::Filter() - : m_CompareType(CompareType::Equal), - m_ObjectType(ObjectType::KeyValue) - { - - } - - Filter::Filter(nlohmann::json& object) - : Filter() - { - - } - - bool FilterGroup::Draw(bool canBeRemoved) -{ - ImGui::PushID(this); - - bool removed = false; - auto name = fmt::format("Group {}", magic_enum::enum_name(m_Rule)); - ImGui::BeginGroupPanel(name.c_str()); - { - ComboEnum("Rule", &m_Rule); - - if (canBeRemoved) - { - ImGui::SameLine(); - if (ImGui::Button("Remove")) - removed = true; - } - - std::optional removeFilter = {}; - for (auto& filter : m_Filters) - { - if (filter->Draw()) - removeFilter = filter; - } - - if (removeFilter) - { - m_Filters.remove(*removeFilter); - delete* removeFilter; - } - - if (ImGui::Button("Add group", ImVec2(70, 0))) - m_Filters.push_back(new FilterGroup()); - - ImGui::SameLine(); - - if (ImGui::Button("Add filter", ImVec2(70, 0))) - m_Filters.push_back(new Filter()); - - } - ImGui::EndGroupPanel(); - - ImGui::PopID(); - - return removed; - } - - - bool FilterGroup::Execute(const sniffer::PacketInfo& info) - { - if (m_Filters.empty()) - return true; - - for (auto& filter : m_Filters) - { - bool result = filter->Execute(info); - if (m_Rule == Rule::AND && !result) - return false; - - if (m_Rule == Rule::NOT && result) - return false; - - if (m_Rule == Rule::OR && result) - return true; - } - return m_Rule != Rule::OR; - } - - - nlohmann::json FilterGroup::Serialize() - { - return {}; - } - - FilterGroup::FilterGroup() : - m_Rule(Rule::AND), - m_Filters() - { - - } - - FilterGroup::FilterGroup(nlohmann::json& object) : FilterGroup() - { - } - -} diff --git a/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.h b/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.h deleted file mode 100644 index f7c4d46..0000000 --- a/cheat-library/src/user/cheat/misc/sniffer/SnifferWindow.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include "PacketInfo.h" - -namespace sniffer -{ - - class IFilter - { - public: - virtual bool Draw(bool canBeRemoved = true) = 0; - virtual bool Execute(const sniffer::PacketInfo& info) = 0; - virtual nlohmann::json Serialize() = 0; - }; - - - class Filter : public IFilter - { - public: - enum class CompareType - { - Regex, Equal, Contains, Less, LessEqual, More, MoreEqual - }; - - enum class ObjectType - { - KeyValue, AnyKey, AnyValue, Name, PacketId - }; - - virtual bool Draw(bool canBeRemoved = true) override; - virtual bool Execute(const sniffer::PacketInfo& info) override; - - virtual nlohmann::json Serialize() override; - - Filter(); - Filter(nlohmann::json& object); - private: - - bool FindAnyValue(const sniffer::PacketInfo& info); - bool FindAnyKey(const sniffer::PacketInfo& info); - bool FindKeyValue(const sniffer::PacketInfo& info); - std::vector FindKeys(const sniffer::PacketInfo& info, bool onlyFirst = false); - - CompareType m_CompareType; - ObjectType m_ObjectType; - - std::string m_KeyPattern; - std::string m_ObjectPattern; - }; - - class FilterGroup : public IFilter - { - public: - - enum class Rule - { - AND, OR, NOT - }; - - virtual bool Draw(bool canBeRemoved = true) override; - virtual bool Execute(const sniffer::PacketInfo& info) override; - - virtual nlohmann::json Serialize() override; - - FilterGroup(); - FilterGroup(nlohmann::json& object); - - private: - Rule m_Rule; - std::list m_Filters; - - }; - - class SnifferWindow - { - public: - config::Field m_Show; - - SnifferWindow(SnifferWindow const&) = delete; - void operator=(SnifferWindow const&) = delete; - - static SnifferWindow& GetInstance(); - void OnPacketIO(const PacketInfo& info); - void Draw(); - - private: - enum class SortValue - { - Time, Name, Size, Id, Type - }; - - enum class SortType - { - Desc, Asc - }; - - SortValue m_SortValue; - SortType m_SortType; - - std::list m_CapturedPackets; - std::list m_CachedPackets; - - std::mutex m_CapturePacketLock; - - FilterGroup m_FilterGroup; - - SnifferWindow(); - }; -} - diff --git a/cheat-library/src/user/cheat/misc/sniffer/messages/PacketData.cpp b/cheat-library/src/user/cheat/misc/sniffer/messages/PacketData.cpp index d4b63ca..30c695d 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/messages/PacketData.cpp +++ b/cheat-library/src/user/cheat/misc/sniffer/messages/PacketData.cpp @@ -5,36 +5,16 @@ void PacketData::Write(PipeTransfer* transfer) { transfer->Write(blockModeEnabled); transfer->Write(ioType); - transfer->Write(dataType); - transfer->Write(valid); - transfer->Write(parentPacketID); transfer->Write(messageID); transfer->Write(headRawData); transfer->Write(messageRawData); - - if (dataType == PacketDataType::Parsed) - { - transfer->Write(name); - transfer->Write(headJson); - transfer->Write(messageJson); - } } void PacketData::Read(PipeTransfer* transfer) { transfer->Read(blockModeEnabled); transfer->Read(ioType); - transfer->Read(dataType); - transfer->Read(valid); - transfer->Read(parentPacketID); transfer->Read(messageID); transfer->Read(headRawData); transfer->Read(messageRawData); - - if (dataType == PacketDataType::Parsed) - { - transfer->Read(name); - transfer->Read(headJson); - transfer->Read(messageJson); - } } diff --git a/cheat-library/src/user/cheat/visuals/Browser.h b/cheat-library/src/user/cheat/visuals/Browser.h index d6f0760..b325145 100644 --- a/cheat-library/src/user/cheat/visuals/Browser.h +++ b/cheat-library/src/user/cheat/visuals/Browser.h @@ -13,13 +13,13 @@ namespace cheat::feature static Browser& GetInstance(); const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; - virtual bool NeedStatusDraw() const override; + bool NeedStatusDraw() const override; void DrawStatus() override; private: SafeQueue toBeUpdate; SafeValue nextUpdate; - int f_DelayUpdate = 20.f; + int f_DelayUpdate = 20; void OnGameUpdate(); Browser(); }; diff --git a/cheat-library/src/user/cheat/visuals/PaimonFollow.h b/cheat-library/src/user/cheat/visuals/PaimonFollow.h index d5dd65d..3713d98 100644 --- a/cheat-library/src/user/cheat/visuals/PaimonFollow.h +++ b/cheat-library/src/user/cheat/visuals/PaimonFollow.h @@ -18,7 +18,7 @@ namespace cheat::feature private: SafeQueue toBeUpdate; SafeValue nextUpdate; - int f_DelayUpdate = 100.f; + int f_DelayUpdate = 100; void OnGameUpdate(); PaimonFollow(); diff --git a/cheat-library/src/user/cheat/visuals/ProfileChanger.h b/cheat-library/src/user/cheat/visuals/ProfileChanger.h index 6d157d4..b649af6 100644 --- a/cheat-library/src/user/cheat/visuals/ProfileChanger.h +++ b/cheat-library/src/user/cheat/visuals/ProfileChanger.h @@ -27,7 +27,7 @@ namespace cheat::feature const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; - virtual bool NeedStatusDraw() const override; + bool NeedStatusDraw() const override; void DrawStatus() override; bool CheckFile(const std::string& name); @@ -35,7 +35,7 @@ namespace cheat::feature private: SafeQueue toBeUpdate; SafeValue nextUpdate; - int f_DelayUpdate = 100.f; + int f_DelayUpdate = 100; void OnGameUpdate(); ProfileChanger(); diff --git a/injector/injector.vcxproj b/injector/injector.vcxproj index 09882c9..836096f 100644 --- a/injector/injector.vcxproj +++ b/injector/injector.vcxproj @@ -74,18 +74,18 @@ false - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ false - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ false - $(SolutionDir)bin\$(Configuration)\ - $(SolutionDir)bin\$(Configuration)\obj\$(ProjectName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\ + $(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\ @@ -99,6 +99,7 @@ ProgramDatabase false $(ProjectDir)include/;$(SolutionDir)cheat-base/src;$(SolutionDir)cheat-base/vendor/simpleIni/ + stdc17 Console @@ -128,6 +129,7 @@ true stdcpp17 $(ProjectDir)include/;$(SolutionDir)cheat-base/src;$(SolutionDir)cheat-base/vendor/simpleIni/ + stdc17 Console @@ -154,6 +156,7 @@ true stdcpp17 $(ProjectDir)include/;$(SolutionDir)cheat-base/src;$(SolutionDir)cheat-base/vendor/simpleIni/ + stdc17 Console diff --git a/injector/src/injector.cpp b/injector/src/injector.cpp index e3dcb0c..1fb7bf3 100644 --- a/injector/src/injector.cpp +++ b/injector/src/injector.cpp @@ -1,414 +1,14 @@ #include "injector.h" -#if defined(DISABLE_OUTPUT) -#define ILog(data, ...) -#define IPrintError(text, ...) -#else -#define ILog(text, ...) printf(text, __VA_ARGS__) -#define ILogError(text, ...) ILog(text, __VA_ARGS__); std::cout << "Error: " << util::GetLastErrorAsString() << std::endl -#endif +#include +#include -#ifdef _WIN64 -#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64 -#else -#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386 -#endif - -bool InjectDLL(HANDLE hProc, const std::string& filepath) +bool InjectDLL(HANDLE hProc, const std::string& filepath) { -#ifndef MANUAL_MAP - // Using LoadLibrary inject to be able to debug DLL in attached process. - // NOTE. For debug also needs disable mhyprot protection. (See protection-bypass.h in cheat-library) - // NOTE 2. Also need find way to disable antidebug. - bool result = LoadLibraryInject(hProc, filepath); +#ifdef MANUAL_MAP + bool result = ManualMapDLL(hProc, filepath); #else - std::ifstream file(filepath, std::ios::in | std::ios::binary | std::ios::ate); - if (!file.is_open()) - { - std::cout << "Error while reading DLL file!" << std::endl; - return false; - } - - std::streampos size = file.tellg(); - auto memblock = new char[size]; - file.seekg(0, std::ios::beg); - file.read(memblock, size); - file.close(); - - BYTE* fileContent = (BYTE*)memblock; - - // Manual map injection will help us to be like a assasin - bool result = ManualMapDll(hProc, fileContent, size); - - delete[] memblock; + bool result = LoadLibraryDLL(hProc, filepath); #endif - return result; -} - -#ifndef MANUAL_MAP -static bool LoadLibraryInject(HANDLE hProc, const std::string& dllpath) -{ - HMODULE hKernel = GetModuleHandle("kernel32.dll"); - if (hKernel == NULL) { - ILogError("[DLL Injection] Failed to get kernel32.dll module address.\n"); - return false; - } - - LPVOID pLoadLibrary = (LPVOID)GetProcAddress(hKernel, "LoadLibraryA"); - if (pLoadLibrary == NULL) { - ILogError("[DLL Injection] Failed to get LoadLibraryA address.\n"); - return false; - } - - LPVOID pDLLPath = VirtualAllocEx(hProc, NULL, strlen(dllpath.c_str()) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (pDLLPath == NULL) { - ILogError("[DLL Injection] Failed to allocate memory for DLLPath in target process.\n"); - return false; - } - - // Write the string name of our DLL in the memory allocated - BOOL writeResult = WriteProcessMemory(hProc, pDLLPath, dllpath.c_str(), strlen(dllpath.c_str()), NULL); - if (writeResult == FALSE) { - ILogError("[DLL Injection] Failed to write remote process memory.\n"); - return false; - } - - // Load our DLL by calling loadlibrary in the other process and passing our dll name - HANDLE hThread = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)pLoadLibrary, (LPVOID)pDLLPath, NULL, NULL); - if (hThread == NULL) { - ILogError("[DLL Injection] Failed to create remote thread.\n"); - VirtualFreeEx(hProc, pDLLPath, 0, MEM_RELEASE); - return false; - } - CloseHandle(hThread); - - // TODO: Add waiting for thread end and release unneccessary data. - // VirtualFreeEx(hProc, pDLLPath, 0, MEM_RELEASE); - - ILog("[DLL Injection] Successfully LoadLibraryA injection.\n"); - return true; -} - -#else - -bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader, bool ClearNonNeededSections, bool AdjustProtections, bool SEHExceptionSupport, DWORD fdwReason) { - IMAGE_NT_HEADERS* pOldNtHeader = nullptr; - IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr; - IMAGE_FILE_HEADER* pOldFileHeader = nullptr; - BYTE* pTargetBase = nullptr; - - if (reinterpret_cast(pSrcData)->e_magic != 0x5A4D) { //"MZ" - ILog("[DLL injection] Invalid file\n"); - return false; - } - - pOldNtHeader = reinterpret_cast(pSrcData + reinterpret_cast(pSrcData)->e_lfanew); - pOldOptHeader = &pOldNtHeader->OptionalHeader; - pOldFileHeader = &pOldNtHeader->FileHeader; - - if (pOldFileHeader->Machine != CURRENT_ARCH) { - ILog("[DLL injection] Invalid platform.\n"); - return false; - } - - ILog("[DLL injection] File ok\n"); - - pTargetBase = reinterpret_cast(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); - if (!pTargetBase) { - ILogError("[DLL injection] Target process memory allocation failed (ex)\n"); - return false; - } - - DWORD oldp = 0; - VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp); - - MANUAL_MAPPING_DATA data{ 0 }; - data.pLoadLibraryA = LoadLibraryA; - data.pGetProcAddress = GetProcAddress; -#ifdef _WIN64 - data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable; -#else - SEHExceptionSupport = false; -#endif - data.pbase = pTargetBase; - data.fdwReasonParam = fdwReason; - data.SEHSupport = SEHExceptionSupport; - - //File header - if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) { //only first 0x1000 bytes for the header - ILogError("[DLL injection] Can't write file header.\n"); - - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; - } - - IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); - for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { - if (pSectionHeader->SizeOfRawData) { - if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr)) { - ILogError("[DLL injection] Can't map sections.\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; - } - } - } - - //Mapping params - BYTE* MappingDataAlloc = reinterpret_cast(VirtualAllocEx(hProc, nullptr, sizeof(MANUAL_MAPPING_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); - if (!MappingDataAlloc) { - ILogError("[DLL injection] Target process mapping allocation failed (ex).\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - return false; - } - - if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr)) { - ILogError("[DLL injection] Can't write mapping.\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - return false; - } - - //Shell code - void* pShellcode = VirtualAllocEx(hProc, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!pShellcode) { - ILogError("[DLL injection] Memory shellcode allocation failed (ex).\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - return false; - } - - if (!WriteProcessMemory(hProc, pShellcode, Shellcode, 0x1000, nullptr)) { - ILogError("[DLL injection] Can't write shellcode.\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; - } - - ILog("[DLL injection] Mapped DLL at %p\n", pTargetBase); - ILog("[DLL injection] Mapping info at %p\n", MappingDataAlloc); - ILog("[DLL injection] Shell code at %p\n", pShellcode); - - ILog("[DLL injection] Data allocated\n"); - -#ifdef _DEBUG - ILog("[DLL injection] My shellcode pointer %p\n", Shellcode); - ILog("[DLL injection] Target point %p\n", pShellcode); -#endif - - HANDLE hThread = CreateRemoteThread(hProc, nullptr, 0, reinterpret_cast(pShellcode), MappingDataAlloc, 0, nullptr); - if (!hThread) { - ILogError("[DLL injection] Thread creation failed.\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; - } - CloseHandle(hThread); - - ILog("[DLL injection] Thread created at: %p, waiting for return...\n", pShellcode); - - HINSTANCE hCheck = NULL; - while (!hCheck) { - DWORD exitcode = 0; - GetExitCodeProcess(hProc, &exitcode); - if (exitcode != STILL_ACTIVE) { - ILog("[DLL injection] Process crashed, exit code: 0x%x\n", exitcode); - return false; - } - - MANUAL_MAPPING_DATA data_checked{ 0 }; - ReadProcessMemory(hProc, MappingDataAlloc, &data_checked, sizeof(data_checked), nullptr); - hCheck = data_checked.hMod; - - if (hCheck == (HINSTANCE)0x404040) { - ILog("[DLL injection] Wrong mapping ptr.\n"); - VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE); - VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE); - VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE); - return false; - } - else if (hCheck == (HINSTANCE)0x505050) { - ILog("[DLL injection] WARNING: Exception support failed!\n"); - } - - Sleep(10); - } - - BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20); - if (emptyBuffer == nullptr) { - ILog("[DLL injection] Unable to allocate memory\n"); - return false; - } - memset(emptyBuffer, 0, 1024 * 1024 * 20); - - //CLEAR PE HEAD - if (ClearHeader) { - if (!WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr)) { - ILogError("[DLL injection] WARNING!: Can't clear HEADER\n"); - } - } - //END CLEAR PE HEAD - - - if (ClearNonNeededSections) { - pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); - for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { - if (pSectionHeader->Misc.VirtualSize) { - if ((SEHExceptionSupport ? 0 : strcmp((char*)pSectionHeader->Name, ".pdata") == 0) || - strcmp((char*)pSectionHeader->Name, ".rsrc") == 0 || - strcmp((char*)pSectionHeader->Name, ".reloc") == 0) { - ILog("[DLL injection] Processing %s removal\n", pSectionHeader->Name); - if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, emptyBuffer, pSectionHeader->Misc.VirtualSize, nullptr)) { - ILogError("[DLL injection] Can't clear section %s.\n", pSectionHeader->Name); - } - } - } - } - } - - if (AdjustProtections) { - pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader); - for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader) { - if (pSectionHeader->Misc.VirtualSize) { - DWORD old = 0; - DWORD newP = PAGE_READONLY; - - if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) > 0) { - newP = PAGE_READWRITE; - } - else if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) > 0) { - newP = PAGE_EXECUTE_READ; - } - if (VirtualProtectEx(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSectionHeader->Misc.VirtualSize, newP, &old)) { - ILog("[DLL injection] Section %s set as %lX\n", (char*)pSectionHeader->Name, newP); - } - else { - ILog("[DLL injection] FAIL: section %s not set as %lX\n", (char*)pSectionHeader->Name, newP); - } - } - } - DWORD old = 0; - VirtualProtectEx(hProc, pTargetBase, IMAGE_FIRST_SECTION(pOldNtHeader)->VirtualAddress, PAGE_READONLY, &old); - } - - if (!WriteProcessMemory(hProc, pShellcode, emptyBuffer, 0x1000, nullptr)) { - ILog("[DLL injection] WARNING: Can't clear shellcode\n"); - } - if (!VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE)) { - ILog("[DLL injection] WARNING: can't release shell code memory\n"); - } - if (!VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE)) { - ILog("[DLL injection] WARNING: can't release mapping data memory\n"); - } - - return true; -} - -#define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW) -#define RELOC_FLAG64(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_DIR64) - -#ifdef _WIN64 -#define RELOC_FLAG RELOC_FLAG64 -#else -#define RELOC_FLAG RELOC_FLAG32 -#endif - -#pragma runtime_checks( "", off ) -#pragma optimize( "", off ) -void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData) { - - if (!pData) { - pData->hMod = (HINSTANCE)0x404040; - return; - } - - BYTE* pBase = pData->pbase; - auto* pOpt = &reinterpret_cast(pBase + reinterpret_cast((uintptr_t)pBase)->e_lfanew)->OptionalHeader; - - auto _LoadLibraryA = pData->pLoadLibraryA; - auto _GetProcAddress = pData->pGetProcAddress; -#ifdef _WIN64 - auto _RtlAddFunctionTable = pData->pRtlAddFunctionTable; -#endif - auto _DllMain = reinterpret_cast(pBase + pOpt->AddressOfEntryPoint); - - - BYTE* LocationDelta = pBase - pOpt->ImageBase; - if (LocationDelta) { - if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) { - auto* pRelocData = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); - const auto* pRelocEnd = reinterpret_cast(reinterpret_cast(pRelocData) + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); - while (pRelocData < pRelocEnd && pRelocData->SizeOfBlock) { - UINT AmountOfEntries = (pRelocData->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); - WORD* pRelativeInfo = reinterpret_cast(pRelocData + 1); - - for (UINT i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo) { - if (RELOC_FLAG(*pRelativeInfo)) { - UINT_PTR* pPatch = reinterpret_cast(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF)); - *pPatch += reinterpret_cast(LocationDelta); - } - } - pRelocData = reinterpret_cast(reinterpret_cast(pRelocData) + pRelocData->SizeOfBlock); - } - } - } - - if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) { - auto* pImportDescr = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); - while (pImportDescr->Name) { - char* szMod = reinterpret_cast(pBase + pImportDescr->Name); - HINSTANCE hDll = _LoadLibraryA(szMod); - - ULONG_PTR* pThunkRef = reinterpret_cast(pBase + pImportDescr->OriginalFirstThunk); - ULONG_PTR* pFuncRef = reinterpret_cast(pBase + pImportDescr->FirstThunk); - - if (!pThunkRef) - pThunkRef = pFuncRef; - - for (; *pThunkRef; ++pThunkRef, ++pFuncRef) { - if (IMAGE_SNAP_BY_ORDINAL(*pThunkRef)) { - *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, reinterpret_cast(*pThunkRef & 0xFFFF)); - } - else { - auto* pImport = reinterpret_cast(pBase + (*pThunkRef)); - *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, pImport->Name); - } - } - ++pImportDescr; - } - } - - if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) { - auto* pTLS = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); - auto* pCallback = reinterpret_cast(pTLS->AddressOfCallBacks); - for (; pCallback && *pCallback; ++pCallback) - (*pCallback)(pBase, DLL_PROCESS_ATTACH, nullptr); - } - - bool ExceptionSupportFailed = false; - -#ifdef _WIN64 - - if (pData->SEHSupport) { - auto excep = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; - if (excep.Size) { - if (!_RtlAddFunctionTable( - reinterpret_cast(pBase + excep.VirtualAddress), - excep.Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY), (DWORD64)pBase)) { - ExceptionSupportFailed = true; - } - } - } - -#endif - - _DllMain(pBase, pData->fdwReasonParam, nullptr); - - if (ExceptionSupportFailed) - pData->hMod = reinterpret_cast(0x505050); - else - pData->hMod = reinterpret_cast(pBase); -} -#endif // MANUAL_MAP \ No newline at end of file +} \ No newline at end of file diff --git a/injector/src/injector.h b/injector/src/injector.h index e83bddf..3c31a03 100644 --- a/injector/src/injector.h +++ b/injector/src/injector.h @@ -3,46 +3,10 @@ #include #include #include -#include -#include #include #include "util.h" -using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename); -using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName); -using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReserved); +// #define MANUAL_MAP -#ifdef _WIN64 -using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress); -#endif - -struct ConfigInfo { - bool disableMhyprot; - bool consoleLogging; -}; - -struct MANUAL_MAPPING_DATA -{ - f_LoadLibraryA pLoadLibraryA; - f_GetProcAddress pGetProcAddress; -#ifdef _WIN64 - f_RtlAddFunctionTable pRtlAddFunctionTable; -#endif - BYTE* pbase; - HINSTANCE hMod; - DWORD fdwReasonParam; - LPVOID reservedParam; - BOOL SEHSupport; -}; - - -bool InjectDLL(HANDLE hProc, const std::string& filepath); - -#ifdef MANUAL_MAP -// Note: Exception support only x64 with build params /EHa or /EHc -bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = false, bool ClearNonNeededSections = false, bool AdjustProtections = true, bool SEHExceptionSupport = false, DWORD fdwReason = DLL_PROCESS_ATTACH); -void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData); -#else -static bool LoadLibraryInject(HANDLE hProc, const std::string& dllpath); -#endif \ No newline at end of file +bool InjectDLL(HANDLE hProc, const std::string& filepath); \ No newline at end of file