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
DyMain/WebServer/WebServer.cpp
Hermes / DyMain / WebServer / WebServer.cpp
1#include "WebServer/WebServer.h"
2#include <chrono>
3#include <sstream>
4#include <nlohmann/json.hpp>
5#include <filesystem>
6#include <capstone/capstone.h>
7 
8using json = nlohmann::json;
9namespace fs = std::filesystem;
10 
11namespace DyMain::WebServer {
12 
13// Inizializzazione delle variabili statiche
14WebServerManager* WebServerManager::instance = nullptr;
15std::mutex WebServerManager::instanceMutex;
16 
17WebServerManager& WebServerManager::getInstance() {
18 std::lock_guard<std::mutex> lock(instanceMutex);
19 if (instance == nullptr) {
20 instance = new WebServerManager();
21 }
22 return *instance;
23}
24 
25WebServerManager::~WebServerManager() {
26 if (running) {
27 stop();
28 }
29}
30 
31bool WebServerManager::start(int port) {
32 if (running) return false;
33
34 this->port = port;
35 mg_mgr_init(&mgr);
36
37 // Configura l'URL di ascolto
38 std::string listen_url = "http://0.0.0.0:" + std::to_string(port);
39 mg_connection* conn = mg_http_listen(&mgr, listen_url.c_str(), eventHandler, this);
40
41 if (conn == nullptr) {
42 mg_mgr_free(&mgr);
43 return false;
44 }
45
46 // Registra gli endpoint predefiniti
47 registerEndpoint("/api/memory", [this](auto conn, auto msg) { handleMemoryEndpoint(conn, msg); });
48 registerEndpoint("/api/memory/scan", [this](auto conn, auto msg) { handleMemoryScanEndpoint(conn, msg); });
49 registerEndpoint("/api/threads", [this](auto conn, auto msg) { handleThreadsEndpoint(conn, msg); });
50 registerEndpoint("/api/thread", [this](auto conn, auto msg) { handleThreadEndpoint(conn, msg); });
51 registerEndpoint("/api/modules", [this](auto conn, auto msg) { handleModulesEndpoint(conn, msg); });
52 registerEndpoint("/api/hooks", [this](auto conn, auto msg) { handleHooksEndpoint(conn, msg); });
53 registerEndpoint("/api/assembly", [this](auto conn, auto msg) { handleAssemblyEndpoint(conn, msg); });
54 registerEndpoint("/api/calls", [this](auto conn, auto msg) { handleCallsEndpoint(conn, msg); });
55 registerEndpoint("/api/process", [this](auto conn, auto msg) { handleProcessEndpoint(conn, msg); });
56 registerEndpoint("/api/command", [this](auto conn, auto msg) { handleCommandEndpoint(conn, msg); });
57
58 running = true;
59
60 // Avvia il polling loop in un thread separato
61 std::thread([this]() {
62 while (running) {
63 mg_mgr_poll(&mgr, 1000);
64 cleanupInactiveConnections();
65 }
66 }).detach();
67
68 return true;
69}
70 
71void WebServerManager::stop() {
72 if (!running) return;
73
74 running = false;
75 mg_mgr_free(&mgr);
76
77 {
78 std::lock_guard<std::mutex> lock(connectionsMutex);
79 wsConnections.clear();
80 }
81}
82 
83void WebServerManager::eventHandler(mg_connection* conn, int ev, void* ev_data, void* fn_data) {
84 WebServerManager* self = static_cast<WebServerManager*>(fn_data);
85
86 switch (ev) {
87 case MG_EV_HTTP_MSG: {
88 mg_http_message* msg = static_cast<mg_http_message*>(ev_data);
89 self->handleHttpRequest(conn, msg);
90 break;
91 }
92 case MG_EV_WS_MSG: {
93 mg_ws_message* ws_msg = static_cast<mg_ws_message*>(ev_data);
94 self->handleWebSocket(conn, ws_msg);
95 break;
96 }
97 case MG_EV_CLOSE: {
98 self->cleanupInactiveConnections();
99 break;
100 }
101 }
102}
103 
104void WebServerManager::handleHttpRequest(mg_connection* conn, mg_http_message* msg) {
105 // Gestisci richiesta di upgrade WebSocket
106 if (mg_http_match_uri(msg, "/ws")) {
107 mg_ws_upgrade(conn, msg, nullptr);
108 std::lock_guard<std::mutex> lock(connectionsMutex);
109 wsConnections.push_back(conn);
110 return;
111 }
112
113 // Gestisci richiesta della dashboard
114 if (mg_http_match_uri(msg, "/")) {
115 std::string dashboardPath = "src/WebServer/dashboard/index.html";
116 if (fs::exists(dashboardPath)) {
117 mg_http_serve_file(conn, msg, dashboardPath.c_str(), mg_mk_str("text/html"));
118 } else {
119 mg_http_reply(conn, 404, "Content-Type: text/plain\r\n", "Dashboard non trovata\n");
120 }
121 return;
122 }
123
124 // Trova e esegui l'handler per l'endpoint
125 std::string uri(msg->uri.ptr, msg->uri.len);
126 auto it = endpoints.find(uri);
127 if (it != endpoints.end()) {
128 it->second(conn, msg);
129 } else {
130 // 404 Not Found
131 mg_http_reply(conn, 404, "Content-Type: application/json\r\n",
132 "{\"error\":\"Endpoint not found\"}\n");
133 }
134}
135 
136void WebServerManager::handleWebSocket(mg_connection* conn, mg_ws_message* ws_msg) {
137 // Gestisci messaggi WebSocket (comandi dal client)
138 std::string msg(reinterpret_cast<char*>(ws_msg->data.ptr), ws_msg->data.len);
139 try {
140 json command = json::parse(msg);
141 // Processa il comando e invia risposta
142 json response = {
143 {"status", "success"},
144 {"message", "Command received"}
145 };
146 mg_ws_send(conn, response.dump().c_str(), response.dump().length(), WEBSOCKET_OP_TEXT);
147 } catch (const std::exception& e) {
148 json error = {
149 {"status", "error"},
150 {"message", e.what()}
151 };
152 mg_ws_send(conn, error.dump().c_str(), error.dump().length(), WEBSOCKET_OP_TEXT);
153 }
154}
155 
156void WebServerManager::broadcastEvent(EventType type, const std::string& data) {
157 Event event{type, data, std::chrono::system_clock::now().time_since_epoch().count()};
158 {
159 std::lock_guard<std::mutex> lock(eventQueueMutex);
160 eventQueue.push(event);
161 }
162
163 json eventJson = {
164 {"type", static_cast<int>(type)},
165 {"data", data},
166 {"timestamp", event.timestamp}
167 };
168
169 broadcastToWebSocket(eventJson.dump());
170}
171 
172void WebServerManager::broadcastToWebSocket(const std::string& data) {
173 std::lock_guard<std::mutex> lock(connectionsMutex);
174 for (auto conn : wsConnections) {
175 mg_ws_send(conn, data.c_str(), data.length(), WEBSOCKET_OP_TEXT);
176 }
177}
178 
179void WebServerManager::cleanupInactiveConnections() {
180 std::lock_guard<std::mutex> lock(connectionsMutex);
181 wsConnections.erase(
182 std::remove_if(wsConnections.begin(), wsConnections.end(),
183 [](mg_connection* conn) { return conn->is_closing; }),
184 wsConnections.end());
185}
186 
187// Implementazione degli endpoint predefiniti
188void WebServerManager::handleMemoryEndpoint(mg_connection* conn, mg_http_message* msg) {
189 // Ottieni informazioni sulla memoria
190 PROCESS_MEMORY_COUNTERS_EX pmc;
191 if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) {
192 json response = {
193 {"status", "success"},
194 {"data", {
195 {"workingSetSize", pmc.WorkingSetSize},
196 {"privateUsage", pmc.PrivateUsage},
197 {"regions", getMemoryRegions()}
198 }}
199 };
200 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
201 response.dump().c_str());
202 } else {
203 mg_http_reply(conn, 500, "Content-Type: application/json\r\n",
204 "{\"error\":\"Failed to get memory info\"}\n");
205 }
206}
207 
208void WebServerManager::handleMemoryScanEndpoint(mg_connection* conn, mg_http_message* msg) {
209 if (msg->method.len != 4 || strncmp(msg->method.ptr, "POST", 4) != 0) {
210 mg_http_reply(conn, 405, "Content-Type: application/json\r\n",
211 "{\"error\":\"Method not allowed\"}\n");
212 return;
213 }
214 
215 try {
216 std::string body(msg->body.ptr, msg->body.len);
217 json request = json::parse(body);
218 std::string pattern = request["pattern"];
219 
220 // Esegui la scansione della memoria
221 std::vector<uintptr_t> matches = scanMemoryForPattern(pattern);
222
223 json response = {
224 {"status", "success"},
225 {"data", {
226 {"matches", matches}
227 }}
228 };
229 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
230 response.dump().c_str());
231 } catch (const std::exception& e) {
232 mg_http_reply(conn, 400, "Content-Type: application/json\r\n",
233 "{\"error\":\"Invalid request format\"}\n");
234 }
235}
236 
237void WebServerManager::handleThreadsEndpoint(mg_connection* conn, mg_http_message* msg) {
238 std::vector<ThreadInfo> threads = getThreadsInfo();
239 json response = {
240 {"status", "success"},
241 {"data", threads}
242 };
243 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
244 response.dump().c_str());
245}
246 
247void WebServerManager::handleThreadEndpoint(mg_connection* conn, mg_http_message* msg) {
248 // Estrai l'ID del thread dall'URL
249 std::string uri(msg->uri.ptr, msg->uri.len);
250 size_t pos = uri.find_last_of('/');
251 if (pos == std::string::npos) {
252 mg_http_reply(conn, 400, "Content-Type: application/json\r\n",
253 "{\"error\":\"Invalid thread ID\"}\n");
254 return;
255 }
256 
257 DWORD threadId = std::stoul(uri.substr(pos + 1));
258 ThreadInfo threadInfo = getThreadInfo(threadId);
259
260 json response = {
261 {"status", "success"},
262 {"data", threadInfo}
263 };
264 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
265 response.dump().c_str());
266}
267 
268void WebServerManager::handleModulesEndpoint(mg_connection* conn, mg_http_message* msg) {
269 std::vector<ModuleInfo> modules = getModulesInfo();
270 json response = {
271 {"status", "success"},
272 {"data", modules}
273 };
274 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
275 response.dump().c_str());
276}
277 
278void WebServerManager::handleHooksEndpoint(mg_connection* conn, mg_http_message* msg) {
279 std::vector<HookInfo> hooks = getHooksInfo();
280 json response = {
281 {"status", "success"},
282 {"data", hooks}
283 };
284 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
285 response.dump().c_str());
286}
287 
288void WebServerManager::handleAssemblyEndpoint(mg_connection* conn, mg_http_message* msg) {
289 if (msg->method.len != 4 || strncmp(msg->method.ptr, "POST", 4) != 0) {
290 mg_http_reply(conn, 405, "Content-Type: application/json\r\n",
291 "{\"error\":\"Method not allowed\"}\n");
292 return;
293 }
294 
295 try {
296 std::string body(msg->body.ptr, msg->body.len);
297 json request = json::parse(body);
298 uintptr_t address = std::stoull(request["address"].get<std::string>(), nullptr, 16);
299 
300 // Disassembla il codice
301 std::string assembly = disassembleCode(address);
302
303 json response = {
304 {"status", "success"},
305 {"data", {
306 {"assembly", assembly}
307 }}
308 };
309 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
310 response.dump().c_str());
311 } catch (const std::exception& e) {
312 mg_http_reply(conn, 400, "Content-Type: application/json\r\n",
313 "{\"error\":\"Invalid request format\"}\n");
314 }
315}
316 
317void WebServerManager::handleCallsEndpoint(mg_connection* conn, mg_http_message* msg) {
318 std::vector<CallInfo> calls = getCallsInfo();
319 json response = {
320 {"status", "success"},
321 {"data", calls}
322 };
323 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
324 response.dump().c_str());
325}
326 
327void WebServerManager::handleProcessEndpoint(mg_connection* conn, mg_http_message* msg) {
328 ProcessInfo processInfo = getProcessInfo();
329 json response = {
330 {"status", "success"},
331 {"data", processInfo}
332 };
333 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
334 response.dump().c_str());
335}
336 
337void WebServerManager::handleCommandEndpoint(mg_connection* conn, mg_http_message* msg) {
338 if (msg->method.len != 4 || strncmp(msg->method.ptr, "POST", 4) != 0) {
339 mg_http_reply(conn, 405, "Content-Type: application/json\r\n",
340 "{\"error\":\"Method not allowed\"}\n");
341 return;
342 }
343
344 try {
345 std::string body(msg->body.ptr, msg->body.len);
346 json command = json::parse(body);
347
348 // Processa il comando
349 json response = {
350 {"status", "success"},
351 {"message", "Command executed successfully"}
352 };
353 mg_http_reply(conn, 200, "Content-Type: application/json\r\n",
354 response.dump().c_str());
355 } catch (const std::exception& e) {
356 mg_http_reply(conn, 400, "Content-Type: application/json\r\n",
357 "{\"error\":\"Invalid command format\"}\n");
358 }
359}
360 
361// Funzioni helper esposte
362bool StartWebServer(int port) {
363 return WebServerManager::getInstance().start(port);
364}
365 
366void StopWebServer() {
367 WebServerManager::getInstance().stop();
368}
369 
370void BroadcastEvent(const std::string& event) {
371 WebServerManager::getInstance().broadcastEvent(EventType::PROCESS_INFO, event);
372}
373 
374// Funzione di utilità per sostituire mg_http_match_uri
375bool SimpleHttpMatch(mg_http_message* msg, const char* pattern) {
376 if (!msg || !pattern) return false;
377
378 std::string uri(msg->uri.ptr, msg->uri.len);
379 return uri == pattern;
380}
381 
382} // namespace DyMain::WebServer