├── .gitignore ├── .gitmodules ├── GTAO_Booster.sln ├── GTAO_Booster.vcxproj ├── GTAO_Booster.vcxproj.filters ├── LICENSE ├── README.md └── boost.c /.gitignore: -------------------------------------------------------------------------------- 1 | #OS junk files 2 | [Tt]humbs.db 3 | *.DS_Store 4 | 5 | #Visual Studio files 6 | *.[Oo]bj 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *.vssscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.[Cc]ache 20 | *.ilk 21 | *.log 22 | *.sbr 23 | *.sdf 24 | *.opensdf 25 | *.unsuccessfulbuild 26 | ipch/ 27 | obj/ 28 | [Ll]ib 29 | [Bb]in 30 | [Dd]ebug*/ 31 | [Rr]elease*/ 32 | Ankh.NoLoad 33 | *.VC.db 34 | .vs/ 35 | 36 | #GCC files 37 | *.o 38 | *.d 39 | *.res 40 | *.dll 41 | *.a 42 | 43 | #Visual Studio Code files 44 | .vscode/ 45 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "minhook"] 2 | path = minhook 3 | url = https://github.com/TsudaKageyu/minhook.git 4 | -------------------------------------------------------------------------------- /GTAO_Booster.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GTAO_Booster", "GTAO_Booster.vcxproj", "{95272FBE-8D4C-45D1-A8A1-75A070FEA46E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {95272FBE-8D4C-45D1-A8A1-75A070FEA46E}.Release|x64.ActiveCfg = Release|x64 14 | {95272FBE-8D4C-45D1-A8A1-75A070FEA46E}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityGlobals) = postSolution 20 | SolutionGuid = {7BE09CDD-82FE-47EE-A206-B8ABE14D1C95} 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /GTAO_Booster.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 | {95272fbe-8d4c-45d1-a8a1-75a070fea46e} 25 | GTAOBooster 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 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 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | false 85 | 86 | 87 | true 88 | 89 | 90 | false 91 | 92 | 93 | 94 | Level3 95 | true 96 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 97 | true 98 | 99 | 100 | Console 101 | true 102 | 103 | 104 | 105 | 106 | Level3 107 | true 108 | true 109 | true 110 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | true 112 | 113 | 114 | Console 115 | true 116 | true 117 | true 118 | 119 | 120 | 121 | 122 | Level3 123 | true 124 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | 127 | 128 | Console 129 | true 130 | 131 | 132 | 133 | 134 | Level3 135 | true 136 | true 137 | false 138 | _NO_CRT_STDIO_INLINE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | MultiThreadedDLL 141 | AnySuitable 142 | false 143 | false 144 | false 145 | CompileAsC 146 | 147 | 148 | Windows 149 | false 150 | true 151 | DebugFull 152 | true 153 | DllMain 154 | kernel32.lib;%(AdditionalDependencies) 155 | false 156 | UseFastLinkTimeCodeGeneration 157 | false 158 | false 159 | NoErrorReport 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /GTAO_Booster.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 | {fd82ee02-bb7f-4a82-a75f-cf4498cb04d9} 18 | 19 | 20 | {08371a9a-7de2-4ec1-9794-e59030fab34c} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files\minhook 29 | 30 | 31 | Source Files\minhook 32 | 33 | 34 | Source Files\minhook 35 | 36 | 37 | Source Files\minhook\hde 38 | 39 | 40 | Source Files\minhook\hde 41 | 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Project status 2 | 3 | [Officially fixed by R* 2021-03-16](https://support.rockstargames.com/articles/360061161574/) :) 4 | 5 | ## PoC that fixes two GTA Online bugs and drastically improves load times for CPU-bound systems 6 | 7 | All addresses hardcoded for Steam and RL versions 2215/1.53 8 | 9 | This is a proof of concept, not meant for casual use 10 | 11 | Modifying your game while in online mode might get your account suspended, proceed with care 12 | 13 | ## How to 14 | 15 | * `git clone --recurse-submodules https://github.com/tostercx/GTAO_Booster_PoC` 16 | * build the project with MSVC 17 | * inject the DLL with your favorite injector while the game is starting up 18 | 19 | Might have to wait a few seconds before injecting - the game needs to deobfuscate some parts of itself 20 | 21 | ## More details 22 | 23 | [Writeup](https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/) 24 | -------------------------------------------------------------------------------- /boost.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minhook/include/MinHook.h" 3 | 4 | 5 | typedef void(__fastcall* netcat_insert_direct_t)(uint64_t catalog, uint64_t* key, uint64_t** item); 6 | netcat_insert_direct_t netcat_insert_direct = NULL; 7 | 8 | typedef size_t (__cdecl* strlen_t)(const char *str); 9 | strlen_t builtin_strlen = NULL; 10 | 11 | HMODULE g_hmod = NULL; 12 | HANDLE g_uninject_thread = NULL; 13 | 14 | uint64_t netcat_insert_dedupe_addr = 0; 15 | uint64_t strlen_addr = 0; 16 | 17 | 18 | // proper dll self unloading - not sure where I got this from 19 | DWORD WINAPI unload_thread(LPVOID lpThreadParameter) 20 | { 21 | CloseHandle(g_uninject_thread); 22 | FreeLibraryAndExitThread(g_hmod, 0); 23 | } 24 | 25 | void unload() 26 | { 27 | g_uninject_thread = CreateThread(NULL, 0, &unload_thread, NULL, 0, NULL); 28 | } 29 | 30 | 31 | // not-really-safe strlen 32 | // comes with a built in "cache" for exactly one item 33 | size_t strlen_cacher(char* str) 34 | { 35 | static char* start = NULL; 36 | static char* end = NULL; 37 | size_t len = 0; 38 | const size_t cap = 20000; 39 | 40 | // if we have a "cached" string and current pointer is within it 41 | if (start && str >= start && str <= end) { 42 | // calculate the new strlen 43 | len = end - str; 44 | 45 | // if we're near the end, unload self 46 | // we don't want to mess something else up 47 | if (len < cap / 2) 48 | MH_DisableHook((LPVOID)strlen_addr); 49 | 50 | // super-fast return! 51 | return len; 52 | } 53 | 54 | // count the actual length 55 | // we need at least one measurement of the large JSON 56 | // or normal strlen for other strings 57 | len = builtin_strlen(str); 58 | 59 | // if it was the really long string 60 | // save it's start and end addresses 61 | if (len > cap) { 62 | start = str; 63 | end = str + len; 64 | } 65 | 66 | // slow, boring return 67 | return len; 68 | } 69 | 70 | 71 | // normally this checks for duplicates before inserting 72 | // but to speed things up we just skip that and insert directly 73 | char __fastcall netcat_insert_dedupe_hooked(uint64_t catalog, uint64_t* key, uint64_t* item) 74 | { 75 | // didn't bother reversing the structure 76 | uint64_t not_a_hashmap = catalog + 88; 77 | 78 | // no idea what this does, but repeat what the original did 79 | if (!(*(uint8_t(__fastcall**)(uint64_t*))(*item + 48))(item)) 80 | return 0; 81 | 82 | // insert directly 83 | netcat_insert_direct(not_a_hashmap, key, &item); 84 | 85 | // remove hooks when the last item's hash is hit 86 | // and unload the .dll, we are done here :) 87 | if (*key == 0x7FFFD6BE) { 88 | MH_DisableHook((LPVOID)netcat_insert_dedupe_addr); 89 | unload(); 90 | } 91 | 92 | return 1; 93 | } 94 | 95 | void initialize() 96 | { 97 | // set up function hooks 98 | uint64_t base_addr = (uint64_t)GetModuleHandleA(NULL); 99 | 100 | if (GetModuleHandleA("steam_api64.dll") == NULL) { 101 | // addresses hardcoded for Social Club version 2215/1.53 102 | netcat_insert_dedupe_addr = base_addr + 0x10A9664; 103 | strlen_addr = base_addr + 0x17BD600; 104 | 105 | netcat_insert_direct = (netcat_insert_direct_t)(base_addr + 0x24EA8C); 106 | } else { 107 | // addresses hardcoded for Steam version 2215/1.53 108 | netcat_insert_dedupe_addr = base_addr + 0x10AA918; 109 | strlen_addr = base_addr + 0x17C01A0; 110 | 111 | netcat_insert_direct = (netcat_insert_direct_t)(base_addr + 0x5BB07C); 112 | } 113 | 114 | MH_Initialize(); 115 | 116 | MH_CreateHook((LPVOID)strlen_addr, &strlen_cacher, (LPVOID*)&builtin_strlen); 117 | MH_CreateHook((LPVOID)netcat_insert_dedupe_addr, &netcat_insert_dedupe_hooked, NULL); 118 | 119 | MH_EnableHook((LPVOID)strlen_addr); 120 | MH_EnableHook((LPVOID)netcat_insert_dedupe_addr); 121 | } 122 | 123 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReversed) 124 | { 125 | switch (fdwReason) 126 | { 127 | case DLL_PROCESS_ATTACH: 128 | g_hmod = hinstDLL; 129 | initialize(); 130 | 131 | break; 132 | case DLL_PROCESS_DETACH: 133 | MH_Uninitialize(); 134 | break; 135 | } 136 | 137 | return TRUE; 138 | } 139 | --------------------------------------------------------------------------------