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/ui/UIManager.cpp
Hermes / DyForge / src / ui / UIManager.cpp
1#include "../../include/DyForge.h"
2#include <stdexcept>
3#include <sstream>
4#include <windowsx.h>
5#include <commctrl.h>
6#include <shlwapi.h>
7#include <commdlg.h>
8#include <tlhelp32.h>
9#include <psapi.h>
10 
11#pragma comment(lib, "comctl32.lib")
12#pragma comment(lib, "shlwapi.lib")
13#pragma comment(lib, "comdlg32.lib")
14#pragma comment(lib, "psapi.lib")
15 
16namespace DyForge {
17 
18// Constants
19const wchar_t* UIManager::WINDOW_CLASS_NAME = L"DyForgeMainWindow";
20const int UIManager::WINDOW_WIDTH = 800;
21const int UIManager::WINDOW_HEIGHT = 600;
22 
23// Control IDs
24enum {
25 IDC_PROCESS_LIST = 1001,
26 IDC_INJECT_BUTTON = 1002,
27 IDC_START_ANALYSIS_BUTTON = 1003,
28 IDC_STOP_ANALYSIS_BUTTON = 1004,
29 IDC_GENERATE_REPORT_BUTTON = 1005,
30 IDC_EXPORT_DATA_BUTTON = 1006,
31 IDC_STATUS_BAR = 1007
32};
33 
34// Constructor
35UIManager::UIManager(DyForge& dyForge)
36 : m_dyForge(dyForge)
37 , m_windowVisible(false)
38 , m_hwnd(NULL)
39 , m_hwndProcessList(NULL)
40 , m_hwndInjectButton(NULL)
41 , m_hwndStartAnalysisButton(NULL)
42 , m_hwndStopAnalysisButton(NULL)
43 , m_hwndGenerateReportButton(NULL)
44 , m_hwndExportDataButton(NULL)
45 , m_hwndStatusBar(NULL) {
46}
47 
48// Destructor
49UIManager::~UIManager() {
50 if (m_windowVisible) {
51 HideMainWindow();
52 }
53}
54 
55// UI management
56bool UIManager::ShowMainWindow() {
57 if (m_windowVisible) {
58 return true;
59 }
60
61 // Register window class
62 WNDCLASSEXW wc = {};
63 wc.cbSize = sizeof(WNDCLASSEXW);
64 wc.lpfnWndProc = WindowProc;
65 wc.hInstance = GetModuleHandle(NULL);
66 wc.lpszClassName = WINDOW_CLASS_NAME;
67 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
68 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
69
70 if (!RegisterClassExW(&wc)) {
71 throw std::runtime_error("Failed to register window class");
72 }
73
74 // Create main window
75 m_hwnd = CreateWindowExW(
76 0,
77 WINDOW_CLASS_NAME,
78 L"DyForge - Dynamic Process Sculptor",
79 WS_OVERLAPPEDWINDOW,
80 CW_USEDEFAULT,
81 CW_USEDEFAULT,
82 WINDOW_WIDTH,
83 WINDOW_HEIGHT,
84 NULL,
85 NULL,
86 GetModuleHandle(NULL),
87 this
88 );
89
90 if (!m_hwnd) {
91 throw std::runtime_error("Failed to create main window");
92 }
93
94 // Initialize common controls
95 INITCOMMONCONTROLSEX icex = {};
96 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
97 icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES;
98 InitCommonControlsEx(&icex);
99
100 // Create controls
101 CreateControls();
102
103 // Show window
104 ShowWindow(m_hwnd, SW_SHOW);
105 UpdateWindow(m_hwnd);
106
107 m_windowVisible = true;
108 return true;
109}
110 
111bool UIManager::HideMainWindow() {
112 if (!m_windowVisible) {
113 return true;
114 }
115
116 if (m_hwnd) {
117 DestroyWindow(m_hwnd);
118 m_hwnd = NULL;
119 }
120
121 m_windowVisible = false;
122 return true;
123}
124 
125bool UIManager::IsMainWindowVisible() const {
126 return m_windowVisible;
127}
128 
129// Private methods
130void UIManager::CreateControls() {
131 // Create process list
132 m_hwndProcessList = CreateWindowExW(
133 0,
134 WC_LISTVIEWW,
135 L"",
136 WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL,
137 10,
138 10,
139 WINDOW_WIDTH - 20,
140 200,
141 m_hwnd,
142 (HMENU)IDC_PROCESS_LIST,
143 GetModuleHandle(NULL),
144 NULL
145 );
146
147 // Add columns to process list
148 LVCOLUMNW lvc = {};
149 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
150
151 lvc.pszText = (LPWSTR)L"PID";
152 lvc.cx = 80;
153 ListView_InsertColumn(m_hwndProcessList, 0, &lvc);
154
155 lvc.pszText = (LPWSTR)L"Name";
156 lvc.cx = 200;
157 ListView_InsertColumn(m_hwndProcessList, 1, &lvc);
158
159 lvc.pszText = (LPWSTR)L"Path";
160 lvc.cx = 300;
161 ListView_InsertColumn(m_hwndProcessList, 2, &lvc);
162
163 // Create buttons
164 m_hwndInjectButton = CreateWindowExW(
165 0,
166 L"BUTTON",
167 L"Inject DLL",
168 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
169 10,
170 220,
171 120,
172 30,
173 m_hwnd,
174 (HMENU)IDC_INJECT_BUTTON,
175 GetModuleHandle(NULL),
176 NULL
177 );
178
179 m_hwndStartAnalysisButton = CreateWindowExW(
180 0,
181 L"BUTTON",
182 L"Start Analysis",
183 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
184 140,
185 220,
186 120,
187 30,
188 m_hwnd,
189 (HMENU)IDC_START_ANALYSIS_BUTTON,
190 GetModuleHandle(NULL),
191 NULL
192 );
193
194 m_hwndStopAnalysisButton = CreateWindowExW(
195 0,
196 L"BUTTON",
197 L"Stop Analysis",
198 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
199 270,
200 220,
201 120,
202 30,
203 m_hwnd,
204 (HMENU)IDC_STOP_ANALYSIS_BUTTON,
205 GetModuleHandle(NULL),
206 NULL
207 );
208
209 m_hwndGenerateReportButton = CreateWindowExW(
210 0,
211 L"BUTTON",
212 L"Generate Report",
213 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
214 400,
215 220,
216 120,
217 30,
218 m_hwnd,
219 (HMENU)IDC_GENERATE_REPORT_BUTTON,
220 GetModuleHandle(NULL),
221 NULL
222 );
223
224 m_hwndExportDataButton = CreateWindowExW(
225 0,
226 L"BUTTON",
227 L"Export Data",
228 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
229 530,
230 220,
231 120,
232 30,
233 m_hwnd,
234 (HMENU)IDC_EXPORT_DATA_BUTTON,
235 GetModuleHandle(NULL),
236 NULL
237 );
238
239 // Create status bar
240 m_hwndStatusBar = CreateWindowExW(
241 0,
242 STATUSCLASSNAMEW,
243 NULL,
244 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
245 0,
246 0,
247 0,
248 0,
249 m_hwnd,
250 (HMENU)IDC_STATUS_BAR,
251 GetModuleHandle(NULL),
252 NULL
253 );
254
255 // Set status bar text
256 ShowStatus(L"Ready");
257
258 // Update button states
259 UpdateButtonStates();
260
261 // Update process list
262 UpdateProcessList();
263}
264 
265void UIManager::UpdateProcessList() {
266 // Clear existing items
267 ListView_DeleteAllItems(m_hwndProcessList);
268
269 // Get process list
270 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
271 if (hSnapshot == INVALID_HANDLE_VALUE) {
272 ShowError(L"Failed to create process snapshot");
273 return;
274 }
275
276 PROCESSENTRY32W pe32;
277 pe32.dwSize = sizeof(pe32);
278
279 if (Process32FirstW(hSnapshot, &pe32)) {
280 do {
281 // Add process to list
282 LVITEMW lvi = {};
283 lvi.mask = LVIF_TEXT;
284
285 // PID
286 wchar_t pidStr[16];
287 swprintf_s(pidStr, L"%lu", pe32.th32ProcessID);
288 lvi.iItem = ListView_GetItemCount(m_hwndProcessList);
289 lvi.iSubItem = 0;
290 lvi.pszText = pidStr;
291 ListView_InsertItem(m_hwndProcessList, &lvi);
292
293 // Name
294 lvi.iSubItem = 1;
295 lvi.pszText = pe32.szExeFile;
296 ListView_SetItem(m_hwndProcessList, &lvi);
297
298 // Path
299 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
300 if (hProcess) {
301 wchar_t path[MAX_PATH];
302 if (GetModuleFileNameExW(hProcess, NULL, path, MAX_PATH)) {
303 lvi.iSubItem = 2;
304 lvi.pszText = path;
305 ListView_SetItem(m_hwndProcessList, &lvi);
306 }
307 CloseHandle(hProcess);
308 }
309 } while (Process32NextW(hSnapshot, &pe32));
310 }
311
312 CloseHandle(hSnapshot);
313}
314 
315void UIManager::UpdateButtonStates() {
316 bool processOpen = m_dyForge.IsProcessOpen();
317 bool dllInjected = m_dyForge.IsDllInjected();
318 bool analysisRunning = m_dyForge.IsAnalysisRunning();
319
320 EnableWindow(m_hwndInjectButton, processOpen && !dllInjected);
321 EnableWindow(m_hwndStartAnalysisButton, dllInjected && !analysisRunning);
322 EnableWindow(m_hwndStopAnalysisButton, analysisRunning);
323 EnableWindow(m_hwndGenerateReportButton, analysisRunning);
324 EnableWindow(m_hwndExportDataButton, analysisRunning);
325}
326 
327void UIManager::ShowError(const std::wstring& message) {
328 MessageBoxW(m_hwnd, message.c_str(), L"Error", MB_ICONERROR | MB_OK);
329}
330 
331void UIManager::ShowStatus(const std::wstring& message) {
332 SendMessageW(m_hwndStatusBar, SB_SETTEXT, 0, (LPARAM)message.c_str());
333}
334 
335// File dialogs
336std::wstring UIManager::ShowOpenDllDialog() {
337 wchar_t filename[MAX_PATH] = L"";
338
339 OPENFILENAMEW ofn = {};
340 ofn.lStructSize = sizeof(ofn);
341 ofn.hwndOwner = m_hwnd;
342 ofn.lpstrFilter = L"DLL Files\0*.dll\0All Files\0*.*\0";
343 ofn.lpstrFile = filename;
344 ofn.nMaxFile = MAX_PATH;
345 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
346 ofn.lpstrDefExt = L"dll";
347
348 if (GetOpenFileNameW(&ofn)) {
349 return filename;
350 }
351
352 return L"";
353}
354 
355std::wstring UIManager::ShowSaveReportDialog() {
356 wchar_t filename[MAX_PATH] = L"";
357
358 OPENFILENAMEW ofn = {};
359 ofn.lStructSize = sizeof(ofn);
360 ofn.hwndOwner = m_hwnd;
361 ofn.lpstrFilter = L"Text Files\0*.txt\0All Files\0*.*\0";
362 ofn.lpstrFile = filename;
363 ofn.nMaxFile = MAX_PATH;
364 ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
365 ofn.lpstrDefExt = L"txt";
366
367 if (GetSaveFileNameW(&ofn)) {
368 return filename;
369 }
370
371 return L"";
372}
373 
374std::wstring UIManager::ShowSaveExportDialog() {
375 wchar_t filename[MAX_PATH] = L"";
376
377 OPENFILENAMEW ofn = {};
378 ofn.lStructSize = sizeof(ofn);
379 ofn.hwndOwner = m_hwnd;
380 ofn.lpstrFilter = L"JSON Files\0*.json\0CSV Files\0*.csv\0All Files\0*.*\0";
381 ofn.lpstrFile = filename;
382 ofn.nMaxFile = MAX_PATH;
383 ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
384 ofn.lpstrDefExt = L"json";
385
386 if (GetSaveFileNameW(&ofn)) {
387 return filename;
388 }
389
390 return L"";
391}
392 
393// Event handlers
394void UIManager::OnProcessSelected() {
395 int selectedIndex = ListView_GetNextItem(m_hwndProcessList, -1, LVNI_SELECTED);
396 if (selectedIndex >= 0) {
397 wchar_t pidStr[16];
398 LVITEMW lvi = {};
399 lvi.mask = LVIF_TEXT;
400 lvi.iItem = selectedIndex;
401 lvi.iSubItem = 0;
402 lvi.pszText = pidStr;
403 lvi.cchTextMax = sizeof(pidStr) / sizeof(wchar_t);
404
405 if (ListView_GetItem(m_hwndProcessList, &lvi)) {
406 DWORD processId = _wtoi(pidStr);
407 if (m_dyForge.OpenProcess(processId)) {
408 ShowStatus(L"Process opened successfully");
409 UpdateButtonStates();
410 }
411 else {
412 ShowError(L"Failed to open process");
413 }
414 }
415 }
416}
417 
418void UIManager::OnInjectDll() {
419 std::wstring dllPath = ShowOpenDllDialog();
420 if (!dllPath.empty()) {
421 if (m_dyForge.InjectDll(dllPath)) {
422 ShowStatus(L"DLL injected successfully");
423 UpdateButtonStates();
424 }
425 else {
426 ShowError(L"Failed to inject DLL");
427 }
428 }
429}
430 
431void UIManager::OnStartAnalysis() {
432 if (m_dyForge.StartAnalysis()) {
433 ShowStatus(L"Analysis started");
434 UpdateButtonStates();
435 }
436 else {
437 ShowError(L"Failed to start analysis");
438 }
439}
440 
441void UIManager::OnStopAnalysis() {
442 if (m_dyForge.StopAnalysis()) {
443 ShowStatus(L"Analysis stopped");
444 UpdateButtonStates();
445 }
446 else {
447 ShowError(L"Failed to stop analysis");
448 }
449}
450 
451void UIManager::OnGenerateReport() {
452 std::wstring outputPath = ShowSaveReportDialog();
453 if (!outputPath.empty()) {
454 if (m_dyForge.GenerateReport(outputPath)) {
455 ShowStatus(L"Report generated successfully");
456 }
457 else {
458 ShowError(L"Failed to generate report");
459 }
460 }
461}
462 
463void UIManager::OnExportData() {
464 std::wstring outputPath = ShowSaveExportDialog();
465 if (!outputPath.empty()) {
466 std::wstring format = L"json";
467 if (outputPath.length() >= 4 && outputPath.substr(outputPath.length() - 4) == L".csv") {
468 format = L"csv";
469 }
470
471 if (m_dyForge.ExportData(format, outputPath)) {
472 ShowStatus(L"Data exported successfully");
473 }
474 else {
475 ShowError(L"Failed to export data");
476 }
477 }
478}
479 
480// Window procedure
481LRESULT CALLBACK UIManager::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
482 UIManager* uiManager = NULL;
483
484 if (uMsg == WM_NCCREATE) {
485 CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
486 uiManager = (UIManager*)pCreate->lpCreateParams;
487 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)uiManager);
488 }
489 else {
490 uiManager = (UIManager*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
491 }
492
493 if (uiManager) {
494 return uiManager->HandleMessage(hwnd, uMsg, wParam, lParam);
495 }
496
497 return DefWindowProc(hwnd, uMsg, wParam, lParam);
498}
499 
500LRESULT UIManager::HandleMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
501 switch (uMsg) {
502 case WM_COMMAND:
503 return HandleCommand(LOWORD(wParam));
504
505 case WM_NOTIFY:
506 return HandleNotify((LPNMHDR)lParam);
507
508 case WM_SIZE:
509 return HandleSize(LOWORD(lParam), HIWORD(lParam));
510
511 case WM_DESTROY:
512 PostQuitMessage(0);
513 return 0;
514 }
515
516 return DefWindowProc(hwnd, uMsg, wParam, lParam);
517}
518 
519LRESULT UIManager::HandleCommand(int id) {
520 switch (id) {
521 case IDC_INJECT_BUTTON:
522 OnInjectDll();
523 return 0;
524
525 case IDC_START_ANALYSIS_BUTTON:
526 OnStartAnalysis();
527 return 0;
528
529 case IDC_STOP_ANALYSIS_BUTTON:
530 OnStopAnalysis();
531 return 0;
532
533 case IDC_GENERATE_REPORT_BUTTON:
534 OnGenerateReport();
535 return 0;
536
537 case IDC_EXPORT_DATA_BUTTON:
538 OnExportData();
539 return 0;
540 }
541
542 return 0;
543}
544 
545LRESULT UIManager::HandleNotify(LPNMHDR pnmh) {
546 switch (pnmh->code) {
547 case LVN_ITEMCHANGED:
548 OnProcessSelected();
549 return 0;
550 }
551
552 return 0;
553}
554 
555LRESULT UIManager::HandleSize(int width, int height) {
556 // Resize status bar
557 SendMessage(m_hwndStatusBar, WM_SIZE, 0, 0);
558
559 // Resize process list
560 SetWindowPos(
561 m_hwndProcessList,
562 NULL,
563 10,
564 10,
565 width - 20,
566 200,
567 SWP_NOZORDER
568 );
569
570 // Reposition buttons
571 SetWindowPos(
572 m_hwndInjectButton,
573 NULL,
574 10,
575 220,
576 120,
577 30,
578 SWP_NOZORDER
579 );
580
581 SetWindowPos(
582 m_hwndStartAnalysisButton,
583 NULL,
584 140,
585 220,
586 120,
587 30,
588 SWP_NOZORDER
589 );
590
591 SetWindowPos(
592 m_hwndStopAnalysisButton,
593 NULL,
594 270,
595 220,
596 120,
597 30,
598 SWP_NOZORDER
599 );
600
601 SetWindowPos(
602 m_hwndGenerateReportButton,
603 NULL,
604 400,
605 220,
606 120,
607 30,
608 SWP_NOZORDER
609 );
610
611 SetWindowPos(
612 m_hwndExportDataButton,
613 NULL,
614 530,
615 220,
616 120,
617 30,
618 SWP_NOZORDER
619 );
620
621 return 0;
622}
623 
624} // namespace DyForge