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