Seregon/Hermes

Hermes/Dyforge is a program written in c++ allows you to inject a dll that can analyze all processes in a program, can be used for mod and reverse engeneering

C/3.8 KB/No license
DyForge/src/injection/InjectionManager.cpp
Hermes / DyForge / src / injection / InjectionManager.cpp
1#include "InjectionManager.h"
2#include "../../../DyHexInject/include/DyHexInjectTypes.h"
3#include "../../../DyHexInject/DyHexInject.h"
4#include <stdexcept>
5#include <sstream>
6#include <iostream>
7#include <mutex>
8#include <cstdarg>
9#include <thread>
10 
11namespace DyForge {
12namespace Injection {
13 
14InjectionManager* InjectionManager::instance = nullptr;
15std::mutex InjectionManager::instanceMutex;
16 
17InjectionManager& InjectionManager::getInstance() {
18 std::lock_guard<std::mutex> lock(instanceMutex);
19 if (instance == nullptr) {
20 instance = new InjectionManager();
21 }
22 return *instance;
23}
24 
25InjectionManager::InjectionManager() : initialized(false) {
26}
27 
28InjectionManager::~InjectionManager() {
29 cleanup();
30}
31 
32bool InjectionManager::initialize() {
33 if (initialized) return true;
34 
35 DyHexInjectError error = DyHexInject_Initialize();
36 if (error != DYHEXINJECT_SUCCESS) {
37 handleError(DyHexInject_GetErrorString(error));
38 return false;
39 }
40 
41 initialized = true;
42 return true;
43}
44 
45void InjectionManager::cleanup() {
46 if (!initialized) return;
47 
48 stopCommunication();
49 DyHexInject_Cleanup();
50 initialized = false;
51}
52 
53bool InjectionManager::injectDll(const std::wstring& dllPath, DWORD processId) {
54 if (!initialized) {
55 handleError("InjectionManager not initialized");
56 return false;
57 }
58 
59 DyHexInjectError error = DyHexInject_OpenProcess(processId, &processInfo);
60 if (error != DYHEXINJECT_SUCCESS) {
61 handleError(DyHexInject_GetErrorString(error));
62 return false;
63 }
64 
65 DyHexInjectConfig config = {
66 dllPath.c_str(),
67 true, // waitForInjection
68 false, // hideInjection
69 true, // enableDebugLogging
70 true, // enableSharedMemory
71 4096 // sharedMemorySize
72 };
73 
74 error = DyHexInject_InjectDll(&processInfo, &config);
75 if (error != DYHEXINJECT_SUCCESS) {
76 handleError(DyHexInject_GetErrorString(error));
77 DyHexInject_CloseProcess(&processInfo);
78 return false;
79 }
80 
81 return true;
82}
83 
84bool InjectionManager::ejectDll(const std::wstring& dllPath, DWORD processId) {
85 if (!initialized) {
86 handleError("InjectionManager not initialized");
87 return false;
88 }
89 
90 DyHexInjectError error = DyHexInject_OpenProcess(processId, &processInfo);
91 if (error != DYHEXINJECT_SUCCESS) {
92 handleError(DyHexInject_GetErrorString(error));
93 return false;
94 }
95 
96 error = DyHexInject_EjectDll(&processInfo, dllPath.c_str());
97 if (error != DYHEXINJECT_SUCCESS) {
98 handleError(DyHexInject_GetErrorString(error));
99 DyHexInject_CloseProcess(&processInfo);
100 return false;
101 }
102 
103 DyHexInject_CloseProcess(&processInfo);
104 return true;
105}
106 
107bool InjectionManager::startCommunication(DWORD processId) {
108 if (!initialized) {
109 handleError("InjectionManager not initialized");
110 return false;
111 }
112 
113 std::lock_guard<std::mutex> lock(communicationMutex);
114 
115 DyHexInjectError error = DyHexInject_OpenProcess(processId, &processInfo);
116 if (error != DYHEXINJECT_SUCCESS) {
117 handleError(DyHexInject_GetErrorString(error));
118 return false;
119 }
120 
121 error = DyHexInject_StartCommunication(&processInfo, &communication);
122 if (error != DYHEXINJECT_SUCCESS) {
123 handleError(DyHexInject_GetErrorString(error));
124 DyHexInject_CloseProcess(&processInfo);
125 return false;
126 }
127 
128 m_communicationThread = std::thread(&InjectionManager::communicationThread, this);
129 return true;
130}
131 
132void InjectionManager::stopCommunication() {
133 std::lock_guard<std::mutex> lock(communicationMutex);
134 
135 if (communication.isConnected) {
136 DyHexInject_StopCommunication(&communication);
137 DyHexInject_CloseProcess(&processInfo);
138 }
139 
140 if (m_communicationThread.joinable()) {
141 m_communicationThread.join();
142 }
143}
144 
145bool InjectionManager::sendCommand(const Command& command) {
146 std::lock_guard<std::mutex> lock(communicationMutex);
147 
148 if (!communication.isConnected) {
149 handleError("Communication not started");
150 return false;
151 }
152 
153 commandQueue.push(command);
154 commandCondition.notify_one();
155 return true;
156}
157 
158bool InjectionManager::receiveResponse(Response& response) {
159 std::lock_guard<std::mutex> lock(communicationMutex);
160 
161 if (responseQueue.empty()) {
162 return false;
163 }
164 
165 response = responseQueue.front();
166 responseQueue.pop();
167 return true;
168}
169 
170bool InjectionManager::waitForResponse(Response& response, DWORD timeout) {
171 std::unique_lock<std::mutex> lock(communicationMutex);
172 if (commandCondition.wait_for(lock, std::chrono::milliseconds(timeout),
173 [this] { return !responseQueue.empty(); })) {
174 response = responseQueue.front();
175 responseQueue.pop();
176 return true;
177 }
178 return false;
179}
180 
181void InjectionManager::communicationThread() {
182 while (communication.isConnected) {
183 Command command;
184 {
185 std::unique_lock<std::mutex> lock(communicationMutex);
186 commandCondition.wait(lock, [this] {
187 return !commandQueue.empty() || !communication.isConnected;
188 });
189 
190 if (!communication.isConnected) {
191 break;
192 }
193 
194 command = commandQueue.front();
195 commandQueue.pop();
196 }
197 
198 if (!processCommand(command)) {
199 Response errorResponse;
200 errorResponse.type = static_cast<ResponseType>(1); // ERROR
201 errorResponse.message = lastError;
202
203 std::lock_guard<std::mutex> lock(communicationMutex);
204 responseQueue.push(errorResponse);
205 commandCondition.notify_one();
206 }
207 }
208}
209 
210bool InjectionManager::processCommand(const Command& command) {
211 std::stringstream ss;
212 ss << static_cast<int>(command.type);
213 if (!command.parameters.empty()) {
214 ss << " " << command.parameters;
215 }
216 
217 DyHexInjectError error = DyHexInject_SendCommand(
218 &communication,
219 ss.str().c_str(),
220 ss.str().length()
221 );
222 
223 if (error != DYHEXINJECT_SUCCESS) {
224 handleError(DyHexInject_GetErrorString(error));
225 return false;
226 }
227 
228 char responseBuffer[4096];
229 size_t bytesReceived = 0;
230 
231 error = DyHexInject_ReceiveResponse(
232 &communication,
233 responseBuffer,
234 sizeof(responseBuffer),
235 &bytesReceived
236 );
237 
238 if (error != DYHEXINJECT_SUCCESS) {
239 handleError(DyHexInject_GetErrorString(error));
240 return false;
241 }
242 
243 Response response;
244 response.type = ResponseType::SUCCESS;
245 response.message = std::string(responseBuffer, bytesReceived);
246 
247 std::lock_guard<std::mutex> lock(communicationMutex);
248 responseQueue.push(response);
249 commandCondition.notify_one();
250 
251 return true;
252}
253 
254void InjectionManager::handleError(const char* error) {
255 lastError = error;
256 logDebug("Error: %s", error);
257}
258 
259void InjectionManager::logDebug(const char* format, ...) {
260 va_list args;
261 va_start(args, format);
262
263 char buffer[1024];
264 vsnprintf(buffer, sizeof(buffer), format, args);
265
266 va_end(args);
267 
268 std::cout << "[DEBUG] " << buffer << std::endl;
269}
270 
271bool InjectionManager::initializeSharedMemory() {
272 char sharedMemoryName[32];
273 sprintf_s(sharedMemoryName, sizeof(sharedMemoryName), "DyForge_%d", processInfo.processId);
274 
275 communication.sharedMemory = CreateFileMappingA(
276 INVALID_HANDLE_VALUE,
277 NULL,
278 PAGE_READWRITE,
279 0,
280 4096,
281 sharedMemoryName
282 );
283 
284 if (!communication.sharedMemory) {
285 handleError("Failed to create shared memory");
286 return false;
287 }
288 
289 communication.mappedMemory = MapViewOfFile(
290 communication.sharedMemory,
291 FILE_MAP_ALL_ACCESS,
292 0,
293 0,
294 4096
295 );
296 
297 if (!communication.mappedMemory) {
298 CloseHandle(communication.sharedMemory);
299 communication.sharedMemory = NULL;
300 handleError("Failed to map shared memory");
301 return false;
302 }
303 
304 return true;
305}
306 
307void InjectionManager::cleanupSharedMemory() {
308 if (communication.mappedMemory) {
309 UnmapViewOfFile(communication.mappedMemory);
310 communication.mappedMemory = NULL;
311 }
312 
313 if (communication.sharedMemory) {
314 CloseHandle(communication.sharedMemory);
315 communication.sharedMemory = NULL;
316 }
317}
318 
319} // namespace Injection
320} // namespace DyForge