Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

1575 righe
53 KiB

  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN
  3. #endif
  4. #include <string>
  5. #include <windows.h>
  6. //#include <winhttp.h>
  7. #include <iostream>
  8. #include <fstream>
  9. #include <atomic>
  10. //#include <vector>
  11. #include "include/MinHook.h"
  12. #ifdef __clang__
  13. #pragma comment(lib, "lib/libMinHook-MD.x64.Clang.lib")
  14. #else
  15. #pragma comment(lib, "lib/libMinHook-MD.x64.lib")
  16. #endif
  17. //#include "F:/Programmieren/C++/myhelpers/xorstr.h"
  18. #define JM_XORSTR_DISABLE_AVX_INTRINSICS 1
  19. #include "F:/Programmieren/C++/xorstr-master/include/xorstr.hpp"
  20. //#include "F:/Programmieren/C++/myhelpers/SuspendResume.hpp"
  21. #include "include/patternscan.hpp"
  22. //
  23. #include "F:/Programmieren/C++/myhelpers/DebugHelper.hpp"
  24. #include "SparkClasses.h"
  25. // Link with ws2_32.lib
  26. #pragma comment(lib, "Ws2_32.lib")
  27. #include "F:/Programmieren/C++/json.hpp"
  28. using json = nlohmann::json;
  29. #include "include/easywsclient.hpp"
  30. #include "include/easywsclient.cpp"
  31. using easywsclient::WebSocket;
  32. WebSocket::pointer ws = nullptr;
  33. //#include <map>
  34. //#include <fstream>
  35. //typedef BOOL(__stdcall* tWinHttpGetIEProxyConfigForCurrentUser)(IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*);
  36. //tWinHttpGetIEProxyConfigForCurrentUser oWinHttpGetIEProxyConfigForCurrentUser;
  37. typedef void*(__stdcall* tCurl_Easy_Init)();
  38. tCurl_Easy_Init oCurl_Easy_Init;
  39. typedef void(__stdcall* tCurl_Easy_Cleanup)(void* handle);
  40. tCurl_Easy_Cleanup oCurl_Easy_Cleanup;
  41. typedef DWORD(__stdcall* tCurl_Easy_SetOpt)(void*, long, void*);
  42. tCurl_Easy_SetOpt oCurl_Easy_SetOpt;
  43. typedef DWORD(__stdcall* tCurl_Easy_Perform)(void*);
  44. tCurl_Easy_Perform oCurl_Easy_Perform;
  45. typedef DWORD(__stdcall* tCurl_Multi_Perform)(void* multi_handle, int* running_handles);
  46. tCurl_Multi_Perform oCurl_Multi_Perform;
  47. typedef void*(__stdcall* tCurl_Multi_Init)();
  48. tCurl_Multi_Init oCurl_Multi_Init = NULL;
  49. typedef void* (__fastcall* tFSparkManagerCtor)(void*);
  50. tFSparkManagerCtor oFSparkManagerCtor = NULL;
  51. //const std::wstring proxyURLW = L"https=127.0.0.1:9999";
  52. std::string proxyURLA = "https://127.0.0.1:";
  53. std::string proxyPort = "9999";
  54. auto curl_easy_init_pattern = xorstr("48 83 EC 28 83 3D ?? ?? ?? ?? 00 75 ?? 48 8B 05");
  55. auto curl_easy_cleanup_pattern = xorstr("40 53 48 83 EC 20 48 8B D9 48 85 C9 0F 84 ?? ?? ?? ?? 33 D2");
  56. auto curl_easy_setopt_pattern = xorstr("89 54 24 10 4c 89 44 24 18 4c 89 4c 24 20 48 83 ec 28 48 85 c9 75");
  57. auto curl_easy_perform_pattern = xorstr("33 d2 e9 09 01 00 00 cc cc cc cc cc cc cc");
  58. auto curl_easy_getinfo_pattern = xorstr("89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 48 83 EC 28 4C 8D 44 24 ?? 4D 8B 00");
  59. auto curl_multi_perform_pattern = xorstr("48 89 5c 24 18 56 57 41 57 48 83 ec 20 4c 8b fa 48 8b f9");
  60. auto curl_multi_init_pattern = xorstr("BA 61 00 00 00 B9 8F 03 00 00");
  61. auto sparkManagerCtorPattern = xorstr("40 53 48 83 EC 20 48 8B D9 E8 ?? ?? ?? ?? 4C 8B C8 48 8D 15 ?? ?? ?? ?? 0F 57 D2 48 8B CB E8 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 03 33 C0");
  62. auto generateMicropatchArrayPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 8B 72 08");
  63. auto generateMicropatchArrayBackupPattern = xorstr("48 8D 54 24 ?? E8 ?? ?? ?? ?? 48 8D 55 60");
  64. auto getNewsItemsPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 55 41 ?? 41 ?? 41 ?? 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? ?? 8D");
  65. auto FGbxSparkModuleStartupModulePattern = xorstr("40 53 48 83 EC 50 48 8B D9 48 89 0D");
  66. auto onMicropatchesReceivedPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 55 57 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 63 51 08");
  67. auto areMicropatchesDifferentPattern = xorstr("48 89 5C 24 ?? 55 56 57 48 83 EC 20 C7 02");
  68. // + 0x33
  69. auto parseJSONString = xorstr("40 55 53 56 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 10 48 8B D9");
  70. // result at +0x88 (E8 ** ** ** **)
  71. auto getNewsServicePattern = xorstr("45 8B C7 48 8D 15 ?? ?? ?? ?? 48 8D 8D ?? ?? ?? ?? E8 ?? ?? ?? ?? 4C 8D 85");
  72. auto mallocPattern = xorstr("48 89 5C 24 ?? 57 48 83 EC 20 48 8B F9 8B DA 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 0C E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01 44 8B C3 48 8B D7 48 8B 5C 24 ?? 48 83 C4 20 5F 48 FF 60 10");
  73. auto reallocPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 41 8B D8 48 8B 0D ?? ?? ?? ?? 48 8B FA 48 85 C9 75 0C E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01 44 8B CB 4C 8B C7 48 8B D6 48 8B 5C 24 ?? 48 8B 74 24 ?? 48 83 C4 20 5F 48 FF 60 18");
  74. auto hardcodedHotfixCallPattern = xorstr("40 55 53 56 57 41 54 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 8B BD");
  75. CRITICAL_SECTION critsec;
  76. static bool isInInternalMode = false;
  77. //
  78. //std::string startReceiveHotfixes_Pattern = xorstr("48 63 81 c4 00 00 00 83 f8 06 77 49 4c 8d 05");
  79. ////
  80. //std::string beforeInit_Pattern = xorstr("40 53 48 83 ec 40 80 b9 c0 00 00 00 00 48 8b d9 0f 85 41 01 00 00 83 b9 cc 00 00 00 00 0f 84 34 01 00 00 f3 0f 58 89 bc 00 00 00 f3 0f 11 89 bc 00 00 00 8b 89 d0 00 00 00 85 c9 0f 84 fe 00 00 00");
  81. ////
  82. //std::string someInterestingFunc_Pattern = xorstr("40 53 48 83 ec 30 48 8b d9 48 85 d2 74 21 45 8b c8 c7 44 24 28 ff ff ff ff");
  83. //
  84. //std::ofstream myfile;
  85. /* long may be 32 or 64 bits, but we should never depend on anything else
  86. but 32 */
  87. #define CURLOPTTYPE_LONG 0
  88. #define CURLOPTTYPE_OBJECTPOINT 10000
  89. #define CURLOPTTYPE_FUNCTIONPOINT 20000
  90. #define CURLOPTTYPE_OFF_T 30000
  91. #define CURLOPTTYPE_BLOB 40000
  92. #define CURLOPT(na,t,nu) na = t + nu
  93. /* 'char *' argument to a string with a trailing zero */
  94. #define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT
  95. /* 'struct curl_slist *' argument */
  96. #define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT
  97. /* 'void *' argument passed untouched to callback */
  98. #define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT
  99. /* 'long' argument with a set of values/bitmask */
  100. #define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG
  101. typedef enum {
  102. /* The full URL to get/put */
  103. CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2),
  104. /* Name of proxy to use. */
  105. CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4),
  106. /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
  107. * bytes big. */
  108. CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10),
  109. /* Function that will be called to store the output (instead of fwrite). The
  110. * parameters will use fwrite() syntax, make sure to follow them. */
  111. CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11),
  112. /* Function that will be called to read the input (instead of fread). The
  113. * parameters will use fread() syntax, make sure to follow them. */
  114. CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12),
  115. /* POST static input fields. */
  116. CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15),
  117. /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
  118. CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64),
  119. /* The CApath or CAfile used to validate the peer certificate
  120. this option is used only if SSL_VERIFYPEER is true */
  121. CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65),
  122. /* Set if we should verify the Common name from the peer certificate in ssl
  123. * handshake, set 1 to check existence, 2 to ensure that it matches the
  124. * provided hostname. */
  125. CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81),
  126. /* The CApath directory used to validate the peer certificate
  127. this option is used only if SSL_VERIFYPEER is true */
  128. CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97),
  129. /* Enable SSL/TLS for FTP, pick one of:
  130. CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
  131. CURLUSESSL_CONTROL - SSL for the control connection or fail
  132. CURLUSESSL_ALL - SSL for all communication or fail
  133. */
  134. CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119),
  135. /* send linked-list of name:port:address sets */
  136. CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203),
  137. /* Set if we should verify the certificate status. */
  138. CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232),
  139. /* The CApath or CAfile used to validate the proxy certificate
  140. this option is used only if PROXY_SSL_VERIFYPEER is true */
  141. CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246),
  142. /* Set if we should verify the proxy in ssl handshake,
  143. set 1 to verify. */
  144. CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248),
  145. /* Set if we should verify the Common name from the proxy certificate in ssl
  146. * handshake, set 1 to check existence, 2 to ensure that it matches
  147. * the provided hostname. */
  148. CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249),
  149. /* The public key in DER form used to validate the proxy public key
  150. this option is used only if PROXY_SSL_VERIFYPEER is true */
  151. CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263),
  152. /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */
  153. CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306),
  154. /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */
  155. CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307),
  156. /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */
  157. CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308),
  158. /* The CA certificates as "blob" used to validate the peer certificate
  159. this option is used only if SSL_VERIFYPEER is true */
  160. CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309),
  161. /* The CA certificates as "blob" used to validate the proxy certificate
  162. this option is used only if PROXY_SSL_VERIFYPEER is true */
  163. CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310),
  164. };
  165. #define CURL_ERROR_SIZE 256
  166. typedef enum {
  167. CURLE_OK = 0
  168. };
  169. typedef enum {
  170. CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
  171. CONNECT HTTP/1.1 */
  172. CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
  173. HTTP/1.0 */
  174. CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
  175. CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already in 7.10 */
  176. CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
  177. CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
  178. CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
  179. host name rather than the IP address. added
  180. in 7.18.0 */
  181. } curl_proxytype; /* this enum was added in 7.10 */
  182. /* parameter for the CURLOPT_USE_SSL option */
  183. typedef enum {
  184. CURLUSESSL_NONE, /* do not attempt to use SSL */
  185. CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
  186. CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
  187. CURLUSESSL_ALL, /* SSL for all communication or fail */
  188. CURLUSESSL_LAST /* not an option, never use */
  189. } curl_usessl;
  190. #define CURLINFO_STRING 0x100000
  191. #define CURLINFO_LONG 0x200000
  192. #define CURLINFO_DOUBLE 0x300000
  193. #define CURLINFO_SLIST 0x400000
  194. #define CURLINFO_PTR 0x400000 /* same as SLIST */
  195. #define CURLINFO_SOCKET 0x500000
  196. #define CURLINFO_OFF_T 0x600000
  197. #define CURLINFO_MASK 0x0fffff
  198. #define CURLINFO_TYPEMASK 0xf00000
  199. typedef enum {
  200. CURLINFO_NONE, /* first, never use this */
  201. CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
  202. CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
  203. CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
  204. CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
  205. CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
  206. CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
  207. CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
  208. CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7,
  209. CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
  210. CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8,
  211. CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
  212. CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9,
  213. CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
  214. CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10,
  215. CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
  216. CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
  217. CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
  218. CURLINFO_FILETIME = CURLINFO_LONG + 14,
  219. CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
  220. CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
  221. CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
  222. CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
  223. CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16,
  224. CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
  225. CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
  226. CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
  227. CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
  228. CURLINFO_PRIVATE = CURLINFO_STRING + 21,
  229. CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
  230. CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
  231. CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
  232. CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
  233. CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
  234. CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
  235. CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
  236. CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
  237. CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
  238. CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
  239. CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
  240. CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
  241. CURLINFO_CERTINFO = CURLINFO_PTR + 34,
  242. CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
  243. CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
  244. CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
  245. CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
  246. CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
  247. CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
  248. CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
  249. CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
  250. CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
  251. CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
  252. CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
  253. CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
  254. CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
  255. CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
  256. CURLINFO_SCHEME = CURLINFO_STRING + 49,
  257. CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
  258. CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
  259. CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52,
  260. CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
  261. CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
  262. CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55,
  263. CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
  264. CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57,
  265. CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
  266. CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
  267. CURLINFO_REFERER = CURLINFO_STRING + 60,
  268. CURLINFO_LASTONE = 60
  269. } CURLINFO;
  270. typedef DWORD(__stdcall* tCurl_Easy_GetInfo)(void*, CURLINFO info, void*);
  271. tCurl_Easy_GetInfo oCurl_Easy_GetInfo;
  272. /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
  273. CURLINFO_HTTP_CODE */
  274. #define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
  275. typedef enum {
  276. CURLCLOSEPOLICY_NONE, /* first, never use this */
  277. CURLCLOSEPOLICY_OLDEST,
  278. CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
  279. CURLCLOSEPOLICY_LEAST_TRAFFIC,
  280. CURLCLOSEPOLICY_SLOWEST,
  281. CURLCLOSEPOLICY_CALLBACK,
  282. CURLCLOSEPOLICY_LAST /* last, never use this */
  283. } curl_closepolicy;
  284. char errbuf[CURL_ERROR_SIZE];
  285. typedef void* (__fastcall* tMalloc)(uint32_t, uint32_t);
  286. tMalloc oMalloc;
  287. typedef void* (__fastcall* tRealloc)(void*, size_t, uint32_t);
  288. tRealloc oRealloc;
  289. typedef void (__fastcall* tGetNewsItems)(void*);
  290. tGetNewsItems oGetNewsItems = NULL;
  291. using EMicropatchOperation = uintptr_t;
  292. typedef bool (__fastcall* tHardcodedHotfixes)(EMicropatchOperation, const wchar_t* patchString, const wchar_t*, bool, void* pFunc, void* someObject);
  293. tHardcodedHotfixes oHardcodedHotfixes = NULL;
  294. template<class T>
  295. struct TArray
  296. {
  297. friend struct FString;
  298. public:
  299. inline TArray()
  300. {
  301. Data = nullptr;
  302. Count = Max = 0;
  303. };
  304. inline int Num() const
  305. {
  306. return Count;
  307. };
  308. inline T& operator[](int i)
  309. {
  310. return Data[i];
  311. };
  312. inline const T& operator[](int i) const
  313. {
  314. return Data[i];
  315. };
  316. inline bool IsValidIndex(int i) const
  317. {
  318. return i < Num();
  319. }
  320. FORCEINLINE int32_t DefaultCalculateSlackGrow(int32_t NumElements, int32_t NumAllocatedElements, int32_t BytesPerElement, bool bAllowQuantize, uint32_t Alignment = 0)
  321. {
  322. int32_t Retval = 0;
  323. int32_t Grow = 4; // this is the amount for the first alloc
  324. if (NumAllocatedElements || size_t(NumElements) > Grow)
  325. {
  326. // Allocate slack for the array proportional to its size.
  327. Grow = size_t(NumElements) + 3 * size_t(NumElements) / 8 + 16;
  328. }
  329. if (bAllowQuantize)
  330. {
  331. //Retval = FMemory::QuantizeSize(Grow * BytesPerElement, Alignment) / BytesPerElement;
  332. Retval = Retval * BytesPerElement;
  333. }
  334. else
  335. {
  336. Retval = Grow;
  337. }
  338. // NumElements and MaxElements are stored in 32 bit signed integers so we must be careful not to overflow here.
  339. if (NumElements > Retval)
  340. {
  341. Retval = ((int32_t)0x7fffffff);
  342. }
  343. return Retval;
  344. }
  345. void ResizeGrow(int32_t OldNum, int32_t numElems, size_t sizePElem)
  346. {
  347. if (Data || Count) {
  348. Data = (T*)Realloc(Data, numElems * sizePElem, 0);
  349. }
  350. }
  351. void* Realloc(void* Original, size_t count, uint32_t alignment) {
  352. if (oRealloc) {
  353. return oRealloc(Original, count, alignment);
  354. }
  355. return NULL;
  356. }
  357. void* Malloc(uint32_t count, uint32_t alignment) {
  358. if (oMalloc) {
  359. return oMalloc(count, alignment);
  360. }
  361. return NULL;
  362. }
  363. void ResizeGrow(int32_t OldNum)
  364. {
  365. Max = DefaultCalculateSlackGrow(Count + 1, Max, sizeof(T), 0);
  366. ResizeGrow(Count, Max, sizeof(T));
  367. }
  368. /**
  369. * Adds a new item to the end of the array, possibly reallocating the whole array to fit.
  370. *
  371. * @param Item The item to add
  372. * @return Index to the new item
  373. * @see AddDefaulted, AddUnique, AddZeroed, Append, Insert
  374. */
  375. FORCEINLINE int32_t Add(const T& Item)
  376. {
  377. if (Count + 1 > Max) {
  378. Max = DefaultCalculateSlackGrow(Count + 1, Max, sizeof(T), 0);
  379. ResizeGrow(Count, Max, sizeof(T));
  380. }
  381. if (Data == NULL) {
  382. Data = (T*)Malloc(Max, sizeof(T));
  383. //memset(Data, 0, Max * sizeof(T));
  384. }
  385. Data[Count] = Item;
  386. Count++;
  387. return Count - 1;
  388. }
  389. /**
  390. * Inserts a given element into the array at given location.
  391. *
  392. * @param Item The element to insert.
  393. * @param Index Tells where to insert the new elements.
  394. * @returns Location at which the insert was done.
  395. * @see Add, Remove
  396. */
  397. FORCEINLINE int32_t Insert(const T& Item, int32_t Index)
  398. {
  399. if (Index >= 0 && IsValidIndex(Index)) {
  400. const int32_t OldNum = Count;
  401. if ((Count += 1) > Max)
  402. {
  403. ResizeGrow(OldNum);
  404. }
  405. for (int i = Count; i >= Index; i--)
  406. {
  407. Data[i + 1] = Data[i];
  408. }
  409. Data[Index] = Item;
  410. }
  411. return Index;
  412. }
  413. public:
  414. T* Data;
  415. int32_t Count;
  416. int32_t Max;
  417. };
  418. struct FString : TArray<wchar_t>
  419. {
  420. inline FString()
  421. {
  422. };
  423. FString(const wchar_t* other)
  424. {
  425. Max = Count = *other ? static_cast<int32_t>(std::wcslen(other) + 1) : 0;
  426. if (Count)
  427. {
  428. this->Data = const_cast<wchar_t*>(other);
  429. }
  430. };
  431. FString(const char* other)
  432. {
  433. if (other && *other) {
  434. size_t len = strlen(other) + 1;
  435. int32_t destLen = int32_t(MultiByteToWideChar(CP_ACP, 0, other, -1, NULL, 0)) + 1;
  436. const int32_t oldNum = Count;
  437. if ((Count += destLen) > Max) {
  438. this->ResizeGrow(oldNum);
  439. }
  440. mbstowcs_s(NULL, this->Data, len, other, len - 1);
  441. }
  442. //if (Data != other) {
  443. // int nchars = MultiByteToWideChar(CP_ACP, 0, other, -1, NULL, 0);
  444. // wchar_t* wc = new wchar_t[nchars];
  445. // MultiByteToWideChar(CP_ACP, 0, other, -1, (LPWSTR)wc, nchars);
  446. // Max = Count = *wc ? static_cast<int32_t>(std::wcslen(wc) + 1) : 0;
  447. //}
  448. ///*int nchars = MultiByteToWideChar(CP_ACP, 0, other, -1, NULL, 0);
  449. //wchar_t* wc = new wchar_t[nchars];
  450. //MultiByteToWideChar(CP_ACP, 0, other, -1, (LPWSTR)wc, nchars);
  451. //Max = Count = *wc ? static_cast<int32_t>(std::wcslen(wc) + 1) : 0;*/
  452. /*if (Count)
  453. {
  454. Data = const_cast<wchar_t*>(wc);
  455. }*/
  456. };
  457. inline bool IsValid() const
  458. {
  459. return this->Data != nullptr;
  460. }
  461. inline const wchar_t* c_str() const
  462. {
  463. return this->Data;
  464. }
  465. std::string ToString() const
  466. {
  467. if (!this->Data)
  468. return "NULL";
  469. auto length = std::wcslen(this->Data);
  470. std::string str(length, '\0');
  471. std::use_facet<std::ctype<wchar_t>>(std::locale()).narrow(this->Data, this->Data + length, '?', &str[0]);
  472. return str;
  473. }
  474. };
  475. struct FArticleTag {
  476. FString Tag;
  477. FString TagName;
  478. FString TagValue;
  479. };
  480. struct FNewsItem {
  481. FString NewsText;
  482. char Unknown1[0x8];
  483. char Unknown2[0x8];
  484. char Unknown3[0x8];
  485. char Unknown4[0x8];
  486. char Unknown5[0x8];
  487. char Unknown6[0x8];
  488. FString IconName;
  489. FString TargetLink;
  490. char Unknown7[0x8];
  491. char Unknown8[0x8];
  492. char Unknown9[0x8];
  493. char Unknown10[0x8];
  494. char Unknown11[0x8];
  495. char Unknown12[0x8];
  496. TArray<FArticleTag> ArticleTags;
  497. };
  498. class FSparkNewsService
  499. {
  500. public:
  501. char pad_0000[64]; //0x0000
  502. class TArray<FNewsItem> NewsItems; //0x0040
  503. char pad_0050[64]; //0x0050
  504. }; //Size: 0x0090
  505. static_assert(sizeof(FSparkNewsService) == 0x90);
  506. class FSparkModule
  507. {
  508. public:
  509. wchar_t* ConfigFile; //0x0008
  510. char pad_0010[8]; //0x0010
  511. class FSparkManager* SparkManager; //0x0018
  512. char pad_0020[240]; //0x0020
  513. class FSparkNewsService* SparkNewsService; //0x0110
  514. char pad_0118[1192]; //0x0118
  515. virtual void Function0();
  516. virtual void Function1();
  517. virtual void Function2();
  518. virtual void Function3();
  519. virtual void Function4();
  520. virtual void Function5();
  521. virtual void Function6();
  522. virtual void Function7();
  523. }; //Size: 0x05C0
  524. static_assert(sizeof(FSparkModule) == 0x5C0);
  525. enum HotfixType : uint32_t {
  526. SparkPatchEntry = 1,
  527. SparkLevelPatchEntry = 2,
  528. SparkStreamedPackageEntry = 3,
  529. SparkSaveGameEntry = 4,
  530. SparkPostLoadedEntry = 5,
  531. SparkCharacterLoadedEntry = 6,
  532. SparkEarlyLevelPatchEntry = 7
  533. };
  534. class FMicropatch
  535. {
  536. public:
  537. HotfixType PatchType; //0x0000
  538. uint32_t N00001B5E; //0x0004
  539. FString Patchname; //0x0008
  540. FString Patchdata; //0x0018
  541. }; //Size: 0x0028
  542. static_assert(sizeof(FMicropatch) == 0x28);
  543. class UserWriteData
  544. {
  545. public:
  546. char pad_0000[16]; //0x0000
  547. TArray<char> Content; //0x0010
  548. //char* Content;
  549. //uint32_t WriteSize; //0x0018
  550. //uint32_t MaxSize; //0x001C
  551. uint32_t DataSize; //0x0020
  552. char pad_0024[4]; //0x0024
  553. }; //Size: 0x0028
  554. static_assert(sizeof(UserWriteData) == 0x28);
  555. class Curl_Write_Data
  556. {
  557. public:
  558. char pad_0000[88]; //0x0000
  559. class FString RequestURL; //0x0058
  560. char pad_0068[32]; //0x0068
  561. class UserWriteData* Body; //0x0088
  562. char pad_0090[32]; //0x0090
  563. class TArray<FString>* Headers; //0x00B0
  564. }; //Size: 0x00B8
  565. static_assert(sizeof(Curl_Write_Data) == 0xB8);
  566. typedef void(__fastcall* tGenerateMicropatchArray)(void* someTMap, TArray<FMicropatch>* outMicropatches);
  567. tGenerateMicropatchArray oGenerateMicropatchArray = NULL;
  568. typedef void* (__fastcall* tParseJSONString)(void** jsonReader, const FString* text);
  569. tParseJSONString oParseJSONString = NULL;
  570. typedef bool(__fastcall* tAreMicropatchesDifferent)(TArray<FMicropatch>* micropatches, void* severity);
  571. tAreMicropatchesDifferent oAreMicropatchesDifferent = NULL;
  572. FSparkModule** pSparkModule = NULL;
  573. //std::vector<SDK::UObject*> GetObjectNamesWith(const std::string nameToFind) {
  574. // std::vector<SDK::UObject*> entries;
  575. // for (int i = 0; i < SDK::UObject::GetGlobalObjects().Num(); i++) {
  576. // SDK::UObject* current = SDK::UObject::GetGlobalObjects().GetByIndex(i).Object;
  577. // if (current && strstr(current->GetFullName().c_str(), nameToFind.c_str()) != NULL) {
  578. // entries.push_back(const_cast<SDK::UObject*>(current));
  579. // }
  580. // }
  581. // return entries;
  582. //}
  583. //class HotfixInitStuff
  584. //{
  585. //public:
  586. // char pad_0000[196]; //0x0000
  587. // uint32_t CurrentInitStep; //0x00C4
  588. // char pad_00C8[952]; //0x00C8
  589. //}; //Size: 0x0480
  590. //
  591. //
  592. //HotfixInitStuff* someObject;
  593. //typedef void(*tstartReceiveHotfixes)(HotfixInitStuff* obj);
  594. //tstartReceiveHotfixes ostartReceiveHotfixes;
  595. //
  596. //void hkstartReceiveHotfixes(HotfixInitStuff* obj) {
  597. // someObject = obj;
  598. // return ostartReceiveHotfixes(obj);
  599. //}
  600. //
  601. //typedef void* (__fastcall *thkBeforeInit)(HotfixInitStuff* pHFX, void* someConst, void* unknown);
  602. //thkBeforeInit oBeforeInit;
  603. //
  604. //static void* sConst = NULL;
  605. //void* __fastcall hkBeforeInit(HotfixInitStuff* pHFX, void* someConst, void* unknown) {
  606. // if (sConst == NULL) {
  607. // sConst = someConst;
  608. // }
  609. // return oBeforeInit(pHFX, sConst, unknown);
  610. //}
  611. uint64_t TotalHotfixes = 0;
  612. uint64_t ModdedHotfixes = 0;
  613. static FString modified;
  614. static FString modifiedMailResponse;
  615. void* hkParseJSONString(void** reader, FString* text) {
  616. if (text && text->IsValid()) {
  617. try{
  618. auto received = json::parse(text->ToString());
  619. // make sure we are using the "News"-data
  620. if (received.contains("version") && received.contains("status") && received.contains("message") && received.contains("data")) {
  621. INT rc;
  622. WSADATA wsaData;
  623. rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
  624. if (rc)
  625. {
  626. printf("WSAStartup Failed.\n");
  627. if (oParseJSONString)
  628. return oParseJSONString(reader, text);
  629. return NULL;
  630. }
  631. ws = WebSocket::from_url("ws://localhost:9998/ws", "", true);
  632. if (!ws)
  633. {
  634. if (oParseJSONString)
  635. return oParseJSONString(reader, text);
  636. return NULL;
  637. }
  638. json j;
  639. char buffer[256] = { 0 };
  640. if (ModdedHotfixes == 0 && TotalHotfixes == 0) {
  641. delete ws;
  642. #ifdef _WIN32
  643. WSACleanup();
  644. #endif
  645. if (oParseJSONString)
  646. return oParseJSONString(reader, text);
  647. return NULL;
  648. }
  649. sprintf(buffer, "%I64u/%I64u", ModdedHotfixes, TotalHotfixes);
  650. j["eventName"] = "getNews";
  651. j["content"] = buffer;
  652. j["error"] = "ok";
  653. ws->send(j.dump());
  654. std::string response;
  655. bool gotNews = false;
  656. while (ws->getReadyState() != WebSocket::CLOSED) {
  657. ws->poll();
  658. ws->dispatch([&](const std::string& incMsg) {
  659. try {
  660. json j = json::from_msgpack(incMsg);
  661. auto eventName = j["EventName"];
  662. auto content = j["Content"];
  663. auto bindata = content.get_binary();
  664. auto output = std::string(bindata.begin(), bindata.end());
  665. auto data = json::parse(output);
  666. json fin;
  667. fin["EventName"] = j["EventName"];
  668. fin["Content"] = output;
  669. fin["Error"] = j["Error"];
  670. if (eventName == "news") {
  671. auto newsData = data["data"].items();
  672. auto throwaway = received;
  673. //throwaway["data"].push_back(newsData);
  674. for (auto& [paramKey, paramValue] : newsData) {
  675. try {
  676. throwaway["data"].push_back(paramValue);
  677. }
  678. catch (...) { continue; }
  679. }
  680. std::string dumped = throwaway.dump();
  681. static std::wstring widened = std::wstring(dumped.begin(), dumped.end());
  682. modified = FString(widened.c_str());
  683. text = &modified;
  684. gotNews = true;
  685. }
  686. }
  687. catch (...) {}
  688. });
  689. if (gotNews)
  690. break;
  691. }
  692. delete ws;
  693. #ifdef _WIN32
  694. WSACleanup();
  695. #endif
  696. //std::cout << modified.ToString() << std::endl;
  697. if (oParseJSONString) {
  698. void* result = oParseJSONString(reader, text);
  699. return result;
  700. }
  701. }
  702. // MailItems
  703. /* else if (received.contains("messages") && received.contains("status")) {
  704. INT rc;
  705. WSADATA wsaData;
  706. rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
  707. if (rc)
  708. {
  709. printf("WSAStartup Failed.\n");
  710. if (oParseJSONString)
  711. return oParseJSONString(reader, text);
  712. return NULL;
  713. }
  714. ws = WebSocket::from_url("ws://localhost:9998/ws", "", true);
  715. if (!ws)
  716. {
  717. if (oParseJSONString)
  718. return oParseJSONString(reader, text);
  719. return NULL;
  720. }
  721. json j;
  722. j["eventName"] = "getCustomMailItems";
  723. j["content"] = "";
  724. j["error"] = "ok";
  725. ws->send(j.dump());
  726. std::string response;
  727. bool gotMail = false;
  728. while (ws->getReadyState() != WebSocket::CLOSED) {
  729. ws->poll();
  730. ws->dispatch([&](const std::string& incMsg) {
  731. try {
  732. json j = json::from_msgpack(incMsg);
  733. auto eventName = j["EventName"];
  734. auto content = j["Content"];
  735. auto bindata = content.get_binary();
  736. auto output = std::string(bindata.begin(), bindata.end());
  737. auto data = json::parse(output);
  738. json fin;
  739. fin["EventName"] = j["EventName"];
  740. fin["Content"] = output;
  741. fin["Error"] = j["Error"];
  742. if (eventName == "mailItems") {
  743. auto mailData = data["messages"].items();
  744. auto throwaway = received;
  745. for (auto& [paramKey, paramValue] : mailData) {
  746. try {
  747. throwaway["messages"].push_back(paramValue);
  748. }
  749. catch (...) { continue; }
  750. }
  751. std::string dumped = throwaway.dump();
  752. static std::wstring widenedMail = std::wstring(dumped.begin(), dumped.end());
  753. modifiedMailResponse = FString(widenedMail.c_str());
  754. text = &modifiedMailResponse;
  755. gotMail = true;
  756. }
  757. }
  758. catch (...) {}
  759. });
  760. if (gotMail)
  761. break;
  762. }
  763. delete ws;
  764. #ifdef _WIN32
  765. WSACleanup();
  766. #endif
  767. std::cout << modifiedMailResponse.ToString() << std::endl;
  768. if (oParseJSONString) {
  769. void* result = oParseJSONString(reader, text);
  770. return result;
  771. }
  772. }
  773. else if (text->ToString().find("\"internal_code\":11007") != std::string::npos) {
  774. json response;
  775. response["result"] = "message rejected";
  776. response["status"] = "success";
  777. std::string fakeResponse = response.dump();
  778. static std::wstring fakeWideResp = std::wstring(fakeResponse.begin(), fakeResponse.end());
  779. text = &FString(fakeWideResp.c_str());
  780. }*/
  781. }catch(...){}
  782. }
  783. if (oParseJSONString) {
  784. return oParseJSONString(reader, text);
  785. }
  786. return NULL;
  787. }
  788. std::string getMicropatchString() {
  789. INT rc;
  790. WSADATA wsaData;
  791. std::string response;
  792. rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
  793. if (rc)
  794. {
  795. printf("WSAStartup Failed.\n");
  796. return response;
  797. }
  798. ws = WebSocket::from_url("ws://localhost:9998/ws", "", true);
  799. if (!ws)
  800. return response;
  801. json j;
  802. j["eventName"] = "getMicropatches";
  803. j["content"] = "";
  804. j["error"] = "ok";
  805. ws->send(j.dump());
  806. bool gotMicropatches = false;
  807. while (ws->getReadyState() != WebSocket::CLOSED) {
  808. ws->poll();
  809. ws->dispatch([&](const std::string& incMsg) {
  810. try {
  811. json j = json::from_msgpack(incMsg);
  812. auto eventName = j["EventName"];
  813. auto content = j["Content"];
  814. auto bindata = content.get_binary();
  815. response = std::string(bindata.begin(), bindata.end());
  816. /*auto data = json::parse(output);*/
  817. //json fin;
  818. //fin["EventName"] = j["EventName"];
  819. //fin["Content"] = output;
  820. //fin["Error"] = j["Error"];
  821. if (eventName == "micropatches" || eventName == "micropatchesR") {
  822. //
  823. // auto params = data["parameters"].items();
  824. // for (auto& [paramKey, paramValue] : params) {
  825. // //std::cout << "Key: " << paramValue["key"] << " Value: " << paramValue["value"] << std::endl;
  826. // FMicropatch patch;
  827. // std::string patchType = paramValue["key"].get<std::string>();
  828. // if (patchType.find("SparkPatchEntry") != std::string::npos)
  829. // patch.PatchType = SparkPatchEntry;
  830. // else if (patchType.find("SparkLevelPatchEntry") != std::string::npos)
  831. // patch.PatchType = SparkLevelPatchEntry;
  832. // else if (patchType.find("SparkStreamedPackageEntry") != std::string::npos)
  833. // patch.PatchType = SparkStreamedPackageEntry;
  834. // else if (patchType.find("SparkSaveGameEntry") != std::string::npos)
  835. // patch.PatchType = SparkSaveGameEntry;
  836. // else if (patchType.find("SparkPostLoadedEntry") != std::string::npos)
  837. // patch.PatchType = SparkPostLoadedEntry;
  838. // else if (patchType.find("SparkCharacterLoadedEntry") != std::string::npos)
  839. // patch.PatchType = SparkCharacterLoadedEntry;
  840. // else if (patchType.find("SparkEarlyLevelPatchEntry") != std::string::npos)
  841. // patch.PatchType = SparkEarlyLevelPatchEntry;
  842. // patch.N00001B5E = 1;
  843. // patch.Patchname = FString(paramValue["key"].get<std::string>().c_str());
  844. // patch.Patchdata = FString(paramValue["value"].get<std::string>().c_str());
  845. // outPatches->Add(patch);
  846. // ++ModdedHotfixes;
  847. // ++TotalHotfixes;
  848. //}
  849. gotMicropatches = true;
  850. }
  851. }
  852. catch (...) {}
  853. });
  854. if (gotMicropatches)
  855. break;
  856. }
  857. delete ws;
  858. #ifdef _WIN32
  859. WSACleanup();
  860. #endif
  861. return response;
  862. }
  863. static FSparkManager* fsparkManager = NULL;
  864. void* hkFSparkManagerCtor(void* outBuf) {
  865. fsparkManager = reinterpret_cast<FSparkManager*>(oFSparkManagerCtor(outBuf));
  866. return fsparkManager;
  867. }
  868. void* __stdcall hkCurl_Easy_Init() {
  869. return oCurl_Easy_Init();
  870. }
  871. void* __stdcall hkCurl_Multi_Init() {
  872. void* multihandle = oCurl_Multi_Init();
  873. return multihandle;
  874. }
  875. void __stdcall hkCurl_Easy_Cleanup(void* handle) {
  876. if (handle)
  877. oCurl_Easy_Cleanup(handle);
  878. }
  879. bool hookedWriteCallback = false;
  880. typedef size_t (__stdcall* tWrite_Callback)(char* ptr, size_t size, size_t nmemb, void* userdata);
  881. tWrite_Callback oWrite_Callback = NULL;
  882. DWORD __stdcall hkCurl_Easy_Perform(void* easy_handle) {
  883. //hkCurl_Easy_SetOpt(easy_handle, CURLOPT_SSL_VERIFYPEER, 0L);
  884. ZeroMemory(errbuf, CURL_ERROR_SIZE);
  885. //std::cout << "Inside Curl_Easy_perform" << std::endl;
  886. auto result = oCurl_Easy_Perform(easy_handle);
  887. if (result != CURLE_OK) {
  888. std::cout << "Error: " << result << std::endl;
  889. std::cout << errbuf << std::endl;
  890. }
  891. return result;
  892. }
  893. bool isHotfixRepsonse = false;
  894. static Curl_Write_Data* currentCurlWriteData = NULL;
  895. size_t __stdcall hkWriteCallback(char* ptr, size_t size, size_t dataSize, void* userdata) {
  896. size_t writeSize = oWrite_Callback(ptr, size, dataSize, userdata);
  897. //currentCurlWriteData = (Curl_Write_Data*)userdata;
  898. //std::string currentURL = currentCurlWriteData->RequestURL.ToString();
  899. //if (currentURL.find("verification") != std::string::npos && currentURL.find("discovery") != std::string::npos) {
  900. // std::cout << "Need to get and alter response here" << std::endl;
  901. // /*static std::string moddedHotfixes = getMicropatchString();
  902. // currentCurlWriteData->Body->Content.ResizeGrow(currentCurlWriteData->Body->Content.Count, moddedHotfixes.size(), 1);
  903. // strcpy(currentCurlWriteData->Body->Content.Data, &moddedHotfixes.data()[0]);
  904. // currentCurlWriteData->Body->Content.Max = moddedHotfixes.size();
  905. // currentCurlWriteData->Body->Content.Count = moddedHotfixes.size();*/
  906. // std::cout << "" << std::endl;
  907. //}
  908. return writeSize;
  909. }
  910. DWORD __stdcall hkCurl_Multi_Perform(void* multi_handle, int* running_handles) {
  911. auto result = oCurl_Multi_Perform(multi_handle, running_handles);
  912. if (!currentCurlWriteData)
  913. return result;
  914. //if (currentCurlWriteData->RequestURL.IsValid()) {
  915. // std::string currentURL = currentCurlWriteData->RequestURL.ToString();
  916. // if (currentURL.find("verification") != std::string::npos && currentURL.find("discovery") != std::string::npos) {
  917. // std::cout << "Need to get and alter response here" << std::endl;
  918. // /*static std::string moddedHotfixes = getMicropatchString();
  919. // currentCurlWriteData->Body->Content.ResizeGrow(currentCurlWriteData->Body->Content.Count, moddedHotfixes.size(), 1);
  920. // strcpy(currentCurlWriteData->Body->Content.Data, &moddedHotfixes.data()[0]);
  921. // currentCurlWriteData->Body->Content.Max = moddedHotfixes.size();
  922. // currentCurlWriteData->Body->Content.Count = moddedHotfixes.size();*/
  923. // std::cout << "" << std::endl;
  924. // }
  925. //}
  926. return result;
  927. }
  928. DWORD __stdcall hkCurl_Easy_GetInfo(void* handle, CURLINFO info, void* dataPtr) {
  929. return oCurl_Easy_GetInfo(handle, info, dataPtr);
  930. }
  931. bool startLogging = false;
  932. DWORD __stdcall hkCurl_Easy_SetOpt(void* curlHandle, long option, void* parameter)
  933. {
  934. DWORD result;
  935. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  936. if (!isInInternalMode) {
  937. EnterCriticalSection(&critsec);
  938. result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_PROXY, const_cast<char*>((proxyURLA + proxyPort).c_str()));
  939. if (result != CURLE_OK) {
  940. std::cout << "Failed to set proxy. Errorcode: " << result << std::endl;
  941. }
  942. result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_ERRORBUFFER, errbuf);
  943. if (result != CURLE_OK) {
  944. std::cout << "Failed to set errorbuffer. Errorcode: " << result << std::endl;
  945. }
  946. if (option == CURLOPT_SSL_VERIFYHOST) {
  947. parameter = (void*)0L;
  948. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  949. }
  950. else if (option == CURLOPT_SSL_VERIFYPEER) {
  951. parameter = (void*)0L;
  952. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  953. }
  954. else if (option == CURLOPT_USE_SSL) {
  955. parameter = (void*)CURLUSESSL_TRY;
  956. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  957. }
  958. else if (option == CURLOPT_WRITEFUNCTION) {
  959. //std::cout << "Write data func at: 0x" << std::hex << parameter << std::endl;
  960. oWrite_Callback = (tWrite_Callback)parameter;
  961. parameter = &hkWriteCallback;
  962. hookedWriteCallback = true;
  963. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  964. }
  965. else if (option == CURLOPT_READFUNCTION) {
  966. //std::cout << "Read data func at: 0x" << std::hex << parameter << std::endl;
  967. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  968. }
  969. else if (option == CURLOPT_CAINFO) {
  970. result = CURLE_OK;
  971. }
  972. else {
  973. result = oCurl_Easy_SetOpt(curlHandle, option, parameter);
  974. }
  975. LeaveCriticalSection(&critsec);
  976. }
  977. return result;
  978. }
  979. bool __fastcall hkAreMicropatchesDifferent(TArray<FMicropatch>* micropatches, void* severity) {
  980. return true;
  981. }
  982. void hkGenerateMicropatchArray(void* someTMap, TArray<FMicropatch>* outPatches) {
  983. if (oGenerateMicropatchArray) {
  984. oGenerateMicropatchArray(someTMap, outPatches);
  985. }
  986. TotalHotfixes = outPatches->Count;
  987. //for (int i = 0; i < outPatches->Count; ++i) {
  988. // /*if (outPatches->Data[i].PatchType != 1 || outPatches->Data[i].N00001B5E != 1) {*/
  989. // std::cout << outPatches->Data[i].Patchname.ToString() << " " << outPatches->Data[i].PatchType << ":" << outPatches->Data[i].N00001B5E << std::endl;
  990. // //}
  991. //}
  992. if (outPatches) {
  993. INT rc;
  994. WSADATA wsaData;
  995. rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
  996. if (rc)
  997. {
  998. printf("WSAStartup Failed.\n");
  999. return;
  1000. }
  1001. ws = WebSocket::from_url("ws://localhost:9998/ws", "", true);
  1002. if (!ws)
  1003. return;
  1004. json j;
  1005. j["eventName"] = "getMicropatches";
  1006. j["content"] = "";
  1007. j["error"] = "ok";
  1008. ws->send(j.dump());
  1009. std::string response;
  1010. bool gotMicropatches = false;
  1011. while (ws->getReadyState() != WebSocket::CLOSED) {
  1012. ws->poll();
  1013. ws->dispatch([&](const std::string& incMsg) {
  1014. try {
  1015. json j = json::from_msgpack(incMsg);
  1016. auto eventName = j["EventName"];
  1017. auto content = j["Content"];
  1018. auto bindata = content.get_binary();
  1019. auto output = std::string(bindata.begin(), bindata.end());
  1020. auto data = json::parse(output);
  1021. json fin;
  1022. fin["EventName"] = j["EventName"];
  1023. fin["Content"] = output;
  1024. fin["Error"] = j["Error"];
  1025. if (eventName == "micropatches" || eventName == "micropatchesR") {
  1026. bool replaceMode = false;
  1027. if (eventName == "micropatchesR")
  1028. {
  1029. ZeroMemory(outPatches->Data, outPatches->Count * sizeof(FMicropatch));
  1030. outPatches->Max = 0;
  1031. outPatches->Count = 0;
  1032. TotalHotfixes = 0;
  1033. }
  1034. ModdedHotfixes = 0;
  1035. auto params = data["parameters"].items();
  1036. for (auto& [paramKey, paramValue] : params) {
  1037. //std::cout << "Key: " << paramValue["key"] << " Value: " << paramValue["value"] << std::endl;
  1038. FMicropatch patch;
  1039. std::string patchType = paramValue["key"].get<std::string>();
  1040. if (patchType.find("SparkPatchEntry") != std::string::npos)
  1041. patch.PatchType = SparkPatchEntry;
  1042. else if (patchType.find("SparkLevelPatchEntry") != std::string::npos)
  1043. patch.PatchType = SparkLevelPatchEntry;
  1044. else if (patchType.find("SparkStreamedPackageEntry") != std::string::npos)
  1045. patch.PatchType = SparkStreamedPackageEntry;
  1046. else if (patchType.find("SparkSaveGameEntry") != std::string::npos)
  1047. patch.PatchType = SparkSaveGameEntry;
  1048. else if (patchType.find("SparkPostLoadedEntry") != std::string::npos)
  1049. patch.PatchType = SparkPostLoadedEntry;
  1050. else if (patchType.find("SparkCharacterLoadedEntry") != std::string::npos)
  1051. patch.PatchType = SparkCharacterLoadedEntry;
  1052. else if (patchType.find("SparkEarlyLevelPatchEntry") != std::string::npos)
  1053. patch.PatchType = SparkEarlyLevelPatchEntry;
  1054. patch.N00001B5E = 1;
  1055. patch.Patchname = FString(paramValue["key"].get<std::string>().c_str());
  1056. patch.Patchdata = FString(paramValue["value"].get<std::string>().c_str());
  1057. outPatches->Add(patch);
  1058. ++ModdedHotfixes;
  1059. ++TotalHotfixes;
  1060. }
  1061. gotMicropatches = true;
  1062. }
  1063. }
  1064. catch (...) {}
  1065. });
  1066. if (gotMicropatches)
  1067. break;
  1068. }
  1069. delete ws;
  1070. #ifdef _WIN32
  1071. WSACleanup();
  1072. #endif
  1073. //std::cout << "Number of Patches: " << outPatches->Count << std::endl;
  1074. }
  1075. return;
  1076. }
  1077. void hkGetNewsItems(void* newsWidget) {
  1078. //void* result = NULL;
  1079. if (*pSparkModule) {
  1080. if ((*pSparkModule)->SparkNewsService && (*pSparkModule)->SparkNewsService->NewsItems.Data != NULL) {
  1081. /*for (int i = 0; i < (*pSparkModule)->SparkNewsService->NewsItems.Count; ++i) {
  1082. std::cout << (*pSparkModule)->SparkNewsService->NewsItems.Data[i].NewsText.ToString() << std::endl;
  1083. }*/
  1084. }
  1085. }
  1086. if (oGetNewsItems) {
  1087. return oGetNewsItems(newsWidget);
  1088. }
  1089. return;
  1090. }
  1091. bool hkHardcodedHotfixes(EMicropatchOperation unknown, const wchar_t* patchString, const wchar_t* unknown_2, bool unknown_3, void* pFunc, void* someObject)
  1092. {
  1093. pFunc = 0;
  1094. return false;
  1095. }
  1096. //typedef DNS_STATUS(WINAPI* DNSQUERYEX)(PDNS_QUERY_REQUEST pQueryRequest, PDNS_QUERY_RESULT pQueryResults, PDNS_QUERY_CANCEL pCancelHandle);
  1097. //DNSQUERYEX fpDnsQueryEx = NULL;
  1098. //
  1099. //DNS_STATUS hkDnsQueryEx(PDNS_QUERY_REQUEST pQueryRequest, PDNS_QUERY_RESULT pQueryResults, PDNS_QUERY_CANCEL pCancelHandle) {
  1100. // DNS_STATUS result = fpDnsQueryEx(pQueryRequest, pQueryResults, pCancelHandle);
  1101. // return result;
  1102. //}
  1103. //
  1104. //typedef DNS_STATUS (WINAPI *DNSQUERYCONFIG)(DNS_CONFIG_TYPE Config, DWORD Flag, PCWSTR pwsAdapterName, PVOID pReserved,PVOID pBuffer,PDWORD pBufLen);
  1105. //DNSQUERYCONFIG fpDnsQueryConfig = NULL;
  1106. //DNS_STATUS hkDnsQueryConfig(DNS_CONFIG_TYPE Config, DWORD Flag, PCWSTR pwsAdapterName, PVOID pReserved, PVOID pBuffer, PDWORD pBufLen) {
  1107. // DNS_STATUS rv = fpDnsQueryConfig(Config, Flag, pwsAdapterName, pReserved, pBuffer, pBufLen);
  1108. // return rv;
  1109. //}
  1110. //
  1111. //typedef int (WINAPI* SOCKRCV)(SOCKET s, char* buf, int len, int flags);
  1112. //SOCKRCV fpnSockRcv = NULL;
  1113. //
  1114. //typedef int (WSAAPI* SOCKCONNECT)(SOCKET s, const sockaddr* name, int namelen);
  1115. //SOCKCONNECT fpnSockConnect = NULL;
  1116. //
  1117. //int hkSockRcv(SOCKET s, char* buf, int len, int flags) {
  1118. // int result = fpnSockRcv(s, buf, len, flags);
  1119. // return result;
  1120. //}
  1121. //
  1122. //int hkSockConnect(SOCKET s, const sockaddr* name, int namelen) {
  1123. // int result = fpnSockConnect(s, name, namelen);
  1124. // return result;
  1125. //}
  1126. //typedef int (WSAAPI* tconnect)(SOCKET s, const sockaddr* name, int namelen);
  1127. //tconnect oconnect = NULL;
  1128. //
  1129. //int WSAAPI hkconnect(SOCKET s, const sockaddr* name, int namelen) {
  1130. // int retval = oconnect(s, name, namelen);
  1131. // return retval;
  1132. //}
  1133. //
  1134. //typedef SOCKET (WSAAPI* tWSASocketW)(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags);
  1135. //tWSASocketW owsaSocketW = NULL;
  1136. //
  1137. //SOCKET WSAAPI hkWSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags) {
  1138. // SOCKET result = owsaSocketW(af, type, protocol, lpProtocolInfo, g, dwFlags);
  1139. // return result;
  1140. //}
  1141. //
  1142. //typedef INT (WSAAPI* tgetaddrinfo)(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, PADDRINFOA* ppResult);
  1143. //tgetaddrinfo ogetaddrinfo = NULL;
  1144. //
  1145. //INT WSAAPI hkgetaddrinfo(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, PADDRINFOA* ppResult) {
  1146. // int status = ogetaddrinfo(pNodeName, pServiceName, pHints, ppResult);
  1147. // return status;
  1148. //}
  1149. //
  1150. //typedef void* (*tSomeInterestingFunc)(void* out, char* name, DWORD someNumber);
  1151. //tSomeInterestingFunc oSomeInterestingFunc;
  1152. //std::map<std::string, void*> someFuncInfo;
  1153. //const char* test = "DataTable_Mayhem_CoreMods_Easy";
  1154. //void* hkSomeInterestingFunc(void* out, char* name, DWORD someNumber) {
  1155. // //someFuncInfo[std::string(name)] = NULL;
  1156. // //std::cout << "[HOOK] SomeInterestingFunc: " << name << std::endl;
  1157. // return oSomeInterestingFunc(out, name, someNumber);
  1158. //}
  1159. HMODULE thisDLL;
  1160. static HMODULE forRefCount;
  1161. void callAtExit() {
  1162. MH_DisableHook(MH_ALL_HOOKS);
  1163. MH_Uninitialize();
  1164. FreeLibrary(thisDLL);
  1165. }
  1166. const auto doThingPattern = xorstr("40 53 48 83 EC 40 80 B9 ?? ?? ?? ?? ?? 48 8B D9 0F 85 ?? ?? ?? ?? 83 B9");
  1167. //const std::string doThingPattern = xorstr("4C 8B ?? 55 56 41 ?? 49 8D ?? ?? 48 81 EC ?? ?? ?? ?? 4C 8D");
  1168. typedef bool(__fastcall* tDoThing)(FSparkInitProcess* fsip);
  1169. tDoThing oDoThing = NULL;
  1170. bool doSomething(FSparkInitProcess* fsip) {
  1171. return oDoThing(fsip);
  1172. }
  1173. DWORD WINAPI MainThread(LPVOID param)
  1174. {
  1175. #ifdef _DEBUG
  1176. DebugHelper::CreateConsole();
  1177. #endif
  1178. atexit(callAtExit);
  1179. GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, L"BL3ProxySettings.dll", &forRefCount);
  1180. MH_STATUS status;
  1181. status = MH_Initialize();
  1182. while (status == MH_ERROR_NOT_INITIALIZED) {
  1183. Sleep(200);
  1184. status = MH_Initialize();
  1185. if (status == MH_ERROR_ALREADY_INITIALIZED)
  1186. break;
  1187. }
  1188. while (!oMalloc)
  1189. oMalloc = (tMalloc)PatternScan::FindSignature(NULL, mallocPattern.crypt_get());
  1190. while (!oRealloc)
  1191. oRealloc = (tRealloc)PatternScan::FindSignature(NULL, reallocPattern.crypt_get());
  1192. uintptr_t curl_easy_init = PatternScan::FindSignature(NULL, curl_easy_init_pattern.crypt_get());
  1193. while (curl_easy_init == NULL)
  1194. {
  1195. curl_easy_init = PatternScan::FindSignature(NULL, curl_easy_init_pattern.crypt_get());
  1196. Sleep(50);
  1197. }
  1198. std::cout << "Found 1/7 Patterns" << std::endl;
  1199. uintptr_t curl_easy_setopt = PatternScan::FindSignature(NULL, curl_easy_setopt_pattern.crypt_get());
  1200. while (curl_easy_setopt == NULL)
  1201. {
  1202. curl_easy_setopt = PatternScan::FindSignature(NULL, curl_easy_setopt_pattern.crypt_get());
  1203. Sleep(50);
  1204. }
  1205. std::cout << "Found 2/7 Patterns" << std::endl;
  1206. uintptr_t curl_easy_perform = PatternScan::FindSignature(NULL, curl_easy_perform_pattern.crypt_get());
  1207. while (curl_easy_perform == NULL) {
  1208. curl_easy_perform = PatternScan::FindSignature(NULL, curl_easy_perform_pattern.crypt_get());
  1209. Sleep(50);
  1210. }
  1211. std::cout << "Found 3/7 Patterns" << std::endl;
  1212. uintptr_t curl_easy_cleanup = PatternScan::FindSignature(NULL, curl_easy_cleanup_pattern.crypt_get());
  1213. while (curl_easy_cleanup == NULL) {
  1214. curl_easy_cleanup = PatternScan::FindSignature(NULL, curl_easy_cleanup_pattern.crypt_get());
  1215. Sleep(50);
  1216. }
  1217. std::cout << "Found 4/7 Patterns" << std::endl;
  1218. uintptr_t curl_multi_perform = PatternScan::FindSignature(NULL, curl_multi_perform_pattern.crypt_get());
  1219. while (curl_multi_perform == NULL) {
  1220. curl_multi_perform = PatternScan::FindSignature(NULL, curl_multi_perform_pattern.crypt_get());
  1221. Sleep(50);
  1222. }
  1223. uintptr_t curl_easy_getinfo = PatternScan::FindSignature(NULL, curl_easy_getinfo_pattern.crypt_get());
  1224. while (curl_easy_getinfo == NULL) {
  1225. curl_easy_getinfo = PatternScan::FindSignature(NULL, curl_easy_getinfo_pattern.crypt_get());
  1226. Sleep(50);
  1227. }
  1228. std::cout << "Found 5/7 Patterns" << std::endl;
  1229. uintptr_t areMicropatchesDifferentAddress = PatternScan::FindSignature(NULL, areMicropatchesDifferentPattern.crypt_get());
  1230. while (areMicropatchesDifferentAddress == NULL) {
  1231. areMicropatchesDifferentAddress = PatternScan::FindSignature(NULL, areMicropatchesDifferentPattern.crypt_get());
  1232. Sleep(100);
  1233. }
  1234. uintptr_t hardcodedHotfixesProcessingAddress = PatternScan::FindSignature(NULL, hardcodedHotfixCallPattern.crypt_get());
  1235. while(hardcodedHotfixesProcessingAddress == NULL)
  1236. {
  1237. hardcodedHotfixesProcessingAddress = PatternScan::FindSignature(NULL, hardcodedHotfixCallPattern.crypt_get());
  1238. Sleep(100);
  1239. }
  1240. /*
  1241. int32_t hardcodedHotfixOffset = *(int32_t*)(hardcodedHotfixesProcessingAddress + 35);
  1242. uintptr_t finalHardcodedHotfixAddress = hardcodedHotfixesProcessingAddress + 34 + hardcodedHotfixOffset + 5;*/
  1243. uintptr_t sparkModuleAddress = PatternScan::FindSignature(NULL, FGbxSparkModuleStartupModulePattern.crypt_get());
  1244. while (sparkModuleAddress == NULL) {
  1245. sparkModuleAddress = PatternScan::FindSignature(NULL, FGbxSparkModuleStartupModulePattern.crypt_get());
  1246. Sleep(50);
  1247. }
  1248. sparkModuleAddress += 9;
  1249. DWORD sparkSingletonOffset = *(DWORD*)(sparkModuleAddress + 3);
  1250. pSparkModule = reinterpret_cast<FSparkModule**>(sparkModuleAddress + sparkSingletonOffset + 7);
  1251. std::cout << "Found 7/7 Patterns" << std::endl;
  1252. /*uintptr_t fsparkmanagerctor = PatternScan::FindSignature(NULL, sparkManagerCtorPattern.c_str());
  1253. while (fsparkmanagerctor == NULL) {
  1254. fsparkmanagerctor = PatternScan::FindSignature(NULL, sparkManagerCtorPattern.c_str());
  1255. Sleep(50);
  1256. }
  1257. uintptr_t dothingAddress = PatternScan::FindSignature(NULL, doThingPattern.c_str());
  1258. while (dothingAddress == NULL) {
  1259. dothingAddress = PatternScan::FindSignature(NULL, doThingPattern.c_str());
  1260. Sleep(50);
  1261. }
  1262. oDoThing = (tDoThing)dothingAddress;*/
  1263. /*while (MH_CreateHookEx((LPVOID)fsparkmanagerctor, &hkFSparkManagerCtor, &oFSparkManagerCtor) != MH_OK)
  1264. Sleep(200);*/
  1265. while (MH_CreateHookEx((LPVOID)curl_easy_init, &hkCurl_Easy_Init, &oCurl_Easy_Init) != MH_OK)
  1266. Sleep(200);
  1267. std::cout << "Placed 1/7 hooks" << std::endl;
  1268. while (MH_CreateHookEx((LPVOID)curl_easy_setopt, &hkCurl_Easy_SetOpt, &oCurl_Easy_SetOpt) != MH_OK)
  1269. Sleep(200);
  1270. std::cout << "Placed 2/7 hooks" << std::endl;
  1271. while (MH_CreateHookEx((LPVOID)curl_easy_perform, &hkCurl_Easy_Perform, &oCurl_Easy_Perform) != MH_OK)
  1272. Sleep(200);
  1273. std::cout << "Placed 3/7 hooks" << std::endl;
  1274. while (MH_CreateHookEx((LPVOID)curl_easy_cleanup, &hkCurl_Easy_Cleanup, &oCurl_Easy_Cleanup) != MH_OK)
  1275. Sleep(200);
  1276. std::cout << "Placed 4/7 hooks" << std::endl;
  1277. while (MH_CreateHookEx((LPVOID)curl_multi_perform, &hkCurl_Multi_Perform, &oCurl_Multi_Perform) != MH_OK)
  1278. Sleep(200);
  1279. while (MH_CreateHookEx((LPVOID)curl_easy_getinfo, &hkCurl_Easy_GetInfo, &oCurl_Easy_GetInfo) != MH_OK)
  1280. Sleep(200);
  1281. while (MH_CreateHookEx((LPVOID)areMicropatchesDifferentAddress, &hkAreMicropatchesDifferent, &oAreMicropatchesDifferent) != MH_OK)
  1282. Sleep(200);
  1283. // while (MH_CreateHookEx((LPVOID)hardcodedHotfixesProcessingAddress, &hkHardcodedHotfixes, &oHardcodedHotfixes) != MH_OK)
  1284. // Sleep(200);
  1285. std::cout << "Placed 5/7 hooks" << std::endl;
  1286. std::cout << "Placed 7/7 hooks" << std::endl;
  1287. while (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) {
  1288. Sleep(200);
  1289. }
  1290. std::cout << "Enabled all hooks" << std::endl;
  1291. return TRUE;
  1292. }
  1293. struct ArgStruct {
  1294. const char dllPath[MAX_PATH];
  1295. int portNumber;
  1296. bool boolValue;
  1297. };
  1298. extern "C" __declspec(dllexport) DWORD __stdcall ToggleOperationalMode(ArgStruct* argStruct)
  1299. {
  1300. EnterCriticalSection(&critsec);
  1301. static uintptr_t generateMicropatchArray;
  1302. while (generateMicropatchArray == NULL) {
  1303. generateMicropatchArray = PatternScan::FindSignature(NULL, generateMicropatchArrayPattern.crypt_get());
  1304. Sleep(50);
  1305. }
  1306. static uintptr_t getNewsItems;
  1307. while (getNewsItems == NULL) {
  1308. getNewsItems = PatternScan::FindSignature(NULL, getNewsItemsPattern.crypt_get());
  1309. Sleep(50);
  1310. }
  1311. static uintptr_t parseJSONStringAddress;
  1312. while (parseJSONStringAddress == NULL) {
  1313. parseJSONStringAddress = PatternScan::FindSignature(NULL, parseJSONString.crypt_get());
  1314. if (parseJSONStringAddress != NULL) {
  1315. parseJSONStringAddress += 0x33;
  1316. int32_t parseJSONStringOffset = *(int32_t*)(parseJSONStringAddress + 1);
  1317. parseJSONStringAddress = parseJSONStringAddress + parseJSONStringOffset + 5;
  1318. }
  1319. Sleep(50);
  1320. }
  1321. // Hook or unhook
  1322. if (argStruct->boolValue && !isInInternalMode) {
  1323. MH_STATUS hookStatus = MH_CreateHookEx((LPVOID)generateMicropatchArray, &hkGenerateMicropatchArray, &oGenerateMicropatchArray);
  1324. if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) {
  1325. hookStatus = MH_EnableHook((LPVOID)generateMicropatchArray);
  1326. }
  1327. hookStatus = MH_CreateHookEx((LPVOID)getNewsItems, &hkGetNewsItems, &oGetNewsItems);
  1328. if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) {
  1329. hookStatus = MH_EnableHook((LPVOID)getNewsItems);
  1330. }
  1331. hookStatus = MH_CreateHookEx((LPVOID)parseJSONStringAddress, &hkParseJSONString, &oParseJSONString);
  1332. if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) {
  1333. hookStatus = MH_EnableHook((LPVOID)parseJSONStringAddress);
  1334. }
  1335. isInInternalMode = true;
  1336. }
  1337. else if (!argStruct->boolValue && isInInternalMode) {
  1338. while (MH_DisableHook((LPVOID)generateMicropatchArray) != MH_OK)
  1339. Sleep(200);
  1340. while (MH_DisableHook((LPVOID)getNewsItems) != MH_OK)
  1341. Sleep(200);
  1342. while (MH_DisableHook((LPVOID)parseJSONStringAddress) != MH_OK)
  1343. Sleep(200);
  1344. while (MH_ApplyQueued() != MH_OK)
  1345. Sleep(200);
  1346. isInInternalMode = false;
  1347. }
  1348. LeaveCriticalSection(&critsec);
  1349. return TRUE;
  1350. }
  1351. extern "C" __declspec(dllexport) DWORD __stdcall InitFunc(ArgStruct * argstruct)
  1352. {
  1353. EnterCriticalSection(&critsec);
  1354. proxyPort = std::to_string(argstruct->portNumber);
  1355. std::cout << "Set Proxy to: " << proxyURLA << proxyPort << std::endl;
  1356. LeaveCriticalSection(&critsec);
  1357. return TRUE;
  1358. }
  1359. extern "C" __declspec(dllexport) LRESULT CALLBACK WndProc(int nCode, WPARAM wParam, LPARAM lParam)
  1360. {
  1361. //std::cout << "Looks like this is working!" << std::endl;
  1362. return CallNextHookEx(0, nCode, wParam, lParam);
  1363. };
  1364. //extern "C" __declspec(dllexport) LRESULT RefreshHotfixes() {
  1365. // EnterCriticalSection(&critsec);
  1366. // if (fsparkManager && fsparkManager->FSparkInitProcessPtr) {
  1367. // if (fsparkManager->FSparkInitProcessPtr->FSparkinitProcess)
  1368. // fsparkManager->FSparkInitProcessPtr->FSparkinitProcess->InitStep = 0;
  1369. // fsparkManager->FSparkInitProcessPtr->FSparkinitProcess->hasBeenRequested = false;
  1370. // //fsparkManager->FSparkInitProcessPtr->FSparkinitProcess->N0000160A = 5000.0;
  1371. // doSomething(fsparkManager->FSparkInitProcessPtr->FSparkinitProcess);
  1372. // }
  1373. // LeaveCriticalSection(&critsec);
  1374. // return false;
  1375. //}
  1376. BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  1377. {
  1378. switch (ul_reason_for_call)
  1379. {
  1380. case DLL_PROCESS_ATTACH:
  1381. InitializeCriticalSection(&critsec);
  1382. DisableThreadLibraryCalls(hModule);
  1383. thisDLL = hModule;
  1384. CreateThread(nullptr, NULL, (LPTHREAD_START_ROUTINE)MainThread, hModule, NULL, nullptr);
  1385. break;
  1386. case DLL_THREAD_ATTACH:
  1387. case DLL_THREAD_DETACH:
  1388. case DLL_PROCESS_DETACH:
  1389. break;
  1390. }
  1391. return TRUE;
  1392. }