· 10 months ago · Nov 27, 2024, 09:45 AM
1==++ Here's the full source code for (file 1/1) "main.cpp":: ++==
2#define STRICT
3#define WIN32_LEAN_AND_MEAN
4#include <Windows.h>
5#include <winternl.h>
6#include <CommCtrl.h>
7#include <commdlg.h>
8#include <string>
9#include <strsafe.h>
10#include <sstream>
11#include <iomanip>
12#include <stdio.h>
13#include <vector>
14//#include "helpers.h"
15#include "resource.h"
16#pragma comment(lib, "comctl32.lib")
17
18namespace PEHelpers {
19 std::wstring GetImageCharacteristics(DWORD characteristics) {
20 if (characteristics & IMAGE_FILE_DLL) return L"(DLL)";
21 if (characteristics & IMAGE_FILE_SYSTEM) return L"(DRIVER)";
22 if (characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) return L"(EXE)";
23 return L"(UNKNOWN)";
24 }
25
26 std::wstring GetSubsystem(WORD subsystem) {
27 switch (subsystem) {
28 case IMAGE_SUBSYSTEM_NATIVE: return L"(NATIVE/DRIVER)";
29 case IMAGE_SUBSYSTEM_WINDOWS_GUI: return L"(GUI)";
30 case IMAGE_SUBSYSTEM_WINDOWS_CUI: return L"(CONSOLE)";
31 default: return L"(UNKNOWN)";
32 }
33 }
34
35 std::wstring GetDataDirectoryName(int DirectoryNumber) {
36 switch (DirectoryNumber) {
37 case 0: return L"Export Table";
38 case 1: return L"Import Table";
39 case 2: return L"Resource Table";
40 case 3: return L"Exception Entry";
41 case 4: return L"Security Entry";
42 case 5: return L"Relocation Table";
43 case 6: return L"Debug Entry";
44 case 7: return L"Copyright Entry";
45 case 8: return L"Global PTR Entry";
46 case 9: return L"TLS Entry";
47 case 10: return L"Configuration Entry";
48 case 11: return L"Bound Import Entry";
49 case 12: return L"IAT";
50 case 13: return L"Delay Import Descriptor";
51 case 14: return L"COM Descriptor";
52 default: return L"Unknown";
53 }
54 }
55
56 std::wstring GetSectionProtection(DWORD characteristics) {
57 std::wstring protection = L"(";
58 bool needsSeparator = false;
59
60 if (characteristics & IMAGE_SCN_MEM_EXECUTE) {
61 protection += L"EXECUTE";
62 needsSeparator = true;
63 }
64
65 if (characteristics & IMAGE_SCN_MEM_READ) {
66 if (needsSeparator) protection += L" | ";
67 protection += L"READ";
68 needsSeparator = true;
69 }
70
71 if (characteristics & IMAGE_SCN_MEM_WRITE) {
72 if (needsSeparator) protection += L" | ";
73 protection += L"WRITE";
74 }
75
76 protection += L")";
77 return protection;
78 }
79}
80
81using namespace std;
82
83// At the top of your file, change the window class name to wide string
84#define WINDOW_CLASS_NAME L"PEAnalyzerWindow"
85//const wchar_t* const WINDOW_CLASS_NAME = L"PEAnalyzerWindow";
86
87// Use ANSI versions explicitly
88//#undef CreateWindow
89//#undef CreateWindowEx
90//#define CreateWindow CreateWindowW
91//#define CreateWindowEx CreateWindowExW
92
93// Helper function to replace printf with GUI output
94#define OUTPUT(format, ...) AppendToOutput(L##format, ##__VA_ARGS__)
95//#define OUTPUT(format, ...) AppendToOutput(format, ##__VA_ARGS__)
96//#define printf(format, ...) AppendToOutput(format, ##__VA_ARGS__)
97
98// Window dimensions
99#define WINDOW_WIDTH 1024
100#define WINDOW_HEIGHT 768
101#define EDIT_MARGIN 10
102
103// Global variables
104HWND g_hMainWindow = NULL;
105HWND g_hEditControl = NULL;
106HFONT g_hFont = NULL;
107std::wstringstream g_OutputText;
108WCHAR filePathW[MAX_PATH];
109std::vector<wchar_t> g_OutputBuffer;
110std::wstring tempBuffer; // Declare tempBuffer globally
111
112// Function declarations
113LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
114LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
115void CreateMainWindow(HINSTANCE hInstance);
116void InitializeControls(HWND hwnd);
117void AddMenus(HWND hwnd);
118void OpenFileDialog(HWND hwnd);
119//void AnalyzePEFile(const WCHAR* filePathW);
120void AnalyzePEFile(const wchar_t* filePathW);
121HANDLE GetFileContent(const wchar_t* lpFilePath);
122/*void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory);
123PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
124 int NumberOfSections, DWORD dImportAddress);
125void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
126 DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);
127void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
128 DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);*/
129void AppendToOutput(const wchar_t* format, ...);
130void UpdateEditControl();
131
132// Main window class name
133//const char* const WINDOW_CLASS_NAME = "PEAnalyzerWindow";
134
135int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
136 INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
137 InitCommonControlsEx(&icc);
138
139 CreateMainWindow(hInstance);
140 if (!g_hMainWindow) return -1;
141
142 ShowWindow(g_hMainWindow, nCmdShow);
143 UpdateWindow(g_hMainWindow);
144
145 MSG msg = {};
146 while (GetMessage(&msg, NULL, 0, 0)) {
147 TranslateMessage(&msg);
148 DispatchMessage(&msg);
149 }
150
151 if (g_hFont) DeleteObject(g_hFont);
152 return (int)msg.wParam;
153}
154
155void CreateMainWindow(HINSTANCE hInstance) {
156 WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), 0, WindowProc, 0, 0, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, WINDOW_CLASS_NAME, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)) };
157 RegisterClassExW(&wc);
158
159 // Get screen dimensions
160 int screenWidth = GetSystemMetrics(SM_CXSCREEN);
161 int screenHeight = GetSystemMetrics(SM_CYSCREEN);
162
163 // Calculate center position
164 int windowX = (screenWidth - WINDOW_WIDTH) / 2;
165 int windowY = (screenHeight - WINDOW_HEIGHT) / 2;
166
167 // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
168 DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
169 //WS_OVERLAPPEDWINDOW ~~> style
170 g_hMainWindow = CreateWindowExW(0, WINDOW_CLASS_NAME, L"PE File Analyzer", style, windowX, windowY, WINDOW_WIDTH, WINDOW_HEIGHT, nullptr, nullptr, hInstance, nullptr);
171}
172
173void InitializeControls(HWND hwnd) {
174 g_hEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
175 WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
176 EDIT_MARGIN, EDIT_MARGIN,
177 WINDOW_WIDTH - (2 * EDIT_MARGIN), WINDOW_HEIGHT - (2 * EDIT_MARGIN),
178 hwnd, nullptr,
179 (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), nullptr);
180
181 g_hFont = CreateFont(-14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
182 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
183 DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, L"Consolas");
184
185 if (g_hFont)
186 SendMessage(g_hEditControl, WM_SETFONT, (WPARAM)g_hFont, TRUE);
187
188 // Add this line to subclass the Edit control
189 SetWindowSubclass(g_hEditControl, EditSubclassProc, 0, 0);
190}
191
192void AddMenus(HWND hwnd) {
193 HMENU hMenuBar = CreateMenu();
194 HMENU hFileMenu = CreateMenu();
195 AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
196 AppendMenu(hFileMenu, MF_STRING, 1, L"&Open");
197 AppendMenu(hFileMenu, MF_STRING, 2, L"E&xit");
198 SetMenu(hwnd, hMenuBar);
199}
200
201LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
202 if (uMsg == WM_KEYDOWN) {
203 switch (wParam) {
204 case VK_F1: // F1 key
205 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
206 return 0;
207 case VK_ESCAPE: // Escape key
208 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
209 return 0;
210 }
211 }
212 return DefSubclassProc(hwnd, uMsg, wParam, lParam);
213}
214
215LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
216 switch (uMsg) {
217 case WM_CREATE: InitializeControls(hwnd); AddMenus(hwnd); return 0;
218 case WM_SIZE: SetWindowPos(g_hEditControl, NULL, EDIT_MARGIN, EDIT_MARGIN, LOWORD(lParam) - (2 * EDIT_MARGIN), HIWORD(lParam) - (2 * EDIT_MARGIN), SWP_NOZORDER); return 0;
219 case WM_KEYDOWN:
220 switch (wParam) {
221 case VK_F1:
222 MessageBoxW(hwnd,
223 L"PE Header Parser 2.3 GUI-based Programmed in C++ Win32 API (1173 lines of code) by Entisoft Software(c) Evans Thorpemorton",
224 L"About",
225 MB_OK | MB_ICONINFORMATION);
226 return 0;
227
228 case VK_ESCAPE:
229 PostQuitMessage(0);
230 return 0;
231 }
232 break;
233 case WM_COMMAND: if (LOWORD(wParam) == 1) OpenFileDialog(hwnd); if (LOWORD(wParam) == 2) PostQuitMessage(0); return 0;
234 case WM_DESTROY: PostQuitMessage(0); return 0;
235 }
236 return DefWindowProc(hwnd, uMsg, wParam, lParam);
237}
238
239void OpenFileDialog(HWND hwnd) {
240 WCHAR fileName[MAX_PATH] = L"";
241 OPENFILENAMEW ofn = { sizeof(OPENFILENAMEW), hwnd, NULL, L"Executable Files (*.exe;*.dll)\0*.exe;*.dll\0All Files (*.*)\0*.*\0", NULL, 0, 1, fileName, MAX_PATH, NULL, 0, NULL, NULL, OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, 0, 0, L"exe", NULL, NULL, NULL };
242 if (GetOpenFileNameW(&ofn)) {
243 SetWindowTextW(g_hEditControl, L"");
244 g_OutputText.str(L"");
245 g_OutputText.clear();
246 AnalyzePEFile(ofn.lpstrFile);
247 UpdateEditControl();
248 }
249}
250
251class FileMapper {
252private:
253 HANDLE hFile = INVALID_HANDLE_VALUE;
254 HANDLE hMapping = nullptr;
255 LPVOID lpView = nullptr;
256
257public:
258 ~FileMapper() {
259 if (lpView) UnmapViewOfFile(lpView);
260 if (hMapping) CloseHandle(hMapping);
261 if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
262 }
263
264 bool Initialize(const wchar_t* path) {
265 hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr,
266 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
267 if (hFile == INVALID_HANDLE_VALUE) return false;
268
269 hMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
270 if (!hMapping) return false;
271
272 lpView = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
273 return lpView != nullptr;
274 }
275
276 LPVOID GetView() const { return lpView; }
277};
278
279// Modified AppendToOutput to handle newlines properly:
280void AppendToOutput(const wchar_t* format, ...) {
281 std::vector<wchar_t> buffer(1024);
282 va_list args;
283 va_start(args, format);
284
285 while (true) {
286 int result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
287 if (result >= 0) break;
288 buffer.resize(buffer.size() * 2);
289 }
290 va_end(args);
291
292 // Convert \n to \r\n
293 std::wstring output = buffer.data();
294 size_t pos = 0;
295 while ((pos = output.find(L'\n', pos)) != std::wstring::npos) {
296 if (pos == 0 || output[pos - 1] != L'\r') {
297 output.insert(pos, L"\r");
298 pos += 2;
299 }
300 else {
301 pos++;
302 }
303 }
304
305 g_OutputText << output;
306 UpdateEditControl();
307}
308
309/*
310void AppendToOutput(const wchar_t* format, ...) {
311 wchar_t buffer[16384]; // Ensure sufficient buffer size
312 va_list args;
313 va_start(args, format);
314 StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
315 va_end(args);
316
317 tempBuffer += buffer;
318
319 // Update Edit Control periodically to improve performance
320 if (tempBuffer.size() > 8000) {
321 g_OutputText << tempBuffer;
322 tempBuffer.clear();
323
324 SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
325 SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
326 SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
327 }
328}
329
330
331// Final update to flush any remaining content
332void FlushOutput() {
333 if (!tempBuffer.empty()) {
334 g_OutputText << tempBuffer;
335 tempBuffer.clear();
336
337 SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
338 SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
339 SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
340 }
341}
342*/
343
344
345/*
346//use below ^^ ALWAYS
347void AppendToOutput(const wchar_t* format, ...) {
348 va_list args;
349 va_start(args, format);
350
351 // Use a vector as a dynamically resizable buffer
352 std::vector<wchar_t> buffer(16384); // Start with an initial size
353 int result = -1;
354
355 while (true) {
356 // Attempt to format the string
357 result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
358
359 if (result >= 0 && static_cast<size_t>(result) < buffer.size()) {
360 // Successfully formatted within the current buffer size
361 break;
362 }
363
364 // Resize the buffer and try again
365 buffer.resize(buffer.size() * 2);
366 }
367 va_end(args);
368
369 // Convert `\n` to `\r\n` for proper display in the EditBox
370 std::wstring formattedOutput(buffer.data());
371 size_t pos = 0;
372 while ((pos = formattedOutput.find(L'\n', pos)) != std::wstring::npos) {
373 formattedOutput.replace(pos, 1, L"\r\n");
374 pos += 2; // Move past the replacement
375 }
376
377 // Append to the global output buffer
378 g_OutputText << formattedOutput;
379
380 // Update the EditBox periodically to prevent overloading
381 if (g_OutputText.str().size() > 8000) {
382 SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
383 SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
384 SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
385 }
386}
387//use above ^^ ALWAYS
388*/
389
390//currentlatest
391/*void AppendToOutput(const wchar_t* format, ...) {
392 wchar_t buffer[4096];
393 va_list args;
394 va_start(args, format);
395 StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
396 va_end(args);
397 g_OutputText << buffer;
398 SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
399 SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
400 SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
401}
402*/
403
404//use-below-basic-failsafe-working vv
405//basic test function
406/*void AnalyzePEFile(const wchar_t* filePathW) {
407 OUTPUT("[+] Analyzing file: %s\n", filePathW);
408 LPVOID lpFileContent = GetFileContent(filePathW);
409 if (!lpFileContent) { OUTPUT("[-] Could not read file.\n"); return; }
410 PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileContent;
411 if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { OUTPUT("[-] Invalid DOS signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
412 PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpFileContent + dosHeader->e_lfanew);
413 if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { OUTPUT("[-] Invalid NT signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
414 OUTPUT("[+] PE file analyzed successfully.\n");
415 HeapFree(GetProcessHeap(), 0, lpFileContent);
416 UpdateEditControl();
417}*/
418//use-above-basic-failsafe-working vv
419
420//use vectors for unlimited size growth of buffer, use an alternative to editbox, check for fast loops overloading, in its primitive form it works properly! try w/o getimports3264 datadirectories getsections
421
422void AnalyzePEFile(const wchar_t* filePathW) {
423 OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
424
425 FileMapper mapper;
426 if (!mapper.Initialize(filePathW)) {
427 OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
428 return;
429 }
430
431
432 // Open and read file
433 HANDLE hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
434 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
435 if (hFile == INVALID_HANDLE_VALUE) {
436 OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
437 return;
438 }
439
440 DWORD fileSize = GetFileSize(hFile, nullptr);
441 if (fileSize == INVALID_FILE_SIZE) {
442 CloseHandle(hFile);
443 OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
444 return;
445 }
446
447 HANDLE hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
448 if (!hFileMapping) {
449 CloseHandle(hFile);
450 OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
451 return;
452 }
453
454 LPVOID lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
455 if (!lpFileContent) {
456 CloseHandle(hFileMapping);
457 CloseHandle(hFile);
458 OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
459 return;
460 }
461
462 const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
463 if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
464 OUTPUT("[-] Invalid DOS signature!\r\n");
465 return;
466 }
467
468 const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
469 static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
470 if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
471 OUTPUT("[-] Invalid NT signature!\r\n");
472 return;
473 }
474
475 // Print File Header Information
476 OUTPUT("[+] PE FILE HEADER\n");
477 OUTPUT("\tMachine: 0x%X\n", pImageNtHeaders->FileHeader.Machine);
478 OUTPUT("\tNumberOfSections: 0x%X\n", pImageNtHeaders->FileHeader.NumberOfSections);
479 OUTPUT("\tTimeDateStamp: 0x%X\n", pImageNtHeaders->FileHeader.TimeDateStamp);
480 OUTPUT("\tPointerToSymbolTable: 0x%X\r\n",
481 static_cast<DWORD>(pImageNtHeaders->FileHeader.PointerToSymbolTable));
482 OUTPUT("\tNumberOfSymbols: 0x%X\r\n",
483 static_cast<DWORD>(pImageNtHeaders->FileHeader.NumberOfSymbols));
484 OUTPUT("\tSizeOfOptionalHeader: 0x%X\r\n",
485 static_cast<DWORD>(pImageNtHeaders->FileHeader.SizeOfOptionalHeader));
486 OUTPUT("\tCharacteristics: 0x%X %s\n\n",
487 pImageNtHeaders->FileHeader.Characteristics,
488 PEHelpers::GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics).c_str());
489
490 // Print Optional Header Information
491 OUTPUT("[+] PE OPTIONAL HEADER\n");
492 OUTPUT("\tMagic: 0x%X\n", pImageNtHeaders->OptionalHeader.Magic);
493 OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
494 OUTPUT("\tImageBase: 0x%llX\n", (ULONGLONG)pImageNtHeaders->OptionalHeader.ImageBase);
495 OUTPUT("\tSectionAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.SectionAlignment);
496 OUTPUT("\tFileAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.FileAlignment);
497
498 // Added missing Optional Header fields
499 OUTPUT("\tMajorOperatingSystemVersion: 0x%X\r\n",
500 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion));
501 OUTPUT("\tMinorOperatingSystemVersion: 0x%X\r\n",
502 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion));
503 OUTPUT("\tMajorImageVersion: 0x%X\r\n",
504 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorImageVersion));
505 OUTPUT("\tMinorImageVersion: 0x%X\r\n",
506 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorImageVersion));
507 OUTPUT("\tMajorSubsystemVersion: 0x%X\r\n",
508 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorSubsystemVersion));
509 OUTPUT("\tMinorSubsystemVersion: 0x%X\r\n",
510 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorSubsystemVersion));
511 OUTPUT("\tWin32VersionValue: 0x%X\r\n",
512 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Win32VersionValue));
513 OUTPUT("\tSizeOfImage: 0x%X\r\n",
514 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfImage));
515 OUTPUT("\tSizeOfHeaders: 0x%X\r\n",
516 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfHeaders));
517 OUTPUT("\tCheckSum: 0x%X\r\n",
518 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.CheckSum));
519 OUTPUT("\tSubsystem: 0x%X %s\r\n",
520 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Subsystem),
521 PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
522 OUTPUT("\tDllCharacteristics: 0x%X\r\n",
523 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.DllCharacteristics));
524 OUTPUT("\tSizeOfStackReserve: 0x%llX\r\n",
525 static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackReserve));
526 OUTPUT("\tSizeOfStackCommit: 0x%llX\r\n",
527 static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackCommit));
528 OUTPUT("\tSizeOfHeapReserve: 0x%llX\r\n",
529 static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapReserve));
530 OUTPUT("\tSizeOfHeapCommit: 0x%llX\r\n",
531 static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapCommit));
532 OUTPUT("\tLoaderFlags: 0x%X\r\n",
533 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.LoaderFlags));
534 OUTPUT("\tNumberOfRvaAndSizes: 0x%X\r\n\r\n",
535 static_cast<DWORD>(pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes));
536
537 OUTPUT("\tSubsystem: 0x%X %s\n\n",
538 pImageNtHeaders->OptionalHeader.Subsystem,
539 PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
540
541 // Print Data Directories
542 OUTPUT("[+] PE DATA DIRECTORIES\n");
543 for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
544 const auto& dir = pImageNtHeaders->OptionalHeader.DataDirectory[i];
545 if (dir.VirtualAddress != 0) {
546 OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
547 OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
548 OUTPUT("\t\tSize: 0x%X\n", dir.Size);
549 }
550 }
551
552 // Analyze Sections
553 OUTPUT("\n[+] PE IMAGE SECTIONS\r\n");
554 auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
555 for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
556 // Create a null-terminated string from the section name
557 char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
558 memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
559
560 // Remove any non-printable characters
561 for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
562 if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
563 sectionName[j] = '\0';
564 }
565 }
566
567 // Convert to wide string
568 wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
569 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
570 sectionName, -1,
571 wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
572
573 OUTPUT("\tSECTION : %s\r\n", wideSectionName);
574 OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\r\n", pSection->Misc.PhysicalAddress);
575 OUTPUT("\t\tMisc (VirtualSize) : 0x%X\r\n", pSection->Misc.VirtualSize);
576 OUTPUT("\t\tVirtualAddress : 0x%X\r\n", pSection->VirtualAddress);
577 OUTPUT("\t\tSizeOfRawData : 0x%X\r\n", pSection->SizeOfRawData);
578 OUTPUT("\t\tPointerToRawData : 0x%X\r\n", pSection->PointerToRawData);
579 OUTPUT("\t\tPointerToRelocations : 0x%X\r\n", pSection->PointerToRelocations);
580 OUTPUT("\t\tPointerToLinenumbers : 0x%X\r\n", pSection->PointerToLinenumbers);
581 OUTPUT("\t\tNumberOfRelocations : 0x%X\r\n", pSection->NumberOfRelocations);
582 OUTPUT("\t\tNumberOfLinenumbers : 0x%X\r\n", pSection->NumberOfLinenumbers);
583 OUTPUT("\t\tCharacteristics : 0x%X %s\r\n\r\n",
584 pSection->Characteristics,
585 PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
586 }
587
588 // Analyze Imports
589 const auto& importDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
590 if (importDir.VirtualAddress && importDir.Size) {
591 OUTPUT("\n[+] IMPORTED DLLS AND FUNCTIONS\r\n");
592
593 // Find the section containing imports
594 auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
595 PIMAGE_SECTION_HEADER pImportSection = nullptr;
596
597 // Find the import section
598 for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
599 if (importDir.VirtualAddress >= pSection->VirtualAddress &&
600 importDir.VirtualAddress < (pSection->VirtualAddress + pSection->Misc.VirtualSize)) {
601 pImportSection = pSection;
602 break;
603 }
604 }
605
606 if (!pImportSection) {
607 OUTPUT("[-] Could not find import section\r\n");
608 return;
609 }
610
611 // Get the import descriptor
612 auto pImportDesc = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
613 (BYTE*)lpFileContent +
614 pImportSection->PointerToRawData +
615 (importDir.VirtualAddress - pImportSection->VirtualAddress));
616
617 // Process all DLLs
618 while (pImportDesc && pImportDesc->Name != 0) {
619 // Get DLL name
620 const char* dllName = reinterpret_cast<const char*>(
621 (BYTE*)lpFileContent +
622 pImportSection->PointerToRawData +
623 (pImportDesc->Name - pImportSection->VirtualAddress));
624
625 if (!IsBadReadPtr(dllName, 1)) {
626 std::vector<wchar_t> wideDllName(MAX_PATH);
627 MultiByteToWideChar(CP_ACP, 0, dllName, -1,
628 wideDllName.data(), MAX_PATH);
629
630 // Print DLL information
631 OUTPUT("\n\tDLL NAME : %s\r\n", wideDllName.data());
632 OUTPUT("\tCharacteristics : 0x%X\r\n", pImportDesc->Characteristics);
633 OUTPUT("\tOriginalFirstThunk : 0x%X\r\n", pImportDesc->OriginalFirstThunk);
634 OUTPUT("\tTimeDateStamp : 0x%X\r\n", pImportDesc->TimeDateStamp);
635 OUTPUT("\tForwarderChain : 0x%X\r\n", pImportDesc->ForwarderChain);
636 OUTPUT("\tFirstThunk : 0x%X\r\n", pImportDesc->FirstThunk);
637
638 OUTPUT("\n\tImported Functions :\r\n\r\n");
639
640 // Process functions using OriginalFirstThunk
641 if (pImportDesc->OriginalFirstThunk) {
642 auto pThunk = reinterpret_cast<PIMAGE_THUNK_DATA>(
643 (BYTE*)lpFileContent +
644 pImportSection->PointerToRawData +
645 (pImportDesc->OriginalFirstThunk - pImportSection->VirtualAddress));
646
647 // Process all functions for this DLL
648 while (pThunk && pThunk->u1.AddressOfData) {
649 if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
650 auto pImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
651 (BYTE*)lpFileContent +
652 pImportSection->PointerToRawData +
653 (pThunk->u1.AddressOfData - pImportSection->VirtualAddress));
654
655 if (!IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
656 std::vector<wchar_t> wideFuncName(MAX_PATH);
657 MultiByteToWideChar(CP_ACP, 0,
658 reinterpret_cast<const char*>(pImportByName->Name),
659 -1, wideFuncName.data(), MAX_PATH);
660
661 OUTPUT("\t\t%s\r\n", wideFuncName.data());
662 }
663 }
664 pThunk++;
665 }
666 }
667 }
668 pImportDesc++;
669 }
670 }
671
672cleanup:
673 if (lpFileContent) {
674 UnmapViewOfFile(lpFileContent);
675 }
676 if (hFileMapping) {
677 CloseHandle(hFileMapping);
678 }
679 if (hFile) {
680 CloseHandle(hFile);
681 }
682
683 UpdateEditControl();
684}
685
686/*
687//use below vv ALWAYS
688void AnalyzePEFile(const wchar_t* filePathW) {
689 OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
690
691 LPVOID lpFileContent = GetFileContent(filePathW);
692 if (!lpFileContent) {
693 OUTPUT("[-] Failed to read file content!\n");
694 return;
695 }
696
697 const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
698 if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
699 OUTPUT("[-] Invalid DOS signature!\n");
700 HeapFree(GetProcessHeap(), 0, lpFileContent);
701 return;
702 }
703
704 const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
705 if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
706 OUTPUT("[-] Invalid NT signature!\n");
707 HeapFree(GetProcessHeap(), 0, lpFileContent);
708 return;
709 }
710
711 //UpdateEditControl(); //added just now remove line!
712
713 OUTPUT("[+] PE FILE HEADER\n");
714 OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
715 OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
716 OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
717 OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
718 OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
719 OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
720 OUTPUT("\tCharacteristics : 0x%X %s\n\n", (uintptr_t)pImageNtHeaders->FileHeader.Characteristics, GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
721
722 OUTPUT("[+] PE OPTIONAL HEADER\n");
723 OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
724 OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
725 OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
726 OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
727 OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
728 OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
729 OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
730 OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
731 OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
732 OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
733 OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
734 OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
735 OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
736 OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
737 OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
738 OUTPUT("\tSubsystem : 0x%X %s\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem, GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
739 OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
740 OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
741 OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
742 OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
743 OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
744 OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
745 OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
746
747 //UpdateEditControl(); //added just now remove line!
748
749 GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
750
751 const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
752 const auto pImageImportSection = GetSections(pImageSectionHeader, pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
753
754 if (!pImageImportSection) {
755 OUTPUT("[-] Error: Could not find import section!\n");
756 HeapFree(GetProcessHeap(), 0, lpFileContent);
757 return;
758 }
759
760 const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>((DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
761 if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
762 GetImports32(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
763 }
764 else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
765 GetImports64(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
766 }
767 else {
768 OUTPUT("[-] Unsupported architecture!\n");
769 }
770
771 HeapFree(GetProcessHeap(), 0, lpFileContent);
772 UpdateEditControl();
773}
774
775void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory) {
776 OUTPUT("[+] PE DATA DIRECTORIES\n");
777 for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory) {
778 if (pImageDataDirectory->VirtualAddress == 0) continue;
779 OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->VirtualAddress);
780 OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->Size);
781 }
782}
783
784PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader, int NumberOfSections, DWORD dImportAddress) {
785 PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
786 OUTPUT("\n[+] PE IMAGE SECTIONS\n");
787 for (int i = 0; i < NumberOfSections; ++i) {
788 const auto pCurrentSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
789 OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
790 OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
791 OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
792 OUTPUT("\t\tVirtualAddress : 0x%X\n", (uintptr_t)pCurrentSectionHeader->VirtualAddress);
793 OUTPUT("\t\tSizeOfRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
794 OUTPUT("\t\tPointerToRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->PointerToRawData);
795 OUTPUT("\t\tCharacteristics : 0x%X %s\n", (uintptr_t)pCurrentSectionHeader->Characteristics, GetSectionProtection(pCurrentSectionHeader->Characteristics));
796
797 if (dImportAddress >= pCurrentSectionHeader->VirtualAddress && dImportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize) {
798 pImageImportHeader = pCurrentSectionHeader;
799 }
800 }
801 return pImageImportHeader;
802}
803
804void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
805 OUTPUT("\n[+] IMPORTED DLL\n");
806 while (pImageImportDescriptor->Name != 0) {
807 OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
808 if (pImageImportDescriptor->OriginalFirstThunk == 0) {
809 ++pImageImportDescriptor;
810 continue;
811 }
812 auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA32>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
813 while (pOriginalFirstThunk->u1.AddressOfData != 0) {
814 const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
815 if (pImageImportByName) {
816 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
817 }
818 pOriginalFirstThunk++;
819 }
820 pImageImportDescriptor++;
821 }
822}
823
824void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
825 OUTPUT("\n[+] IMPORTED DLL\n");
826 while (pImageImportDescriptor->Name != 0) {
827 OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
828 if (pImageImportDescriptor->OriginalFirstThunk == 0) {
829 ++pImageImportDescriptor;
830 continue;
831 }
832 auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
833 while (pOriginalFirstThunk->u1.AddressOfData != 0) {
834 const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
835 if (pImageImportByName) {
836 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
837 }
838 pOriginalFirstThunk++;
839 }
840 pImageImportDescriptor++;
841 }
842}
843//use above ^^ ALWAYS
844*/
845
846
847/*
848// older-orig-deprecated vv
849// Main PE Analysis function
850void AnalyzePEFile(const wchar_t* filePathW)
851{
852 //WCHAR filePathW[MAX_PATH];
853 //MultiByteToWideChar(CP_ACP, 0, filePathA, -1, filePathW, MAX_PATH);
854 OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
855 //AppendToOutput(L"[+] Starting PE Analysis for: %ls\n\n", filePathW);
856
857 // Get file content
858 LPVOID lpFileContent = GetFileContent(filePathW);
859 if (!lpFileContent)
860 {
861 OUTPUT("[-] Failed to read file content!\n");
862 return;
863 }
864
865 // Get DOS header
866 const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
867 if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
868 {
869 OUTPUT("[-] Invalid DOS signature!\n");
870 HeapFree(GetProcessHeap(), 0, lpFileContent);
871 return;
872 }
873
874 // Get NT headers
875 const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
876 if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
877 {
878 OUTPUT("[-] Invalid NT signature!\n");
879 HeapFree(GetProcessHeap(), 0, lpFileContent);
880 return;
881 }
882
883 // Display File Header information
884 OUTPUT("[+] PE FILE HEADER\n");
885 OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
886 OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
887 OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
888 OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
889 OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
890 OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
891 OUTPUT("\tCharacteristics : 0x%X %s\n\n",
892 (uintptr_t)pImageNtHeaders->FileHeader.Characteristics,
893 GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
894
895 // Display Optional Header information
896 OUTPUT("[+] PE OPTIONAL HEADER\n");
897 OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
898 OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
899 OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
900 OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
901 OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
902 OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
903 OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
904 OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
905 OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
906 OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
907 OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
908 OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
909 OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
910 OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
911 OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
912 OUTPUT("\tSubsystem : 0x%X %s\n",
913 (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem,
914 GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
915 OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
916 OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
917 OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
918 OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
919 OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
920 OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
921 OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
922
923 // Get Data Directories
924 GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
925
926 // Get the import section
927 const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
928 (DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
929
930 const auto pImageImportSection = GetSections(
931 pImageSectionHeader,
932 pImageNtHeaders->FileHeader.NumberOfSections,
933 pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
934
935 if (!pImageImportSection)
936 {
937 OUTPUT("[-] Error: Could not find import section!\n");
938 HeapFree(GetProcessHeap(), 0, lpFileContent);
939 return;
940 }
941
942 // Get imports based on architecture
943 const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
944 (DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
945
946 if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
947 {
948 GetImports32(
949 pImageImportDescriptor,
950 (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
951 pImageImportSection);
952 }
953 else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
954 {
955 GetImports64(
956 pImageImportDescriptor,
957 (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
958 pImageImportSection);
959 }
960 else
961 {
962 OUTPUT("[-] Unsupported architecture!\n");
963 }
964
965 // Cleanup
966 HeapFree(GetProcessHeap(), 0, lpFileContent);
967
968 // Update the GUI with the analysis results
969 UpdateEditControl();
970}
971
972void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory)
973{
974 OUTPUT("[+] PE DATA DIRECTORIES\n");
975 for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory)
976 {
977 if (pImageDataDirectory->VirtualAddress == 0)
978 continue;
979
980 OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n",
981 GetDataDirectoryName(i),
982 (uintptr_t)pImageDataDirectory->VirtualAddress);
983 OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n",
984 GetDataDirectoryName(i),
985 (uintptr_t)pImageDataDirectory->Size);
986 }
987}
988
989PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
990 int NumberOfSections, DWORD dImportAddress)
991{
992 PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
993
994 OUTPUT("\n[+] PE IMAGE SECTIONS\n");
995
996 for (int i = 0; i < NumberOfSections; ++i)
997 {
998 const auto pCurrentSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader +
999 i * sizeof(IMAGE_SECTION_HEADER));
1000
1001 OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
1002 OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n",
1003 (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
1004 OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n",
1005 (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
1006 OUTPUT("\t\tVirtualAddress : 0x%X\n",
1007 (uintptr_t)pCurrentSectionHeader->VirtualAddress);
1008 OUTPUT("\t\tSizeOfRawData : 0x%X\n",
1009 (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
1010 OUTPUT("\t\tPointerToRawData : 0x%X\n",
1011 (uintptr_t)pCurrentSectionHeader->PointerToRawData);
1012 OUTPUT("\t\tPointerToRelocations : 0x%X\n",
1013 (uintptr_t)pCurrentSectionHeader->PointerToRelocations);
1014 OUTPUT("\t\tPointerToLinenumbers : 0x%X\n",
1015 (uintptr_t)pCurrentSectionHeader->PointerToLinenumbers);
1016 OUTPUT("\t\tNumberOfRelocations : 0x%X\n",
1017 (uintptr_t)pCurrentSectionHeader->NumberOfRelocations);
1018 OUTPUT("\t\tNumberOfLinenumbers : 0x%X\n",
1019 (uintptr_t)pCurrentSectionHeader->NumberOfLinenumbers);
1020 OUTPUT("\t\tCharacteristics : 0x%X %s\n",
1021 (uintptr_t)pCurrentSectionHeader->Characteristics,
1022 GetSectionProtection(pCurrentSectionHeader->Characteristics));
1023
1024 if (dImportAddress >= pCurrentSectionHeader->VirtualAddress &&
1025 dImportAddress < pCurrentSectionHeader->VirtualAddress +
1026 pCurrentSectionHeader->Misc.VirtualSize)
1027 {
1028 pImageImportHeader = pCurrentSectionHeader;
1029 }
1030 }
1031
1032 return pImageImportHeader;
1033}
1034void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
1035 DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
1036{
1037 OUTPUT("\n[+] IMPORTED DLL\n");
1038
1039 while (pImageImportDescriptor->Name != 0)
1040 {
1041 OUTPUT("\n\tDLL NAME : %s\n",
1042 (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
1043 OUTPUT("\tCharacteristics : 0x%X\n",
1044 (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
1045 OUTPUT("\tOriginalFirstThunk : 0x%X\n",
1046 (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
1047 OUTPUT("\tTimeDateStamp : 0x%X\n",
1048 (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
1049 OUTPUT("\tForwarderChain : 0x%X\n",
1050 (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
1051 OUTPUT("\tFirstThunk : 0x%X\n",
1052 (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
1053
1054 if (pImageImportDescriptor->OriginalFirstThunk == 0)
1055 {
1056 ++pImageImportDescriptor;
1057 continue;
1058 }
1059
1060 auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA32)(dRawOffset +
1061 (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
1062
1063 OUTPUT("\n\tImported Functions : \n\n");
1064
1065 while (pOriginalFirstThrunk->u1.AddressOfData != 0)
1066 {
1067 if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG32)
1068 {
1069 ++pOriginalFirstThrunk;
1070 continue;
1071 }
1072
1073 const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(dRawOffset +
1074 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
1075
1076 if (pImageImportByName == nullptr)
1077 {
1078 ++pOriginalFirstThrunk;
1079 continue;
1080 }
1081
1082 if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
1083 {
1084 OUTPUT("\t\t0x%X (Ordinal) : %s\n",
1085 (uintptr_t)pOriginalFirstThrunk->u1.AddressOfData,
1086 (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
1087 }
1088 else
1089 {
1090 OUTPUT("\t\t%s\n",
1091 (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
1092 }
1093
1094 ++pOriginalFirstThrunk;
1095 }
1096
1097 ++pImageImportDescriptor;
1098 }
1099}
1100
1101void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
1102 DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
1103{
1104 OUTPUT("\n[+] IMPORTED DLL\n");
1105
1106 while (pImageImportDescriptor->Name != 0)
1107 {
1108 OUTPUT("\n\tDLL NAME : %s\n",
1109 (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
1110 OUTPUT("\tCharacteristics : 0x%X\n",
1111 (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
1112 OUTPUT("\tOriginalFirstThunk : 0x%X\n",
1113 (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
1114 OUTPUT("\tTimeDateStamp : 0x%X\n",
1115 (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
1116 OUTPUT("\tForwarderChain : 0x%X\n",
1117 (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
1118 OUTPUT("\tFirstThunk : 0x%X\n",
1119 (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
1120
1121 if (pImageImportDescriptor->OriginalFirstThunk == 0)
1122 {
1123 ++pImageImportDescriptor;
1124 continue;
1125 }
1126
1127 auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA64)(dRawOffset +
1128 (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
1129
1130 OUTPUT("\n\tImported Functions : \n\n");
1131
1132 while (pOriginalFirstThrunk->u1.AddressOfData != 0)
1133 {
1134 if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG64)
1135 {
1136 ++pOriginalFirstThrunk;
1137 continue;
1138 }
1139
1140 const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dRawOffset +
1141 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
1142
1143 if (pImageImportByName == nullptr)
1144 {
1145 ++pOriginalFirstThrunk;
1146 continue;
1147 }
1148
1149 if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
1150 {
1151 OUTPUT("\t\t0x%llX (Ordinal) : %s\n",
1152 pOriginalFirstThrunk->u1.AddressOfData,
1153 (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
1154 }
1155 else
1156 {
1157 OUTPUT("\t\t%s\n",
1158 (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
1159 }
1160
1161 ++pOriginalFirstThrunk;
1162 }
1163
1164 ++pImageImportDescriptor;
1165 }
1166}
1167// older-orig-deprecated ^^
1168*/
1169
1170//filePathW
1171//lpFilePath
1172HANDLE GetFileContent(const wchar_t* lpFilePath) {
1173 HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
1174 if (hFile == INVALID_HANDLE_VALUE) return nullptr;
1175 DWORD fileSize = GetFileSize(hFile, nullptr);
1176 auto lpFileContent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileSize);
1177 DWORD bytesRead;
1178 ReadFile(hFile, lpFileContent, fileSize, &bytesRead, nullptr);
1179 CloseHandle(hFile);
1180 return lpFileContent;
1181}
1182
1183void UpdateEditControl() {
1184 SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
1185 SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
1186 SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
1187}