alien_fx_fiend

Compiler Error Needs WinMain WinProc Outside Namespaces!

Dec 19th, 2024
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 88.04 KB | Source Code | 0 0
  1. /*
  2. WinMain and WindowProc need to be outside any namespaces! Also Global Variables can be outside any namespaces! Restructuring the code...
  3. */
  4.  
  5.     #define STRICT
  6.     #define WIN32_LEAN_AND_MEAN
  7.     #include <Windows.h>
  8.     #include <winternl.h>
  9.     #include <CommCtrl.h>
  10.     #include <commdlg.h>
  11.     #include <string>
  12.     #include <strsafe.h>
  13.     #include <sstream>
  14.     #include <iomanip>
  15.     #include <stdio.h>
  16.     #include <vector>
  17.     #include <shellapi.h>
  18.     //#include "helpers.h"
  19.     #include "resource.h"
  20.     #pragma comment(lib, "comctl32.lib")
  21.  
  22.     //bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders);
  23.  
  24.     namespace PEHelpers {
  25.         // Add these new helper functions
  26.         bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  27.             return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  28.         }
  29.  
  30.         DWORD_PTR GetImageBase(PIMAGE_NT_HEADERS pNtHeaders) {
  31.             if (PEHelpers::Is64BitPE(pNtHeaders)) {
  32.                 auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  33.                 return static_cast<DWORD_PTR>(pNtHeaders64->OptionalHeader.ImageBase);
  34.             }
  35.             else {
  36.                 auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  37.                 return static_cast<DWORD_PTR>(pNtHeaders32->OptionalHeader.ImageBase);
  38.             }
  39.         }
  40.  
  41.         DWORD GetSizeOfImage(PIMAGE_NT_HEADERS pNtHeaders) {
  42.             if (PEHelpers::Is64BitPE(pNtHeaders)) {
  43.                 auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  44.                 return pNtHeaders64->OptionalHeader.SizeOfImage;
  45.             }
  46.             else {
  47.                 auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  48.                 return pNtHeaders32->OptionalHeader.SizeOfImage;
  49.             }
  50.         }
  51.  
  52.         bool ValidateFileSize(DWORD expectedSize, DWORD fileSize) {
  53.             // Validate against SizeOfHeaders instead of SizeOfImage
  54.             return expectedSize > 0 && expectedSize <= fileSize;
  55.         }
  56.         //}
  57.  
  58.             // Replace the existing GetRvaPtr function in PEHelpers namespace with this:
  59.         DWORD_PTR GetRvaPtr(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections, LPVOID baseAddress) {
  60.             for (WORD i = 0; i < numberOfSections; i++) {
  61.                 if (rva >= pSectionHeader[i].VirtualAddress &&
  62.                     rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  63.                     DWORD_PTR delta = (DWORD_PTR)baseAddress + pSectionHeader[i].PointerToRawData;
  64.                     return delta + (rva - pSectionHeader[i].VirtualAddress);
  65.                 }
  66.             }
  67.             return 0;
  68.         }
  69.  
  70.         // Add to PEHelpers namespace:
  71.         bool IsRvaValid(DWORD rva, DWORD fileSize, PIMAGE_NT_HEADERS pNtHeaders) {
  72.             return rva < pNtHeaders->OptionalHeader.SizeOfImage&& rva < fileSize;
  73.         }
  74.  
  75.         // Add this new helper function in PEHelpers namespace:
  76.         PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  77.             for (WORD i = 0; i < numberOfSections; i++) {
  78.                 if ((rva >= pSectionHeader[i].VirtualAddress) &&
  79.                     (rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData))) {
  80.                     return &pSectionHeader[i];
  81.                 }
  82.             }
  83.             return nullptr;
  84.         }
  85.  
  86.         std::wstring GetImageCharacteristics(DWORD characteristics) {
  87.             if (characteristics & IMAGE_FILE_DLL) return L"(DLL)";
  88.             if (characteristics & IMAGE_FILE_SYSTEM) return L"(DRIVER)";
  89.             if (characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) return L"(EXE)";
  90.             return L"(UNKNOWN)";
  91.         }
  92.  
  93.         std::wstring GetSubsystem(WORD subsystem) {
  94.             switch (subsystem) {
  95.             case IMAGE_SUBSYSTEM_NATIVE: return L"(NATIVE/DRIVER)";
  96.             case IMAGE_SUBSYSTEM_WINDOWS_GUI: return L"(GUI)";
  97.             case IMAGE_SUBSYSTEM_WINDOWS_CUI: return L"(CONSOLE)";
  98.             default: return L"(UNKNOWN)";
  99.             }
  100.         }
  101.  
  102.         std::wstring GetDataDirectoryName(int DirectoryNumber) {
  103.             switch (DirectoryNumber) {
  104.             case 0: return L"Export Table";
  105.             case 1: return L"Import Table";
  106.             case 2: return L"Resource Table";
  107.             case 3: return L"Exception Entry";
  108.             case 4: return L"Security Entry";
  109.             case 5: return L"Relocation Table";
  110.             case 6: return L"Debug Entry";
  111.             case 7: return L"Copyright Entry";
  112.             case 8: return L"Global PTR Entry";
  113.             case 9: return L"TLS Entry";
  114.             case 10: return L"Configuration Entry";
  115.             case 11: return L"Bound Import Entry";
  116.             case 12: return L"IAT";
  117.             case 13: return L"Delay Import Descriptor";
  118.             case 14: return L"COM Descriptor";
  119.             default: return L"Unknown";
  120.             }
  121.         }
  122.  
  123.         std::wstring GetSectionProtection(DWORD characteristics) {
  124.             std::wstring protection = L"(";
  125.             bool needsSeparator = false;
  126.  
  127.             if (characteristics & IMAGE_SCN_MEM_EXECUTE) {
  128.                 protection += L"EXECUTE";
  129.                 needsSeparator = true;
  130.             }
  131.  
  132.             if (characteristics & IMAGE_SCN_MEM_READ) {
  133.                 if (needsSeparator) protection += L" | ";
  134.                 protection += L"READ";
  135.                 needsSeparator = true;
  136.             }
  137.  
  138.             if (characteristics & IMAGE_SCN_MEM_WRITE) {
  139.                 if (needsSeparator) protection += L" | ";
  140.                 protection += L"WRITE";
  141.             }
  142.  
  143.             protection += L")";
  144.             return protection;
  145.         }
  146.  
  147.         PIMAGE_SECTION_HEADER GetExportSection(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  148.             const int NumberOfSections,
  149.             const DWORD_PTR dExportAddress) {
  150.             for (int i = 0; i < NumberOfSections; ++i) {
  151.                 const auto pCurrentSectionHeader =
  152.                     (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  153.  
  154.                 if (dExportAddress >= pCurrentSectionHeader->VirtualAddress &&
  155.                     dExportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize)
  156.                     return pCurrentSectionHeader;
  157.             }
  158.             return nullptr;
  159.         }
  160.  
  161.         DWORD RvaToOffset(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  162.             for (WORD i = 0; i < numberOfSections; i++) {
  163.                 if (rva >= pSectionHeader[i].VirtualAddress &&
  164.                     rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  165.                     return (rva - pSectionHeader[i].VirtualAddress) + pSectionHeader[i].PointerToRawData;
  166.                 }
  167.             }
  168.             return 0;
  169.         }
  170.     }
  171.  
  172.     namespace PEParser {
  173.         using namespace std;
  174.         struct PEAnalyzer {
  175.             LPVOID lpFileContent;
  176.             DWORD fileSize;
  177.             bool is64Bit;
  178.             PIMAGE_NT_HEADERS32 pNtHeaders32;
  179.             PIMAGE_NT_HEADERS64 pNtHeaders64;
  180.             PIMAGE_DOS_HEADER pDosHeader;
  181.  
  182.             PEAnalyzer() :
  183.                 lpFileContent(nullptr),
  184.                 fileSize(0),
  185.                 is64Bit(false),
  186.                 pNtHeaders32(nullptr),
  187.                 pNtHeaders64(nullptr),
  188.                 pDosHeader(nullptr) {}
  189.  
  190.             ~PEAnalyzer() {
  191.                 if (lpFileContent) {
  192.                     UnmapViewOfFile(lpFileContent);
  193.                     lpFileContent = nullptr;
  194.                 }
  195.             }
  196.         };
  197.  
  198.         // At the top of your file, change the window class name to wide string
  199.     #define WINDOW_CLASS_NAME L"PEAnalyzerWindow"
  200.     //const wchar_t* const WINDOW_CLASS_NAME = L"PEAnalyzerWindow";
  201.  
  202.     // Use ANSI versions explicitly
  203.     //#undef CreateWindow
  204.     //#undef CreateWindowEx
  205.     //#define CreateWindow  CreateWindowW
  206.     //#define CreateWindowEx CreateWindowExW
  207.  
  208.     // Helper function to replace printf with GUI output
  209.     #define OUTPUT(format, ...) AppendToOutput(L##format, ##__VA_ARGS__)
  210.     //#define OUTPUT(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  211.     //#define printf(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  212.  
  213.     // Window dimensions
  214.     #define WINDOW_WIDTH    1024
  215.     #define WINDOW_HEIGHT   768
  216.     #define EDIT_MARGIN    10
  217.  
  218.     // Global variables
  219.         HWND g_hMainWindow = NULL;
  220.         HWND g_hEditControl = NULL;
  221.         HFONT g_hFont = NULL;
  222.         std::wstringstream g_OutputText;
  223.         WCHAR filePathW[MAX_PATH];
  224.         std::vector<wchar_t> g_OutputBuffer;
  225.         std::wstring tempBuffer; // Declare tempBuffer globally
  226.         HWND g_hStatusBar = NULL;
  227.         HWND g_hProgressBar = NULL;  // Add this with your other global variables
  228.         //int virtualHeight = 100;  // Initialize with an appropriate value
  229.  
  230.         // Function declarations
  231.         LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  232.         LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  233.         void CreateMainWindow(HINSTANCE hInstance);
  234.         void InitializeControls(HWND hwnd);
  235.         void AddMenus(HWND hwnd);
  236.         void OpenFileDialog(HWND hwnd);
  237.         //void AnalyzePEFile(const WCHAR* filePathW);
  238.         void AnalyzePEFile(const wchar_t* filePathW);
  239.         HANDLE GetFileContent(const wchar_t* lpFilePath);
  240.         /*void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory);
  241.         PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  242.             int NumberOfSections, DWORD dImportAddress);
  243.         void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  244.             DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);
  245.         void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  246.             DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);*/
  247.         void AppendToOutput(const wchar_t* format, ...);
  248.         //newfunctionshere (lateest fixes)
  249.         void ParseSections(const PEAnalyzer& analyzer); //forwarddeclare parse+ bring namespace up
  250.         void ParseImportDirectory(const PEAnalyzer& analyzer);
  251.         void ParseExportDirectory(const PEAnalyzer& analyzer);
  252.         void ParseResourceDirectory(const PEAnalyzer& analyzer);
  253.         void ParseDebugDirectory(const PEAnalyzer& analyzer);
  254.         void SetStatusText(const wchar_t* text);
  255.         void ShowProgress(int percentage);
  256.         void UpdateEditControl();
  257.         bool InitializePEAnalyzer(PEAnalyzer& analyzer, const wchar_t* filePath);
  258.         DWORD GetFileSizeCustom(const wchar_t* filePath);
  259.  
  260.         void ProcessResourceDirectory32(
  261.             PIMAGE_RESOURCE_DIRECTORY resDir,
  262.             int level,
  263.             const wchar_t* type,
  264.             PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  265.             const wchar_t* resourceTypes[],
  266.             const PEAnalyzer& analyzer);
  267.  
  268.         void ProcessResourceDirectory64(
  269.             PIMAGE_RESOURCE_DIRECTORY resDir,
  270.             int level,
  271.             const wchar_t* type,
  272.             PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  273.             const wchar_t* resourceTypes[],
  274.             const PEAnalyzer& analyzer);
  275.  
  276.         // Main window class name
  277.         //const char* const WINDOW_CLASS_NAME = "PEAnalyzerWindow";
  278.  
  279.         //new inserted here >>
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.         //here
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.         int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  325.             INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
  326.             InitCommonControlsEx(&icc);
  327.  
  328.             // Get command line parameters in Unicode
  329.             int argc;
  330.             LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  331.  
  332.             CreateMainWindow(hInstance);
  333.             if (!g_hMainWindow) {
  334.                 LocalFree(argv);
  335.                 return -1;
  336.             }
  337.  
  338.             ShowWindow(g_hMainWindow, nCmdShow);
  339.             UpdateWindow(g_hMainWindow);
  340.  
  341.             // If there's a command line parameter, process it
  342.             if (argc > 1) {
  343.                 // Process the first parameter as file path
  344.                 SetWindowTextW(g_hEditControl, L"");
  345.                 g_OutputText.str(L"");
  346.                 g_OutputText.clear();
  347.                 AnalyzePEFile(argv[1]);
  348.                 UpdateEditControl();
  349.             }
  350.  
  351.             LocalFree(argv);
  352.  
  353.             MSG msg = {};
  354.             while (GetMessage(&msg, NULL, 0, 0)) {
  355.                 TranslateMessage(&msg);
  356.                 DispatchMessage(&msg);
  357.             }
  358.  
  359.             if (g_hFont) DeleteObject(g_hFont);
  360.             return (int)msg.wParam;
  361.         }
  362.  
  363.         void CreateMainWindow(HINSTANCE hInstance) {
  364.             WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), 0, WindowProc, 0, 0, hInstance,
  365.                 LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)),
  366.                 LoadCursor(NULL, IDC_ARROW),
  367.                 (HBRUSH)(COLOR_WINDOW + 1),
  368.                 NULL, WINDOW_CLASS_NAME,
  369.                 LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)) };
  370.             RegisterClassExW(&wc);
  371.  
  372.             // Get screen dimensions
  373.             int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  374.             int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  375.  
  376.             // Calculate center position
  377.             int windowX = (screenWidth - WINDOW_WIDTH) / 2;
  378.             int windowY = (screenHeight - WINDOW_HEIGHT) / 2;
  379.  
  380.             // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
  381.             DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
  382.             //WS_OVERLAPPEDWINDOW ~~> style
  383.             g_hMainWindow = CreateWindowExW(0, WINDOW_CLASS_NAME, L"PE File Analyzer",
  384.                 style, windowX, windowY, WINDOW_WIDTH, WINDOW_HEIGHT,
  385.                 nullptr, nullptr, hInstance, nullptr);
  386.         }
  387.  
  388.         void InitializeControls(HWND hwnd) {
  389.             // Create status bar
  390.             g_hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
  391.                 WS_CHILD | WS_VISIBLE,
  392.                 0, 0, 0, 0, hwnd, NULL,
  393.                 (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  394.  
  395.             // Set up status bar parts
  396.             RECT rcClient;
  397.             GetClientRect(hwnd, &rcClient);
  398.             int statusParts[2] = { 150, rcClient.right };
  399.             SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  400.  
  401.             // Create progress bar in the second part of status bar
  402.             RECT rcPart;
  403.             SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  404.  
  405.             g_hProgressBar = CreateWindowEx(0, PROGRESS_CLASS, NULL,
  406.                 WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
  407.                 rcPart.left + 5, rcPart.top + 2,
  408.                 rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  409.                 g_hStatusBar, NULL,
  410.                 (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  411.  
  412.             // Set blue color and range
  413.             SendMessage(g_hProgressBar, PBM_SETBARCOLOR, 0, (LPARAM)RGB(0, 120, 215));  // Windows 10 blue
  414.             SendMessage(g_hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  415.             SendMessage(g_hProgressBar, PBM_SETSTEP, 1, 0);
  416.  
  417.             // Get status bar height for edit control positioning
  418.             RECT rcStatus;
  419.             GetWindowRect(g_hStatusBar, &rcStatus);
  420.             int statusHeight = rcStatus.bottom - rcStatus.top;
  421.  
  422.             // Create edit control
  423.             g_hEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
  424.                 WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
  425.                 ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
  426.                 EDIT_MARGIN, EDIT_MARGIN,
  427.                 rcClient.right - (2 * EDIT_MARGIN),
  428.                 rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  429.                 hwnd, nullptr,
  430.                 (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), nullptr);
  431.  
  432.             // Create and set font
  433.             g_hFont = CreateFont(-14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
  434.                 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  435.                 DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, L"Consolas");
  436.  
  437.             if (g_hFont)
  438.                 SendMessage(g_hEditControl, WM_SETFONT, (WPARAM)g_hFont, TRUE);
  439.  
  440.             SetWindowSubclass(g_hEditControl, EditSubclassProc, 0, 0);
  441.         }
  442.  
  443.         void AddMenus(HWND hwnd) {
  444.             HMENU hMenuBar = CreateMenu();
  445.             HMENU hFileMenu = CreateMenu();
  446.             AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
  447.             AppendMenu(hFileMenu, MF_STRING, 1, L"&Open\tCtrl+O");  // Updated to show shortcut
  448.             AppendMenu(hFileMenu, MF_STRING, 2, L"E&xit");
  449.             SetMenu(hwnd, hMenuBar);
  450.         }
  451.      
  452.  
  453.         // First, add this helper function to determine if the PE file is 64-bit
  454.         bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  455.             return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  456.         }
  457.  
  458.         // Helper function to safely get file size
  459.         DWORD GetFileSizeCustom(const wchar_t* filePath) {
  460.             HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ,
  461.                 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  462.  
  463.             if (hFile == INVALID_HANDLE_VALUE) {
  464.                 return 0;
  465.             }
  466.  
  467.             DWORD fileSize = ::GetFileSize(hFile, nullptr);
  468.             CloseHandle(hFile);
  469.             return fileSize;
  470.         }
  471.  
  472.         // Add this helper function
  473.         void SafeOutput(const std::wstring& text) {
  474.             try {
  475.                 g_OutputText << text;
  476.                 UpdateEditControl();
  477.             }
  478.             catch (...) {
  479.                 SetStatusText(L"Error writing output");
  480.             }
  481.         }
  482.  
  483.         void UpdateStatusBar(const wchar_t* text, int progress = -1) {
  484.             if (text) {
  485.                 SetStatusText(text);
  486.             }
  487.             if (progress >= 0) {
  488.                 ShowProgress(progress);
  489.             }
  490.         }
  491.  
  492.         void ClearProgress() {
  493.             ShowWindow(g_hProgressBar, SW_HIDE);
  494.             SetStatusText(L"Ready");
  495.         }
  496.  
  497.         LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  498.             if (uMsg == WM_KEYDOWN) {
  499.                 if ((GetKeyState(VK_CONTROL) & 0x8000) && wParam == 'O') {
  500.                     SendMessage(GetParent(hwnd), WM_COMMAND, 1, 0);
  501.                     return 0;
  502.                 }
  503.                 switch (wParam) {
  504.                 case VK_F1:
  505.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
  506.                     return 0;
  507.                 case VK_ESCAPE:
  508.                     SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
  509.                     return 0;
  510.                 case VK_PRIOR:
  511.                     // Scroll up
  512.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  513.                     return 0;
  514.                 case VK_NEXT:
  515.                     // Scroll down
  516.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  517.                     return 0;
  518.                 case VK_UP:
  519.                     // Scroll one line up
  520.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  521.                     return 0;
  522.                 case VK_DOWN:
  523.                     // Scroll one line down
  524.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  525.                     return 0;
  526.                 }
  527.             }
  528.             if (uMsg == WM_MOUSEWHEEL) {
  529.                 int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  530.                 if (delta > 0) {
  531.                     // Scroll up
  532.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  533.                 }
  534.                 else {
  535.                     // Scroll down
  536.                     SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  537.                 }
  538.                 return 0;
  539.             }
  540.             return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  541.         }
  542.  
  543.         LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  544.             switch (uMsg) {
  545.             case WM_CREATE: InitializeControls(hwnd); AddMenus(hwnd); return 0;
  546.             case WM_SIZE:
  547.             {
  548.                 RECT rcClient;
  549.                 GetClientRect(hwnd, &rcClient);
  550.  
  551.                 // Resize status bar
  552.                 SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
  553.  
  554.                 // Recalculate status bar parts
  555.                 int statusParts[2] = { 150, rcClient.right };
  556.                 SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  557.  
  558.                 // Reposition progress bar
  559.                 RECT rcPart;
  560.                 SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  561.                 SetWindowPos(g_hProgressBar, NULL,
  562.                     rcPart.left + 5, rcPart.top + 2,
  563.                     rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  564.                     SWP_NOZORDER);
  565.  
  566.                 // Get status bar height
  567.                 RECT rcStatus;
  568.                 GetWindowRect(g_hStatusBar, &rcStatus);
  569.                 int statusHeight = rcStatus.bottom - rcStatus.top;
  570.  
  571.                 // Resize edit control
  572.                 SetWindowPos(g_hEditControl, NULL,
  573.                     EDIT_MARGIN,
  574.                     EDIT_MARGIN,
  575.                     rcClient.right - (2 * EDIT_MARGIN),
  576.                     rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  577.                     SWP_NOZORDER);
  578.                 return 0;
  579.             }
  580.        
  581.             case WM_KEYDOWN:
  582.             {
  583.                 if (GetKeyState(VK_CONTROL) & 0x8000) {
  584.                     switch (wParam) {
  585.                     case 'O':
  586.                         OpenFileDialog(hwnd);
  587.                         return 0;
  588.                     }
  589.                 }
  590.                 switch (wParam) {
  591.                 case VK_F1:
  592.                     MessageBoxW(hwnd,
  593.                         L"PE Header Parser 4.3 GUI-based Programmed in C++ Win32 API (1546 lines of code) by Entisoft Software(c) Evans Thorpemorton",
  594.                         L"About",
  595.                         MB_OK | MB_ICONINFORMATION);
  596.                     return 0;
  597.                 case VK_ESCAPE:
  598.                     PostQuitMessage(0);
  599.                     return 0;
  600.                 case VK_PRIOR:
  601.                     // Scroll up
  602.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  603.                     return 0;
  604.                 case VK_NEXT:
  605.                     // Scroll down
  606.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  607.                     return 0;
  608.                 case VK_UP:
  609.                     // Scroll one line up
  610.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  611.                     return 0;
  612.                 case VK_DOWN:
  613.                     // Scroll one line down
  614.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  615.                     return 0;
  616.                 }
  617.                 break;
  618.             }
  619.             case WM_MOUSEWHEEL:
  620.             {
  621.                 int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  622.                 if (delta > 0) {
  623.                     // Scroll up
  624.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  625.                 }
  626.                 else {
  627.                     // Scroll down
  628.                     SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  629.                 }
  630.                 return 0;
  631.             }
  632.             case WM_COMMAND: if (LOWORD(wParam) == 1) OpenFileDialog(hwnd); if (LOWORD(wParam) == 2) PostQuitMessage(0); return 0;
  633.             case WM_DESTROY:
  634.                 if (g_hStatusBar) DestroyWindow(g_hStatusBar);
  635.                 PostQuitMessage(0);
  636.                 return 0;
  637.             }
  638.             return DefWindowProc(hwnd, uMsg, wParam, lParam);
  639.         }
  640.  
  641.         void SetStatusText(const wchar_t* text) {
  642.             SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
  643.         }
  644.  
  645.         void ShowProgress(int percentage) {
  646.             // Update progress bar
  647.             SendMessage(g_hProgressBar, PBM_SETPOS, (WPARAM)percentage, 0);
  648.  
  649.             // Update status text in first part
  650.             wchar_t status[256];
  651.             swprintf_s(status, L"Analyzing... %d%%", percentage);
  652.             //swprintf_s(status, L"Analyzing...");
  653.             SetStatusText(status); //commented-out
  654.             SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)status);
  655.         }
  656.  
  657.         void OpenFileDialog(HWND hwnd) {
  658.             WCHAR fileName[MAX_PATH] = L"";
  659.             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 };
  660.             if (GetOpenFileNameW(&ofn)) {
  661.                 SetWindowTextW(g_hEditControl, L"");
  662.                 g_OutputText.str(L"");
  663.                 g_OutputText.clear();
  664.                 AnalyzePEFile(ofn.lpstrFile);
  665.                 UpdateEditControl();
  666.             }
  667.         }
  668.  
  669.         class FileMapper {
  670.         private:
  671.             HANDLE hFile;
  672.             HANDLE hMapping;
  673.             LPVOID lpView;
  674.  
  675.         public:
  676.             FileMapper() : hFile(INVALID_HANDLE_VALUE), hMapping(nullptr), lpView(nullptr) {}
  677.  
  678.             ~FileMapper() {
  679.                 Cleanup();
  680.             }
  681.  
  682.             void Cleanup() {
  683.                 if (lpView) {
  684.                     UnmapViewOfFile(lpView);
  685.                     lpView = nullptr;
  686.                 }
  687.                 if (hMapping) {
  688.                     CloseHandle(hMapping);
  689.                     hMapping = nullptr;
  690.                 }
  691.                 if (hFile != INVALID_HANDLE_VALUE) {
  692.                     CloseHandle(hFile);
  693.                     hFile = INVALID_HANDLE_VALUE;
  694.                 }
  695.             }
  696.  
  697.             bool Initialize(const wchar_t* path) {
  698.                 Cleanup();  // Ensure clean state
  699.  
  700.                 hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
  701.                     nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  702.                 if (hFile == INVALID_HANDLE_VALUE) return false;
  703.  
  704.                 hMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  705.                 if (!hMapping) {
  706.                     Cleanup();
  707.                     return false;
  708.                 }
  709.  
  710.                 lpView = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  711.                 if (!lpView) {
  712.                     Cleanup();
  713.                     return false;
  714.                 }
  715.  
  716.                 return true;
  717.             }
  718.  
  719.             LPVOID GetView() const { return lpView; }
  720.         };
  721.  
  722.         // Modified AppendToOutput to handle newlines properly:
  723.         void AppendToOutput(const wchar_t* format, ...) {
  724.             std::vector<wchar_t> buffer(1024);
  725.             va_list args;
  726.             va_start(args, format);
  727.  
  728.             while (true) {
  729.                 int result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  730.                 if (result >= 0) break;
  731.                 buffer.resize(buffer.size() * 2);
  732.             }
  733.             va_end(args);
  734.  
  735.             // Convert \n to \r\n
  736.             std::wstring output = buffer.data();
  737.             size_t pos = 0;
  738.             while ((pos = output.find(L'\n', pos)) != std::wstring::npos) {
  739.                 if (pos == 0 || output[pos - 1] != L'\r') {
  740.                     output.insert(pos, L"\r");
  741.                     pos += 2;
  742.                 }
  743.                 else {
  744.                     pos++;
  745.                 }
  746.             }
  747.  
  748.             g_OutputText << output;
  749.             UpdateEditControl();
  750.         }
  751.  
  752.    
  753.         //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
  754.  
  755.         void ProcessResourceDirectory(
  756.             PIMAGE_RESOURCE_DIRECTORY resDir,
  757.             int level,
  758.             const wchar_t* type,
  759.             PIMAGE_RESOURCE_DIRECTORY pResourceDir,
  760.             const wchar_t* resourceTypes[],
  761.             PIMAGE_NT_HEADERS pNtHeaders,
  762.             LPVOID lpFileContent)
  763.         {
  764.             if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  765.                 return;
  766.             }
  767.  
  768.             auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  769.             WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  770.  
  771.             for (WORD i = 0; i < totalEntries; i++) {
  772.                 if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  773.                     break;
  774.                 }
  775.  
  776.                 for (int indent = 0; indent < level; indent++) {
  777.                     OUTPUT("\t");
  778.                 }
  779.  
  780.                 if (entry[i].NameIsString) {
  781.                     auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)pResourceDir + entry[i].NameOffset);
  782.                     if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  783.                         std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  784.                         wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  785.                             nameEntry->NameString, nameEntry->Length);
  786.                         resourceName[nameEntry->Length] = L'\0';
  787.  
  788.                         if (level == 0) {
  789.                             OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  790.                         }
  791.                         else {
  792.                             OUTPUT("Name: %s\n", resourceName.data());
  793.                         }
  794.                     }
  795.                 }
  796.                 else {
  797.                     if (level == 0) {
  798.                         DWORD resourceType = entry[i].Id;
  799.                         if (resourceType < 16) {
  800.                             OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  801.                         }
  802.                         else {
  803.                             OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  804.                         }
  805.                     }
  806.                     else {
  807.                         OUTPUT("ID: %d\n", entry[i].Id);
  808.                     }
  809.                 }
  810.  
  811.                 if (entry[i].DataIsDirectory) {
  812.                     auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pResourceDir + entry[i].OffsetToDirectory);
  813.                     if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  814.                         ProcessResourceDirectory(nextDir, level + 1,
  815.                             level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  816.                             pResourceDir, resourceTypes, pNtHeaders, lpFileContent);
  817.                     }
  818.                 }
  819.                 else {
  820.                     auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)pResourceDir + entry[i].OffsetToData);
  821.                     if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  822.                         for (int indent = 0; indent < level + 1; indent++) {
  823.                             OUTPUT("\t");
  824.                         }
  825.                         OUTPUT("Size: %d bytes, RVA: 0x%X\n",
  826.                             dataEntry->Size, dataEntry->OffsetToData);
  827.  
  828.                         if (type && wcscmp(type, L"Version") == 0) {
  829.                             auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  830.                                 dataEntry->OffsetToData,
  831.                                 IMAGE_FIRST_SECTION(pNtHeaders),
  832.                                 pNtHeaders->FileHeader.NumberOfSections,
  833.                                 lpFileContent);
  834.  
  835.                             if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  836.                                 auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  837.                                 if (versionInfo->dwSignature == 0xFEEF04BD) {
  838.                                     for (int indent = 0; indent < level + 2; indent++) {
  839.                                         OUTPUT("\t");
  840.                                     }
  841.                                     OUTPUT("File Version: %d.%d.%d.%d\n",
  842.                                         HIWORD(versionInfo->dwFileVersionMS),
  843.                                         LOWORD(versionInfo->dwFileVersionMS),
  844.                                         HIWORD(versionInfo->dwFileVersionLS),
  845.                                         LOWORD(versionInfo->dwFileVersionLS));
  846.                                 }
  847.                             }
  848.                         }
  849.                     }
  850.                 }
  851.             }
  852.         }
  853.  
  854.         //adding here
  855.         //######################################################################################
  856.         //######################################################################################
  857.         //        ##    endroughxfer - urldump #1#
  858.         //        ##    <EOF><EOF>
  859.         //######################################################################################
  860.         //######################################################################################
  861.         //
  862.         // new code below starting here vv
  863.  
  864.         bool InitializePEAnalyzer(PEAnalyzer& analyzer, const wchar_t* filePath) {
  865.             FileMapper mapper;
  866.             if (!mapper.Initialize(filePath)) {
  867.                 OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  868.                 return false;
  869.             }
  870.  
  871.             analyzer.lpFileContent = mapper.GetView();
  872.             analyzer.fileSize = GetFileSizeCustom(filePath);
  873.  
  874.             analyzer.pDosHeader = static_cast<PIMAGE_DOS_HEADER>(analyzer.lpFileContent);
  875.             if (analyzer.pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  876.                 OUTPUT("[-] Invalid DOS signature!\n");
  877.                 return false;
  878.             }
  879.  
  880.             auto pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
  881.                 static_cast<BYTE*>(analyzer.lpFileContent) + analyzer.pDosHeader->e_lfanew);
  882.  
  883.             if (IsBadReadPtr(pNtHeaders, sizeof(IMAGE_NT_HEADERS)) ||
  884.                 pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  885.                 OUTPUT("[-] Invalid NT signature!\n");
  886.                 return false;
  887.             }
  888.  
  889.             analyzer.is64Bit = (pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
  890.  
  891.             if (analyzer.is64Bit) {
  892.                 analyzer.pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  893.                 analyzer.pNtHeaders32 = nullptr;
  894.             }
  895.             else {
  896.                 analyzer.pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  897.                 analyzer.pNtHeaders64 = nullptr;
  898.             }
  899.  
  900.             return true;
  901.         }
  902.  
  903.         DWORD GetFileSize(const wchar_t* filePath) {
  904.             HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ,
  905.                 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  906.             if (hFile == INVALID_HANDLE_VALUE) return 0;
  907.  
  908.             DWORD fileSize = ::GetFileSize(hFile, nullptr);
  909.             CloseHandle(hFile);
  910.             return fileSize;
  911.         }
  912.     //}
  913.  
  914.     void ParseImportDirectory32(const PEAnalyzer& analyzer) {
  915.         const auto& importDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  916.         if (!importDir.VirtualAddress || !importDir.Size) return;
  917.  
  918.         if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, analyzer.fileSize,
  919.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  920.             OUTPUT("[-] Invalid import directory RVA!\n");
  921.             return;
  922.         }
  923.  
  924.         OUTPUT("\n[+] IMPORT DIRECTORY (32-bit)\n");
  925.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  926.             importDir.VirtualAddress,
  927.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  928.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  929.             analyzer.lpFileContent);
  930.  
  931.         if (!pImportDesc) return;
  932.  
  933.         while (pImportDesc->Name != 0) {
  934.             if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  935.                 OUTPUT("[-] Invalid import descriptor detected!\n");
  936.                 break;
  937.             }
  938.  
  939.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  940.                 pImportDesc->Name,
  941.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  942.                 analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  943.                 analyzer.lpFileContent);
  944.  
  945.             if (dllName && !IsBadReadPtr(dllName, 1)) {
  946.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  947.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  948.  
  949.                 OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  950.                 OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  951.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  952.                 OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  953.                 OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  954.                 OUTPUT("\n\tImported Functions:\n");
  955.  
  956.                 auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  957.                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  958.                     IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  959.                     analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  960.                     analyzer.lpFileContent);
  961.  
  962.                 while (pThunk && pThunk->u1.AddressOfData) {
  963.                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) {
  964.                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  965.                             pThunk->u1.AddressOfData,
  966.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  967.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  968.                             analyzer.lpFileContent);
  969.  
  970.                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  971.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  972.                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  973.                                 wideFuncName.data(), MAX_PATH);
  974.                             OUTPUT("\t\t%s\n", wideFuncName.data());
  975.                         }
  976.                     }
  977.                     else {
  978.                         OUTPUT("\t\tOrdinal: %d\n", pThunk->u1.Ordinal & 0xFFFF);
  979.                     }
  980.                     pThunk++;
  981.                 }
  982.             }
  983.             pImportDesc++;
  984.         }
  985.     }
  986.  
  987.     void ParseImportDirectory64(const PEAnalyzer& analyzer) {
  988.         const auto& importDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  989.         if (!importDir.VirtualAddress || !importDir.Size) return;
  990.  
  991.         if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, analyzer.fileSize,
  992.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  993.             OUTPUT("[-] Invalid import directory RVA!\n");
  994.             return;
  995.         }
  996.  
  997.         OUTPUT("\n[+] IMPORT DIRECTORY (64-bit)\n");
  998.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  999.             importDir.VirtualAddress,
  1000.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1001.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1002.             analyzer.lpFileContent);
  1003.  
  1004.         if (!pImportDesc) return;
  1005.  
  1006.         while (pImportDesc->Name != 0) {
  1007.             if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  1008.                 OUTPUT("[-] Invalid import descriptor detected!\n");
  1009.                 break;
  1010.             }
  1011.  
  1012.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  1013.                 pImportDesc->Name,
  1014.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1015.                 analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1016.                 analyzer.lpFileContent);
  1017.  
  1018.             if (dllName && !IsBadReadPtr(dllName, 1)) {
  1019.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  1020.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  1021.  
  1022.                 OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  1023.                 OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  1024.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  1025.                 OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  1026.                 OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  1027.                 OUTPUT("\n\tImported Functions:\n");
  1028.  
  1029.                 auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  1030.                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1031.                     IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1032.                     analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1033.                     analyzer.lpFileContent);
  1034.  
  1035.                 while (pThunk && pThunk->u1.AddressOfData) {
  1036.                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)) {
  1037.                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1038.                             (DWORD)pThunk->u1.AddressOfData,
  1039.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1040.                             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1041.                             analyzer.lpFileContent);
  1042.  
  1043.                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1044.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  1045.                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1046.                                 wideFuncName.data(), MAX_PATH);
  1047.                             OUTPUT("\t\t%s\n", wideFuncName.data());
  1048.                         }
  1049.                     }
  1050.                     else {
  1051.                         OUTPUT("\t\tOrdinal: %lld\n", pThunk->u1.Ordinal & 0xFFFF);
  1052.                     }
  1053.                     pThunk++;
  1054.                 }
  1055.             }
  1056.             pImportDesc++;
  1057.         }
  1058.     }
  1059.  
  1060.     void ParseImportDirectory(const PEAnalyzer& analyzer) {
  1061.         if (analyzer.is64Bit) {
  1062.             ParseImportDirectory64(analyzer);
  1063.         }
  1064.         else {
  1065.             ParseImportDirectory32(analyzer);
  1066.         }
  1067.     }
  1068.     //}
  1069.  
  1070.     void ParseExportDirectory32(const PEAnalyzer& analyzer) {
  1071.         const auto& exportDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1072.         if (!exportDir.VirtualAddress || !exportDir.Size) return;
  1073.  
  1074.         if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, analyzer.fileSize,
  1075.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1076.             OUTPUT("[-] Invalid export directory RVA!\n");
  1077.             return;
  1078.         }
  1079.  
  1080.         OUTPUT("\n[+] EXPORT DIRECTORY (32-bit)\n");
  1081.         auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1082.             exportDir.VirtualAddress,
  1083.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1084.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1085.             analyzer.lpFileContent);
  1086.  
  1087.         if (!pExportDir || IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  1088.             OUTPUT("[-] Invalid export directory structure!\n");
  1089.             return;
  1090.         }
  1091.  
  1092.         OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  1093.         OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  1094.         OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  1095.         OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  1096.         OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  1097.         OUTPUT("\tBase: %d\n", pExportDir->Base);
  1098.         OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  1099.         OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  1100.         OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  1101.         OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  1102.         OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  1103.  
  1104.         auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1105.             pExportDir->AddressOfFunctions,
  1106.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1107.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1108.             analyzer.lpFileContent);
  1109.  
  1110.         auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1111.             pExportDir->AddressOfNames,
  1112.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1113.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1114.             analyzer.lpFileContent);
  1115.  
  1116.         auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1117.             pExportDir->AddressOfNameOrdinals,
  1118.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1119.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1120.             analyzer.lpFileContent);
  1121.  
  1122.         if (!pNames || !pNameOrdinals || !pFunctions) {
  1123.             OUTPUT("[-] Invalid export address tables!\n");
  1124.             return;
  1125.         }
  1126.  
  1127.         OUTPUT("\tExported Functions:\n\n");
  1128.         for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1129.             if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  1130.                 IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  1131.                 break;
  1132.             }
  1133.  
  1134.             const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1135.                 pNames[i],
  1136.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1137.                 analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1138.                 analyzer.lpFileContent);
  1139.  
  1140.             if (functionName && !IsBadReadPtr(functionName, 1)) {
  1141.                 WORD ordinal = pNameOrdinals[i];
  1142.                 if (ordinal < pExportDir->NumberOfFunctions) {
  1143.                     DWORD functionRva = pFunctions[ordinal];
  1144.  
  1145.                     // Check for forwarded export
  1146.                     if (functionRva >= exportDir.VirtualAddress &&
  1147.                         functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1148.  
  1149.                         const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1150.                             functionRva,
  1151.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1152.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1153.                             analyzer.lpFileContent);
  1154.  
  1155.                         if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  1156.                             std::vector<wchar_t> wideForwardName(MAX_PATH);
  1157.                             MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1158.                                 wideForwardName.data(), MAX_PATH);
  1159.                             OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1160.                                 functionName,
  1161.                                 ordinal + pExportDir->Base,
  1162.                                 wideForwardName.data());
  1163.                         }
  1164.                     }
  1165.                     else {
  1166.                         OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1167.                             functionName,
  1168.                             ordinal + pExportDir->Base,
  1169.                             functionRva);
  1170.                     }
  1171.                 }
  1172.             }
  1173.         }
  1174.     }
  1175.  
  1176.     void ParseExportDirectory64(const PEAnalyzer& analyzer) {
  1177.         const auto& exportDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1178.         if (!exportDir.VirtualAddress || !exportDir.Size) return;
  1179.  
  1180.         if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, analyzer.fileSize,
  1181.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  1182.             OUTPUT("[-] Invalid export directory RVA!\n");
  1183.             return;
  1184.         }
  1185.  
  1186.         OUTPUT("\n[+] EXPORT DIRECTORY (64-bit)\n");
  1187.         // Rest of the implementation is identical to 32-bit version
  1188.         // Just using pNtHeaders64 instead of pNtHeaders64
  1189.         auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1190.             exportDir.VirtualAddress,
  1191.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1192.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1193.             analyzer.lpFileContent);
  1194.  
  1195.         if (!pExportDir || IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  1196.             OUTPUT("[-] Invalid export directory structure!\n");
  1197.             return;
  1198.         }
  1199.  
  1200.         OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  1201.         OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  1202.         OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  1203.         OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  1204.         OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  1205.         OUTPUT("\tBase: %d\n", pExportDir->Base);
  1206.         OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  1207.         OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  1208.         OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  1209.         OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  1210.         OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  1211.  
  1212.         auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1213.             pExportDir->AddressOfFunctions,
  1214.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1215.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1216.             analyzer.lpFileContent);
  1217.  
  1218.         auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1219.             pExportDir->AddressOfNames,
  1220.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1221.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1222.             analyzer.lpFileContent);
  1223.  
  1224.         auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1225.             pExportDir->AddressOfNameOrdinals,
  1226.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1227.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1228.             analyzer.lpFileContent);
  1229.  
  1230.         if (!pNames || !pNameOrdinals || !pFunctions) {
  1231.             OUTPUT("[-] Invalid export address tables!\n");
  1232.             return;
  1233.         }
  1234.  
  1235.         OUTPUT("\tExported Functions:\n\n");
  1236.         for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1237.             if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  1238.                 IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  1239.                 break;
  1240.             }
  1241.  
  1242.             const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1243.                 pNames[i],
  1244.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1245.                 analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1246.                 analyzer.lpFileContent);
  1247.  
  1248.             if (functionName && !IsBadReadPtr(functionName, 1)) {
  1249.                 WORD ordinal = pNameOrdinals[i];
  1250.                 if (ordinal < pExportDir->NumberOfFunctions) {
  1251.                     DWORD functionRva = pFunctions[ordinal];
  1252.  
  1253.                     // Check for forwarded export
  1254.                     if (functionRva >= exportDir.VirtualAddress &&
  1255.                         functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1256.  
  1257.                         const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1258.                             functionRva,
  1259.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1260.                             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1261.                             analyzer.lpFileContent);
  1262.  
  1263.                         if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  1264.                             std::vector<wchar_t> wideForwardName(MAX_PATH);
  1265.                             MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1266.                                 wideForwardName.data(), MAX_PATH);
  1267.                             OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1268.                                 functionName,
  1269.                                 ordinal + pExportDir->Base,
  1270.                                 wideForwardName.data());
  1271.                         }
  1272.                     }
  1273.                     else {
  1274.                         OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1275.                             functionName,
  1276.                             ordinal + pExportDir->Base,
  1277.                             functionRva);
  1278.                     }
  1279.                 }
  1280.             }
  1281.         }
  1282.     }
  1283.     // Copying the same logic as ParseExportDirectory32 but with 64-bit headers
  1284.     // ... [Same implementation as above, just using pNtHeaders64]
  1285.  
  1286.     void ParseExportDirectory(const PEAnalyzer& analyzer) {
  1287.         if (analyzer.is64Bit) {
  1288.             ParseExportDirectory64(analyzer);
  1289.         }
  1290.         else {
  1291.             ParseExportDirectory32(analyzer);
  1292.         }
  1293.     }
  1294.  
  1295.     void ProcessResourceDirectory32(
  1296.         PIMAGE_RESOURCE_DIRECTORY resDir,
  1297.         int level,
  1298.         const wchar_t* type,
  1299.         PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  1300.         const wchar_t* resourceTypes[],
  1301.         const PEAnalyzer& analyzer)
  1302.     {
  1303.         if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1304.             return;
  1305.         }
  1306.  
  1307.         auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  1308.         WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  1309.  
  1310.         for (WORD i = 0; i < totalEntries; i++) {
  1311.             if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  1312.                 break;
  1313.             }
  1314.  
  1315.             for (int indent = 0; indent < level; indent++) {
  1316.                 OUTPUT("\t");
  1317.             }
  1318.  
  1319.             if (entry[i].NameIsString) {
  1320.                 auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)baseResourceDir + entry[i].NameOffset);
  1321.                 if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  1322.                     std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  1323.                     wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  1324.                         nameEntry->NameString, nameEntry->Length);
  1325.                     resourceName[nameEntry->Length] = L'\0';
  1326.  
  1327.                     if (level == 0) {
  1328.                         OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  1329.                     }
  1330.                     else {
  1331.                         OUTPUT("Name: %s\n", resourceName.data());
  1332.                     }
  1333.                 }
  1334.             }
  1335.             else {
  1336.                 if (level == 0) {
  1337.                     DWORD resourceType = entry[i].Id;
  1338.                     if (resourceType < 16) {
  1339.                         OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  1340.                     }
  1341.                     else {
  1342.                         OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  1343.                     }
  1344.                 }
  1345.                 else {
  1346.                     OUTPUT("ID: %d\n", entry[i].Id);
  1347.                 }
  1348.             }
  1349.  
  1350.             if (entry[i].DataIsDirectory) {
  1351.                 auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)baseResourceDir + entry[i].OffsetToDirectory);
  1352.                 if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1353.                     ProcessResourceDirectory32(nextDir, level + 1,
  1354.                         level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  1355.                         baseResourceDir, resourceTypes, analyzer);
  1356.                 }
  1357.             }
  1358.             else {
  1359.                 auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)baseResourceDir + entry[i].OffsetToData);
  1360.                 if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  1361.                     for (int indent = 0; indent < level + 1; indent++) {
  1362.                         OUTPUT("\t");
  1363.                     }
  1364.                     OUTPUT("Size: %d bytes, RVA: 0x%X\n", dataEntry->Size, dataEntry->OffsetToData);
  1365.  
  1366.                     // Special handling for Version resources
  1367.                     if (type && wcscmp(type, L"Version") == 0) {
  1368.                         auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  1369.                             dataEntry->OffsetToData,
  1370.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1371.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1372.                             analyzer.lpFileContent);
  1373.  
  1374.                         if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  1375.                             auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  1376.                             if (versionInfo->dwSignature == 0xFEEF04BD) {
  1377.                                 for (int indent = 0; indent < level + 2; indent++) {
  1378.                                     OUTPUT("\t");
  1379.                                 }
  1380.                                 OUTPUT("File Version: %d.%d.%d.%d\n",
  1381.                                     HIWORD(versionInfo->dwFileVersionMS),
  1382.                                     LOWORD(versionInfo->dwFileVersionMS),
  1383.                                     HIWORD(versionInfo->dwFileVersionLS),
  1384.                                     LOWORD(versionInfo->dwFileVersionLS));
  1385.                             }
  1386.                         }
  1387.                     }
  1388.                 }
  1389.             }
  1390.         }
  1391.     }
  1392.  
  1393.     void ProcessResourceDirectory64(
  1394.         PIMAGE_RESOURCE_DIRECTORY resDir,
  1395.         int level,
  1396.         const wchar_t* type,
  1397.         PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  1398.         const wchar_t* resourceTypes[],
  1399.         const PEAnalyzer& analyzer)
  1400.     {
  1401.         // Similar to ProcessResourceDirectory32 but using 64-bit structures
  1402.         // Main difference is using analyzer.pNtHeaders64 instead of analyzer.pNtHeaders32
  1403.         if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1404.             return;
  1405.             // Rest of the implementation follows the same pattern
  1406.         }
  1407.  
  1408.         auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  1409.         WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  1410.  
  1411.         for (WORD i = 0; i < totalEntries; i++) {
  1412.             if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  1413.                 break;
  1414.             }
  1415.  
  1416.             for (int indent = 0; indent < level; indent++) {
  1417.                 OUTPUT("\t");
  1418.             }
  1419.  
  1420.             if (entry[i].NameIsString) {
  1421.                 auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)baseResourceDir + entry[i].NameOffset);
  1422.                 if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  1423.                     std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  1424.                     wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  1425.                         nameEntry->NameString, nameEntry->Length);
  1426.                     resourceName[nameEntry->Length] = L'\0';
  1427.  
  1428.                     if (level == 0) {
  1429.                         OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  1430.                     }
  1431.                     else {
  1432.                         OUTPUT("Name: %s\n", resourceName.data());
  1433.                     }
  1434.                 }
  1435.             }
  1436.             else {
  1437.                 if (level == 0) {
  1438.                     DWORD resourceType = entry[i].Id;
  1439.                     if (resourceType < 16) {
  1440.                         OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  1441.                     }
  1442.                     else {
  1443.                         OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  1444.                     }
  1445.                 }
  1446.                 else {
  1447.                     OUTPUT("ID: %d\n", entry[i].Id);
  1448.                 }
  1449.             }
  1450.  
  1451.             if (entry[i].DataIsDirectory) {
  1452.                 auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)baseResourceDir + entry[i].OffsetToDirectory);
  1453.                 if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1454.                     ProcessResourceDirectory32(nextDir, level + 1,
  1455.                         level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  1456.                         baseResourceDir, resourceTypes, analyzer);
  1457.                 }
  1458.             }
  1459.             else {
  1460.                 auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)baseResourceDir + entry[i].OffsetToData);
  1461.                 if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  1462.                     for (int indent = 0; indent < level + 1; indent++) {
  1463.                         OUTPUT("\t");
  1464.                     }
  1465.                     OUTPUT("Size: %d bytes, RVA: 0x%X\n", dataEntry->Size, dataEntry->OffsetToData);
  1466.  
  1467.                     // Special handling for Version resources
  1468.                     if (type && wcscmp(type, L"Version") == 0) {
  1469.                         auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  1470.                             dataEntry->OffsetToData,
  1471.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1472.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1473.                             analyzer.lpFileContent);
  1474.  
  1475.                         if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  1476.                             auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  1477.                             if (versionInfo->dwSignature == 0xFEEF04BD) {
  1478.                                 for (int indent = 0; indent < level + 2; indent++) {
  1479.                                     OUTPUT("\t");
  1480.                                 }
  1481.                                 OUTPUT("File Version: %d.%d.%d.%d\n",
  1482.                                     HIWORD(versionInfo->dwFileVersionMS),
  1483.                                     LOWORD(versionInfo->dwFileVersionMS),
  1484.                                     HIWORD(versionInfo->dwFileVersionLS),
  1485.                                     LOWORD(versionInfo->dwFileVersionLS));
  1486.                             }
  1487.                         }
  1488.                     }
  1489.                 }
  1490.             }
  1491.         }
  1492.     }
  1493.  
  1494.     void ParseResourceDirectory32(const PEAnalyzer& analyzer) {
  1495.         const auto& resourceDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1496.         if (!resourceDir.VirtualAddress || !resourceDir.Size) return;
  1497.  
  1498.         if (!PEHelpers::IsRvaValid(resourceDir.VirtualAddress, analyzer.fileSize,
  1499.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1500.             OUTPUT("[-] Invalid resource directory RVA!\n");
  1501.             return;
  1502.         }
  1503.  
  1504.         OUTPUT("\n[+] RESOURCE DIRECTORY (32-bit)\n");
  1505.         auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  1506.             resourceDir.VirtualAddress,
  1507.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1508.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1509.             analyzer.lpFileContent);
  1510.  
  1511.         if (!pResourceDir || IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1512.             OUTPUT("[-] Invalid or corrupted resource directory\n");
  1513.             return;
  1514.         }
  1515.  
  1516.         const wchar_t* resourceTypes[] = {
  1517.             L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  1518.             L"Menu",        L"Dialog",      L"String",      L"FontDir",
  1519.             L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  1520.             L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  1521.         };
  1522.  
  1523.         ProcessResourceDirectory32(pResourceDir, 0, nullptr, pResourceDir, resourceTypes, analyzer);
  1524.     }
  1525.  
  1526.     void ParseResourceDirectory64(const PEAnalyzer& analyzer) {
  1527.         // Similar to ParseResourceDirectory32 but using 64-bit structures
  1528.         const auto& resourceDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1529.         // Rest of implementation follows same pattern as 32-bit version
  1530.     }
  1531.  
  1532.     void ParseResourceDirectory(const PEAnalyzer& analyzer) {
  1533.         if (analyzer.is64Bit) {
  1534.             ParseResourceDirectory64(analyzer);
  1535.         }
  1536.         else {
  1537.             ParseResourceDirectory32(analyzer);
  1538.         }
  1539.     }
  1540.  
  1541.     void ParseDebugDirectory32(const PEAnalyzer& analyzer) {
  1542.         const auto& debugDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1543.         if (!debugDir.VirtualAddress || !debugDir.Size) return;
  1544.  
  1545.         if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, analyzer.fileSize,
  1546.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1547.             OUTPUT("[-] Invalid debug directory RVA!\n");
  1548.             return;
  1549.         }
  1550.  
  1551.         OUTPUT("\n[+] DEBUG DIRECTORY (32-bit)\n");
  1552.         auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  1553.             debugDir.VirtualAddress,
  1554.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1555.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1556.             analyzer.lpFileContent);
  1557.  
  1558.         if (!pDebugDir || IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1559.             OUTPUT("[-] Invalid debug directory structure!\n");
  1560.             return;
  1561.         }
  1562.  
  1563.         DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  1564.         for (DWORD i = 0; i < numEntries; i++) {
  1565.             OUTPUT("\tDebug Entry %d:\n", i + 1);
  1566.             OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  1567.             OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  1568.             OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  1569.             OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  1570.             OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  1571.  
  1572.             switch (pDebugDir[i].Type) {
  1573.             case IMAGE_DEBUG_TYPE_COFF:
  1574.                 OUTPUT(" (COFF)\n"); break;
  1575.             case IMAGE_DEBUG_TYPE_CODEVIEW:
  1576.                 OUTPUT(" (CodeView)\n"); break;
  1577.             case IMAGE_DEBUG_TYPE_FPO:
  1578.                 OUTPUT(" (FPO)\n"); break;
  1579.             case IMAGE_DEBUG_TYPE_MISC:
  1580.                 OUTPUT(" (Misc)\n"); break;
  1581.             case IMAGE_DEBUG_TYPE_EXCEPTION:
  1582.                 OUTPUT(" (Exception)\n"); break;
  1583.             case IMAGE_DEBUG_TYPE_FIXUP:
  1584.                 OUTPUT(" (Fixup)\n"); break;
  1585.             case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1586.                 OUTPUT(" (OMAP to Src)\n"); break;
  1587.             case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1588.                 OUTPUT(" (OMAP from Src)\n"); break;
  1589.             case IMAGE_DEBUG_TYPE_BORLAND:
  1590.                 OUTPUT(" (Borland)\n"); break;
  1591.             default:
  1592.                 OUTPUT(" (Unknown)\n"); break;
  1593.             }
  1594.  
  1595.             OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  1596.             OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  1597.             OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  1598.  
  1599.             // Special handling for CodeView debug information
  1600.             if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1601.                 pDebugDir[i].PointerToRawData != 0 &&
  1602.                 pDebugDir[i].SizeOfData >= sizeof(DWORD)) {
  1603.  
  1604.                 auto pCVHeader = (DWORD*)((BYTE*)analyzer.lpFileContent + pDebugDir[i].PointerToRawData);
  1605.                 if (!IsBadReadPtr(pCVHeader, sizeof(DWORD))) {
  1606.                     switch (*pCVHeader) {
  1607.                     case 0x53445352: // 'RSDS'
  1608.                         if (pDebugDir[i].SizeOfData >= (sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + 1)) {
  1609.                             auto pCVData = (char*)(pCVHeader + 1);
  1610.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  1611.                                 auto guid = (GUID*)pCVData;
  1612.                                 DWORD age = *(DWORD*)(pCVData + 16);
  1613.                                 const char* pdbPath = pCVData + 20;
  1614.  
  1615.                                 OUTPUT("\tPDB Information:\n");
  1616.                                 OUTPUT("\tGUID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
  1617.                                     guid->Data1, guid->Data2, guid->Data3,
  1618.                                     guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
  1619.                                     guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
  1620.                                 OUTPUT("\tAge: %d\n", age);
  1621.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1622.                             }
  1623.                         }
  1624.                         break;
  1625.  
  1626.                     case 0x3031424E: // 'NB10'
  1627.                         if (pDebugDir[i].SizeOfData >= 16) {
  1628.                             auto pNB10Data = (char*)(pCVHeader + 1);
  1629.                             DWORD offset = *(DWORD*)pNB10Data;
  1630.                             DWORD timestamp = *(DWORD*)(pNB10Data + 4);
  1631.                             DWORD age = *(DWORD*)(pNB10Data + 8);
  1632.                             const char* pdbPath = pNB10Data + 12;
  1633.  
  1634.                             OUTPUT("\tPDB Information (NB10):\n");
  1635.                             OUTPUT("\tOffset: 0x%X\n", offset);
  1636.                             OUTPUT("\tTimestamp: 0x%X\n", timestamp);
  1637.                             OUTPUT("\tAge: %d\n", age);
  1638.                             OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1639.                         }
  1640.                         break;
  1641.                     }
  1642.                 }
  1643.             }
  1644.         }
  1645.     }
  1646.  
  1647.     void ParseDebugDirectory64(const PEAnalyzer& analyzer) {
  1648.         const auto& debugDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1649.         if (!debugDir.VirtualAddress || !debugDir.Size) return;
  1650.  
  1651.         if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, analyzer.fileSize,
  1652.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  1653.             OUTPUT("[-] Invalid debug directory RVA!\n");
  1654.             return;
  1655.         }
  1656.  
  1657.         OUTPUT("\n[+] DEBUG DIRECTORY (64-bit)\n");
  1658.         // Rest of implementation follows same pattern as 32-bit version
  1659.         // Just using pNtHeaders64 instead of pNtHeaders32
  1660.         auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  1661.             debugDir.VirtualAddress,
  1662.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1663.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1664.             analyzer.lpFileContent);
  1665.  
  1666.         if (!pDebugDir || IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1667.             OUTPUT("[-] Invalid debug directory structure!\n");
  1668.             return;
  1669.         }
  1670.  
  1671.         DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  1672.         for (DWORD i = 0; i < numEntries; i++) {
  1673.             OUTPUT("\tDebug Entry %d:\n", i + 1);
  1674.             OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  1675.             OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  1676.             OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  1677.             OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  1678.             OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  1679.  
  1680.             switch (pDebugDir[i].Type) {
  1681.             case IMAGE_DEBUG_TYPE_COFF:
  1682.                 OUTPUT(" (COFF)\n"); break;
  1683.             case IMAGE_DEBUG_TYPE_CODEVIEW:
  1684.                 OUTPUT(" (CodeView)\n"); break;
  1685.             case IMAGE_DEBUG_TYPE_FPO:
  1686.                 OUTPUT(" (FPO)\n"); break;
  1687.             case IMAGE_DEBUG_TYPE_MISC:
  1688.                 OUTPUT(" (Misc)\n"); break;
  1689.             case IMAGE_DEBUG_TYPE_EXCEPTION:
  1690.                 OUTPUT(" (Exception)\n"); break;
  1691.             case IMAGE_DEBUG_TYPE_FIXUP:
  1692.                 OUTPUT(" (Fixup)\n"); break;
  1693.             case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1694.                 OUTPUT(" (OMAP to Src)\n"); break;
  1695.             case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1696.                 OUTPUT(" (OMAP from Src)\n"); break;
  1697.             case IMAGE_DEBUG_TYPE_BORLAND:
  1698.                 OUTPUT(" (Borland)\n"); break;
  1699.             default:
  1700.                 OUTPUT(" (Unknown)\n"); break;
  1701.             }
  1702.  
  1703.             OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  1704.             OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  1705.             OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  1706.  
  1707.             // Special handling for CodeView debug information
  1708.             if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1709.                 pDebugDir[i].PointerToRawData != 0 &&
  1710.                 pDebugDir[i].SizeOfData >= sizeof(DWORD)) {
  1711.  
  1712.                 auto pCVHeader = (DWORD*)((BYTE*)analyzer.lpFileContent + pDebugDir[i].PointerToRawData);
  1713.                 if (!IsBadReadPtr(pCVHeader, sizeof(DWORD))) {
  1714.                     switch (*pCVHeader) {
  1715.                     case 0x53445352: // 'RSDS'
  1716.                         if (pDebugDir[i].SizeOfData >= (sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + 1)) {
  1717.                             auto pCVData = (char*)(pCVHeader + 1);
  1718.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  1719.                                 auto guid = (GUID*)pCVData;
  1720.                                 DWORD age = *(DWORD*)(pCVData + 16);
  1721.                                 const char* pdbPath = pCVData + 20;
  1722.  
  1723.                                 OUTPUT("\tPDB Information:\n");
  1724.                                 OUTPUT("\tGUID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
  1725.                                     guid->Data1, guid->Data2, guid->Data3,
  1726.                                     guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
  1727.                                     guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
  1728.                                 OUTPUT("\tAge: %d\n", age);
  1729.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1730.                             }
  1731.                         }
  1732.                         break;
  1733.  
  1734.                     case 0x3031424E: // 'NB10'
  1735.                         if (pDebugDir[i].SizeOfData >= 16) {
  1736.                             auto pNB10Data = (char*)(pCVHeader + 1);
  1737.                             DWORD offset = *(DWORD*)pNB10Data;
  1738.                             DWORD timestamp = *(DWORD*)(pNB10Data + 4);
  1739.                             DWORD age = *(DWORD*)(pNB10Data + 8);
  1740.                             const char* pdbPath = pNB10Data + 12;
  1741.  
  1742.                             OUTPUT("\tPDB Information (NB10):\n");
  1743.                             OUTPUT("\tOffset: 0x%X\n", offset);
  1744.                             OUTPUT("\tTimestamp: 0x%X\n", timestamp);
  1745.                             OUTPUT("\tAge: %d\n", age);
  1746.                             OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1747.                         }
  1748.                         break;
  1749.                     }
  1750.                 }
  1751.             }
  1752.         }
  1753.     }
  1754.     // ... [Same implementation as ParseDebugDirectory32]
  1755.  
  1756.     void ParseDebugDirectory(const PEAnalyzer& analyzer) {
  1757.         if (analyzer.is64Bit) {
  1758.             ParseDebugDirectory64(analyzer);
  1759.         }
  1760.         else {
  1761.             ParseDebugDirectory32(analyzer);
  1762.         }
  1763.     }
  1764.  
  1765.     // Add Section Parser if not already defined
  1766.     void ParseSections(const PEAnalyzer& analyzer) {
  1767.         OUTPUT("[+] SECTION HEADERS\n");
  1768.  
  1769.         PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(
  1770.             analyzer.is64Bit ?
  1771.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64) :
  1772.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32));
  1773.  
  1774.         WORD numberOfSections = analyzer.is64Bit ?
  1775.             analyzer.pNtHeaders64->FileHeader.NumberOfSections :
  1776.             analyzer.pNtHeaders32->FileHeader.NumberOfSections;
  1777.  
  1778.         for (WORD i = 0; i < numberOfSections; i++, pSection++) {
  1779.             if (IsBadReadPtr(pSection, sizeof(IMAGE_SECTION_HEADER))) {
  1780.                 OUTPUT("[-] Invalid section header detected!\n");
  1781.                 break;
  1782.             }
  1783.  
  1784.             char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1785.             memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  1786.  
  1787.             // Ensure section name is printable
  1788.             for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  1789.                 if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  1790.                     sectionName[j] = '\0';
  1791.                 }
  1792.             }
  1793.  
  1794.             wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  1795.             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1796.                 sectionName, -1,
  1797.                 wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  1798.  
  1799.             OUTPUT("\tSECTION: %s\n", wideSectionName);
  1800.             OUTPUT("\t\tVirtualSize: 0x%X\n", pSection->Misc.VirtualSize);
  1801.             OUTPUT("\t\tVirtualAddress: 0x%X\n", pSection->VirtualAddress);
  1802.             OUTPUT("\t\tSizeOfRawData: 0x%X\n", pSection->SizeOfRawData);
  1803.             OUTPUT("\t\tPointerToRawData: 0x%X\n", pSection->PointerToRawData);
  1804.             OUTPUT("\t\tPointerToRelocations: 0x%X\n", pSection->PointerToRelocations);
  1805.             OUTPUT("\t\tPointerToLinenumbers: 0x%X\n", pSection->PointerToLinenumbers);
  1806.             OUTPUT("\t\tNumberOfRelocations: 0x%X\n", pSection->NumberOfRelocations);
  1807.             OUTPUT("\t\tNumberOfLinenumbers: 0x%X\n", pSection->NumberOfLinenumbers);
  1808.             OUTPUT("\t\tCharacteristics: 0x%X %s\n\n",
  1809.                 pSection->Characteristics,
  1810.                 PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  1811.         }
  1812.     } //end of parsesection here
  1813.  
  1814.     void AnalyzePEFile(const wchar_t* filePathW) {
  1815.         OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  1816.         ShowProgress(10);
  1817.  
  1818.         PEAnalyzer analyzer;
  1819.         if (!PEParser::InitializePEAnalyzer(analyzer, filePathW)) {
  1820.             SetStatusText(L"Failed to initialize PE analysis!");
  1821.             return;
  1822.         }
  1823.  
  1824.         ShowProgress(20);
  1825.  
  1826.         // Basic PE Information
  1827.         OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  1828.         OUTPUT("[+] Architecture: %s\n\n", analyzer.is64Bit ? "x64" : "x86");
  1829.  
  1830.         // DOS Header
  1831.         OUTPUT("[+] DOS HEADER\n");
  1832.         OUTPUT("\te_magic    : 0x%X\n", analyzer.pDosHeader->e_magic);
  1833.         OUTPUT("\te_cblp     : 0x%X\n", analyzer.pDosHeader->e_cblp);
  1834.         OUTPUT("\te_cp       : 0x%X\n", analyzer.pDosHeader->e_cp);
  1835.         OUTPUT("\te_crlc     : 0x%X\n", analyzer.pDosHeader->e_crlc);
  1836.         OUTPUT("\te_cparhdr  : 0x%X\n", analyzer.pDosHeader->e_cparhdr);
  1837.         OUTPUT("\te_minalloc : 0x%X\n", analyzer.pDosHeader->e_minalloc);
  1838.         OUTPUT("\te_maxalloc : 0x%X\n", analyzer.pDosHeader->e_maxalloc);
  1839.         OUTPUT("\te_ss       : 0x%X\n", analyzer.pDosHeader->e_ss);
  1840.         OUTPUT("\te_sp       : 0x%X\n", analyzer.pDosHeader->e_sp);
  1841.         OUTPUT("\te_csum     : 0x%X\n", analyzer.pDosHeader->e_csum);
  1842.         OUTPUT("\te_ip       : 0x%X\n", analyzer.pDosHeader->e_ip);
  1843.         OUTPUT("\te_cs       : 0x%X\n", analyzer.pDosHeader->e_cs);
  1844.         OUTPUT("\te_lfarlc   : 0x%X\n", analyzer.pDosHeader->e_lfarlc);
  1845.         OUTPUT("\te_ovno     : 0x%X\n", analyzer.pDosHeader->e_ovno);
  1846.         OUTPUT("\te_oemid    : 0x%X\n", analyzer.pDosHeader->e_oemid);
  1847.         OUTPUT("\te_oeminfo  : 0x%X\n", analyzer.pDosHeader->e_oeminfo);
  1848.         OUTPUT("\te_lfanew   : 0x%X\n\n", analyzer.pDosHeader->e_lfanew);
  1849.  
  1850.         ShowProgress(30);
  1851.  
  1852.         // NT Headers
  1853.         if (analyzer.is64Bit) {
  1854.             OUTPUT("[+] NT HEADER (64-bit)\n");
  1855.             OUTPUT("\tSignature: 0x%X\n\n", analyzer.pNtHeaders64->Signature);
  1856.  
  1857.             OUTPUT("[+] FILE HEADER\n");
  1858.             OUTPUT("\tMachine: 0x%X\n", analyzer.pNtHeaders64->FileHeader.Machine);
  1859.             OUTPUT("\tNumberOfSections: 0x%X\n", analyzer.pNtHeaders64->FileHeader.NumberOfSections);
  1860.             OUTPUT("\tTimeDateStamp: 0x%X\n", analyzer.pNtHeaders64->FileHeader.TimeDateStamp);
  1861.             OUTPUT("\tPointerToSymbolTable: 0x%X\n", analyzer.pNtHeaders64->FileHeader.PointerToSymbolTable);
  1862.             OUTPUT("\tNumberOfSymbols: 0x%X\n", analyzer.pNtHeaders64->FileHeader.NumberOfSymbols);
  1863.             OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", analyzer.pNtHeaders64->FileHeader.SizeOfOptionalHeader);
  1864.             OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1865.                 analyzer.pNtHeaders64->FileHeader.Characteristics,
  1866.                 PEHelpers::GetImageCharacteristics(analyzer.pNtHeaders64->FileHeader.Characteristics).c_str());
  1867.  
  1868.             OUTPUT("[+] OPTIONAL HEADER\n");
  1869.             OUTPUT("\tMagic: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.Magic);
  1870.             OUTPUT("\tAddressOfEntryPoint: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.AddressOfEntryPoint);
  1871.             OUTPUT("\tImageBase: 0x%llX\n", analyzer.pNtHeaders64->OptionalHeader.ImageBase);
  1872.             OUTPUT("\tSectionAlignment: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SectionAlignment);
  1873.             OUTPUT("\tFileAlignment: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.FileAlignment);
  1874.             OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorOperatingSystemVersion);
  1875.             OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorOperatingSystemVersion);
  1876.             OUTPUT("\tMajorImageVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorImageVersion);
  1877.             OUTPUT("\tMinorImageVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorImageVersion);
  1878.             OUTPUT("\tMajorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorSubsystemVersion);
  1879.             OUTPUT("\tMinorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorSubsystemVersion);
  1880.             OUTPUT("\tWin32VersionValue: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.Win32VersionValue);
  1881.             OUTPUT("\tSizeOfImage: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SizeOfImage);
  1882.             OUTPUT("\tSizeOfHeaders: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SizeOfHeaders);
  1883.             OUTPUT("\tCheckSum: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.CheckSum);
  1884.             OUTPUT("\tSubsystem: 0x%X %s\n\n",
  1885.                 analyzer.pNtHeaders64->OptionalHeader.Subsystem,
  1886.                 PEHelpers::GetSubsystem(analyzer.pNtHeaders64->OptionalHeader.Subsystem).c_str());
  1887.         }
  1888.         else {
  1889.             // Similar output for 32-bit headers using analyzer.pNtHeaders32
  1890.             //if (analyzer.is64Bit) {
  1891.             OUTPUT("[+] NT HEADER (32-bit)\n");
  1892.             OUTPUT("\tSignature: 0x%X\n\n", analyzer.pNtHeaders32->Signature);
  1893.  
  1894.             OUTPUT("[+] FILE HEADER\n");
  1895.             OUTPUT("\tMachine: 0x%X\n", analyzer.pNtHeaders32->FileHeader.Machine);
  1896.             OUTPUT("\tNumberOfSections: 0x%X\n", analyzer.pNtHeaders32->FileHeader.NumberOfSections);
  1897.             OUTPUT("\tTimeDateStamp: 0x%X\n", analyzer.pNtHeaders32->FileHeader.TimeDateStamp);
  1898.             OUTPUT("\tPointerToSymbolTable: 0x%X\n", analyzer.pNtHeaders32->FileHeader.PointerToSymbolTable);
  1899.             OUTPUT("\tNumberOfSymbols: 0x%X\n", analyzer.pNtHeaders32->FileHeader.NumberOfSymbols);
  1900.             OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", analyzer.pNtHeaders32->FileHeader.SizeOfOptionalHeader);
  1901.             OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1902.                 analyzer.pNtHeaders32->FileHeader.Characteristics,
  1903.                 PEHelpers::GetImageCharacteristics(analyzer.pNtHeaders32->FileHeader.Characteristics).c_str());
  1904.  
  1905.             OUTPUT("[+] OPTIONAL HEADER\n");
  1906.             OUTPUT("\tMagic: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.Magic);
  1907.             OUTPUT("\tAddressOfEntryPoint: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.AddressOfEntryPoint);
  1908.             OUTPUT("\tImageBase: 0x%llX\n", analyzer.pNtHeaders32->OptionalHeader.ImageBase);
  1909.             OUTPUT("\tSectionAlignment: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SectionAlignment);
  1910.             OUTPUT("\tFileAlignment: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.FileAlignment);
  1911.             OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorOperatingSystemVersion);
  1912.             OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorOperatingSystemVersion);
  1913.             OUTPUT("\tMajorImageVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorImageVersion);
  1914.             OUTPUT("\tMinorImageVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorImageVersion);
  1915.             OUTPUT("\tMajorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorSubsystemVersion);
  1916.             OUTPUT("\tMinorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorSubsystemVersion);
  1917.             OUTPUT("\tWin32VersionValue: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.Win32VersionValue);
  1918.             OUTPUT("\tSizeOfImage: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SizeOfImage);
  1919.             OUTPUT("\tSizeOfHeaders: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SizeOfHeaders);
  1920.             OUTPUT("\tCheckSum: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.CheckSum);
  1921.             OUTPUT("\tSubsystem: 0x%X %s\n\n",
  1922.                 analyzer.pNtHeaders32->OptionalHeader.Subsystem,
  1923.                 PEHelpers::GetSubsystem(analyzer.pNtHeaders32->OptionalHeader.Subsystem).c_str());
  1924.             // ... [32-bit header output code]
  1925.         }
  1926.  
  1927.         ShowProgress(40);
  1928.  
  1929.         // Parse Data Directories
  1930.         OUTPUT("[+] DATA DIRECTORIES\n");
  1931.         const IMAGE_DATA_DIRECTORY* dataDirectories = analyzer.is64Bit ?
  1932.             analyzer.pNtHeaders64->OptionalHeader.DataDirectory :
  1933.             analyzer.pNtHeaders32->OptionalHeader.DataDirectory;
  1934.  
  1935.         for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  1936.             if (dataDirectories[i].VirtualAddress != 0) {
  1937.                 OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  1938.                 OUTPUT("\t\tVirtualAddress: 0x%X\n", dataDirectories[i].VirtualAddress);
  1939.                 OUTPUT("\t\tSize: 0x%X\n", dataDirectories[i].Size);
  1940.             }
  1941.         }
  1942.         OUTPUT("\n");
  1943.  
  1944.         ShowProgress(50);
  1945.  
  1946.         // Parse Sections
  1947.         PEParser::ParseSections(analyzer);
  1948.         ShowProgress(60);
  1949.  
  1950.         // Parse Import Directory
  1951.         PEParser::ParseImportDirectory(analyzer);
  1952.         ShowProgress(70);
  1953.  
  1954.         // Parse Export Directory
  1955.         PEParser::ParseExportDirectory(analyzer);
  1956.         ShowProgress(80);
  1957.  
  1958.         // Parse Resource Directory
  1959.         PEParser::ParseResourceDirectory(analyzer);
  1960.         ShowProgress(90);
  1961.  
  1962.         // Parse Debug Directory
  1963.         PEParser::ParseDebugDirectory(analyzer);
  1964.  
  1965.         ShowProgress(100);
  1966.         SetStatusText(L"Analysis complete");
  1967.         ShowWindow(g_hProgressBar, SW_HIDE);
  1968.     }
  1969.  
  1970.            
  1971.         //}
  1972.  
  1973.         //UpdateEditControl();
  1974.     //}
  1975.  
  1976.     // new code upto here ending here ^^
  1977.     //
  1978.     //######################################################################################
  1979.     //######################################################################################
  1980.     //        ##    endroughxfer - urldump #1#
  1981.     //        ##    <EOF><EOF>
  1982.     //######################################################################################
  1983.     //######################################################################################
  1984.         //end adding here
  1985.  
  1986.  
  1987.  
  1988.     //filePathW
  1989.     //lpFilePath
  1990.     HANDLE GetFileContent(const wchar_t* lpFilePath) {
  1991.         HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  1992.         if (hFile == INVALID_HANDLE_VALUE) return nullptr;
  1993.         DWORD fileSize = ::GetFileSize(hFile, nullptr);
  1994.         auto lpFileContent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileSize);
  1995.         DWORD bytesRead;
  1996.         ReadFile(hFile, lpFileContent, fileSize, &bytesRead, nullptr);
  1997.         CloseHandle(hFile);
  1998.         return lpFileContent;
  1999.     }
  2000.  
  2001.     void UpdateEditControl() {
  2002.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  2003.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  2004.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  2005.         }
  2006.     }
Tags: #final-bug
Add Comment
Please, Sign In to add comment