├── .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 |
--------------------------------------------------------------------------------