alien_fx_fiend

Fix Chinese Chars Arch+ExportFunc & 64bit Imports+Res 32bit90%Stuck

Dec 17th, 2024 (edited)
6
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 115.50 KB | Source Code | 0 0
  1. /*
  2. There's some Chinese characters in "Architecture:" output and a whole lot in "Exported Functions:" output especially for 64bit files, and also the "Imported Functions:" and Exports and "Resource Directory:" output doesn't display for 64bit files. Also when opening 32bit files the Progress Bar gets stuck at "Analyzing 90%". Can you fix these issues please?
  3. */
  4.  
  5. /*
  6. Wait for me to say "O.K. I finished" while I post my source code in multi-parts, then read my prompt with reference to the code O.K. ? I have a cpp file (Win32 GUI-based) for Parsing a PE Header, I will explain what I need help with after the full code is posted, please hold on till then.
  7. */
  8.  
  9. #define STRICT
  10. #define WIN32_LEAN_AND_MEAN
  11. #include <Windows.h>
  12. #include <winternl.h>
  13. #include <CommCtrl.h>
  14. #include <commdlg.h>
  15. #include <string>
  16. #include <strsafe.h>
  17. #include <sstream>
  18. #include <iomanip>
  19. #include <stdio.h>
  20. #include <vector>
  21. #include <shellapi.h>
  22. //#include "helpers.h"
  23. #include "resource.h"
  24. #pragma comment(lib, "comctl32.lib")
  25.  
  26. //bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders);
  27.  
  28. namespace PEHelpers {    
  29.     // Add these new helper functions
  30.     bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  31.         return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  32.     }
  33.  
  34.     DWORD_PTR GetImageBase(PIMAGE_NT_HEADERS pNtHeaders) {
  35.         if (PEHelpers::Is64BitPE(pNtHeaders)) {
  36.             auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  37.             return static_cast<DWORD_PTR>(pNtHeaders64->OptionalHeader.ImageBase);
  38.         }
  39.         else {
  40.             auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  41.             return static_cast<DWORD_PTR>(pNtHeaders32->OptionalHeader.ImageBase);
  42.         }
  43.     }
  44.  
  45.     DWORD GetSizeOfImage(PIMAGE_NT_HEADERS pNtHeaders) {
  46.         if (PEHelpers::Is64BitPE(pNtHeaders)) {
  47.             auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  48.             return pNtHeaders64->OptionalHeader.SizeOfImage;
  49.         }
  50.         else {
  51.             auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  52.             return pNtHeaders32->OptionalHeader.SizeOfImage;
  53.         }
  54.     }
  55.  
  56.     bool ValidateFileSize(DWORD expectedSize, DWORD fileSize) {
  57.         // Validate against SizeOfHeaders instead of SizeOfImage
  58.         return expectedSize > 0 && expectedSize <= fileSize;
  59.     }
  60. //}
  61.  
  62.     // Replace the existing GetRvaPtr function in PEHelpers namespace with this:
  63.     DWORD_PTR GetRvaPtr(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections, LPVOID baseAddress) {
  64.         for (WORD i = 0; i < numberOfSections; i++) {
  65.             if (rva >= pSectionHeader[i].VirtualAddress &&
  66.                 rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  67.                 DWORD_PTR delta = (DWORD_PTR)baseAddress + pSectionHeader[i].PointerToRawData;
  68.                 return delta + (rva - pSectionHeader[i].VirtualAddress);
  69.             }
  70.         }
  71.         return 0;
  72.     }
  73.  
  74.     // Add to PEHelpers namespace:
  75.     bool IsRvaValid(DWORD rva, DWORD fileSize, PIMAGE_NT_HEADERS pNtHeaders) {
  76.         return rva < pNtHeaders->OptionalHeader.SizeOfImage&& rva < fileSize;
  77.     }
  78.  
  79.     // Add this new helper function in PEHelpers namespace:
  80.     PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  81.         for (WORD i = 0; i < numberOfSections; i++) {
  82.             if ((rva >= pSectionHeader[i].VirtualAddress) &&
  83.                 (rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData))) {
  84.                 return &pSectionHeader[i];
  85.             }
  86.         }
  87.         return nullptr;
  88.     }
  89.  
  90.     std::wstring GetImageCharacteristics(DWORD characteristics) {
  91.         if (characteristics & IMAGE_FILE_DLL) return L"(DLL)";
  92.         if (characteristics & IMAGE_FILE_SYSTEM) return L"(DRIVER)";
  93.         if (characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) return L"(EXE)";
  94.         return L"(UNKNOWN)";
  95.     }
  96.  
  97.     std::wstring GetSubsystem(WORD subsystem) {
  98.         switch (subsystem) {
  99.         case IMAGE_SUBSYSTEM_NATIVE: return L"(NATIVE/DRIVER)";
  100.         case IMAGE_SUBSYSTEM_WINDOWS_GUI: return L"(GUI)";
  101.         case IMAGE_SUBSYSTEM_WINDOWS_CUI: return L"(CONSOLE)";
  102.         default: return L"(UNKNOWN)";
  103.         }
  104.     }
  105.  
  106.     std::wstring GetDataDirectoryName(int DirectoryNumber) {
  107.         switch (DirectoryNumber) {
  108.         case 0: return L"Export Table";
  109.         case 1: return L"Import Table";
  110.         case 2: return L"Resource Table";
  111.         case 3: return L"Exception Entry";
  112.         case 4: return L"Security Entry";
  113.         case 5: return L"Relocation Table";
  114.         case 6: return L"Debug Entry";
  115.         case 7: return L"Copyright Entry";
  116.         case 8: return L"Global PTR Entry";
  117.         case 9: return L"TLS Entry";
  118.         case 10: return L"Configuration Entry";
  119.         case 11: return L"Bound Import Entry";
  120.         case 12: return L"IAT";
  121.         case 13: return L"Delay Import Descriptor";
  122.         case 14: return L"COM Descriptor";
  123.         default: return L"Unknown";
  124.         }
  125.     }
  126.  
  127.     std::wstring GetSectionProtection(DWORD characteristics) {
  128.         std::wstring protection = L"(";
  129.         bool needsSeparator = false;
  130.  
  131.         if (characteristics & IMAGE_SCN_MEM_EXECUTE) {
  132.             protection += L"EXECUTE";
  133.             needsSeparator = true;
  134.         }
  135.  
  136.         if (characteristics & IMAGE_SCN_MEM_READ) {
  137.             if (needsSeparator) protection += L" | ";
  138.             protection += L"READ";
  139.             needsSeparator = true;
  140.         }
  141.  
  142.         if (characteristics & IMAGE_SCN_MEM_WRITE) {
  143.             if (needsSeparator) protection += L" | ";
  144.             protection += L"WRITE";
  145.         }
  146.  
  147.         protection += L")";
  148.         return protection;
  149.     }
  150.  
  151.     PIMAGE_SECTION_HEADER GetExportSection(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  152.         const int NumberOfSections,
  153.         const DWORD_PTR dExportAddress) {
  154.         for (int i = 0; i < NumberOfSections; ++i) {
  155.             const auto pCurrentSectionHeader =
  156.                 (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  157.  
  158.             if (dExportAddress >= pCurrentSectionHeader->VirtualAddress &&
  159.                 dExportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize)
  160.                 return pCurrentSectionHeader;
  161.         }
  162.         return nullptr;
  163.     }
  164.  
  165.     DWORD RvaToOffset(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  166.         for (WORD i = 0; i < numberOfSections; i++) {
  167.             if (rva >= pSectionHeader[i].VirtualAddress &&
  168.                 rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  169.                 return (rva - pSectionHeader[i].VirtualAddress) + pSectionHeader[i].PointerToRawData;
  170.             }
  171.         }
  172.         return 0;
  173.     }
  174. }
  175.  
  176. using namespace std;
  177.  
  178. // At the top of your file, change the window class name to wide string
  179. #define WINDOW_CLASS_NAME L"PEAnalyzerWindow"
  180. //const wchar_t* const WINDOW_CLASS_NAME = L"PEAnalyzerWindow";
  181.  
  182. // Use ANSI versions explicitly
  183. //#undef CreateWindow
  184. //#undef CreateWindowEx
  185. //#define CreateWindow  CreateWindowW
  186. //#define CreateWindowEx CreateWindowExW
  187.  
  188. // Helper function to replace printf with GUI output
  189. #define OUTPUT(format, ...) AppendToOutput(L##format, ##__VA_ARGS__)
  190. //#define OUTPUT(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  191. //#define printf(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  192.  
  193. // Window dimensions
  194. #define WINDOW_WIDTH    1024
  195. #define WINDOW_HEIGHT   768
  196. #define EDIT_MARGIN    10
  197.  
  198. // Global variables
  199. HWND g_hMainWindow = NULL;
  200. HWND g_hEditControl = NULL;
  201. HFONT g_hFont = NULL;
  202. std::wstringstream g_OutputText;
  203. WCHAR filePathW[MAX_PATH];
  204. std::vector<wchar_t> g_OutputBuffer;
  205. std::wstring tempBuffer; // Declare tempBuffer globally
  206. HWND g_hStatusBar = NULL;
  207. HWND g_hProgressBar = NULL;  // Add this with your other global variables
  208. //int virtualHeight = 100;  // Initialize with an appropriate value
  209.  
  210. // Function declarations
  211. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  212. LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  213. void CreateMainWindow(HINSTANCE hInstance);
  214. void InitializeControls(HWND hwnd);
  215. void AddMenus(HWND hwnd);
  216. void OpenFileDialog(HWND hwnd);
  217. //void AnalyzePEFile(const WCHAR* filePathW);
  218. void AnalyzePEFile(const wchar_t* filePathW);
  219. HANDLE GetFileContent(const wchar_t* lpFilePath);
  220. /*void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory);
  221. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  222.     int NumberOfSections, DWORD dImportAddress);
  223. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  224.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);
  225. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  226.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);*/
  227. void AppendToOutput(const wchar_t* format, ...);
  228. void UpdateEditControl();
  229.  
  230. // Main window class name
  231. //const char* const WINDOW_CLASS_NAME = "PEAnalyzerWindow";
  232.  
  233. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  234.     INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
  235.     InitCommonControlsEx(&icc);
  236.  
  237.     // Get command line parameters in Unicode
  238.     int argc;
  239.     LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  240.  
  241.     CreateMainWindow(hInstance);
  242.     if (!g_hMainWindow) {
  243.         LocalFree(argv);
  244.         return -1;
  245.     }
  246.  
  247.     ShowWindow(g_hMainWindow, nCmdShow);
  248.     UpdateWindow(g_hMainWindow);
  249.  
  250.     // If there's a command line parameter, process it
  251.     if (argc > 1) {
  252.         // Process the first parameter as file path
  253.         SetWindowTextW(g_hEditControl, L"");
  254.         g_OutputText.str(L"");
  255.         g_OutputText.clear();
  256.         AnalyzePEFile(argv[1]);
  257.         UpdateEditControl();
  258.     }
  259.  
  260.     LocalFree(argv);
  261.  
  262.     MSG msg = {};
  263.     while (GetMessage(&msg, NULL, 0, 0)) {
  264.         TranslateMessage(&msg);
  265.         DispatchMessage(&msg);
  266.     }
  267.  
  268.     if (g_hFont) DeleteObject(g_hFont);
  269.     return (int)msg.wParam;
  270. }
  271.  
  272. void CreateMainWindow(HINSTANCE hInstance) {
  273.     WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), 0, WindowProc, 0, 0, hInstance,
  274.         LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)),
  275.         LoadCursor(NULL, IDC_ARROW),
  276.         (HBRUSH)(COLOR_WINDOW + 1),
  277.         NULL, WINDOW_CLASS_NAME,
  278.         LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)) };
  279.     RegisterClassExW(&wc);
  280.  
  281.     // Get screen dimensions
  282.     int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  283.     int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  284.  
  285.     // Calculate center position
  286.     int windowX = (screenWidth - WINDOW_WIDTH) / 2;
  287.     int windowY = (screenHeight - WINDOW_HEIGHT) / 2;
  288.  
  289.     // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
  290.     DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
  291.     //WS_OVERLAPPEDWINDOW ~~> style
  292.     g_hMainWindow = CreateWindowExW(0, WINDOW_CLASS_NAME, L"PE File Analyzer",
  293.         style, windowX, windowY, WINDOW_WIDTH, WINDOW_HEIGHT,
  294.         nullptr, nullptr, hInstance, nullptr);
  295. }
  296.  
  297. void InitializeControls(HWND hwnd) {
  298.     // Create status bar
  299.     g_hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
  300.         WS_CHILD | WS_VISIBLE,
  301.         0, 0, 0, 0, hwnd, NULL,
  302.         (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  303.  
  304.     // Set up status bar parts
  305.     RECT rcClient;
  306.     GetClientRect(hwnd, &rcClient);
  307.     int statusParts[2] = { 150, rcClient.right };
  308.     SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  309.  
  310.     // Create progress bar in the second part of status bar
  311.     RECT rcPart;
  312.     SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  313.  
  314.     g_hProgressBar = CreateWindowEx(0, PROGRESS_CLASS, NULL,
  315.         WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
  316.         rcPart.left + 5, rcPart.top + 2,
  317.         rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  318.         g_hStatusBar, NULL,
  319.         (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  320.  
  321.     // Set blue color and range
  322.     SendMessage(g_hProgressBar, PBM_SETBARCOLOR, 0, (LPARAM)RGB(0, 120, 215));  // Windows 10 blue
  323.     SendMessage(g_hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  324.     SendMessage(g_hProgressBar, PBM_SETSTEP, 1, 0);
  325.  
  326.     // Get status bar height for edit control positioning
  327.     RECT rcStatus;
  328.     GetWindowRect(g_hStatusBar, &rcStatus);
  329.     int statusHeight = rcStatus.bottom - rcStatus.top;
  330.  
  331.     // Create edit control
  332.     g_hEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
  333.         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
  334.         ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
  335.         EDIT_MARGIN, EDIT_MARGIN,
  336.         rcClient.right - (2 * EDIT_MARGIN),
  337.         rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  338.         hwnd, nullptr,
  339.         (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), nullptr);
  340.  
  341.     // Create and set font
  342.     g_hFont = CreateFont(-14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
  343.         ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  344.         DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, L"Consolas");
  345.  
  346.     if (g_hFont)
  347.         SendMessage(g_hEditControl, WM_SETFONT, (WPARAM)g_hFont, TRUE);
  348.  
  349.     SetWindowSubclass(g_hEditControl, EditSubclassProc, 0, 0);
  350. }
  351.  
  352. void AddMenus(HWND hwnd) {
  353.     HMENU hMenuBar = CreateMenu();
  354.     HMENU hFileMenu = CreateMenu();
  355.     AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
  356.     AppendMenu(hFileMenu, MF_STRING, 1, L"&Open\tCtrl+O");  // Updated to show shortcut
  357.     AppendMenu(hFileMenu, MF_STRING, 2, L"E&xit");
  358.     SetMenu(hwnd, hMenuBar);
  359. }
  360.  
  361. /*LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  362.     if (uMsg == WM_KEYDOWN) {
  363.         // Check for Ctrl+O
  364.         if ((GetKeyState(VK_CONTROL) & 0x8000) && wParam == 'O') {
  365.             SendMessage(GetParent(hwnd), WM_COMMAND, 1, 0);  // Send the Open command
  366.             return 0;
  367.         }
  368.  
  369.         // Existing cases
  370.         switch (wParam) {
  371.         case VK_F1:
  372.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
  373.             return 0;
  374.         case VK_ESCAPE:
  375.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
  376.             return 0;
  377.         case VK_PRIOR:  // Page Up
  378.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_PRIOR, 0);
  379.             return 0;
  380.         case VK_NEXT:  // Page Down
  381.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_NEXT, 0);
  382.             return 0;
  383.         }
  384.     }
  385.     else if (uMsg == WM_MOUSEWHEEL) {
  386.         int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  387.         if (zDelta > 0) {
  388.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_PRIOR, 0);  // Mouse Wheel Up
  389.         }
  390.         else if (zDelta < 0) {
  391.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_NEXT, 0);  // Mouse Wheel Down
  392.         }
  393.         return 0;
  394.     }
  395.     return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  396. }*/
  397.  
  398. // First, add this helper function to determine if the PE file is 64-bit
  399. bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  400.     return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  401. }
  402.  
  403. LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  404.     if (uMsg == WM_KEYDOWN) {
  405.         if ((GetKeyState(VK_CONTROL) & 0x8000) && wParam == 'O') {
  406.             SendMessage(GetParent(hwnd), WM_COMMAND, 1, 0);
  407.             return 0;
  408.         }
  409.         switch (wParam) {
  410.         case VK_F1:
  411.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
  412.             return 0;
  413.         case VK_ESCAPE:
  414.             SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
  415.             return 0;
  416.         case VK_PRIOR:
  417.             // Scroll up
  418.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  419.             return 0;
  420.         case VK_NEXT:
  421.             // Scroll down
  422.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  423.             return 0;
  424.         case VK_UP:
  425.             // Scroll one line up
  426.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  427.             return 0;
  428.         case VK_DOWN:
  429.             // Scroll one line down
  430.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  431.             return 0;
  432.         }
  433.     }
  434.     if (uMsg == WM_MOUSEWHEEL) {
  435.         int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  436.         if (delta > 0) {
  437.             // Scroll up
  438.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  439.         }
  440.         else {
  441.             // Scroll down
  442.             SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  443.         }
  444.         return 0;
  445.     }
  446.     return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  447. }
  448.  
  449. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  450.     switch (uMsg) {
  451.     case WM_CREATE: InitializeControls(hwnd); AddMenus(hwnd); return 0;
  452.     case WM_SIZE:
  453.     {
  454.         RECT rcClient;
  455.         GetClientRect(hwnd, &rcClient);
  456.  
  457.         // Resize status bar
  458.         SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
  459.  
  460.         // Recalculate status bar parts
  461.         int statusParts[2] = { 150, rcClient.right };
  462.         SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  463.  
  464.         // Reposition progress bar
  465.         RECT rcPart;
  466.         SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  467.         SetWindowPos(g_hProgressBar, NULL,
  468.             rcPart.left + 5, rcPart.top + 2,
  469.             rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  470.             SWP_NOZORDER);
  471.  
  472.         // Get status bar height
  473.         RECT rcStatus;
  474.         GetWindowRect(g_hStatusBar, &rcStatus);
  475.         int statusHeight = rcStatus.bottom - rcStatus.top;
  476.  
  477.         // Resize edit control
  478.         SetWindowPos(g_hEditControl, NULL,
  479.             EDIT_MARGIN,
  480.             EDIT_MARGIN,
  481.             rcClient.right - (2 * EDIT_MARGIN),
  482.             rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  483.             SWP_NOZORDER);
  484.         return 0;
  485.     }
  486.     /*case WM_KEYDOWN:
  487.     {
  488.         // Check if Ctrl is pressed
  489.         if (GetKeyState(VK_CONTROL) & 0x8000) {
  490.             switch (wParam) {
  491.             case 'O':  // Ctrl+O
  492.                 OpenFileDialog(hwnd);
  493.                 return 0;
  494.             }
  495.         }
  496.  
  497.         // Handle Page Up/Page Down
  498.         switch (wParam) {
  499.         case VK_PRIOR:  // Page Up
  500.             ScrollWindow(hwnd, 0, -virtualHeight, NULL, NULL);
  501.             UpdateWindow(hwnd);
  502.             return 0;
  503.         case VK_NEXT:  // Page Down
  504.             ScrollWindow(hwnd, 0, virtualHeight, NULL, NULL);
  505.             UpdateWindow(hwnd);
  506.             return 0;
  507.         case VK_F1:
  508.             MessageBoxW(hwnd,
  509.                 L"PE Header Parser 2.9 GUI-based Programmed in C++ Win32 API (1369 lines of code) by Entisoft Software(c) Evans Thorpemorton",
  510.                 L"About",
  511.                 MB_OK | MB_ICONINFORMATION);
  512.             return 0;
  513.         case VK_ESCAPE:
  514.             PostQuitMessage(0);
  515.             return 0;
  516.         }
  517.     }
  518.     break;
  519.  
  520.     case WM_MOUSEWHEEL:
  521.     {
  522.         int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  523.         if (zDelta > 0) {
  524.             ScrollWindow(hwnd, 0, -virtualHeight, NULL, NULL);  // Mouse Wheel Up
  525.         }
  526.         else if (zDelta < 0) {
  527.             ScrollWindow(hwnd, 0, virtualHeight, NULL, NULL);  // Mouse Wheel Down
  528.         }
  529.         UpdateWindow(hwnd);
  530.         return 0;
  531.     }*/
  532.  
  533.     case WM_KEYDOWN:
  534.     {
  535.         if (GetKeyState(VK_CONTROL) & 0x8000) {
  536.             switch (wParam) {
  537.             case 'O':
  538.                 OpenFileDialog(hwnd);
  539.                 return 0;
  540.             }
  541.         }
  542.         switch (wParam) {
  543.         case VK_F1:
  544.             MessageBoxW(hwnd,
  545.                 L"PE Header Parser 4.3 GUI-based Programmed in C++ Win32 API (1546 lines of code) by Entisoft Software(c) Evans Thorpemorton",
  546.                 L"About",
  547.                 MB_OK | MB_ICONINFORMATION);
  548.             return 0;
  549.         case VK_ESCAPE:
  550.             PostQuitMessage(0);
  551.             return 0;
  552.         case VK_PRIOR:
  553.             // Scroll up
  554.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  555.             return 0;
  556.         case VK_NEXT:
  557.             // Scroll down
  558.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  559.             return 0;
  560.         case VK_UP:
  561.             // Scroll one line up
  562.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  563.             return 0;
  564.         case VK_DOWN:
  565.             // Scroll one line down
  566.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  567.             return 0;
  568.         }
  569.         break;
  570.     }
  571.     case WM_MOUSEWHEEL:
  572.     {
  573.         int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  574.         if (delta > 0) {
  575.             // Scroll up
  576.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  577.         }
  578.         else {
  579.             // Scroll down
  580.             SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  581.         }
  582.         return 0;
  583.     }
  584.     case WM_COMMAND: if (LOWORD(wParam) == 1) OpenFileDialog(hwnd); if (LOWORD(wParam) == 2) PostQuitMessage(0); return 0;
  585.     case WM_DESTROY:
  586.         if (g_hStatusBar) DestroyWindow(g_hStatusBar);
  587.         PostQuitMessage(0);
  588.         return 0;
  589.     }
  590.     return DefWindowProc(hwnd, uMsg, wParam, lParam);
  591. }
  592.  
  593. void SetStatusText(const wchar_t* text) {
  594.     SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
  595. }
  596.  
  597. void ShowProgress(int percentage) {
  598.     // Update progress bar
  599.     SendMessage(g_hProgressBar, PBM_SETPOS, (WPARAM)percentage, 0);
  600.  
  601.     // Update status text in first part
  602.     wchar_t status[256];
  603.     swprintf_s(status, L"Analyzing... %d%%", percentage);
  604.     //swprintf_s(status, L"Analyzing...");
  605.     SetStatusText(status); //commented-out
  606.     SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)status);
  607. }
  608.  
  609. void OpenFileDialog(HWND hwnd) {
  610.     WCHAR fileName[MAX_PATH] = L"";
  611.     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 };
  612.     if (GetOpenFileNameW(&ofn)) {
  613.         SetWindowTextW(g_hEditControl, L"");
  614.         g_OutputText.str(L"");
  615.         g_OutputText.clear();
  616.         AnalyzePEFile(ofn.lpstrFile);
  617.         UpdateEditControl();
  618.     }
  619. }
  620.  
  621. class FileMapper {
  622. private:
  623.     HANDLE hFile = INVALID_HANDLE_VALUE;
  624.     HANDLE hMapping = nullptr;
  625.     LPVOID lpView = nullptr;
  626.  
  627. public:
  628.     ~FileMapper() {
  629.         if (lpView) UnmapViewOfFile(lpView);
  630.         if (hMapping) CloseHandle(hMapping);
  631.         if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
  632.     }
  633.  
  634.     bool Initialize(const wchar_t* path) {
  635.         hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr,
  636.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  637.         if (hFile == INVALID_HANDLE_VALUE) return false;
  638.  
  639.         hMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  640.         if (!hMapping) return false;
  641.  
  642.         lpView = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  643.         return lpView != nullptr;
  644.     }
  645.  
  646.     LPVOID GetView() const { return lpView; }
  647. };
  648.  
  649. // Modified AppendToOutput to handle newlines properly:
  650. void AppendToOutput(const wchar_t* format, ...) {
  651.     std::vector<wchar_t> buffer(1024);
  652.     va_list args;
  653.     va_start(args, format);
  654.  
  655.     while (true) {
  656.         int result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  657.         if (result >= 0) break;
  658.         buffer.resize(buffer.size() * 2);
  659.     }
  660.     va_end(args);
  661.  
  662.     // Convert \n to \r\n
  663.     std::wstring output = buffer.data();
  664.     size_t pos = 0;
  665.     while ((pos = output.find(L'\n', pos)) != std::wstring::npos) {
  666.         if (pos == 0 || output[pos - 1] != L'\r') {
  667.             output.insert(pos, L"\r");
  668.             pos += 2;
  669.         }
  670.         else {
  671.             pos++;
  672.         }
  673.     }
  674.  
  675.     g_OutputText << output;
  676.     UpdateEditControl();
  677. }
  678.  
  679. /*
  680. void AppendToOutput(const wchar_t* format, ...) {
  681.     wchar_t buffer[16384]; // Ensure sufficient buffer size
  682.     va_list args;
  683.     va_start(args, format);
  684.     StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  685.     va_end(args);
  686.  
  687.     tempBuffer += buffer;
  688.  
  689.     // Update Edit Control periodically to improve performance
  690.     if (tempBuffer.size() > 8000) {
  691.         g_OutputText << tempBuffer;
  692.         tempBuffer.clear();
  693.  
  694.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  695.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  696.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  697.     }
  698. }
  699.  
  700.  
  701. // Final update to flush any remaining content
  702. void FlushOutput() {
  703.     if (!tempBuffer.empty()) {
  704.         g_OutputText << tempBuffer;
  705.         tempBuffer.clear();
  706.  
  707.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  708.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  709.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  710.     }
  711. }
  712. */
  713.  
  714.  
  715. /*
  716. //use below ^^ ALWAYS
  717. void AppendToOutput(const wchar_t* format, ...) {
  718.     va_list args;
  719.     va_start(args, format);
  720.  
  721.     // Use a vector as a dynamically resizable buffer
  722.     std::vector<wchar_t> buffer(16384); // Start with an initial size
  723.     int result = -1;
  724.  
  725.     while (true) {
  726.         // Attempt to format the string
  727.         result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  728.  
  729.         if (result >= 0 && static_cast<size_t>(result) < buffer.size()) {
  730.             // Successfully formatted within the current buffer size
  731.             break;
  732.         }
  733.  
  734.         // Resize the buffer and try again
  735.         buffer.resize(buffer.size() * 2);
  736.     }
  737.     va_end(args);
  738.  
  739.     // Convert `\n` to `\r\n` for proper display in the EditBox
  740.     std::wstring formattedOutput(buffer.data());
  741.     size_t pos = 0;
  742.     while ((pos = formattedOutput.find(L'\n', pos)) != std::wstring::npos) {
  743.         formattedOutput.replace(pos, 1, L"\r\n");
  744.         pos += 2; // Move past the replacement
  745.     }
  746.  
  747.     // Append to the global output buffer
  748.     g_OutputText << formattedOutput;
  749.  
  750.     // Update the EditBox periodically to prevent overloading
  751.     if (g_OutputText.str().size() > 8000) {
  752.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  753.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  754.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  755.     }
  756. }
  757. //use above ^^ ALWAYS
  758. */
  759.  
  760. //currentlatest
  761. /*void AppendToOutput(const wchar_t* format, ...) {
  762.     wchar_t buffer[4096];
  763.     va_list args;
  764.     va_start(args, format);
  765.     StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  766.     va_end(args);
  767.     g_OutputText << buffer;
  768.     SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  769.     SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  770.     SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  771. }
  772. */
  773.  
  774. //use-below-basic-failsafe-working vv
  775. //basic test function
  776. /*void AnalyzePEFile(const wchar_t* filePathW) {
  777.     OUTPUT("[+] Analyzing file: %s\n", filePathW);
  778.     LPVOID lpFileContent = GetFileContent(filePathW);
  779.     if (!lpFileContent) { OUTPUT("[-] Could not read file.\n"); return; }
  780.     PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileContent;
  781.     if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { OUTPUT("[-] Invalid DOS signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  782.     PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpFileContent + dosHeader->e_lfanew);
  783.     if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { OUTPUT("[-] Invalid NT signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  784.     OUTPUT("[+] PE file analyzed successfully.\n");
  785.     HeapFree(GetProcessHeap(), 0, lpFileContent);
  786.     UpdateEditControl();
  787. }*/
  788. //use-above-basic-failsafe-working vv
  789.  
  790. //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
  791.  
  792. void ProcessResourceDirectory(
  793.     PIMAGE_RESOURCE_DIRECTORY resDir,
  794.     int level,
  795.     const wchar_t* type,
  796.     PIMAGE_RESOURCE_DIRECTORY pResourceDir,
  797.     const wchar_t* resourceTypes[],
  798.     PIMAGE_NT_HEADERS pNtHeaders,
  799.     LPVOID lpFileContent)
  800. {
  801.     if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  802.         return;
  803.     }
  804.  
  805.     auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  806.     WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  807.  
  808.     for (WORD i = 0; i < totalEntries; i++) {
  809.         if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  810.             break;
  811.         }
  812.  
  813.         for (int indent = 0; indent < level; indent++) {
  814.             OUTPUT("\t");
  815.         }
  816.  
  817.         if (entry[i].NameIsString) {
  818.             auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)pResourceDir + entry[i].NameOffset);
  819.             if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  820.                 std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  821.                 wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  822.                     nameEntry->NameString, nameEntry->Length);
  823.                 resourceName[nameEntry->Length] = L'\0';
  824.  
  825.                 if (level == 0) {
  826.                     OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  827.                 }
  828.                 else {
  829.                     OUTPUT("Name: %s\n", resourceName.data());
  830.                 }
  831.             }
  832.         }
  833.         else {
  834.             if (level == 0) {
  835.                 DWORD resourceType = entry[i].Id;
  836.                 if (resourceType < 16) {
  837.                     OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  838.                 }
  839.                 else {
  840.                     OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  841.                 }
  842.             }
  843.             else {
  844.                 OUTPUT("ID: %d\n", entry[i].Id);
  845.             }
  846.         }
  847.  
  848.         if (entry[i].DataIsDirectory) {
  849.             auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pResourceDir + entry[i].OffsetToDirectory);
  850.             if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  851.                 ProcessResourceDirectory(nextDir, level + 1,
  852.                     level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  853.                     pResourceDir, resourceTypes, pNtHeaders, lpFileContent);
  854.             }
  855.         }
  856.         else {
  857.             auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)pResourceDir + entry[i].OffsetToData);
  858.             if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  859.                 for (int indent = 0; indent < level + 1; indent++) {
  860.                     OUTPUT("\t");
  861.                 }
  862.                 OUTPUT("Size: %d bytes, RVA: 0x%X\n",
  863.                     dataEntry->Size, dataEntry->OffsetToData);
  864.  
  865.                 if (type && wcscmp(type, L"Version") == 0) {
  866.                     auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  867.                         dataEntry->OffsetToData,
  868.                         IMAGE_FIRST_SECTION(pNtHeaders),
  869.                         pNtHeaders->FileHeader.NumberOfSections,
  870.                         lpFileContent);
  871.  
  872.                     if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  873.                         auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  874.                         if (versionInfo->dwSignature == 0xFEEF04BD) {
  875.                             for (int indent = 0; indent < level + 2; indent++) {
  876.                                 OUTPUT("\t");
  877.                             }
  878.                             OUTPUT("File Version: %d.%d.%d.%d\n",
  879.                                 HIWORD(versionInfo->dwFileVersionMS),
  880.                                 LOWORD(versionInfo->dwFileVersionMS),
  881.                                 HIWORD(versionInfo->dwFileVersionLS),
  882.                                 LOWORD(versionInfo->dwFileVersionLS));
  883.                         }
  884.                     }
  885.                 }
  886.             }
  887.         }
  888.     }
  889. }
  890.  
  891. void AnalyzePEFile(const wchar_t* filePathW) {
  892.     OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  893.  
  894.     // Initialize all variables at the start
  895.     HANDLE hFile = INVALID_HANDLE_VALUE;
  896.     HANDLE hFileMapping = nullptr;
  897.     LPVOID lpFileContent = nullptr;
  898.  
  899.     FileMapper mapper;
  900.     if (!mapper.Initialize(filePathW)) {
  901.         SetStatusText(L"Failed to open file!");
  902.         OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
  903.         return;
  904.     }
  905.  
  906.     ShowProgress(20);
  907.  
  908.     hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
  909.         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  910.     if (hFile == INVALID_HANDLE_VALUE) {
  911.         OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  912.         return;
  913.     }
  914.  
  915.     DWORD fileSize = GetFileSize(hFile, nullptr);
  916.     if (fileSize == INVALID_FILE_SIZE) {
  917.         CloseHandle(hFile);
  918.         OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
  919.         return;
  920.     }
  921.  
  922.     hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  923.     if (!hFileMapping) {
  924.         CloseHandle(hFile);
  925.         OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
  926.         return;
  927.     }
  928.  
  929.     lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  930.     if (!lpFileContent) {
  931.         CloseHandle(hFileMapping);
  932.         CloseHandle(hFile);
  933.         OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
  934.         return;
  935.     }
  936.  
  937.     // Declare pNtHeaders here, outside the do-while loop.
  938.     PIMAGE_NT_HEADERS pNtHeaders = nullptr; // Initialize to nullptr
  939.  
  940.     do {
  941.         const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
  942.         if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  943.             OUTPUT("[-] Invalid DOS signature!\r\n");
  944.             break;
  945.         }
  946.         ShowProgress(30);
  947.         pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>( // Assign pNtHeaders here
  948.             static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
  949.         if (IsBadReadPtr(pNtHeaders, sizeof(IMAGE_NT_HEADERS)) ||
  950.             pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  951.             OUTPUT("[-] Invalid NT signature!\r\n");
  952.             break;
  953.         }
  954.         bool is64Bit = PEHelpers::Is64BitPE(pNtHeaders);
  955.         PIMAGE_NT_HEADERS32 pNtHeaders32 = nullptr;
  956.         PIMAGE_NT_HEADERS64 pNtHeaders64 = nullptr;
  957.         if (is64Bit) {
  958.             auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  959.         }
  960.         else {
  961.             auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  962.         }
  963.         DWORD_PTR imageBase = PEHelpers::GetImageBase(pNtHeaders);
  964.         DWORD sizeOfImage = PEHelpers::GetSizeOfImage(pNtHeaders);
  965.         if (pNtHeaders->FileHeader.NumberOfSections > 96) {
  966.             OUTPUT("[-] Suspicious number of sections detected!\n");
  967.             break;
  968.         }
  969.         //Move this check here after pNtHeaders is defined
  970.         if (!PEHelpers::ValidateFileSize(pNtHeaders->OptionalHeader.SizeOfHeaders, fileSize)) {
  971.             OUTPUT("[-] Invalid image size detected!\n");
  972.             return;
  973.         }
  974.  
  975.         OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  976.         OUTPUT("[+] Architecture: %s\n\n", is64Bit ? "x64" : "x86");
  977.         OUTPUT("[+] DOS HEADER\n");
  978.         OUTPUT("\te_magic    : 0x%X\n", pImageDosHeader->e_magic);
  979.         OUTPUT("\te_cblp     : 0x%X\n", pImageDosHeader->e_cblp);
  980.         OUTPUT("\te_cp       : 0x%X\n", pImageDosHeader->e_cp);
  981.         OUTPUT("\te_crlc     : 0x%X\n", pImageDosHeader->e_crlc);
  982.         OUTPUT("\te_cparhdr  : 0x%X\n", pImageDosHeader->e_cparhdr);
  983.         OUTPUT("\te_minalloc : 0x%X\n", pImageDosHeader->e_minalloc);
  984.         OUTPUT("\te_maxalloc : 0x%X\n", pImageDosHeader->e_maxalloc);
  985.         OUTPUT("\te_ss       : 0x%X\n", pImageDosHeader->e_ss);
  986.         OUTPUT("\te_sp       : 0x%X\n", pImageDosHeader->e_sp);
  987.         OUTPUT("\te_csum     : 0x%X\n", pImageDosHeader->e_csum);
  988.         OUTPUT("\te_ip       : 0x%X\n", pImageDosHeader->e_ip);
  989.         OUTPUT("\te_cs       : 0x%X\n", pImageDosHeader->e_cs);
  990.         OUTPUT("\te_lfarlc   : 0x%X\n", pImageDosHeader->e_lfarlc);
  991.         OUTPUT("\te_ovno     : 0x%X\n", pImageDosHeader->e_ovno);
  992.         OUTPUT("\te_oemid    : 0x%X\n", pImageDosHeader->e_oemid);
  993.         OUTPUT("\te_oeminfo  : 0x%X\n", pImageDosHeader->e_oeminfo);
  994.         OUTPUT("\te_lfanew   : 0x%X\n\n", pImageDosHeader->e_lfanew);
  995.         OUTPUT("[+] NT HEADER\n");
  996.         OUTPUT("\tSignature  : 0x%X\n\n", pNtHeaders->Signature);
  997.  
  998.         ShowProgress(40);
  999.  
  1000.         OUTPUT("[+] FILE HEADER\n");
  1001.         OUTPUT("\tMachine: 0x%X\n", pNtHeaders->FileHeader.Machine);
  1002.         OUTPUT("\tNumberOfSections: 0x%X\n", pNtHeaders->FileHeader.NumberOfSections);
  1003.         OUTPUT("\tTimeDateStamp: 0x%X\n", pNtHeaders->FileHeader.TimeDateStamp);
  1004.         OUTPUT("\tPointerToSymbolTable: 0x%X\n", pNtHeaders->FileHeader.PointerToSymbolTable);
  1005.         OUTPUT("\tNumberOfSymbols: 0x%X\n", pNtHeaders->FileHeader.NumberOfSymbols);
  1006.         OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", pNtHeaders->FileHeader.SizeOfOptionalHeader);
  1007.         OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1008.             pNtHeaders->FileHeader.Characteristics,
  1009.             PEHelpers::GetImageCharacteristics(pNtHeaders->FileHeader.Characteristics).c_str());
  1010.  
  1011.         ShowProgress(50);
  1012.  
  1013.         OUTPUT("[+] OPTIONAL HEADER\n");
  1014.         OUTPUT("\tMagic: 0x%X\n", pNtHeaders->OptionalHeader.Magic);
  1015.         OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pNtHeaders->OptionalHeader.AddressOfEntryPoint);
  1016.         OUTPUT("\tImageBase: 0x%p\n", (void*)imageBase);
  1017.         OUTPUT("\tSectionAlignment: 0x%X\n", pNtHeaders->OptionalHeader.SectionAlignment);
  1018.         OUTPUT("\tFileAlignment: 0x%X\n", pNtHeaders->OptionalHeader.FileAlignment);
  1019.         OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  1020.         OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  1021.         OUTPUT("\tMajorImageVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorImageVersion);
  1022.         OUTPUT("\tMinorImageVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorImageVersion);
  1023.         OUTPUT("\tMajorSubsystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorSubsystemVersion);
  1024.         OUTPUT("\tMinorSubsystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorSubsystemVersion);
  1025.         OUTPUT("\tWin32VersionValue: 0x%X\n", pNtHeaders->OptionalHeader.Win32VersionValue);
  1026.         OUTPUT("\tSizeOfImage: 0x%X\n", sizeOfImage);
  1027.         OUTPUT("\tSizeOfHeaders: 0x%X\n", pNtHeaders->OptionalHeader.SizeOfHeaders);
  1028.         OUTPUT("\tCheckSum: 0x%X\n", pNtHeaders->OptionalHeader.CheckSum);
  1029.         OUTPUT("\tSubsystem: 0x%X %s\n",
  1030.             pNtHeaders->OptionalHeader.Subsystem,
  1031.             PEHelpers::GetSubsystem(pNtHeaders->OptionalHeader.Subsystem).c_str());
  1032.  
  1033.         OUTPUT("\n[+] DATA DIRECTORIES\n");
  1034.         for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  1035.             const auto& dir = pNtHeaders->OptionalHeader.DataDirectory[i];
  1036.             if (dir.VirtualAddress != 0) {
  1037.                 if (!PEHelpers::IsRvaValid(dir.VirtualAddress, fileSize, pNtHeaders)) {
  1038.                     OUTPUT("\t%s: Invalid RVA detected!\n", PEHelpers::GetDataDirectoryName(i).c_str());
  1039.                     continue;
  1040.                 }
  1041.                 OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  1042.                 OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
  1043.                 OUTPUT("\t\tSize: 0x%X\n", dir.Size);
  1044.             }
  1045.         }
  1046.  
  1047.         ShowProgress(60);
  1048.         OUTPUT("\n[+] SECTION HEADERS\n");
  1049.         auto pSection = IMAGE_FIRST_SECTION(pNtHeaders);
  1050.         for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  1051.             if (IsBadReadPtr(pSection, sizeof(IMAGE_SECTION_HEADER))) {
  1052.                 OUTPUT("[-] Invalid section header detected!\n");
  1053.                 break;
  1054.             }
  1055.             char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1056.             memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  1057.             for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  1058.                 if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  1059.                     sectionName[j] = '\0';
  1060.                 }
  1061.             }
  1062.             wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1063.             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1064.                 sectionName, -1,
  1065.                 wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  1066.             OUTPUT("\tSECTION: %s\n", wideSectionName);
  1067.             OUTPUT("\t\tVirtualSize: 0x%X\n", pSection->Misc.VirtualSize);
  1068.             OUTPUT("\t\tVirtualAddress: 0x%X\n", pSection->VirtualAddress);
  1069.             OUTPUT("\t\tSizeOfRawData: 0x%X\n", pSection->SizeOfRawData);
  1070.             OUTPUT("\t\tPointerToRawData: 0x%X\n", pSection->PointerToRawData);
  1071.             OUTPUT("\t\tPointerToRelocations: 0x%X\n", pSection->PointerToRelocations);
  1072.             OUTPUT("\t\tPointerToLinenumbers: 0x%X\n", pSection->PointerToLinenumbers);
  1073.             OUTPUT("\t\tNumberOfRelocations: 0x%X\n", pSection->NumberOfRelocations);
  1074.             OUTPUT("\t\tNumberOfLinenumbers: 0x%X\n", pSection->NumberOfLinenumbers);
  1075.             OUTPUT("\t\tCharacteristics: 0x%X %s\n\n",
  1076.                 pSection->Characteristics,
  1077.                 PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  1078.         }
  1079.  
  1080.         ShowProgress(70);
  1081.  
  1082.         const auto& importDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  1083.         if (importDir.VirtualAddress && importDir.Size) {
  1084.             if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, fileSize, pNtHeaders)) {
  1085.                 OUTPUT("[-] Invalid import directory RVA!\n");
  1086.                 break;
  1087.             }
  1088.             OUTPUT("\n[+] IMPORT DIRECTORY\n");
  1089.             auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  1090.                 importDir.VirtualAddress,
  1091.                 IMAGE_FIRST_SECTION(pNtHeaders),
  1092.                 pNtHeaders->FileHeader.NumberOfSections,
  1093.                 lpFileContent);
  1094.             if (pImportDesc) {
  1095.                 while (pImportDesc->Name != 0) {
  1096.                     if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  1097.                         OUTPUT("[-] Invalid import descriptor detected!\n");
  1098.                         break;
  1099.                     }
  1100.                     const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  1101.                         pImportDesc->Name,
  1102.                         IMAGE_FIRST_SECTION(pNtHeaders),
  1103.                         pNtHeaders->FileHeader.NumberOfSections,
  1104.                         lpFileContent);
  1105.                     if (dllName && !IsBadReadPtr(dllName, 1)) {
  1106.                         std::vector<wchar_t> wideDllName(MAX_PATH);
  1107.                         MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  1108.                         OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  1109.                         OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  1110.                         OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  1111.                         OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  1112.                         OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  1113.                         OUTPUT("\n\tImported Functions:\n");
  1114.  
  1115.                         if (is64Bit) {
  1116.                             auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  1117.                                 pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1118.                                 IMAGE_FIRST_SECTION(pNtHeaders),
  1119.                                 pNtHeaders->FileHeader.NumberOfSections,
  1120.                                 lpFileContent);
  1121.                             while (pThunk && pThunk->u1.AddressOfData) {
  1122.                                 if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)) {
  1123.                                     auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1124.                                         (DWORD)pThunk->u1.AddressOfData,
  1125.                                         IMAGE_FIRST_SECTION(pNtHeaders),
  1126.                                         pNtHeaders->FileHeader.NumberOfSections,
  1127.                                         lpFileContent);
  1128.                                     if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1129.                                         std::vector<wchar_t> wideFuncName(MAX_PATH);
  1130.                                         MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1131.                                             wideFuncName.data(), MAX_PATH);
  1132.                                         OUTPUT("\t\t%s\n", wideFuncName.data());
  1133.                                     }
  1134.                                 }
  1135.                                 else {
  1136.                                     OUTPUT("\t\tOrdinal: %lld\n", pThunk->u1.Ordinal & 0xFFFF);
  1137.                                 }
  1138.                                 pThunk++;
  1139.                             }
  1140.                         }
  1141.                         else {
  1142.                             auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  1143.                                 pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1144.                                 IMAGE_FIRST_SECTION(pNtHeaders),
  1145.                                 pNtHeaders->FileHeader.NumberOfSections,
  1146.                                 lpFileContent);
  1147.                             while (pThunk && pThunk->u1.AddressOfData) {
  1148.                                 if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) {
  1149.                                     auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1150.                                         pThunk->u1.AddressOfData,
  1151.                                         IMAGE_FIRST_SECTION(pNtHeaders),
  1152.                                         pNtHeaders->FileHeader.NumberOfSections,
  1153.                                         lpFileContent);
  1154.                                     if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1155.                                         std::vector<wchar_t> wideFuncName(MAX_PATH);
  1156.                                         MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1157.                                             wideFuncName.data(), MAX_PATH);
  1158.                                         OUTPUT("\t\t%s\n", wideFuncName.data());
  1159.                                     }
  1160.                                 }
  1161.                                 else {
  1162.                                     OUTPUT("\t\tOrdinal: %d\n", pThunk->u1.Ordinal & 0xFFFF);
  1163.                                 }
  1164.                                 pThunk++;
  1165.                             }
  1166.                         }
  1167.                     }
  1168.                     pImportDesc++;
  1169.                 }
  1170.             }
  1171.         }
  1172.  
  1173.         ShowProgress(80);
  1174.  
  1175.         const auto& exportDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1176.         if (exportDir.VirtualAddress && exportDir.Size) {
  1177.             if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, fileSize, pNtHeaders)) {
  1178.                 OUTPUT("[-] Invalid export directory RVA!\n");
  1179.                 break;
  1180.             }
  1181.             OUTPUT("\n[+] EXPORT DIRECTORY\n");
  1182.             auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1183.                 exportDir.VirtualAddress,
  1184.                 IMAGE_FIRST_SECTION(pNtHeaders),
  1185.                 pNtHeaders->FileHeader.NumberOfSections,
  1186.                 lpFileContent);
  1187.             if (pExportDir && !IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  1188.                 OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  1189.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  1190.                 OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  1191.                 OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  1192.                 OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  1193.                 OUTPUT("\tBase: %d\n", pExportDir->Base);
  1194.                 OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  1195.                 OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  1196.                 OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  1197.                 OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  1198.                 OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  1199.  
  1200.                 auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1201.                     pExportDir->AddressOfFunctions,
  1202.                     IMAGE_FIRST_SECTION(pNtHeaders),
  1203.                     pNtHeaders->FileHeader.NumberOfSections,
  1204.                     lpFileContent);
  1205.                 auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1206.                     pExportDir->AddressOfNames,
  1207.                     IMAGE_FIRST_SECTION(pNtHeaders),
  1208.                     pNtHeaders->FileHeader.NumberOfSections,
  1209.                     lpFileContent);
  1210.                 auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1211.                     pExportDir->AddressOfNameOrdinals,
  1212.                     IMAGE_FIRST_SECTION(pNtHeaders),
  1213.                     pNtHeaders->FileHeader.NumberOfSections,
  1214.                     lpFileContent);
  1215.  
  1216.                 if (pNames && pNameOrdinals && pFunctions) {
  1217.                     OUTPUT("\tExported Functions:\n\n");
  1218.                     for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1219.                         if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  1220.                             IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  1221.                             break;
  1222.                         }
  1223.  
  1224.                         const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1225.                             pNames[i],
  1226.                             IMAGE_FIRST_SECTION(pNtHeaders),
  1227.                             pNtHeaders->FileHeader.NumberOfSections,
  1228.                             lpFileContent);
  1229.  
  1230.                         if (functionName && !IsBadReadPtr(functionName, 1)) {
  1231.                             WORD ordinal = pNameOrdinals[i];
  1232.                             if (ordinal < pExportDir->NumberOfFunctions) {
  1233.                                 DWORD functionRva = pFunctions[ordinal];
  1234.                                 if (functionRva >= exportDir.VirtualAddress &&
  1235.                                     functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1236.                                     const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1237.                                         functionRva,
  1238.                                         IMAGE_FIRST_SECTION(pNtHeaders),
  1239.                                         pNtHeaders->FileHeader.NumberOfSections,
  1240.                                         lpFileContent);
  1241.                                     if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  1242.                                         std::vector<wchar_t> wideForwardName(MAX_PATH);
  1243.                                         MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1244.                                             wideForwardName.data(), MAX_PATH);
  1245.                                         OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1246.                                             functionName,
  1247.                                             ordinal + pExportDir->Base,
  1248.                                             wideForwardName.data());
  1249.                                     }
  1250.                                 }
  1251.                                 else {
  1252.                                     OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1253.                                         functionName,
  1254.                                         ordinal + pExportDir->Base,
  1255.                                         functionRva);
  1256.                                 }
  1257.                             }
  1258.                         }
  1259.                     }
  1260.                 }
  1261.             }
  1262.         }
  1263.  
  1264.         ShowProgress(90);
  1265.  
  1266.         const auto& resourceDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1267.         if (resourceDir.VirtualAddress && resourceDir.Size) {
  1268.             if (!PEHelpers::IsRvaValid(resourceDir.VirtualAddress, fileSize, pNtHeaders)) {
  1269.                 OUTPUT("[-] Invalid resource directory RVA!\n");
  1270.                 break;
  1271.             }
  1272.             OUTPUT("\n[+] RESOURCE DIRECTORY\n");
  1273.             auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  1274.                 resourceDir.VirtualAddress,
  1275.                 IMAGE_FIRST_SECTION(pNtHeaders),
  1276.                 pNtHeaders->FileHeader.NumberOfSections,
  1277.                 lpFileContent);
  1278.             if (pResourceDir && !IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1279.                 const wchar_t* resourceTypes[] = {
  1280.                     L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  1281.                     L"Menu",        L"Dialog",      L"String",      L"FontDir",
  1282.                     L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  1283.                     L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  1284.                 };
  1285.                 ProcessResourceDirectory(pResourceDir, 0, nullptr,
  1286.                     pResourceDir, resourceTypes, pNtHeaders, lpFileContent);
  1287.             }
  1288.             else {
  1289.                 OUTPUT("[-] Invalid or corrupted resource directory\n");
  1290.             }
  1291.         }
  1292.  
  1293.         const auto& debugDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1294.         if (debugDir.VirtualAddress && debugDir.Size) {
  1295.             if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, fileSize, pNtHeaders)) {
  1296.                 OUTPUT("[-] Invalid debug directory RVA!\n");
  1297.                 break;
  1298.             }
  1299.             OUTPUT("\n[+] DEBUG DIRECTORY\n");
  1300.             auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  1301.                 debugDir.VirtualAddress,
  1302.                 IMAGE_FIRST_SECTION(pNtHeaders),
  1303.                 pNtHeaders->FileHeader.NumberOfSections,
  1304.                 lpFileContent);
  1305.             if (pDebugDir && !IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1306.                 DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  1307.                 for (DWORD i = 0; i < numEntries; i++) {
  1308.                     OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  1309.                     OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  1310.                     OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  1311.                     OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  1312.                     OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  1313.                     switch (pDebugDir[i].Type) {
  1314.                     case IMAGE_DEBUG_TYPE_COFF:
  1315.                         OUTPUT(" (COFF)\n"); break;
  1316.                     case IMAGE_DEBUG_TYPE_CODEVIEW:
  1317.                         OUTPUT(" (CodeView)\n"); break;
  1318.                     case IMAGE_DEBUG_TYPE_FPO:
  1319.                         OUTPUT(" (FPO)\n"); break;
  1320.                     case IMAGE_DEBUG_TYPE_MISC:
  1321.                         OUTPUT(" (Misc)\n"); break;
  1322.                     case IMAGE_DEBUG_TYPE_EXCEPTION:
  1323.                         OUTPUT(" (Exception)\n"); break;
  1324.                     default:
  1325.                         OUTPUT(" (Unknown)\n"); break;
  1326.                     }
  1327.                     OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  1328.                     OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  1329.                     OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  1330.  
  1331.                     if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1332.                         pDebugDir[i].PointerToRawData != 0 &&
  1333.                         pDebugDir[i].SizeOfData >= 24) {
  1334.                         auto pCVHeader = (DWORD*)((BYTE*)lpFileContent + pDebugDir[i].PointerToRawData);
  1335.                         if (!IsBadReadPtr(pCVHeader, sizeof(DWORD)) && *pCVHeader == 0x53445352) {
  1336.                             auto pCVData = (char*)(pCVHeader + 1);
  1337.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  1338.                                 std::vector<wchar_t> pdbPath(MAX_PATH);
  1339.                                 MultiByteToWideChar(CP_ACP, 0, pCVData + 16, -1,
  1340.                                     pdbPath.data(), MAX_PATH);
  1341.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath.data());
  1342.                             }
  1343.                         }
  1344.                     }
  1345.                 }
  1346.             }
  1347.         }
  1348.  
  1349.         ShowProgress(100);
  1350.         SetStatusText(L"Analysis complete");
  1351.         ShowWindow(g_hProgressBar, SW_HIDE);
  1352.  
  1353.     } while (false); // End of the do-while loop that replaced goto
  1354.  
  1355.     // Cleanup
  1356.     if (lpFileContent) UnmapViewOfFile(lpFileContent);
  1357.     if (hFileMapping) CloseHandle(hFileMapping);
  1358.     if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
  1359.     UpdateEditControl();
  1360. }
  1361.  
  1362.    
  1363.     /*OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  1364.  
  1365.     FileMapper mapper;
  1366.     if (!mapper.Initialize(filePathW)) {
  1367.         SetStatusText(L"Failed to open file!");
  1368.         OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
  1369.         return;
  1370.     }
  1371.  
  1372.     ShowProgress(20);  // After initial file opening
  1373.  
  1374.  
  1375.     // Open and read file
  1376.     HANDLE hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
  1377.         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  1378.     if (hFile == INVALID_HANDLE_VALUE) {
  1379.         OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  1380.         return;
  1381.     }
  1382.  
  1383.     DWORD fileSize = GetFileSize(hFile, nullptr);
  1384.     if (fileSize == INVALID_FILE_SIZE) {
  1385.         CloseHandle(hFile);
  1386.         OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
  1387.         return;
  1388.     }
  1389.  
  1390.     HANDLE hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  1391.     if (!hFileMapping) {
  1392.         CloseHandle(hFile);
  1393.         OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
  1394.         return;
  1395.     }
  1396.  
  1397.     LPVOID lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  1398.     if (!lpFileContent) {
  1399.         CloseHandle(hFileMapping);
  1400.         CloseHandle(hFile);
  1401.         OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
  1402.         return;
  1403.     }
  1404.  
  1405.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
  1406.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  1407.         OUTPUT("[-] Invalid DOS signature!\r\n");
  1408.         return;
  1409.     }
  1410.  
  1411.     ShowProgress(30);
  1412.  
  1413.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
  1414.         static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
  1415.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  1416.         OUTPUT("[-] Invalid NT signature!\r\n");
  1417.         return;
  1418.     }
  1419.  
  1420.     // Add right after this line:
  1421. // OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  1422.  
  1423. // Add PE Image Information and Architecture
  1424.     OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  1425.     // Replace the Architecture output line with this:
  1426.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  1427.         OUTPUT("[+] Architecture: x86\n\n");
  1428.     }
  1429.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
  1430.         OUTPUT("[+] Architecture: x64\n\n");
  1431.     }
  1432.     else {
  1433.         OUTPUT("[+] Architecture: Unknown\n\n");
  1434.     }
  1435.  
  1436.     // Add complete DOS Header information
  1437.     OUTPUT("[+] DOS HEADER\n");
  1438.     OUTPUT("\te_magic    : 0x%X\n", pImageDosHeader->e_magic);
  1439.     OUTPUT("\te_cblp     : 0x%X\n", pImageDosHeader->e_cblp);
  1440.     OUTPUT("\te_cp       : 0x%X\n", pImageDosHeader->e_cp);
  1441.     OUTPUT("\te_crlc     : 0x%X\n", pImageDosHeader->e_crlc);
  1442.     OUTPUT("\te_cparhdr  : 0x%X\n", pImageDosHeader->e_cparhdr);
  1443.     OUTPUT("\te_minalloc : 0x%X\n", pImageDosHeader->e_minalloc);
  1444.     OUTPUT("\te_maxalloc : 0x%X\n", pImageDosHeader->e_maxalloc);
  1445.     OUTPUT("\te_ss       : 0x%X\n", pImageDosHeader->e_ss);
  1446.     OUTPUT("\te_sp       : 0x%X\n", pImageDosHeader->e_sp);
  1447.     OUTPUT("\te_csum     : 0x%X\n", pImageDosHeader->e_csum);
  1448.     OUTPUT("\te_ip       : 0x%X\n", pImageDosHeader->e_ip);
  1449.     OUTPUT("\te_cs       : 0x%X\n", pImageDosHeader->e_cs);
  1450.     OUTPUT("\te_lfarlc   : 0x%X\n", pImageDosHeader->e_lfarlc);
  1451.     OUTPUT("\te_ovno     : 0x%X\n", pImageDosHeader->e_ovno);
  1452.     OUTPUT("\te_oemid    : 0x%X\n", pImageDosHeader->e_oemid);
  1453.     OUTPUT("\te_oeminfo  : 0x%X\n", pImageDosHeader->e_oeminfo);
  1454.     OUTPUT("\te_lfanew   : 0x%X\n\n", pImageDosHeader->e_lfanew);
  1455.  
  1456.     // Add NT Header signature before the existing PE FILE HEADER section
  1457.     OUTPUT("[+] NT HEADER\n");
  1458.     OUTPUT("\tSignature  : 0x%X\n\n", pImageNtHeaders->Signature);
  1459.  
  1460.     // The rest of your existing code continues here...
  1461.     // OUTPUT("[+] PE FILE HEADER\n");
  1462.  
  1463.     ShowProgress(40);
  1464.  
  1465.     // Print File Header Information
  1466.     OUTPUT("[+] PE FILE HEADER\n");
  1467.     OUTPUT("\tMachine: 0x%X\n", pImageNtHeaders->FileHeader.Machine);
  1468.     OUTPUT("\tNumberOfSections: 0x%X\n", pImageNtHeaders->FileHeader.NumberOfSections);
  1469.     OUTPUT("\tTimeDateStamp: 0x%X\n", pImageNtHeaders->FileHeader.TimeDateStamp);
  1470.     OUTPUT("\tPointerToSymbolTable: 0x%X\r\n",
  1471.         static_cast<DWORD>(pImageNtHeaders->FileHeader.PointerToSymbolTable));
  1472.     OUTPUT("\tNumberOfSymbols: 0x%X\r\n",
  1473.         static_cast<DWORD>(pImageNtHeaders->FileHeader.NumberOfSymbols));
  1474.     OUTPUT("\tSizeOfOptionalHeader: 0x%X\r\n",
  1475.         static_cast<DWORD>(pImageNtHeaders->FileHeader.SizeOfOptionalHeader));
  1476.     OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1477.         pImageNtHeaders->FileHeader.Characteristics,
  1478.         PEHelpers::GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics).c_str());
  1479.  
  1480.     ShowProgress(50);
  1481.  
  1482.     // Print Optional Header Information
  1483.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  1484.     OUTPUT("\tMagic: 0x%X\n", pImageNtHeaders->OptionalHeader.Magic);
  1485.     OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  1486.     OUTPUT("\tImageBase: 0x%llX\n", (ULONGLONG)pImageNtHeaders->OptionalHeader.ImageBase);
  1487.     OUTPUT("\tSectionAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.SectionAlignment);
  1488.     OUTPUT("\tFileAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.FileAlignment);
  1489.  
  1490.     // Added missing Optional Header fields
  1491.     OUTPUT("\tMajorOperatingSystemVersion: 0x%X\r\n",
  1492.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion));
  1493.     OUTPUT("\tMinorOperatingSystemVersion: 0x%X\r\n",
  1494.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion));
  1495.     OUTPUT("\tMajorImageVersion: 0x%X\r\n",
  1496.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorImageVersion));
  1497.     OUTPUT("\tMinorImageVersion: 0x%X\r\n",
  1498.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorImageVersion));
  1499.     OUTPUT("\tMajorSubsystemVersion: 0x%X\r\n",
  1500.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorSubsystemVersion));
  1501.     OUTPUT("\tMinorSubsystemVersion: 0x%X\r\n",
  1502.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorSubsystemVersion));
  1503.     OUTPUT("\tWin32VersionValue: 0x%X\r\n",
  1504.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Win32VersionValue));
  1505.     OUTPUT("\tSizeOfImage: 0x%X\r\n",
  1506.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfImage));
  1507.     OUTPUT("\tSizeOfHeaders: 0x%X\r\n",
  1508.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfHeaders));
  1509.     OUTPUT("\tCheckSum: 0x%X\r\n",
  1510.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.CheckSum));
  1511.     OUTPUT("\tSubsystem: 0x%X %s\r\n",
  1512.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Subsystem),
  1513.         PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
  1514.     OUTPUT("\tDllCharacteristics: 0x%X\r\n",
  1515.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.DllCharacteristics));
  1516.     OUTPUT("\tSizeOfStackReserve: 0x%llX\r\n",
  1517.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackReserve));
  1518.     OUTPUT("\tSizeOfStackCommit: 0x%llX\r\n",
  1519.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackCommit));
  1520.     OUTPUT("\tSizeOfHeapReserve: 0x%llX\r\n",
  1521.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapReserve));
  1522.     OUTPUT("\tSizeOfHeapCommit: 0x%llX\r\n",
  1523.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapCommit));
  1524.     OUTPUT("\tLoaderFlags: 0x%X\r\n",
  1525.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.LoaderFlags));
  1526.     OUTPUT("\tNumberOfRvaAndSizes: 0x%X\r\n\r\n",
  1527.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes));
  1528.  
  1529.     OUTPUT("\tSubsystem: 0x%X %s\n\n",
  1530.         pImageNtHeaders->OptionalHeader.Subsystem,
  1531.         PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
  1532.  
  1533.     // Print Data Directories
  1534.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  1535.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  1536.         const auto& dir = pImageNtHeaders->OptionalHeader.DataDirectory[i];
  1537.         if (dir.VirtualAddress != 0) {
  1538.             OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  1539.             OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
  1540.             OUTPUT("\t\tSize: 0x%X\n", dir.Size);
  1541.         }
  1542.     }
  1543.  
  1544.     // Analyze Sections
  1545.     OUTPUT("\n[+] PE IMAGE SECTIONS\r\n");
  1546.     auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  1547.     for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  1548.         // Create a null-terminated string from the section name
  1549.         char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1550.         memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  1551.  
  1552.         // Remove any non-printable characters
  1553.         for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  1554.             if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  1555.                 sectionName[j] = '\0';
  1556.             }
  1557.         }
  1558.  
  1559.         // Convert to wide string
  1560.         wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1561.         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1562.             sectionName, -1,
  1563.             wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  1564.  
  1565.         OUTPUT("\tSECTION : %s\r\n", wideSectionName);
  1566.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\r\n", pSection->Misc.PhysicalAddress);
  1567.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\r\n", pSection->Misc.VirtualSize);
  1568.         OUTPUT("\t\tVirtualAddress : 0x%X\r\n", pSection->VirtualAddress);
  1569.         OUTPUT("\t\tSizeOfRawData : 0x%X\r\n", pSection->SizeOfRawData);
  1570.         OUTPUT("\t\tPointerToRawData : 0x%X\r\n", pSection->PointerToRawData);
  1571.         OUTPUT("\t\tPointerToRelocations : 0x%X\r\n", pSection->PointerToRelocations);
  1572.         OUTPUT("\t\tPointerToLinenumbers : 0x%X\r\n", pSection->PointerToLinenumbers);
  1573.         OUTPUT("\t\tNumberOfRelocations : 0x%X\r\n", pSection->NumberOfRelocations);
  1574.         OUTPUT("\t\tNumberOfLinenumbers : 0x%X\r\n", pSection->NumberOfLinenumbers);
  1575.         OUTPUT("\t\tCharacteristics : 0x%X %s\r\n\r\n",
  1576.             pSection->Characteristics,
  1577.             PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  1578.     }
  1579.  
  1580.     ShowProgress(60);
  1581.  
  1582.     // Analyze Imports
  1583.     // Then modify the Import section like this:
  1584.     const auto& importDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  1585.     if (importDir.VirtualAddress && importDir.Size) {
  1586.         OUTPUT("\n[+] IMPORTED DLLS AND FUNCTIONS\r\n");
  1587.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  1588.             importDir.VirtualAddress,
  1589.             IMAGE_FIRST_SECTION(pImageNtHeaders),
  1590.             pImageNtHeaders->FileHeader.NumberOfSections,
  1591.             lpFileContent);
  1592.  
  1593.         bool is64Bit = Is64BitPE(pImageNtHeaders);
  1594.  
  1595.         while (pImportDesc && pImportDesc->Name != 0) {
  1596.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  1597.                 pImportDesc->Name,
  1598.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  1599.                 pImageNtHeaders->FileHeader.NumberOfSections,
  1600.                 lpFileContent);
  1601.  
  1602.             if (dllName) {
  1603.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  1604.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  1605.  
  1606.                 OUTPUT("\n\tDLL NAME : %s\r\n", wideDllName.data());
  1607.                 OUTPUT("\tCharacteristics : 0x%X\r\n", pImportDesc->Characteristics);
  1608.                 OUTPUT("\tOriginalFirstThunk : 0x%X\r\n", pImportDesc->OriginalFirstThunk);
  1609.                 OUTPUT("\tTimeDateStamp : 0x%X\r\n", pImportDesc->TimeDateStamp);
  1610.                 OUTPUT("\tForwarderChain : 0x%X\r\n", pImportDesc->ForwarderChain);
  1611.                 OUTPUT("\tFirstThunk : 0x%X\r\n", pImportDesc->FirstThunk);
  1612.  
  1613.                 OUTPUT("\n\tImported Functions :\r\n\r\n");
  1614.  
  1615.                 ULONGLONG ordinalFlag = is64Bit ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32;
  1616.  
  1617.                 if (is64Bit) {
  1618.                     auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  1619.                         pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1620.                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  1621.                         pImageNtHeaders->FileHeader.NumberOfSections,
  1622.                         lpFileContent);
  1623.  
  1624.                     while (pThunk && pThunk->u1.AddressOfData) {
  1625.                         if (!(pThunk->u1.Ordinal & ordinalFlag)) {
  1626.                             auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1627.                                 (DWORD)pThunk->u1.AddressOfData,
  1628.                                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  1629.                                 pImageNtHeaders->FileHeader.NumberOfSections,
  1630.                                 lpFileContent);
  1631.  
  1632.                             if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1633.                                 std::vector<wchar_t> wideFuncName(MAX_PATH);
  1634.                                 MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1635.                                     wideFuncName.data(), MAX_PATH);
  1636.                                 OUTPUT("\t\t%s\r\n", wideFuncName.data());
  1637.                             }
  1638.                         }
  1639.                         else {
  1640.                             OUTPUT("\t\tOrdinal: %lld\r\n", pThunk->u1.Ordinal & 0xFFFF);
  1641.                         }
  1642.                         pThunk++;
  1643.                     }
  1644.                 }
  1645.                 else {
  1646.                     auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  1647.                         pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1648.                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  1649.                         pImageNtHeaders->FileHeader.NumberOfSections,
  1650.                         lpFileContent);
  1651.  
  1652.                     while (pThunk && pThunk->u1.AddressOfData) {
  1653.                         if (!(pThunk->u1.Ordinal & ordinalFlag)) {
  1654.                             auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1655.                                 pThunk->u1.AddressOfData,
  1656.                                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  1657.                                 pImageNtHeaders->FileHeader.NumberOfSections,
  1658.                                 lpFileContent);
  1659.  
  1660.                             if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1661.                                 std::vector<wchar_t> wideFuncName(MAX_PATH);
  1662.                                 MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1663.                                     wideFuncName.data(), MAX_PATH);
  1664.                                 OUTPUT("\t\t%s\r\n", wideFuncName.data());
  1665.                             }
  1666.                         }
  1667.                         else {
  1668.                             OUTPUT("\t\tOrdinal: %d\r\n", pThunk->u1.Ordinal & 0xFFFF);
  1669.                         }
  1670.                         pThunk++;
  1671.                     }
  1672.                 }
  1673.             }
  1674.             pImportDesc++;
  1675.         }
  1676.     }
  1677.  
  1678.         ShowProgress(70);
  1679.  
  1680.         // In your AnalyzePEFile function, add this code after the imports section (before the cleanup label):
  1681.  
  1682.         // Handle Exports
  1683.         const auto& exportDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1684.         if (exportDir.VirtualAddress && exportDir.Size) {
  1685.             OUTPUT("\n[+] EXPORTED FUNCTIONS\n");
  1686.             auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1687.                 exportDir.VirtualAddress,
  1688.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  1689.                 pImageNtHeaders->FileHeader.NumberOfSections,
  1690.                 lpFileContent);
  1691.  
  1692.             if (pExportDir) {
  1693.                 // ... (existing code)
  1694.  
  1695.                 auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1696.                     pExportDir->AddressOfFunctions,
  1697.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  1698.                     pImageNtHeaders->FileHeader.NumberOfSections,
  1699.                     lpFileContent);
  1700.  
  1701.                 auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1702.                     pExportDir->AddressOfNames,
  1703.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  1704.                     pImageNtHeaders->FileHeader.NumberOfSections,
  1705.                     lpFileContent);
  1706.  
  1707.                 auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1708.                     pExportDir->AddressOfNameOrdinals,
  1709.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  1710.                     pImageNtHeaders->FileHeader.NumberOfSections,
  1711.                     lpFileContent);
  1712.  
  1713.                 if (pNames && pNameOrdinals && pFunctions) {
  1714.                     for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1715.                         const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1716.                             pNames[i],
  1717.                             IMAGE_FIRST_SECTION(pImageNtHeaders),
  1718.                             pImageNtHeaders->FileHeader.NumberOfSections,
  1719.                             lpFileContent);
  1720.  
  1721.                         if (functionName) {
  1722.                             WORD ordinal = pNameOrdinals[i];
  1723.                             DWORD functionRva = pFunctions[ordinal];
  1724.  
  1725.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  1726.                             MultiByteToWideChar(CP_ACP, 0, functionName, -1,
  1727.                                 wideFuncName.data(), MAX_PATH);
  1728.  
  1729.                             // Check if it's a forwarded export
  1730.                             if (functionRva >= exportDir.VirtualAddress &&
  1731.                                 functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1732.                                 // This is a forwarded export
  1733.                                 const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1734.                                     functionRva,
  1735.                                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  1736.                                     pImageNtHeaders->FileHeader.NumberOfSections,
  1737.                                     lpFileContent);
  1738.  
  1739.                                 if (forwardName) {
  1740.                                     std::vector<wchar_t> wideForwardName(MAX_PATH);
  1741.                                     MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1742.                                         wideForwardName.data(), MAX_PATH);
  1743.                                     OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1744.                                         wideFuncName.data(),
  1745.                                         ordinal + pExportDir->Base,
  1746.                                         wideForwardName.data());
  1747.                                 }
  1748.                             }
  1749.                             else {
  1750.                                 OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1751.                                     wideFuncName.data(),
  1752.                                     ordinal + pExportDir->Base,
  1753.                                     functionRva);
  1754.                             }
  1755.                         }
  1756.                     }
  1757.  
  1758.                     // Check for exports by ordinal only (no names)
  1759.                     for (DWORD i = 0; i < pExportDir->NumberOfFunctions; i++) {
  1760.                         if (pFunctions[i] != 0) {
  1761.                             bool hasName = false;
  1762.                             for (DWORD j = 0; j < pExportDir->NumberOfNames; j++) {
  1763.                                 if (pNameOrdinals[j] == i) {
  1764.                                     hasName = true;
  1765.                                     break;
  1766.                                 }
  1767.                             }
  1768.  
  1769.                             if (!hasName) {
  1770.                                 DWORD functionRva = pFunctions[i];
  1771.                                 if (functionRva >= exportDir.VirtualAddress &&
  1772.                                     functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1773.                                     // This is a forwarded export
  1774.                                     const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1775.                                         functionRva,
  1776.                                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  1777.                                         pImageNtHeaders->FileHeader.NumberOfSections,
  1778.                                         lpFileContent);
  1779.  
  1780.                                     if (forwardName) {
  1781.                                         std::vector<wchar_t> wideForwardName(MAX_PATH);
  1782.                                         MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1783.                                             wideForwardName.data(), MAX_PATH);
  1784.                                         OUTPUT("\t\tOrdinal: %d -> Forward to: %s\n",
  1785.                                             i + pExportDir->Base,
  1786.                                             wideForwardName.data());
  1787.                                     }
  1788.                                 }
  1789.                                 else {
  1790.                                     OUTPUT("\t\tOrdinal: %d (RVA: 0x%08X)\n",
  1791.                                         i + pExportDir->Base,
  1792.                                         functionRva);
  1793.                                 }
  1794.                             }
  1795.                         }
  1796.                     }
  1797.                 }
  1798.             }
  1799.         }
  1800.  
  1801.         ShowProgress(80);
  1802.  
  1803.         // Add after export directory analysis and before ShowProgress(100)
  1804.  
  1805.         // Resource Directory Analysis
  1806.         const auto& resourceDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1807.         if (resourceDir.VirtualAddress && resourceDir.Size) {
  1808.             OUTPUT("\n[+] RESOURCE DIRECTORY\n");
  1809.             auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  1810.                 resourceDir.VirtualAddress,
  1811.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  1812.                 pImageNtHeaders->FileHeader.NumberOfSections,
  1813.                 lpFileContent);
  1814.  
  1815.             if (pResourceDir && !IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1816.                 OUTPUT("\tCharacteristics: 0x%X\n", pResourceDir->Characteristics);
  1817.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pResourceDir->TimeDateStamp);
  1818.                 OUTPUT("\tMajorVersion: %d\n", pResourceDir->MajorVersion);
  1819.                 OUTPUT("\tMinorVersion: %d\n", pResourceDir->MinorVersion);
  1820.                 OUTPUT("\tNumberOfNamedEntries: %d\n", pResourceDir->NumberOfNamedEntries);
  1821.                 OUTPUT("\tNumberOfIdEntries: %d\n\n", pResourceDir->NumberOfIdEntries);
  1822.  
  1823.                 const wchar_t* resourceTypes[] = {
  1824.                     L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  1825.                     L"Menu",        L"Dialog",      L"String",      L"FontDir",
  1826.                     L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  1827.                     L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  1828.                 };
  1829.  
  1830.                 auto ProcessResourceDirectory = [&](PIMAGE_RESOURCE_DIRECTORY resDir, int level, const wchar_t* type = nullptr) {
  1831.                     if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1832.                         return;
  1833.                     }
  1834.  
  1835.                     auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  1836.                     WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  1837.  
  1838.                     for (WORD i = 0; i < totalEntries; i++) {
  1839.                         if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  1840.                             break;
  1841.                         }
  1842.  
  1843.                         for (int indent = 0; indent < level; indent++) {
  1844.                             OUTPUT("\t");
  1845.                         }
  1846.  
  1847.                         if (entry[i].NameIsString) {
  1848.                             auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)pResourceDir + entry[i].NameOffset);
  1849.                             if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  1850.                                 std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  1851.                                 wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  1852.                                     nameEntry->NameString, nameEntry->Length);
  1853.                                 resourceName[nameEntry->Length] = L'\0';
  1854.  
  1855.                                 if (level == 0) {
  1856.                                     OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  1857.                                 }
  1858.                                 else {
  1859.                                     OUTPUT("Name: %s\n", resourceName.data());
  1860.                                 }
  1861.                             }
  1862.                         }
  1863.                         else {
  1864.                             if (level == 0) {
  1865.                                 DWORD resourceType = entry[i].Id;
  1866.                                 if (resourceType < 16) {
  1867.                                     OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  1868.                                 }
  1869.                                 else {
  1870.                                     OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  1871.                                 }
  1872.                             }
  1873.                             else {
  1874.                                 OUTPUT("ID: %d\n", entry[i].Id);
  1875.                             }
  1876.                         }
  1877.  
  1878.                         if (entry[i].DataIsDirectory) {
  1879.                             auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pResourceDir + entry[i].OffsetToDirectory);
  1880.                             if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1881.                                 ProcessResourceDirectory(nextDir, level + 1,
  1882.                                     level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type);
  1883.                             }
  1884.                         }
  1885.                         else {
  1886.                             auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)pResourceDir + entry[i].OffsetToData);
  1887.                             if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  1888.                                 for (int indent = 0; indent < level + 1; indent++) {
  1889.                                     OUTPUT("\t");
  1890.                                 }
  1891.                                 OUTPUT("Size: %d bytes, RVA: 0x%X\n",
  1892.                                     dataEntry->Size, dataEntry->OffsetToData);
  1893.  
  1894.                                 // For Version Info resources, we can extract more details
  1895.                                 if (type && wcscmp(type, L"Version") == 0) {
  1896.                                     auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  1897.                                         dataEntry->OffsetToData,
  1898.                                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  1899.                                         pImageNtHeaders->FileHeader.NumberOfSections,
  1900.                                         lpFileContent);
  1901.  
  1902.                                     if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  1903.                                         auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40); // Skip VS_VERSION_INFO header
  1904.                                         if (versionInfo->dwSignature == 0xFEEF04BD) {
  1905.                                             for (int indent = 0; indent < level + 2; indent++) {
  1906.                                                 OUTPUT("\t");
  1907.                                             }
  1908.                                             OUTPUT("File Version: %d.%d.%d.%d\n",
  1909.                                                 HIWORD(versionInfo->dwFileVersionMS),
  1910.                                                 LOWORD(versionInfo->dwFileVersionMS),
  1911.                                                 HIWORD(versionInfo->dwFileVersionLS),
  1912.                                                 LOWORD(versionInfo->dwFileVersionLS));
  1913.                                         }
  1914.                                     }
  1915.                                 }
  1916.                             }
  1917.                         }
  1918.                     }
  1919.                 };
  1920.  
  1921.                 ProcessResourceDirectory(pResourceDir, 0);
  1922.             }
  1923.             else {
  1924.                 OUTPUT("[-] Invalid or corrupted resource directory\n");
  1925.             }
  1926.         }
  1927.  
  1928.         ShowProgress(90);
  1929.  
  1930.         // Debug Directory Analysis
  1931.         const auto& debugDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1932.         if (debugDir.VirtualAddress && debugDir.Size) {
  1933.             OUTPUT("\n[+] DEBUG DIRECTORY\n");
  1934.             auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  1935.             PIMAGE_SECTION_HEADER pDebugSection = nullptr;
  1936.  
  1937.             // Find the section containing the debug directory
  1938.             for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  1939.                 if (debugDir.VirtualAddress >= pSection->VirtualAddress &&
  1940.                     debugDir.VirtualAddress < (pSection->VirtualAddress + pSection->Misc.VirtualSize)) {
  1941.                     pDebugSection = pSection;
  1942.                     break;
  1943.                 }
  1944.             }
  1945.  
  1946.             if (!pDebugSection) {
  1947.                 OUTPUT("[-] Could not find debug section\n");
  1948.             }
  1949.             else {
  1950.                 // Calculate the correct offset for both 32-bit and 64-bit PE files
  1951.                 DWORD debugDirOffset = pDebugSection->PointerToRawData +
  1952.                     (debugDir.VirtualAddress - pDebugSection->VirtualAddress);
  1953.  
  1954.                 auto pDebugDirectory = reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
  1955.                     (BYTE*)lpFileContent + debugDirOffset);
  1956.  
  1957.                 // Safely process debug entries
  1958.                 DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16); // Limit entries to prevent overflow
  1959.  
  1960.                 for (DWORD i = 0; i < numEntries; i++) {
  1961.                     if (IsBadReadPtr(pDebugDirectory + i, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1962.                         OUTPUT("[-] Invalid debug directory entry detected\n");
  1963.                         break;
  1964.                     }
  1965.  
  1966.                     OUTPUT("\tCharacteristics: 0x%X\n", pDebugDirectory[i].Characteristics);
  1967.                     OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDirectory[i].TimeDateStamp);
  1968.                     OUTPUT("\tMajorVersion: %d\n", pDebugDirectory[i].MajorVersion);
  1969.                     OUTPUT("\tMinorVersion: %d\n", pDebugDirectory[i].MinorVersion);
  1970.                     OUTPUT("\tType: 0x%X", pDebugDirectory[i].Type);
  1971.  
  1972.                     // Process debug type
  1973.                     switch (pDebugDirectory[i].Type) {
  1974.                     case IMAGE_DEBUG_TYPE_COFF:
  1975.                         OUTPUT(" (COFF)\n"); break;
  1976.                     case IMAGE_DEBUG_TYPE_CODEVIEW:
  1977.                         OUTPUT(" (CodeView)\n"); break;
  1978.                     case IMAGE_DEBUG_TYPE_FPO:
  1979.                         OUTPUT(" (FPO)\n"); break;
  1980.                     case IMAGE_DEBUG_TYPE_MISC:
  1981.                         OUTPUT(" (Misc)\n"); break;
  1982.                     case IMAGE_DEBUG_TYPE_EXCEPTION:
  1983.                         OUTPUT(" (Exception)\n"); break;
  1984.                     default:
  1985.                         OUTPUT(" (Unknown)\n"); break;
  1986.                     }
  1987.  
  1988.                     OUTPUT("\tSizeOfData: 0x%X\n", pDebugDirectory[i].SizeOfData);
  1989.                     OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDirectory[i].AddressOfRawData);
  1990.                     OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDirectory[i].PointerToRawData);
  1991.  
  1992.                     // Process CodeView information if available
  1993.                     if (pDebugDirectory[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1994.                         pDebugDirectory[i].PointerToRawData != 0 &&
  1995.                         pDebugDirectory[i].SizeOfData >= 24) { // Minimum size for CodeView data
  1996.  
  1997.                         auto pCVHeader = reinterpret_cast<DWORD*>(
  1998.                             (BYTE*)lpFileContent + pDebugDirectory[i].PointerToRawData);
  1999.  
  2000.                         if (!IsBadReadPtr(pCVHeader, sizeof(DWORD)) && *pCVHeader == 0x53445352) {
  2001.                             auto pCVData = reinterpret_cast<char*>(pCVHeader + 1);
  2002.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  2003.                                 std::vector<wchar_t> pdbPath(MAX_PATH);
  2004.                                 MultiByteToWideChar(CP_ACP, 0, pCVData + 16, -1,
  2005.                                     pdbPath.data(), MAX_PATH);
  2006.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath.data());
  2007.                             }
  2008.                         }
  2009.                     }
  2010.                 }
  2011.             }
  2012.         }
  2013.  
  2014.         // Continue with ShowProgress(100)...
  2015.  
  2016.         // In your AnalyzePEFile function, at the end:
  2017.         ShowProgress(100);
  2018.         SetStatusText(L"Analysis complete");
  2019.         ShowWindow(g_hProgressBar, SW_HIDE);  // Optional: hide progress bar when done
  2020.  
  2021.     cleanup:
  2022.         if (lpFileContent) {
  2023.             UnmapViewOfFile(lpFileContent);
  2024.         }
  2025.         if (hFileMapping) {
  2026.             CloseHandle(hFileMapping);
  2027.         }
  2028.         if (hFile) {
  2029.             CloseHandle(hFile);
  2030.         }
  2031.  
  2032.         UpdateEditControl();
  2033. }*/
  2034.  
  2035. /*
  2036. //use below vv ALWAYS
  2037. void AnalyzePEFile(const wchar_t* filePathW) {
  2038.     OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  2039.  
  2040.     LPVOID lpFileContent = GetFileContent(filePathW);
  2041.     if (!lpFileContent) {
  2042.         OUTPUT("[-] Failed to read file content!\n");
  2043.         return;
  2044.     }
  2045.  
  2046.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  2047.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  2048.         OUTPUT("[-] Invalid DOS signature!\n");
  2049.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2050.         return;
  2051.     }
  2052.  
  2053.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  2054.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  2055.         OUTPUT("[-] Invalid NT signature!\n");
  2056.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2057.         return;
  2058.     }
  2059.  
  2060.     //UpdateEditControl(); //added just now remove line!
  2061.  
  2062.     OUTPUT("[+] PE FILE HEADER\n");
  2063.     OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  2064.     OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  2065.     OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  2066.     OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  2067.     OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  2068.     OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  2069.     OUTPUT("\tCharacteristics : 0x%X %s\n\n", (uintptr_t)pImageNtHeaders->FileHeader.Characteristics, GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  2070.  
  2071.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  2072.     OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  2073.     OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  2074.     OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  2075.     OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  2076.     OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  2077.     OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  2078.     OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  2079.     OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  2080.     OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  2081.     OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  2082.     OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  2083.     OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  2084.     OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  2085.     OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  2086.     OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  2087.     OUTPUT("\tSubsystem : 0x%X %s\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem, GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  2088.     OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  2089.     OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  2090.     OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  2091.     OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  2092.     OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  2093.     OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  2094.     OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  2095.  
  2096.     //UpdateEditControl(); //added just now remove line!
  2097.  
  2098.     GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  2099.  
  2100.     const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  2101.     const auto pImageImportSection = GetSections(pImageSectionHeader, pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  2102.  
  2103.     if (!pImageImportSection) {
  2104.         OUTPUT("[-] Error: Could not find import section!\n");
  2105.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2106.         return;
  2107.     }
  2108.  
  2109.     const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>((DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  2110.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  2111.         GetImports32(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  2112.     }
  2113.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
  2114.         GetImports64(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  2115.     }
  2116.     else {
  2117.         OUTPUT("[-] Unsupported architecture!\n");
  2118.     }
  2119.  
  2120.     HeapFree(GetProcessHeap(), 0, lpFileContent);
  2121.     UpdateEditControl();
  2122. }
  2123.  
  2124. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory) {
  2125.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  2126.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory) {
  2127.         if (pImageDataDirectory->VirtualAddress == 0) continue;
  2128.         OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->VirtualAddress);
  2129.         OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->Size);
  2130.     }
  2131. }
  2132.  
  2133. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader, int NumberOfSections, DWORD dImportAddress) {
  2134.     PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  2135.     OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  2136.     for (int i = 0; i < NumberOfSections; ++i) {
  2137.         const auto pCurrentSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  2138.         OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  2139.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  2140.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  2141.         OUTPUT("\t\tVirtualAddress : 0x%X\n", (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  2142.         OUTPUT("\t\tSizeOfRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  2143.         OUTPUT("\t\tPointerToRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  2144.         OUTPUT("\t\tCharacteristics : 0x%X %s\n", (uintptr_t)pCurrentSectionHeader->Characteristics, GetSectionProtection(pCurrentSectionHeader->Characteristics));
  2145.  
  2146.         if (dImportAddress >= pCurrentSectionHeader->VirtualAddress && dImportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize) {
  2147.             pImageImportHeader = pCurrentSectionHeader;
  2148.         }
  2149.     }
  2150.     return pImageImportHeader;
  2151. }
  2152.  
  2153. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  2154.     OUTPUT("\n[+] IMPORTED DLL\n");
  2155.     while (pImageImportDescriptor->Name != 0) {
  2156.         OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  2157.         if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  2158.             ++pImageImportDescriptor;
  2159.             continue;
  2160.         }
  2161.         auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA32>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  2162.         while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  2163.             const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  2164.             if (pImageImportByName) {
  2165.                 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  2166.             }
  2167.             pOriginalFirstThunk++;
  2168.         }
  2169.         pImageImportDescriptor++;
  2170.     }
  2171. }
  2172.  
  2173. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  2174.     OUTPUT("\n[+] IMPORTED DLL\n");
  2175.     while (pImageImportDescriptor->Name != 0) {
  2176.         OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  2177.         if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  2178.             ++pImageImportDescriptor;
  2179.             continue;
  2180.         }
  2181.         auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  2182.         while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  2183.             const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  2184.             if (pImageImportByName) {
  2185.                 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  2186.             }
  2187.             pOriginalFirstThunk++;
  2188.         }
  2189.         pImageImportDescriptor++;
  2190.     }
  2191. }
  2192. //use above ^^ ALWAYS
  2193. */
  2194.  
  2195.  
  2196. /*
  2197. // older-orig-deprecated vv
  2198. // Main PE Analysis function
  2199. void AnalyzePEFile(const wchar_t* filePathW)
  2200. {
  2201.     //WCHAR filePathW[MAX_PATH];
  2202.     //MultiByteToWideChar(CP_ACP, 0, filePathA, -1, filePathW, MAX_PATH);
  2203.     OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  2204.     //AppendToOutput(L"[+] Starting PE Analysis for: %ls\n\n", filePathW);
  2205.  
  2206.     // Get file content
  2207.     LPVOID lpFileContent = GetFileContent(filePathW);
  2208.     if (!lpFileContent)
  2209.     {
  2210.         OUTPUT("[-] Failed to read file content!\n");
  2211.         return;
  2212.     }
  2213.  
  2214.     // Get DOS header
  2215.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  2216.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
  2217.     {
  2218.         OUTPUT("[-] Invalid DOS signature!\n");
  2219.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2220.         return;
  2221.     }
  2222.  
  2223.     // Get NT headers
  2224.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  2225.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
  2226.     {
  2227.         OUTPUT("[-] Invalid NT signature!\n");
  2228.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2229.         return;
  2230.     }
  2231.  
  2232.     // Display File Header information
  2233.     OUTPUT("[+] PE FILE HEADER\n");
  2234.     OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  2235.     OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  2236.     OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  2237.     OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  2238.     OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  2239.     OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  2240.     OUTPUT("\tCharacteristics : 0x%X %s\n\n",
  2241.         (uintptr_t)pImageNtHeaders->FileHeader.Characteristics,
  2242.         GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  2243.  
  2244.     // Display Optional Header information
  2245.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  2246.     OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  2247.     OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  2248.     OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  2249.     OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  2250.     OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  2251.     OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  2252.     OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  2253.     OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  2254.     OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  2255.     OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  2256.     OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  2257.     OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  2258.     OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  2259.     OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  2260.     OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  2261.     OUTPUT("\tSubsystem : 0x%X %s\n",
  2262.         (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem,
  2263.         GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  2264.     OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  2265.     OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  2266.     OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  2267.     OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  2268.     OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  2269.     OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  2270.     OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  2271.  
  2272.     // Get Data Directories
  2273.     GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  2274.  
  2275.     // Get the import section
  2276.     const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
  2277.         (DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  2278.  
  2279.     const auto pImageImportSection = GetSections(
  2280.         pImageSectionHeader,
  2281.         pImageNtHeaders->FileHeader.NumberOfSections,
  2282.         pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  2283.  
  2284.     if (!pImageImportSection)
  2285.     {
  2286.         OUTPUT("[-] Error: Could not find import section!\n");
  2287.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  2288.         return;
  2289.     }
  2290.  
  2291.     // Get imports based on architecture
  2292.     const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
  2293.         (DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  2294.  
  2295.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
  2296.     {
  2297.         GetImports32(
  2298.             pImageImportDescriptor,
  2299.             (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  2300.             pImageImportSection);
  2301.     }
  2302.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
  2303.     {
  2304.         GetImports64(
  2305.             pImageImportDescriptor,
  2306.             (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  2307.             pImageImportSection);
  2308.     }
  2309.     else
  2310.     {
  2311.         OUTPUT("[-] Unsupported architecture!\n");
  2312.     }
  2313.  
  2314.     // Cleanup
  2315.     HeapFree(GetProcessHeap(), 0, lpFileContent);
  2316.  
  2317.     // Update the GUI with the analysis results
  2318.     UpdateEditControl();
  2319. }
  2320.  
  2321. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory)
  2322. {
  2323.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  2324.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory)
  2325.     {
  2326.         if (pImageDataDirectory->VirtualAddress == 0)
  2327.             continue;
  2328.  
  2329.         OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n",
  2330.             GetDataDirectoryName(i),
  2331.             (uintptr_t)pImageDataDirectory->VirtualAddress);
  2332.         OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n",
  2333.             GetDataDirectoryName(i),
  2334.             (uintptr_t)pImageDataDirectory->Size);
  2335.     }
  2336. }
  2337.  
  2338. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  2339.     int NumberOfSections, DWORD dImportAddress)
  2340. {
  2341.     PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  2342.  
  2343.     OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  2344.  
  2345.     for (int i = 0; i < NumberOfSections; ++i)
  2346.     {
  2347.         const auto pCurrentSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader +
  2348.             i * sizeof(IMAGE_SECTION_HEADER));
  2349.  
  2350.         OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  2351.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n",
  2352.             (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  2353.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n",
  2354.             (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  2355.         OUTPUT("\t\tVirtualAddress : 0x%X\n",
  2356.             (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  2357.         OUTPUT("\t\tSizeOfRawData : 0x%X\n",
  2358.             (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  2359.         OUTPUT("\t\tPointerToRawData : 0x%X\n",
  2360.             (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  2361.         OUTPUT("\t\tPointerToRelocations : 0x%X\n",
  2362.             (uintptr_t)pCurrentSectionHeader->PointerToRelocations);
  2363.         OUTPUT("\t\tPointerToLinenumbers : 0x%X\n",
  2364.             (uintptr_t)pCurrentSectionHeader->PointerToLinenumbers);
  2365.         OUTPUT("\t\tNumberOfRelocations : 0x%X\n",
  2366.             (uintptr_t)pCurrentSectionHeader->NumberOfRelocations);
  2367.         OUTPUT("\t\tNumberOfLinenumbers : 0x%X\n",
  2368.             (uintptr_t)pCurrentSectionHeader->NumberOfLinenumbers);
  2369.         OUTPUT("\t\tCharacteristics : 0x%X %s\n",
  2370.             (uintptr_t)pCurrentSectionHeader->Characteristics,
  2371.             GetSectionProtection(pCurrentSectionHeader->Characteristics));
  2372.  
  2373.         if (dImportAddress >= pCurrentSectionHeader->VirtualAddress &&
  2374.             dImportAddress < pCurrentSectionHeader->VirtualAddress +
  2375.             pCurrentSectionHeader->Misc.VirtualSize)
  2376.         {
  2377.             pImageImportHeader = pCurrentSectionHeader;
  2378.         }
  2379.     }
  2380.  
  2381.     return pImageImportHeader;
  2382. }
  2383. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  2384.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  2385. {
  2386.     OUTPUT("\n[+] IMPORTED DLL\n");
  2387.  
  2388.     while (pImageImportDescriptor->Name != 0)
  2389.     {
  2390.         OUTPUT("\n\tDLL NAME : %s\n",
  2391.             (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  2392.         OUTPUT("\tCharacteristics : 0x%X\n",
  2393.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  2394.         OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  2395.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  2396.         OUTPUT("\tTimeDateStamp : 0x%X\n",
  2397.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  2398.         OUTPUT("\tForwarderChain : 0x%X\n",
  2399.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  2400.         OUTPUT("\tFirstThunk : 0x%X\n",
  2401.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  2402.  
  2403.         if (pImageImportDescriptor->OriginalFirstThunk == 0)
  2404.         {
  2405.             ++pImageImportDescriptor;
  2406.             continue;
  2407.         }
  2408.  
  2409.         auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA32)(dRawOffset +
  2410.             (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  2411.  
  2412.         OUTPUT("\n\tImported Functions : \n\n");
  2413.  
  2414.         while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  2415.         {
  2416.             if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG32)
  2417.             {
  2418.                 ++pOriginalFirstThrunk;
  2419.                 continue;
  2420.             }
  2421.  
  2422.             const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(dRawOffset +
  2423.                 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  2424.  
  2425.             if (pImageImportByName == nullptr)
  2426.             {
  2427.                 ++pOriginalFirstThrunk;
  2428.                 continue;
  2429.             }
  2430.  
  2431.             if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
  2432.             {
  2433.                 OUTPUT("\t\t0x%X (Ordinal) : %s\n",
  2434.                     (uintptr_t)pOriginalFirstThrunk->u1.AddressOfData,
  2435.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  2436.             }
  2437.             else
  2438.             {
  2439.                 OUTPUT("\t\t%s\n",
  2440.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  2441.             }
  2442.  
  2443.             ++pOriginalFirstThrunk;
  2444.         }
  2445.  
  2446.         ++pImageImportDescriptor;
  2447.     }
  2448. }
  2449.  
  2450. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  2451.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  2452. {
  2453.     OUTPUT("\n[+] IMPORTED DLL\n");
  2454.  
  2455.     while (pImageImportDescriptor->Name != 0)
  2456.     {
  2457.         OUTPUT("\n\tDLL NAME : %s\n",
  2458.             (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  2459.         OUTPUT("\tCharacteristics : 0x%X\n",
  2460.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  2461.         OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  2462.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  2463.         OUTPUT("\tTimeDateStamp : 0x%X\n",
  2464.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  2465.         OUTPUT("\tForwarderChain : 0x%X\n",
  2466.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  2467.         OUTPUT("\tFirstThunk : 0x%X\n",
  2468.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  2469.  
  2470.         if (pImageImportDescriptor->OriginalFirstThunk == 0)
  2471.         {
  2472.             ++pImageImportDescriptor;
  2473.             continue;
  2474.         }
  2475.  
  2476.         auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA64)(dRawOffset +
  2477.             (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  2478.  
  2479.         OUTPUT("\n\tImported Functions : \n\n");
  2480.  
  2481.         while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  2482.         {
  2483.             if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG64)
  2484.             {
  2485.                 ++pOriginalFirstThrunk;
  2486.                 continue;
  2487.             }
  2488.  
  2489.             const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dRawOffset +
  2490.                 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  2491.  
  2492.             if (pImageImportByName == nullptr)
  2493.             {
  2494.                 ++pOriginalFirstThrunk;
  2495.                 continue;
  2496.             }
  2497.  
  2498.             if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
  2499.             {
  2500.                 OUTPUT("\t\t0x%llX (Ordinal) : %s\n",
  2501.                     pOriginalFirstThrunk->u1.AddressOfData,
  2502.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  2503.             }
  2504.             else
  2505.             {
  2506.                 OUTPUT("\t\t%s\n",
  2507.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  2508.             }
  2509.  
  2510.             ++pOriginalFirstThrunk;
  2511.         }
  2512.  
  2513.         ++pImageImportDescriptor;
  2514.     }
  2515. }
  2516. // older-orig-deprecated ^^
  2517. */
  2518.  
  2519. //filePathW
  2520. //lpFilePath
  2521. HANDLE GetFileContent(const wchar_t* lpFilePath) {
  2522.     HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  2523.     if (hFile == INVALID_HANDLE_VALUE) return nullptr;
  2524.     DWORD fileSize = GetFileSize(hFile, nullptr);
  2525.     auto lpFileContent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileSize);
  2526.     DWORD bytesRead;
  2527.     ReadFile(hFile, lpFileContent, fileSize, &bytesRead, nullptr);
  2528.     CloseHandle(hFile);
  2529.     return lpFileContent;
  2530. }
  2531.  
  2532. void UpdateEditControl() {
  2533.     SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  2534.     SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  2535.     SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  2536. }
Add Comment
Please, Sign In to add comment