Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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