├── ExeIntegrityBypassAgainstRGL ├── framework.h ├── pch.cpp ├── pch.h ├── Logger.h ├── ExeIntegrityBypassAgainstRGL.vcxproj.filters ├── Logger.cpp ├── dllmain.cpp └── ExeIntegrityBypassAgainstRGL.vcxproj ├── .gitignore ├── README.md ├── LICENSE └── ExeIntegrityBypassAgainstRGL.sln /ExeIntegrityBypassAgainstRGL/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files 5 | #include 6 | #include 7 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | [Bb]in/ 3 | [Oo]bj/ 4 | [Dd]ebug/ 5 | [Ll]og/ 6 | [Tt]mp/ 7 | /x64/ 8 | 9 | # Visual Studio cache files 10 | ipch/ 11 | *.aps 12 | *.cachefile 13 | *.opendb 14 | *.opensdf 15 | *.user 16 | *.sdf 17 | *.suo 18 | *.db 19 | .vs/ 20 | 21 | # Temporary OS files 22 | .DS_Store 23 | Thumbs.db 24 | 25 | # NuGet stuff 26 | [Pp]ackages/ 27 | packages.config 28 | 29 | *.log 30 | *.exe 31 | 32 | # Temp 33 | *.TMP 34 | doc/changelog.pdf 35 | Gears/GitInfo.h 36 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exe Integrity Bypass Against RGL 2 | 3 | This mod disables the integrity check (version check) against the exe of GTA V, where the game will test if it is the latest version as of the game launch using the function that calls `CryptAcquireContextA`, `CryptMsgGetParam`, and `CryptQueryObject`. Looks like Rockstar started testing even in Steam and EGS versions starting from April 4th, 2023 UTC at the latest. 4 | 5 | In short words, this mod just makes GTA5.exe not listen to the result of version check. 6 | 7 | ### License 8 | Exe Integrity Bypass Against RGL is licensed under the BSD Zero Clause License. Too few pieces of materials to be worth keeping secret. 9 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/Logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | enum class LogType : int { 6 | Info, 7 | // the same type as the ERROR info GTAVLauncherBypass by alloc8or can write 8 | Error, 9 | }; 10 | 11 | class Logger 12 | { 13 | private: 14 | std::ofstream log_file_; 15 | 16 | public: 17 | Logger() { 18 | }; 19 | Logger(const std::string& file_name) { 20 | log_file_ = std::ofstream(file_name); 21 | }; 22 | void AddLine(const LogType type, const std::string& message); 23 | 24 | explicit operator bool() const 25 | { 26 | return static_cast(log_file_); 27 | } 28 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2023 by Kazuma Takemura 2 | 3 | Permission to use, copy, modify, and/or distribute this software for 4 | any purpose with or without fee is hereby granted. 5 | 6 | THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL 7 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 8 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 9 | FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 10 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 11 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 12 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExeIntegrityBypassAgainstRGL", "ExeIntegrityBypassAgainstRGL\ExeIntegrityBypassAgainstRGL.vcxproj", "{3350DCE0-9D8A-4345-853F-8B9C658AAA45}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3350DCE0-9D8A-4345-853F-8B9C658AAA45}.Debug|x64.ActiveCfg = Debug|x64 15 | {3350DCE0-9D8A-4345-853F-8B9C658AAA45}.Debug|x64.Build.0 = Debug|x64 16 | {3350DCE0-9D8A-4345-853F-8B9C658AAA45}.Release|x64.ActiveCfg = Release|x64 17 | {3350DCE0-9D8A-4345-853F-8B9C658AAA45}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {31CBD60E-DD3E-4095-A879-3027D6E8935F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/ExeIntegrityBypassAgainstRGL.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Logger.h" 3 | #include 4 | #include 5 | 6 | std::string CreateStringWithBracket(const std::string& str) { 7 | std::string str_with_bracket = std::string(str); 8 | str_with_bracket.insert(0, "["); 9 | str_with_bracket += "]"; 10 | 11 | return str_with_bracket; 12 | } 13 | 14 | // Using std::chrono stuff will result in a large dll 15 | std::string CreateIso8061LocalTimeStringNoTSeparator(const std::time_t unixTime) { 16 | __time64_t time; 17 | _time64(&time); 18 | 19 | struct tm local_time; 20 | _localtime64_s(&local_time, &time); 21 | 22 | constexpr size_t BUF_SIZE_TIME_STR = 0x50u; 23 | std::string temp_buf; 24 | temp_buf.resize(BUF_SIZE_TIME_STR); 25 | 26 | const size_t written_char_count = strftime(temp_buf.data(), BUF_SIZE_TIME_STR, "%Y-%m-%d %H:%M:%S", &local_time); 27 | temp_buf.resize(written_char_count); 28 | 29 | return temp_buf; 30 | } 31 | 32 | std::string GetLogTypeEnumString(LogType type) { 33 | switch (type) { 34 | case LogType::Info: 35 | return std::string("INFO"); 36 | case LogType::Error: 37 | return std::string("ERROR"); 38 | default: return std::string("UNKNOWN"); 39 | } 40 | } 41 | 42 | void Logger::AddLine(const LogType type, const std::string& message) { 43 | std::time_t unixTimeScanStarted = std::time(nullptr); 44 | const auto formatted_time_str = CreateIso8061LocalTimeStringNoTSeparator(unixTimeScanStarted); 45 | log_file_ << "[" << formatted_time_str << "]" << " "; 46 | 47 | log_file_ << "[" << GetLogTypeEnumString(type) << "]" << " "; 48 | 49 | log_file_ << message << std::endl; 50 | } -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Logger.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace { 10 | std::vector split(std::string str, std::string separator) { 11 | if (separator == "") return { str }; 12 | std::vector result; 13 | std::string tstr = str + separator; 14 | size_t l = tstr.length(), sl = separator.length(); 15 | std::string::size_type pos = 0, prev = 0; 16 | 17 | for (; pos < l && (pos = tstr.find(separator, pos)) != std::string::npos; prev = (pos += sl)) { 18 | result.emplace_back(tstr, prev, pos - prev); 19 | } 20 | return result; 21 | } 22 | } 23 | 24 | uintptr_t FindPattern(std::string patternStr) { 25 | auto space_separator = std::string(" "); 26 | std::vector byte_str = split(patternStr, space_separator); 27 | 28 | MODULEINFO module_info{}; 29 | const DWORD module_info_size = static_cast(sizeof(MODULEINFO)); 30 | GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &module_info, module_info_size); 31 | 32 | auto* start_offset = static_cast(module_info.lpBaseOfDll); 33 | const auto size = static_cast(module_info.SizeOfImage); 34 | 35 | uintptr_t pos = 0; 36 | const uintptr_t search_len = byte_str.size(); 37 | 38 | for (auto* ret_address = start_offset; ret_address < start_offset + size; ret_address++) { 39 | if (byte_str[pos] == "??" || byte_str[pos] == "?" || 40 | *ret_address == static_cast(std::strtoul(byte_str[pos].c_str(), nullptr, 16))) { 41 | if (pos + 1 == byte_str.size()) 42 | return (reinterpret_cast(ret_address) - search_len + 1); 43 | pos++; 44 | } 45 | else { 46 | pos = 0; 47 | } 48 | } 49 | return 0; 50 | } 51 | 52 | BOOL SuspendSpecifiedThread(DWORD thread_id, bool suspend) 53 | { 54 | HANDLE snHandle = nullptr; 55 | THREADENTRY32 te32 = { 0 }; 56 | 57 | BOOL succeeded = false; 58 | 59 | DWORD current_process_id = GetCurrentProcessId(); 60 | 61 | snHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 62 | if (snHandle == INVALID_HANDLE_VALUE) return (false); 63 | 64 | te32.dwSize = sizeof(THREADENTRY32); 65 | if (Thread32First(snHandle, &te32)) 66 | { 67 | do 68 | { 69 | if (te32.th32OwnerProcessID == current_process_id && te32.th32ThreadID == thread_id) 70 | { 71 | HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID); 72 | if (hThread == NULL) { 73 | continue; 74 | } else if (!suspend) { 75 | succeeded = (bool)ResumeThread(hThread); 76 | } else { 77 | succeeded = (bool)SuspendThread(hThread); 78 | } 79 | 80 | CloseHandle(hThread); 81 | } 82 | } while (Thread32Next(snHandle, &te32)); 83 | } 84 | CloseHandle(snHandle); 85 | 86 | return succeeded; 87 | } 88 | 89 | Logger logger; 90 | DWORD main_thread_id; 91 | HMODULE this_module; 92 | 93 | void PatchExeIntegrityCheck() { 94 | // Wait for a second, main thread 95 | SuspendSpecifiedThread(main_thread_id, true); 96 | 97 | // The function where this integrity check is done should be already decrypted when this asi is attached (but encrypted when the exe is not started at all) 98 | // Should patch before you can see the game window 99 | // This memory pattern is tested in b2060, b2372, b2699, and b2845 100 | const std::string pattern_for_exe_integrity_check = "84 C0 75 1B 39 ? 60 01 00 00 0F 85"; 101 | const uintptr_t addr = FindPattern(pattern_for_exe_integrity_check); 102 | 103 | if (addr) { 104 | // Let's fuck the integrity check by making the exe not listen to the query result against the function that calls 105 | // CryptAcquireContextA, CryptMsgGetParam, and CryptQueryObject against socialclub.dll 106 | void* write_addr = reinterpret_cast(addr + 2); 107 | const uint8_t instruction_to_write[1] = { 0xEB }; // patch jnz with jmp instruction 108 | 109 | DWORD old_protect = 0; 110 | VirtualProtect(write_addr, 1u, PAGE_EXECUTE_READWRITE, &old_protect); 111 | memcpy(write_addr, instruction_to_write, 1); 112 | VirtualProtect(write_addr, 1u, old_protect, &old_protect); 113 | 114 | if (logger) { 115 | logger.AddLine(LogType::Info, "Done!"); 116 | } 117 | SuspendSpecifiedThread(main_thread_id, false); 118 | FreeLibraryAndExitThread(this_module, 0); 119 | return; 120 | } 121 | 122 | if (logger) { 123 | logger.AddLine(LogType::Error, "Failed to patch the integrity check against exe."); 124 | } 125 | SuspendSpecifiedThread(main_thread_id, false); 126 | FreeLibraryAndExitThread(this_module, 0); 127 | } 128 | 129 | void Main(HMODULE hModule) { 130 | logger = Logger("ExeIntegrityBypassAgainstRGL.log"); 131 | 132 | if (logger) { 133 | logger.AddLine(LogType::Info, "Started to patch the integrity check against exe..."); 134 | } 135 | 136 | this_module = hModule; 137 | main_thread_id = GetCurrentThreadId(); 138 | auto thread_handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)PatchExeIntegrityCheck, hModule, NULL, NULL); 139 | if (thread_handle == nullptr) { 140 | if (logger) { 141 | logger.AddLine(LogType::Error, "Thread creation failed, terminating..."); 142 | FreeLibraryAndExitThread(hModule, 0); 143 | } 144 | } else { 145 | CloseHandle(thread_handle); 146 | } 147 | } 148 | 149 | BOOL APIENTRY DllMain( HMODULE hModule, 150 | DWORD ul_reason_for_call, 151 | LPVOID lpReserved 152 | ) 153 | { 154 | switch (ul_reason_for_call) 155 | { 156 | case DLL_PROCESS_ATTACH: 157 | // Have to patch the assembly with another thread to avoid the "failed to load" error for taking too long time to pass through DllMain 158 | Main(hModule); 159 | break; 160 | case DLL_THREAD_ATTACH: 161 | case DLL_THREAD_DETACH: 162 | case DLL_PROCESS_DETACH: 163 | break; 164 | } 165 | return TRUE; 166 | } 167 | 168 | -------------------------------------------------------------------------------- /ExeIntegrityBypassAgainstRGL/ExeIntegrityBypassAgainstRGL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {3350dce0-9d8a-4345-853f-8b9c658aaa45} 25 | ExeIntegrityBypassAgainstRGL 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | .asi 75 | obj\$(Configuration)\ 76 | bin\$(Configuration)\ 77 | 78 | 79 | .asi 80 | obj\$(Configuration)\ 81 | bin\$(Configuration)\ 82 | 83 | 84 | 85 | Level3 86 | true 87 | WIN32;_DEBUG;EXEINTEGRITYBYPASSAGAINSTRGL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 88 | true 89 | Use 90 | pch.h 91 | 92 | 93 | Windows 94 | true 95 | false 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | WIN32;NDEBUG;EXEINTEGRITYBYPASSAGAINSTRGL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 105 | true 106 | Use 107 | pch.h 108 | 109 | 110 | Windows 111 | true 112 | true 113 | true 114 | false 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | _DEBUG;EXEINTEGRITYBYPASSAGAINSTRGL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 122 | true 123 | Use 124 | pch.h 125 | 126 | 127 | Windows 128 | true 129 | false 130 | 131 | 132 | 133 | 134 | Level3 135 | true 136 | true 137 | true 138 | NDEBUG;EXEINTEGRITYBYPASSAGAINSTRGL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 139 | true 140 | Use 141 | pch.h 142 | MultiThreadedDLL 143 | stdcpplatest 144 | 145 | 146 | Windows 147 | true 148 | true 149 | true 150 | false 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | Create 163 | Create 164 | Create 165 | Create 166 | 167 | 168 | 169 | 170 | 171 | --------------------------------------------------------------------------------