dllmain.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #include <WinSock2.h>
  2. #pragma comment(lib, "Ws2_32.lib")
  3. #include <detours.h>
  4. #include <thread>
  5. #include <string>
  6. #include "framework.h"
  7. #include "PluginConfigApi.h"
  8. #include <iostream>
  9. bool(__cdecl* DSC_EXECUTE_COMMAND)(__int64 dsc_address, float delta_time, __int64 start_time, void* wait_timer, int* a5, int a6, int a7)
  10. = (bool(__cdecl*)(__int64 dsc_address, float delta_time, __int64 start_time, void* wait_timer, int* a5, int a6, int a7))
  11. 0x14011CBA0;
  12. bool hookedDSC_EXECUTE_COMMAND(__int64 dsc_address, float delta_time, __int64 start_time, void* wait_timer, int* a5, int a6, int a7);
  13. void serve();
  14. bool debug = false;
  15. unsigned short port = 8139;
  16. void loadConfig()
  17. {
  18. port = GetPrivateProfileIntW(L"general", L"port", 8139, CONFIG_FILE);
  19. debug = GetPrivateProfileIntW(L"general", L"debug", 0, CONFIG_FILE) > 0;
  20. return;
  21. }
  22. float last_delta_time = 0.0;
  23. __int64 last_start_time = 0i64;
  24. void* last_wait_timer = nullptr;
  25. int* last_a5 = nullptr;
  26. int last_a6 = 0;
  27. int last_a7 = 0;
  28. bool hookedDSC_EXECUTE_COMMAND(__int64 dsc_address, float delta_time, __int64 start_time, void* wait_timer, int* a5, int a6, int a7)
  29. {
  30. last_delta_time = delta_time;
  31. last_start_time = start_time;
  32. last_wait_timer = wait_timer;
  33. last_a5 = a5;
  34. last_a6 = a6;
  35. last_a7 = a7;
  36. return DSC_EXECUTE_COMMAND(dsc_address, delta_time, start_time, wait_timer, a5, a6, a7);
  37. }
  38. void serve()
  39. {
  40. using namespace std;
  41. cout << "[DSCRemote] Staring server..." << endl;
  42. WSADATA wsadata;
  43. int result = WSAStartup(MAKEWORD(2, 2), &wsadata);
  44. if (result) // error
  45. {
  46. cout << "[DSCRemote] E: WSAStartup error " << result << '.' << endl;
  47. return;
  48. }
  49. SOCKET sock;
  50. sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  51. if (result == INVALID_SOCKET)
  52. {
  53. cout << "[DSCRemote] E: Invalid socket." << endl;
  54. WSACleanup();
  55. return;
  56. }
  57. sockaddr_in saddrin;
  58. saddrin.sin_family = AF_INET;
  59. saddrin.sin_addr.s_addr = 0;
  60. saddrin.sin_port = htons(port);
  61. result = ::bind(sock, (sockaddr*)&saddrin, sizeof(sockaddr_in));
  62. if (result) // error
  63. {
  64. cout << "[DSCRemote] E: Couldn't bind port " << port << '.' << endl;
  65. closesocket(sock);
  66. WSACleanup();
  67. return;
  68. }
  69. result = listen(sock, 1);
  70. if (result) // error
  71. {
  72. cout << "[DSCRemote] E: Couldn't listen." << endl;
  73. closesocket(sock);
  74. WSACleanup();
  75. return;
  76. }
  77. while (true)
  78. {
  79. cout << "[DSCRemote] Waiting for client..." << endl;
  80. SOCKET client_sock;
  81. client_sock = accept(sock, NULL, NULL);
  82. cout << "[DSCRemote] Client accepted." << endl;
  83. char buff_recv[64];
  84. vector<int> cmdStack;
  85. do
  86. {
  87. result = recv(client_sock, buff_recv, sizeof(buff_recv), 0);
  88. if (result > 0)
  89. {
  90. if (debug) cout << "[DSCRemote] D: Received: " << buff_recv << endl;
  91. if (buff_recv[0] != 'i')
  92. {
  93. long stack = stol(buff_recv);
  94. for (int i = 0; i < sizeof(buff_recv); i++) buff_recv[i] = '\0';
  95. cmdStack.push_back(stack);
  96. const char buff_out[] = "Stacking command/parameter. Send 'i' to inject.";
  97. send(client_sock, buff_out, sizeof(buff_out), 0);
  98. continue;
  99. }
  100. for (int i = 0; i < sizeof(buff_recv); i++) buff_recv[i] = '\0';
  101. const char buff_out[] = "Injecting stack.";
  102. send(client_sock, buff_out, sizeof(buff_out), 0);
  103. const int64_t dscbaseaddr = 0x140CDD978i64;
  104. int* currentpos = (int*)(dscbaseaddr + 0x2bf2c);
  105. int* command = (int*)(dscbaseaddr + 0xc);
  106. int posbk = *currentpos;
  107. vector<int> cmdbk;
  108. for (int i=0; i<cmdStack.size(); i++)
  109. cmdbk.push_back(command[i]);
  110. *currentpos = 0;
  111. for (int i = 0; i < cmdStack.size(); i++)
  112. {
  113. if (debug) cout << "[DSCRemote] D: Injecting " << cmdStack.at(i) << endl;
  114. command[i] = cmdStack.at(i);
  115. }
  116. cmdStack.clear();
  117. DSC_EXECUTE_COMMAND(dscbaseaddr, last_delta_time, last_start_time, last_wait_timer, last_a5, last_a6, last_a7);
  118. for (int i = 0; i < cmdbk.size(); i++)
  119. {
  120. if (debug) cout << "[DSCRemote] D: Restoring " << cmdbk.at(i) << endl;
  121. command[i] = cmdbk.at(i);
  122. }
  123. cmdbk.clear();
  124. *currentpos = posbk;
  125. }
  126. } while (result > 0);
  127. closesocket(client_sock);
  128. cout << "[DSCRemote] Restarting..." << endl;
  129. }
  130. cout << "[DSCRemote] Bye!" << endl;
  131. closesocket(sock);
  132. WSACleanup();
  133. }
  134. BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  135. {
  136. if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  137. {
  138. using namespace std;
  139. loadConfig();
  140. DisableThreadLibraryCalls(hModule);
  141. DetourTransactionBegin();
  142. DetourUpdateThread(GetCurrentThread());
  143. cout << "[DSCRemote] Hooking functions..." << endl;
  144. DetourAttach(&(PVOID&)DSC_EXECUTE_COMMAND, (PVOID)hookedDSC_EXECUTE_COMMAND);
  145. cout << "[DSCRemote] Functions hooked." << endl;
  146. DetourTransactionCommit();
  147. thread* server_thread = new thread(serve);
  148. }
  149. return TRUE;
  150. }
  151. PluginConfig::PluginConfigOption config[] = {
  152. { PluginConfig::CONFIG_NUMERIC, new PluginConfig::PluginConfigNumericData{ L"port", L"general", CONFIG_FILE, L"Port", L"TCP/IP port.", 8139, 1, USHRT_MAX } },
  153. { PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"debug", L"general", CONFIG_FILE, L"Debug", L"Print extra information.", false } },
  154. };
  155. extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
  156. {
  157. return L"DSCRemote";
  158. }
  159. extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
  160. {
  161. return L"Allows external applications to send DSC commands via TCP/IP.";
  162. }
  163. extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void)
  164. {
  165. return PluginConfig::PluginConfigArray{ _countof(config), config };
  166. }