You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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