alien_fx_fiend

11 Errors = Forward Decl + Combined Func + Namespace Reloc

Dec 19th, 2024
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 174.04 KB | Source Code | 0 0
  1. #define STRICT
  2. #define WIN32_LEAN_AND_MEAN
  3. #include <Windows.h>
  4. #include <winternl.h>
  5. #include <CommCtrl.h>
  6. #include <commdlg.h>
  7. #include <string>
  8. #include <strsafe.h>
  9. #include <sstream>
  10. #include <iomanip>
  11. #include <stdio.h>
  12. #include <vector>
  13. #include <shellapi.h>
  14. //#include "helpers.h"
  15. #include "resource.h"
  16. #pragma comment(lib, "comctl32.lib")
  17.  
  18. //bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders);
  19. struct PEAnalyzer {
  20.     LPVOID lpFileContent;
  21.     DWORD fileSize;
  22.     bool is64Bit;
  23.     PIMAGE_NT_HEADERS32 pNtHeaders32;
  24.     PIMAGE_NT_HEADERS64 pNtHeaders64;
  25.     PIMAGE_DOS_HEADER pDosHeader;
  26.  
  27.     PEAnalyzer() : lpFileContent(nullptr), fileSize(0), is64Bit(false),
  28.         pNtHeaders32(nullptr), pNtHeaders64(nullptr), pDosHeader(nullptr) {}
  29. };
  30.  
  31. namespace PEHelpers {
  32.     // Add these new helper functions
  33.     bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  34.         return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  35.     }
  36.  
  37.     DWORD_PTR GetImageBase(PIMAGE_NT_HEADERS pNtHeaders) {
  38.         if (PEHelpers::Is64BitPE(pNtHeaders)) {
  39.             auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  40.             return static_cast<DWORD_PTR>(pNtHeaders64->OptionalHeader.ImageBase);
  41.         }
  42.         else {
  43.             auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  44.             return static_cast<DWORD_PTR>(pNtHeaders32->OptionalHeader.ImageBase);
  45.         }
  46.     }
  47.  
  48.     DWORD GetSizeOfImage(PIMAGE_NT_HEADERS pNtHeaders) {
  49.         if (PEHelpers::Is64BitPE(pNtHeaders)) {
  50.             auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  51.             return pNtHeaders64->OptionalHeader.SizeOfImage;
  52.         }
  53.         else {
  54.             auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  55.             return pNtHeaders32->OptionalHeader.SizeOfImage;
  56.         }
  57.     }
  58.  
  59.     bool ValidateFileSize(DWORD expectedSize, DWORD fileSize) {
  60.         // Validate against SizeOfHeaders instead of SizeOfImage
  61.         return expectedSize > 0 && expectedSize <= fileSize;
  62.     }
  63.     //}
  64.  
  65.         // Replace the existing GetRvaPtr function in PEHelpers namespace with this:
  66.     DWORD_PTR GetRvaPtr(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections, LPVOID baseAddress) {
  67.         for (WORD i = 0; i < numberOfSections; i++) {
  68.             if (rva >= pSectionHeader[i].VirtualAddress &&
  69.                 rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  70.                 DWORD_PTR delta = (DWORD_PTR)baseAddress + pSectionHeader[i].PointerToRawData;
  71.                 return delta + (rva - pSectionHeader[i].VirtualAddress);
  72.             }
  73.         }
  74.         return 0;
  75.     }
  76.  
  77.     // Add to PEHelpers namespace:
  78.     bool IsRvaValid(DWORD rva, DWORD fileSize, PIMAGE_NT_HEADERS pNtHeaders) {
  79.         return rva < pNtHeaders->OptionalHeader.SizeOfImage&& rva < fileSize;
  80.     }
  81.  
  82.     // Add this new helper function in PEHelpers namespace:
  83.     PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  84.         for (WORD i = 0; i < numberOfSections; i++) {
  85.             if ((rva >= pSectionHeader[i].VirtualAddress) &&
  86.                 (rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData))) {
  87.                 return &pSectionHeader[i];
  88.             }
  89.         }
  90.         return nullptr;
  91.     }
  92.  
  93.     std::wstring GetImageCharacteristics(DWORD characteristics) {
  94.         if (characteristics & IMAGE_FILE_DLL) return L"(DLL)";
  95.         if (characteristics & IMAGE_FILE_SYSTEM) return L"(DRIVER)";
  96.         if (characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) return L"(EXE)";
  97.         return L"(UNKNOWN)";
  98.     }
  99.  
  100.     std::wstring GetSubsystem(WORD subsystem) {
  101.         switch (subsystem) {
  102.         case IMAGE_SUBSYSTEM_NATIVE: return L"(NATIVE/DRIVER)";
  103.         case IMAGE_SUBSYSTEM_WINDOWS_GUI: return L"(GUI)";
  104.         case IMAGE_SUBSYSTEM_WINDOWS_CUI: return L"(CONSOLE)";
  105.         default: return L"(UNKNOWN)";
  106.         }
  107.     }
  108.  
  109.     std::wstring GetDataDirectoryName(int DirectoryNumber) {
  110.         switch (DirectoryNumber) {
  111.         case 0: return L"Export Table";
  112.         case 1: return L"Import Table";
  113.         case 2: return L"Resource Table";
  114.         case 3: return L"Exception Entry";
  115.         case 4: return L"Security Entry";
  116.         case 5: return L"Relocation Table";
  117.         case 6: return L"Debug Entry";
  118.         case 7: return L"Copyright Entry";
  119.         case 8: return L"Global PTR Entry";
  120.         case 9: return L"TLS Entry";
  121.         case 10: return L"Configuration Entry";
  122.         case 11: return L"Bound Import Entry";
  123.         case 12: return L"IAT";
  124.         case 13: return L"Delay Import Descriptor";
  125.         case 14: return L"COM Descriptor";
  126.         default: return L"Unknown";
  127.         }
  128.     }
  129.  
  130.     std::wstring GetSectionProtection(DWORD characteristics) {
  131.         std::wstring protection = L"(";
  132.         bool needsSeparator = false;
  133.  
  134.         if (characteristics & IMAGE_SCN_MEM_EXECUTE) {
  135.             protection += L"EXECUTE";
  136.             needsSeparator = true;
  137.         }
  138.  
  139.         if (characteristics & IMAGE_SCN_MEM_READ) {
  140.             if (needsSeparator) protection += L" | ";
  141.             protection += L"READ";
  142.             needsSeparator = true;
  143.         }
  144.  
  145.         if (characteristics & IMAGE_SCN_MEM_WRITE) {
  146.             if (needsSeparator) protection += L" | ";
  147.             protection += L"WRITE";
  148.         }
  149.  
  150.         protection += L")";
  151.         return protection;
  152.     }
  153.  
  154.     PIMAGE_SECTION_HEADER GetExportSection(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  155.         const int NumberOfSections,
  156.         const DWORD_PTR dExportAddress) {
  157.         for (int i = 0; i < NumberOfSections; ++i) {
  158.             const auto pCurrentSectionHeader =
  159.                 (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  160.  
  161.             if (dExportAddress >= pCurrentSectionHeader->VirtualAddress &&
  162.                 dExportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize)
  163.                 return pCurrentSectionHeader;
  164.         }
  165.         return nullptr;
  166.     }
  167.  
  168.     DWORD RvaToOffset(DWORD rva, PIMAGE_SECTION_HEADER pSectionHeader, WORD numberOfSections) {
  169.         for (WORD i = 0; i < numberOfSections; i++) {
  170.             if (rva >= pSectionHeader[i].VirtualAddress &&
  171.                 rva < (pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)) {
  172.                 return (rva - pSectionHeader[i].VirtualAddress) + pSectionHeader[i].PointerToRawData;
  173.             }
  174.         }
  175.         return 0;
  176.     }
  177. }
  178.  
  179. using namespace std;
  180. // At the top of your file, change the window class name to wide string
  181. #define WINDOW_CLASS_NAME L"PEAnalyzerWindow"
  182. //const wchar_t* const WINDOW_CLASS_NAME = L"PEAnalyzerWindow";
  183.  
  184. // Use ANSI versions explicitly
  185. //#undef CreateWindow
  186. //#undef CreateWindowEx
  187. //#define CreateWindow  CreateWindowW
  188. //#define CreateWindowEx CreateWindowExW
  189.  
  190. // Helper function to replace printf with GUI output
  191. #define OUTPUT(format, ...) AppendToOutput(L##format, ##__VA_ARGS__)
  192. //#define OUTPUT(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  193. //#define printf(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  194.  
  195. // Window dimensions
  196. #define WINDOW_WIDTH    1024
  197. #define WINDOW_HEIGHT   768
  198. #define EDIT_MARGIN    10
  199.  
  200. // Global variables
  201. HWND g_hMainWindow = NULL;
  202. HWND g_hEditControl = NULL;
  203. HFONT g_hFont = NULL;
  204. std::wstringstream g_OutputText;
  205. WCHAR filePathW[MAX_PATH];
  206. std::vector<wchar_t> g_OutputBuffer;
  207. std::wstring tempBuffer; // Declare tempBuffer globally
  208. HWND g_hStatusBar = NULL;
  209. HWND g_hProgressBar = NULL;  // Add this with your other global variables
  210. //int virtualHeight = 100;  // Initialize with an appropriate value
  211.  
  212. // Function declarations
  213. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  214. LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  215. void CreateMainWindow(HINSTANCE hInstance);
  216. void InitializeControls(HWND hwnd);
  217. void AddMenus(HWND hwnd);
  218. void OpenFileDialog(HWND hwnd);
  219. //void AnalyzePEFile(const WCHAR* filePathW);
  220. void AnalyzePEFile(const wchar_t* filePathW);
  221. HANDLE GetFileContent(const wchar_t* lpFilePath);
  222. /*void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory);
  223. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  224.     int NumberOfSections, DWORD dImportAddress);
  225. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  226.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);
  227. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  228.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);*/
  229. void AppendToOutput(const wchar_t* format, ...);
  230. void UpdateEditControl();
  231. //newfunctionshere (lateest fixes)
  232. void ParseSections(const PEAnalyzer& analyzer); //forwarddeclare parse+ bring namespace up
  233.  
  234.  
  235. // Main window class name
  236. //const char* const WINDOW_CLASS_NAME = "PEAnalyzerWindow";
  237.  
  238. //new inserted here >>
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257. //here
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.     int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  284.         INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
  285.         InitCommonControlsEx(&icc);
  286.  
  287.         // Get command line parameters in Unicode
  288.         int argc;
  289.         LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  290.  
  291.         CreateMainWindow(hInstance);
  292.         if (!g_hMainWindow) {
  293.             LocalFree(argv);
  294.             return -1;
  295.         }
  296.  
  297.         ShowWindow(g_hMainWindow, nCmdShow);
  298.         UpdateWindow(g_hMainWindow);
  299.  
  300.         // If there's a command line parameter, process it
  301.         if (argc > 1) {
  302.             // Process the first parameter as file path
  303.             SetWindowTextW(g_hEditControl, L"");
  304.             g_OutputText.str(L"");
  305.             g_OutputText.clear();
  306.             AnalyzePEFile(argv[1]);
  307.             UpdateEditControl();
  308.         }
  309.  
  310.         LocalFree(argv);
  311.  
  312.         MSG msg = {};
  313.         while (GetMessage(&msg, NULL, 0, 0)) {
  314.             TranslateMessage(&msg);
  315.             DispatchMessage(&msg);
  316.         }
  317.  
  318.         if (g_hFont) DeleteObject(g_hFont);
  319.         return (int)msg.wParam;
  320.     }
  321.  
  322.     void CreateMainWindow(HINSTANCE hInstance) {
  323.         WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), 0, WindowProc, 0, 0, hInstance,
  324.             LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)),
  325.             LoadCursor(NULL, IDC_ARROW),
  326.             (HBRUSH)(COLOR_WINDOW + 1),
  327.             NULL, WINDOW_CLASS_NAME,
  328.             LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)) };
  329.         RegisterClassExW(&wc);
  330.  
  331.         // Get screen dimensions
  332.         int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  333.         int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  334.  
  335.         // Calculate center position
  336.         int windowX = (screenWidth - WINDOW_WIDTH) / 2;
  337.         int windowY = (screenHeight - WINDOW_HEIGHT) / 2;
  338.  
  339.         // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
  340.         DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
  341.         //WS_OVERLAPPEDWINDOW ~~> style
  342.         g_hMainWindow = CreateWindowExW(0, WINDOW_CLASS_NAME, L"PE File Analyzer",
  343.             style, windowX, windowY, WINDOW_WIDTH, WINDOW_HEIGHT,
  344.             nullptr, nullptr, hInstance, nullptr);
  345.     }
  346.  
  347.     void InitializeControls(HWND hwnd) {
  348.         // Create status bar
  349.         g_hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
  350.             WS_CHILD | WS_VISIBLE,
  351.             0, 0, 0, 0, hwnd, NULL,
  352.             (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  353.  
  354.         // Set up status bar parts
  355.         RECT rcClient;
  356.         GetClientRect(hwnd, &rcClient);
  357.         int statusParts[2] = { 150, rcClient.right };
  358.         SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  359.  
  360.         // Create progress bar in the second part of status bar
  361.         RECT rcPart;
  362.         SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  363.  
  364.         g_hProgressBar = CreateWindowEx(0, PROGRESS_CLASS, NULL,
  365.             WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
  366.             rcPart.left + 5, rcPart.top + 2,
  367.             rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  368.             g_hStatusBar, NULL,
  369.             (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  370.  
  371.         // Set blue color and range
  372.         SendMessage(g_hProgressBar, PBM_SETBARCOLOR, 0, (LPARAM)RGB(0, 120, 215));  // Windows 10 blue
  373.         SendMessage(g_hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  374.         SendMessage(g_hProgressBar, PBM_SETSTEP, 1, 0);
  375.  
  376.         // Get status bar height for edit control positioning
  377.         RECT rcStatus;
  378.         GetWindowRect(g_hStatusBar, &rcStatus);
  379.         int statusHeight = rcStatus.bottom - rcStatus.top;
  380.  
  381.         // Create edit control
  382.         g_hEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
  383.             WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
  384.             ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
  385.             EDIT_MARGIN, EDIT_MARGIN,
  386.             rcClient.right - (2 * EDIT_MARGIN),
  387.             rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  388.             hwnd, nullptr,
  389.             (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), nullptr);
  390.  
  391.         // Create and set font
  392.         g_hFont = CreateFont(-14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
  393.             ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  394.             DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, L"Consolas");
  395.  
  396.         if (g_hFont)
  397.             SendMessage(g_hEditControl, WM_SETFONT, (WPARAM)g_hFont, TRUE);
  398.  
  399.         SetWindowSubclass(g_hEditControl, EditSubclassProc, 0, 0);
  400.     }
  401.  
  402.     void AddMenus(HWND hwnd) {
  403.         HMENU hMenuBar = CreateMenu();
  404.         HMENU hFileMenu = CreateMenu();
  405.         AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
  406.         AppendMenu(hFileMenu, MF_STRING, 1, L"&Open\tCtrl+O");  // Updated to show shortcut
  407.         AppendMenu(hFileMenu, MF_STRING, 2, L"E&xit");
  408.         SetMenu(hwnd, hMenuBar);
  409.     }
  410.  
  411.     /*LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  412.         if (uMsg == WM_KEYDOWN) {
  413.             // Check for Ctrl+O
  414.             if ((GetKeyState(VK_CONTROL) & 0x8000) && wParam == 'O') {
  415.                 SendMessage(GetParent(hwnd), WM_COMMAND, 1, 0);  // Send the Open command
  416.                 return 0;
  417.             }
  418.  
  419.             // Existing cases
  420.             switch (wParam) {
  421.             case VK_F1:
  422.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
  423.                 return 0;
  424.             case VK_ESCAPE:
  425.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
  426.                 return 0;
  427.             case VK_PRIOR:  // Page Up
  428.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_PRIOR, 0);
  429.                 return 0;
  430.             case VK_NEXT:  // Page Down
  431.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_NEXT, 0);
  432.                 return 0;
  433.             }
  434.         }
  435.         else if (uMsg == WM_MOUSEWHEEL) {
  436.             int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  437.             if (zDelta > 0) {
  438.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_PRIOR, 0);  // Mouse Wheel Up
  439.             }
  440.             else if (zDelta < 0) {
  441.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_NEXT, 0);  // Mouse Wheel Down
  442.             }
  443.             return 0;
  444.         }
  445.         return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  446.     }*/
  447.  
  448.     // First, add this helper function to determine if the PE file is 64-bit
  449.     bool Is64BitPE(PIMAGE_NT_HEADERS pNtHeaders) {
  450.         return pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
  451.     }
  452.  
  453.     LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  454.         if (uMsg == WM_KEYDOWN) {
  455.             if ((GetKeyState(VK_CONTROL) & 0x8000) && wParam == 'O') {
  456.                 SendMessage(GetParent(hwnd), WM_COMMAND, 1, 0);
  457.                 return 0;
  458.             }
  459.             switch (wParam) {
  460.             case VK_F1:
  461.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_F1, 0);
  462.                 return 0;
  463.             case VK_ESCAPE:
  464.                 SendMessage(GetParent(hwnd), WM_KEYDOWN, VK_ESCAPE, 0);
  465.                 return 0;
  466.             case VK_PRIOR:
  467.                 // Scroll up
  468.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  469.                 return 0;
  470.             case VK_NEXT:
  471.                 // Scroll down
  472.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  473.                 return 0;
  474.             case VK_UP:
  475.                 // Scroll one line up
  476.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  477.                 return 0;
  478.             case VK_DOWN:
  479.                 // Scroll one line down
  480.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  481.                 return 0;
  482.             }
  483.         }
  484.         if (uMsg == WM_MOUSEWHEEL) {
  485.             int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  486.             if (delta > 0) {
  487.                 // Scroll up
  488.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  489.             }
  490.             else {
  491.                 // Scroll down
  492.                 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  493.             }
  494.             return 0;
  495.         }
  496.         return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  497.     }
  498.  
  499.     LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  500.         switch (uMsg) {
  501.         case WM_CREATE: InitializeControls(hwnd); AddMenus(hwnd); return 0;
  502.         case WM_SIZE:
  503.         {
  504.             RECT rcClient;
  505.             GetClientRect(hwnd, &rcClient);
  506.  
  507.             // Resize status bar
  508.             SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
  509.  
  510.             // Recalculate status bar parts
  511.             int statusParts[2] = { 150, rcClient.right };
  512.             SendMessage(g_hStatusBar, SB_SETPARTS, 2, (LPARAM)statusParts);
  513.  
  514.             // Reposition progress bar
  515.             RECT rcPart;
  516.             SendMessage(g_hStatusBar, SB_GETRECT, 1, (LPARAM)&rcPart);
  517.             SetWindowPos(g_hProgressBar, NULL,
  518.                 rcPart.left + 5, rcPart.top + 2,
  519.                 rcPart.right - rcPart.left - 10, rcPart.bottom - rcPart.top - 4,
  520.                 SWP_NOZORDER);
  521.  
  522.             // Get status bar height
  523.             RECT rcStatus;
  524.             GetWindowRect(g_hStatusBar, &rcStatus);
  525.             int statusHeight = rcStatus.bottom - rcStatus.top;
  526.  
  527.             // Resize edit control
  528.             SetWindowPos(g_hEditControl, NULL,
  529.                 EDIT_MARGIN,
  530.                 EDIT_MARGIN,
  531.                 rcClient.right - (2 * EDIT_MARGIN),
  532.                 rcClient.bottom - statusHeight - (2 * EDIT_MARGIN),
  533.                 SWP_NOZORDER);
  534.             return 0;
  535.         }
  536.         /*case WM_KEYDOWN:
  537.         {
  538.             // Check if Ctrl is pressed
  539.             if (GetKeyState(VK_CONTROL) & 0x8000) {
  540.                 switch (wParam) {
  541.                 case 'O':  // Ctrl+O
  542.                     OpenFileDialog(hwnd);
  543.                     return 0;
  544.                 }
  545.             }
  546.  
  547.             // Handle Page Up/Page Down
  548.             switch (wParam) {
  549.             case VK_PRIOR:  // Page Up
  550.                 ScrollWindow(hwnd, 0, -virtualHeight, NULL, NULL);
  551.                 UpdateWindow(hwnd);
  552.                 return 0;
  553.             case VK_NEXT:  // Page Down
  554.                 ScrollWindow(hwnd, 0, virtualHeight, NULL, NULL);
  555.                 UpdateWindow(hwnd);
  556.                 return 0;
  557.             case VK_F1:
  558.                 MessageBoxW(hwnd,
  559.                     L"PE Header Parser 2.9 GUI-based Programmed in C++ Win32 API (1369 lines of code) by Entisoft Software(c) Evans Thorpemorton",
  560.                     L"About",
  561.                     MB_OK | MB_ICONINFORMATION);
  562.                 return 0;
  563.             case VK_ESCAPE:
  564.                 PostQuitMessage(0);
  565.                 return 0;
  566.             }
  567.         }
  568.         break;
  569.  
  570.         case WM_MOUSEWHEEL:
  571.         {
  572.             int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  573.             if (zDelta > 0) {
  574.                 ScrollWindow(hwnd, 0, -virtualHeight, NULL, NULL);  // Mouse Wheel Up
  575.             }
  576.             else if (zDelta < 0) {
  577.                 ScrollWindow(hwnd, 0, virtualHeight, NULL, NULL);  // Mouse Wheel Down
  578.             }
  579.             UpdateWindow(hwnd);
  580.             return 0;
  581.         }*/
  582.  
  583.         case WM_KEYDOWN:
  584.         {
  585.             if (GetKeyState(VK_CONTROL) & 0x8000) {
  586.                 switch (wParam) {
  587.                 case 'O':
  588.                     OpenFileDialog(hwnd);
  589.                     return 0;
  590.                 }
  591.             }
  592.             switch (wParam) {
  593.             case VK_F1:
  594.                 MessageBoxW(hwnd,
  595.                     L"PE Header Parser 4.3 GUI-based Programmed in C++ Win32 API (1546 lines of code) by Entisoft Software(c) Evans Thorpemorton",
  596.                     L"About",
  597.                     MB_OK | MB_ICONINFORMATION);
  598.                 return 0;
  599.             case VK_ESCAPE:
  600.                 PostQuitMessage(0);
  601.                 return 0;
  602.             case VK_PRIOR:
  603.                 // Scroll up
  604.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  605.                 return 0;
  606.             case VK_NEXT:
  607.                 // Scroll down
  608.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  609.                 return 0;
  610.             case VK_UP:
  611.                 // Scroll one line up
  612.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
  613.                 return 0;
  614.             case VK_DOWN:
  615.                 // Scroll one line down
  616.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
  617.                 return 0;
  618.             }
  619.             break;
  620.         }
  621.         case WM_MOUSEWHEEL:
  622.         {
  623.             int delta = GET_WHEEL_DELTA_WPARAM(wParam);
  624.             if (delta > 0) {
  625.                 // Scroll up
  626.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
  627.             }
  628.             else {
  629.                 // Scroll down
  630.                 SendMessage(g_hEditControl, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
  631.             }
  632.             return 0;
  633.         }
  634.         case WM_COMMAND: if (LOWORD(wParam) == 1) OpenFileDialog(hwnd); if (LOWORD(wParam) == 2) PostQuitMessage(0); return 0;
  635.         case WM_DESTROY:
  636.             if (g_hStatusBar) DestroyWindow(g_hStatusBar);
  637.             PostQuitMessage(0);
  638.             return 0;
  639.         }
  640.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  641.     }
  642.  
  643.     void SetStatusText(const wchar_t* text) {
  644.         SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
  645.     }
  646.  
  647.     void ShowProgress(int percentage) {
  648.         // Update progress bar
  649.         SendMessage(g_hProgressBar, PBM_SETPOS, (WPARAM)percentage, 0);
  650.  
  651.         // Update status text in first part
  652.         wchar_t status[256];
  653.         swprintf_s(status, L"Analyzing... %d%%", percentage);
  654.         //swprintf_s(status, L"Analyzing...");
  655.         SetStatusText(status); //commented-out
  656.         SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)status);
  657.     }
  658.  
  659.     void OpenFileDialog(HWND hwnd) {
  660.         WCHAR fileName[MAX_PATH] = L"";
  661.         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 };
  662.         if (GetOpenFileNameW(&ofn)) {
  663.             SetWindowTextW(g_hEditControl, L"");
  664.             g_OutputText.str(L"");
  665.             g_OutputText.clear();
  666.             AnalyzePEFile(ofn.lpstrFile);
  667.             UpdateEditControl();
  668.         }
  669.     }
  670.  
  671.     class FileMapper {
  672.     private:
  673.         HANDLE hFile = INVALID_HANDLE_VALUE;
  674.         HANDLE hMapping = nullptr;
  675.         LPVOID lpView = nullptr;
  676.  
  677.     public:
  678.         ~FileMapper() {
  679.             if (lpView) UnmapViewOfFile(lpView);
  680.             if (hMapping) CloseHandle(hMapping);
  681.             if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
  682.         }
  683.  
  684.         bool Initialize(const wchar_t* path) {
  685.             hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr,
  686.                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  687.             if (hFile == INVALID_HANDLE_VALUE) return false;
  688.  
  689.             hMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  690.             if (!hMapping) return false;
  691.  
  692.             lpView = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  693.             return lpView != nullptr;
  694.         }
  695.  
  696.         LPVOID GetView() const { return lpView; }
  697.     };
  698.  
  699.     // Modified AppendToOutput to handle newlines properly:
  700.     void AppendToOutput(const wchar_t* format, ...) {
  701.         std::vector<wchar_t> buffer(1024);
  702.         va_list args;
  703.         va_start(args, format);
  704.  
  705.         while (true) {
  706.             int result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  707.             if (result >= 0) break;
  708.             buffer.resize(buffer.size() * 2);
  709.         }
  710.         va_end(args);
  711.  
  712.         // Convert \n to \r\n
  713.         std::wstring output = buffer.data();
  714.         size_t pos = 0;
  715.         while ((pos = output.find(L'\n', pos)) != std::wstring::npos) {
  716.             if (pos == 0 || output[pos - 1] != L'\r') {
  717.                 output.insert(pos, L"\r");
  718.                 pos += 2;
  719.             }
  720.             else {
  721.                 pos++;
  722.             }
  723.         }
  724.  
  725.         g_OutputText << output;
  726.         UpdateEditControl();
  727.     }
  728.  
  729.     /*
  730.     void AppendToOutput(const wchar_t* format, ...) {
  731.         wchar_t buffer[16384]; // Ensure sufficient buffer size
  732.         va_list args;
  733.         va_start(args, format);
  734.         StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  735.         va_end(args);
  736.  
  737.         tempBuffer += buffer;
  738.  
  739.         // Update Edit Control periodically to improve performance
  740.         if (tempBuffer.size() > 8000) {
  741.             g_OutputText << tempBuffer;
  742.             tempBuffer.clear();
  743.  
  744.             SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  745.             SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  746.             SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  747.         }
  748.     }
  749.  
  750.  
  751.     // Final update to flush any remaining content
  752.     void FlushOutput() {
  753.         if (!tempBuffer.empty()) {
  754.             g_OutputText << tempBuffer;
  755.             tempBuffer.clear();
  756.  
  757.             SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  758.             SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  759.             SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  760.         }
  761.     }
  762.     */
  763.  
  764.  
  765.     /*
  766.     //use below ^^ ALWAYS
  767.     void AppendToOutput(const wchar_t* format, ...) {
  768.         va_list args;
  769.         va_start(args, format);
  770.  
  771.         // Use a vector as a dynamically resizable buffer
  772.         std::vector<wchar_t> buffer(16384); // Start with an initial size
  773.         int result = -1;
  774.  
  775.         while (true) {
  776.             // Attempt to format the string
  777.             result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  778.  
  779.             if (result >= 0 && static_cast<size_t>(result) < buffer.size()) {
  780.                 // Successfully formatted within the current buffer size
  781.                 break;
  782.             }
  783.  
  784.             // Resize the buffer and try again
  785.             buffer.resize(buffer.size() * 2);
  786.         }
  787.         va_end(args);
  788.  
  789.         // Convert `\n` to `\r\n` for proper display in the EditBox
  790.         std::wstring formattedOutput(buffer.data());
  791.         size_t pos = 0;
  792.         while ((pos = formattedOutput.find(L'\n', pos)) != std::wstring::npos) {
  793.             formattedOutput.replace(pos, 1, L"\r\n");
  794.             pos += 2; // Move past the replacement
  795.         }
  796.  
  797.         // Append to the global output buffer
  798.         g_OutputText << formattedOutput;
  799.  
  800.         // Update the EditBox periodically to prevent overloading
  801.         if (g_OutputText.str().size() > 8000) {
  802.             SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  803.             SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  804.             SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  805.         }
  806.     }
  807.     //use above ^^ ALWAYS
  808.     */
  809.  
  810.     //currentlatest
  811.     /*void AppendToOutput(const wchar_t* format, ...) {
  812.         wchar_t buffer[4096];
  813.         va_list args;
  814.         va_start(args, format);
  815.         StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  816.         va_end(args);
  817.         g_OutputText << buffer;
  818.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  819.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  820.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  821.     }
  822.     */
  823.  
  824.     //use-below-basic-failsafe-working vv
  825.     //basic test function
  826.     /*void AnalyzePEFile(const wchar_t* filePathW) {
  827.         OUTPUT("[+] Analyzing file: %s\n", filePathW);
  828.         LPVOID lpFileContent = GetFileContent(filePathW);
  829.         if (!lpFileContent) { OUTPUT("[-] Could not read file.\n"); return; }
  830.         PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileContent;
  831.         if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { OUTPUT("[-] Invalid DOS signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  832.         PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpFileContent + dosHeader->e_lfanew);
  833.         if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { OUTPUT("[-] Invalid NT signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  834.         OUTPUT("[+] PE file analyzed successfully.\n");
  835.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  836.         UpdateEditControl();
  837.     }*/
  838.     //use-above-basic-failsafe-working vv
  839.  
  840.     //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
  841.  
  842.     void ProcessResourceDirectory(
  843.         PIMAGE_RESOURCE_DIRECTORY resDir,
  844.         int level,
  845.         const wchar_t* type,
  846.         PIMAGE_RESOURCE_DIRECTORY pResourceDir,
  847.         const wchar_t* resourceTypes[],
  848.         PIMAGE_NT_HEADERS pNtHeaders,
  849.         LPVOID lpFileContent)
  850.     {
  851.         if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  852.             return;
  853.         }
  854.  
  855.         auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  856.         WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  857.  
  858.         for (WORD i = 0; i < totalEntries; i++) {
  859.             if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  860.                 break;
  861.             }
  862.  
  863.             for (int indent = 0; indent < level; indent++) {
  864.                 OUTPUT("\t");
  865.             }
  866.  
  867.             if (entry[i].NameIsString) {
  868.                 auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)pResourceDir + entry[i].NameOffset);
  869.                 if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  870.                     std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  871.                     wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  872.                         nameEntry->NameString, nameEntry->Length);
  873.                     resourceName[nameEntry->Length] = L'\0';
  874.  
  875.                     if (level == 0) {
  876.                         OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  877.                     }
  878.                     else {
  879.                         OUTPUT("Name: %s\n", resourceName.data());
  880.                     }
  881.                 }
  882.             }
  883.             else {
  884.                 if (level == 0) {
  885.                     DWORD resourceType = entry[i].Id;
  886.                     if (resourceType < 16) {
  887.                         OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  888.                     }
  889.                     else {
  890.                         OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  891.                     }
  892.                 }
  893.                 else {
  894.                     OUTPUT("ID: %d\n", entry[i].Id);
  895.                 }
  896.             }
  897.  
  898.             if (entry[i].DataIsDirectory) {
  899.                 auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pResourceDir + entry[i].OffsetToDirectory);
  900.                 if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  901.                     ProcessResourceDirectory(nextDir, level + 1,
  902.                         level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  903.                         pResourceDir, resourceTypes, pNtHeaders, lpFileContent);
  904.                 }
  905.             }
  906.             else {
  907.                 auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)pResourceDir + entry[i].OffsetToData);
  908.                 if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  909.                     for (int indent = 0; indent < level + 1; indent++) {
  910.                         OUTPUT("\t");
  911.                     }
  912.                     OUTPUT("Size: %d bytes, RVA: 0x%X\n",
  913.                         dataEntry->Size, dataEntry->OffsetToData);
  914.  
  915.                     if (type && wcscmp(type, L"Version") == 0) {
  916.                         auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  917.                             dataEntry->OffsetToData,
  918.                             IMAGE_FIRST_SECTION(pNtHeaders),
  919.                             pNtHeaders->FileHeader.NumberOfSections,
  920.                             lpFileContent);
  921.  
  922.                         if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  923.                             auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  924.                             if (versionInfo->dwSignature == 0xFEEF04BD) {
  925.                                 for (int indent = 0; indent < level + 2; indent++) {
  926.                                     OUTPUT("\t");
  927.                                 }
  928.                                 OUTPUT("File Version: %d.%d.%d.%d\n",
  929.                                     HIWORD(versionInfo->dwFileVersionMS),
  930.                                     LOWORD(versionInfo->dwFileVersionMS),
  931.                                     HIWORD(versionInfo->dwFileVersionLS),
  932.                                     LOWORD(versionInfo->dwFileVersionLS));
  933.                             }
  934.                         }
  935.                     }
  936.                 }
  937.             }
  938.         }
  939.     }
  940.  
  941.     //adding here
  942.     //######################################################################################
  943. //######################################################################################
  944. //        ##    endroughxfer - urldump #1#
  945. //        ##    <EOF><EOF>
  946. //######################################################################################
  947. //######################################################################################
  948. //
  949. // new code below starting here vv
  950.     namespace PEParser {
  951.         bool InitializePEAnalyzer(PEAnalyzer& analyzer, const wchar_t* filePath) {
  952.             FileMapper mapper;
  953.             if (!mapper.Initialize(filePath)) {
  954.                 OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  955.                 return false;
  956.             }
  957.  
  958.             analyzer.lpFileContent = mapper.GetView();
  959.             analyzer.fileSize = GetFileSize(filePath);
  960.  
  961.             analyzer.pDosHeader = static_cast<PIMAGE_DOS_HEADER>(analyzer.lpFileContent);
  962.             if (analyzer.pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  963.                 OUTPUT("[-] Invalid DOS signature!\n");
  964.                 return false;
  965.             }
  966.  
  967.             auto pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
  968.                 static_cast<BYTE*>(analyzer.lpFileContent) + analyzer.pDosHeader->e_lfanew);
  969.  
  970.             if (IsBadReadPtr(pNtHeaders, sizeof(IMAGE_NT_HEADERS)) ||
  971.                 pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  972.                 OUTPUT("[-] Invalid NT signature!\n");
  973.                 return false;
  974.             }
  975.  
  976.             analyzer.is64Bit = (pNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
  977.  
  978.             if (analyzer.is64Bit) {
  979.                 analyzer.pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  980.                 analyzer.pNtHeaders32 = nullptr;
  981.             }
  982.             else {
  983.                 analyzer.pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  984.                 analyzer.pNtHeaders64 = nullptr;
  985.             }
  986.  
  987.             return true;
  988.         }
  989.  
  990.         DWORD GetFileSize(const wchar_t* filePath) {
  991.             HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ,
  992.                 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  993.             if (hFile == INVALID_HANDLE_VALUE) return 0;
  994.  
  995.             DWORD fileSize = ::GetFileSize(hFile, nullptr);
  996.             CloseHandle(hFile);
  997.             return fileSize;
  998.         }
  999.     }
  1000.  
  1001.     void ParseImportDirectory32(const PEAnalyzer& analyzer) {
  1002.         const auto& importDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  1003.         if (!importDir.VirtualAddress || !importDir.Size) return;
  1004.  
  1005.         if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, analyzer.fileSize,
  1006.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1007.             OUTPUT("[-] Invalid import directory RVA!\n");
  1008.             return;
  1009.         }
  1010.  
  1011.         OUTPUT("\n[+] IMPORT DIRECTORY (32-bit)\n");
  1012.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  1013.             importDir.VirtualAddress,
  1014.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1015.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1016.             analyzer.lpFileContent);
  1017.  
  1018.         if (!pImportDesc) return;
  1019.  
  1020.         while (pImportDesc->Name != 0) {
  1021.             if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  1022.                 OUTPUT("[-] Invalid import descriptor detected!\n");
  1023.                 break;
  1024.             }
  1025.  
  1026.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  1027.                 pImportDesc->Name,
  1028.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1029.                 analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1030.                 analyzer.lpFileContent);
  1031.  
  1032.             if (dllName && !IsBadReadPtr(dllName, 1)) {
  1033.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  1034.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  1035.  
  1036.                 OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  1037.                 OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  1038.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  1039.                 OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  1040.                 OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  1041.                 OUTPUT("\n\tImported Functions:\n");
  1042.  
  1043.                 auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  1044.                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1045.                     IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1046.                     analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1047.                     analyzer.lpFileContent);
  1048.  
  1049.                 while (pThunk && pThunk->u1.AddressOfData) {
  1050.                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) {
  1051.                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1052.                             pThunk->u1.AddressOfData,
  1053.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1054.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1055.                             analyzer.lpFileContent);
  1056.  
  1057.                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1058.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  1059.                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1060.                                 wideFuncName.data(), MAX_PATH);
  1061.                             OUTPUT("\t\t%s\n", wideFuncName.data());
  1062.                         }
  1063.                     }
  1064.                     else {
  1065.                         OUTPUT("\t\tOrdinal: %d\n", pThunk->u1.Ordinal & 0xFFFF);
  1066.                     }
  1067.                     pThunk++;
  1068.                 }
  1069.             }
  1070.             pImportDesc++;
  1071.         }
  1072.     }
  1073.  
  1074.     void ParseImportDirectory64(const PEAnalyzer& analyzer) {
  1075.         const auto& importDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  1076.         if (!importDir.VirtualAddress || !importDir.Size) return;
  1077.  
  1078.         if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, analyzer.fileSize,
  1079.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  1080.             OUTPUT("[-] Invalid import directory RVA!\n");
  1081.             return;
  1082.         }
  1083.  
  1084.         OUTPUT("\n[+] IMPORT DIRECTORY (64-bit)\n");
  1085.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  1086.             importDir.VirtualAddress,
  1087.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1088.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1089.             analyzer.lpFileContent);
  1090.  
  1091.         if (!pImportDesc) return;
  1092.  
  1093.         while (pImportDesc->Name != 0) {
  1094.             if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  1095.                 OUTPUT("[-] Invalid import descriptor detected!\n");
  1096.                 break;
  1097.             }
  1098.  
  1099.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  1100.                 pImportDesc->Name,
  1101.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1102.                 analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1103.                 analyzer.lpFileContent);
  1104.  
  1105.             if (dllName && !IsBadReadPtr(dllName, 1)) {
  1106.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  1107.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  1108.  
  1109.                 OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  1110.                 OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  1111.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  1112.                 OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  1113.                 OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  1114.                 OUTPUT("\n\tImported Functions:\n");
  1115.  
  1116.                 auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  1117.                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  1118.                     IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1119.                     analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1120.                     analyzer.lpFileContent);
  1121.  
  1122.                 while (pThunk && pThunk->u1.AddressOfData) {
  1123.                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)) {
  1124.                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  1125.                             (DWORD)pThunk->u1.AddressOfData,
  1126.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1127.                             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1128.                             analyzer.lpFileContent);
  1129.  
  1130.                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  1131.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  1132.                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  1133.                                 wideFuncName.data(), MAX_PATH);
  1134.                             OUTPUT("\t\t%s\n", wideFuncName.data());
  1135.                         }
  1136.                     }
  1137.                     else {
  1138.                         OUTPUT("\t\tOrdinal: %lld\n", pThunk->u1.Ordinal & 0xFFFF);
  1139.                     }
  1140.                     pThunk++;
  1141.                 }
  1142.             }
  1143.             pImportDesc++;
  1144.         }
  1145.     }
  1146.  
  1147.     void ParseImportDirectory(const PEAnalyzer& analyzer) {
  1148.         if (analyzer.is64Bit) {
  1149.             ParseImportDirectory64(analyzer);
  1150.         }
  1151.         else {
  1152.             ParseImportDirectory32(analyzer);
  1153.         }
  1154.     }
  1155. //}
  1156.  
  1157.     void ParseExportDirectory32(const PEAnalyzer& analyzer) {
  1158.         const auto& exportDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1159.         if (!exportDir.VirtualAddress || !exportDir.Size) return;
  1160.  
  1161.         if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, analyzer.fileSize,
  1162.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1163.             OUTPUT("[-] Invalid export directory RVA!\n");
  1164.             return;
  1165.         }
  1166.  
  1167.         OUTPUT("\n[+] EXPORT DIRECTORY (32-bit)\n");
  1168.         auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1169.             exportDir.VirtualAddress,
  1170.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1171.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1172.             analyzer.lpFileContent);
  1173.  
  1174.         if (!pExportDir || IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  1175.             OUTPUT("[-] Invalid export directory structure!\n");
  1176.             return;
  1177.         }
  1178.  
  1179.         OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  1180.         OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  1181.         OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  1182.         OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  1183.         OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  1184.         OUTPUT("\tBase: %d\n", pExportDir->Base);
  1185.         OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  1186.         OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  1187.         OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  1188.         OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  1189.         OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  1190.  
  1191.         auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1192.             pExportDir->AddressOfFunctions,
  1193.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1194.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1195.             analyzer.lpFileContent);
  1196.  
  1197.         auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1198.             pExportDir->AddressOfNames,
  1199.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1200.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1201.             analyzer.lpFileContent);
  1202.  
  1203.         auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1204.             pExportDir->AddressOfNameOrdinals,
  1205.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1206.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1207.             analyzer.lpFileContent);
  1208.  
  1209.         if (!pNames || !pNameOrdinals || !pFunctions) {
  1210.             OUTPUT("[-] Invalid export address tables!\n");
  1211.             return;
  1212.         }
  1213.  
  1214.         OUTPUT("\tExported Functions:\n\n");
  1215.         for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1216.             if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  1217.                 IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  1218.                 break;
  1219.             }
  1220.  
  1221.             const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1222.                 pNames[i],
  1223.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1224.                 analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1225.                 analyzer.lpFileContent);
  1226.  
  1227.             if (functionName && !IsBadReadPtr(functionName, 1)) {
  1228.                 WORD ordinal = pNameOrdinals[i];
  1229.                 if (ordinal < pExportDir->NumberOfFunctions) {
  1230.                     DWORD functionRva = pFunctions[ordinal];
  1231.  
  1232.                     // Check for forwarded export
  1233.                     if (functionRva >= exportDir.VirtualAddress &&
  1234.                         functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1235.  
  1236.                         const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1237.                             functionRva,
  1238.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1239.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1240.                             analyzer.lpFileContent);
  1241.  
  1242.                         if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  1243.                             std::vector<wchar_t> wideForwardName(MAX_PATH);
  1244.                             MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1245.                                 wideForwardName.data(), MAX_PATH);
  1246.                             OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1247.                                 functionName,
  1248.                                 ordinal + pExportDir->Base,
  1249.                                 wideForwardName.data());
  1250.                         }
  1251.                     }
  1252.                     else {
  1253.                         OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1254.                             functionName,
  1255.                             ordinal + pExportDir->Base,
  1256.                             functionRva);
  1257.                     }
  1258.                 }
  1259.             }
  1260.         }
  1261.     }
  1262.  
  1263.     void ParseExportDirectory64(const PEAnalyzer& analyzer) {
  1264.         const auto& exportDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  1265.         if (!exportDir.VirtualAddress || !exportDir.Size) return;
  1266.  
  1267.         if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, analyzer.fileSize,
  1268.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  1269.             OUTPUT("[-] Invalid export directory RVA!\n");
  1270.             return;
  1271.         }
  1272.  
  1273.         OUTPUT("\n[+] EXPORT DIRECTORY (64-bit)\n");
  1274.         // Rest of the implementation is identical to 32-bit version
  1275.         // Just using pNtHeaders64 instead of pNtHeaders32
  1276.         auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  1277.             exportDir.VirtualAddress,
  1278.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1279.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1280.             analyzer.lpFileContent);
  1281.  
  1282.         if (!pExportDir || IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  1283.             OUTPUT("[-] Invalid export directory structure!\n");
  1284.             return;
  1285.         }
  1286.  
  1287.         OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  1288.         OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  1289.         OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  1290.         OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  1291.         OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  1292.         OUTPUT("\tBase: %d\n", pExportDir->Base);
  1293.         OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  1294.         OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  1295.         OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  1296.         OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  1297.         OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  1298.  
  1299.         auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  1300.             pExportDir->AddressOfFunctions,
  1301.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1302.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1303.             analyzer.lpFileContent);
  1304.  
  1305.         auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  1306.             pExportDir->AddressOfNames,
  1307.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1308.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1309.             analyzer.lpFileContent);
  1310.  
  1311.         auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  1312.             pExportDir->AddressOfNameOrdinals,
  1313.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1314.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1315.             analyzer.lpFileContent);
  1316.  
  1317.         if (!pNames || !pNameOrdinals || !pFunctions) {
  1318.             OUTPUT("[-] Invalid export address tables!\n");
  1319.             return;
  1320.         }
  1321.  
  1322.         OUTPUT("\tExported Functions:\n\n");
  1323.         for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  1324.             if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  1325.                 IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  1326.                 break;
  1327.             }
  1328.  
  1329.             const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  1330.                 pNames[i],
  1331.                 IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1332.                 analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1333.                 analyzer.lpFileContent);
  1334.  
  1335.             if (functionName && !IsBadReadPtr(functionName, 1)) {
  1336.                 WORD ordinal = pNameOrdinals[i];
  1337.                 if (ordinal < pExportDir->NumberOfFunctions) {
  1338.                     DWORD functionRva = pFunctions[ordinal];
  1339.  
  1340.                     // Check for forwarded export
  1341.                     if (functionRva >= exportDir.VirtualAddress &&
  1342.                         functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  1343.  
  1344.                         const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  1345.                             functionRva,
  1346.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1347.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1348.                             analyzer.lpFileContent);
  1349.  
  1350.                         if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  1351.                             std::vector<wchar_t> wideForwardName(MAX_PATH);
  1352.                             MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  1353.                                 wideForwardName.data(), MAX_PATH);
  1354.                             OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  1355.                                 functionName,
  1356.                                 ordinal + pExportDir->Base,
  1357.                                 wideForwardName.data());
  1358.                         }
  1359.                     }
  1360.                     else {
  1361.                         OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  1362.                             functionName,
  1363.                             ordinal + pExportDir->Base,
  1364.                             functionRva);
  1365.                     }
  1366.                 }
  1367.             }
  1368.         }
  1369.     }
  1370. // Copying the same logic as ParseExportDirectory32 but with 64-bit headers
  1371. // ... [Same implementation as above, just using pNtHeaders64]
  1372.  
  1373.     void ParseExportDirectory(const PEAnalyzer& analyzer) {
  1374.         if (analyzer.is64Bit) {
  1375.             ParseExportDirectory64(analyzer);
  1376.         }
  1377.         else {
  1378.             ParseExportDirectory32(analyzer);
  1379.         }
  1380.     }
  1381.  
  1382.     void ProcessResourceDirectory32(
  1383.         PIMAGE_RESOURCE_DIRECTORY resDir,
  1384.         int level,
  1385.         const wchar_t* type,
  1386.         PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  1387.         const wchar_t* resourceTypes[],
  1388.         const PEAnalyzer& analyzer)
  1389.     {
  1390.         if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1391.             return;
  1392.         }
  1393.  
  1394.         auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  1395.         WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  1396.  
  1397.         for (WORD i = 0; i < totalEntries; i++) {
  1398.             if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  1399.                 break;
  1400.             }
  1401.  
  1402.             for (int indent = 0; indent < level; indent++) {
  1403.                 OUTPUT("\t");
  1404.             }
  1405.  
  1406.             if (entry[i].NameIsString) {
  1407.                 auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)baseResourceDir + entry[i].NameOffset);
  1408.                 if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  1409.                     std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  1410.                     wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  1411.                         nameEntry->NameString, nameEntry->Length);
  1412.                     resourceName[nameEntry->Length] = L'\0';
  1413.  
  1414.                     if (level == 0) {
  1415.                         OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  1416.                     }
  1417.                     else {
  1418.                         OUTPUT("Name: %s\n", resourceName.data());
  1419.                     }
  1420.                 }
  1421.             }
  1422.             else {
  1423.                 if (level == 0) {
  1424.                     DWORD resourceType = entry[i].Id;
  1425.                     if (resourceType < 16) {
  1426.                         OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  1427.                     }
  1428.                     else {
  1429.                         OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  1430.                     }
  1431.                 }
  1432.                 else {
  1433.                     OUTPUT("ID: %d\n", entry[i].Id);
  1434.                 }
  1435.             }
  1436.  
  1437.             if (entry[i].DataIsDirectory) {
  1438.                 auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)baseResourceDir + entry[i].OffsetToDirectory);
  1439.                 if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1440.                     ProcessResourceDirectory32(nextDir, level + 1,
  1441.                         level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  1442.                         baseResourceDir, resourceTypes, analyzer);
  1443.                 }
  1444.             }
  1445.             else {
  1446.                 auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)baseResourceDir + entry[i].OffsetToData);
  1447.                 if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  1448.                     for (int indent = 0; indent < level + 1; indent++) {
  1449.                         OUTPUT("\t");
  1450.                     }
  1451.                     OUTPUT("Size: %d bytes, RVA: 0x%X\n", dataEntry->Size, dataEntry->OffsetToData);
  1452.  
  1453.                     // Special handling for Version resources
  1454.                     if (type && wcscmp(type, L"Version") == 0) {
  1455.                         auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  1456.                             dataEntry->OffsetToData,
  1457.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1458.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1459.                             analyzer.lpFileContent);
  1460.  
  1461.                         if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  1462.                             auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  1463.                             if (versionInfo->dwSignature == 0xFEEF04BD) {
  1464.                                 for (int indent = 0; indent < level + 2; indent++) {
  1465.                                     OUTPUT("\t");
  1466.                                 }
  1467.                                 OUTPUT("File Version: %d.%d.%d.%d\n",
  1468.                                     HIWORD(versionInfo->dwFileVersionMS),
  1469.                                     LOWORD(versionInfo->dwFileVersionMS),
  1470.                                     HIWORD(versionInfo->dwFileVersionLS),
  1471.                                     LOWORD(versionInfo->dwFileVersionLS));
  1472.                             }
  1473.                         }
  1474.                     }
  1475.                 }
  1476.             }
  1477.         }
  1478.     }
  1479.  
  1480.     void ProcessResourceDirectory64(
  1481.         PIMAGE_RESOURCE_DIRECTORY resDir,
  1482.         int level,
  1483.         const wchar_t* type,
  1484.         PIMAGE_RESOURCE_DIRECTORY baseResourceDir,
  1485.         const wchar_t* resourceTypes[],
  1486.         const PEAnalyzer& analyzer)
  1487.     {
  1488.         // Similar to ProcessResourceDirectory32 but using 64-bit structures
  1489.         // Main difference is using analyzer.pNtHeaders64 instead of analyzer.pNtHeaders32
  1490.         if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1491.             return;
  1492.             // Rest of the implementation follows the same pattern
  1493.         }
  1494.  
  1495.         auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  1496.         WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  1497.  
  1498.         for (WORD i = 0; i < totalEntries; i++) {
  1499.             if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  1500.                 break;
  1501.             }
  1502.  
  1503.             for (int indent = 0; indent < level; indent++) {
  1504.                 OUTPUT("\t");
  1505.             }
  1506.  
  1507.             if (entry[i].NameIsString) {
  1508.                 auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)baseResourceDir + entry[i].NameOffset);
  1509.                 if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  1510.                     std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  1511.                     wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  1512.                         nameEntry->NameString, nameEntry->Length);
  1513.                     resourceName[nameEntry->Length] = L'\0';
  1514.  
  1515.                     if (level == 0) {
  1516.                         OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  1517.                     }
  1518.                     else {
  1519.                         OUTPUT("Name: %s\n", resourceName.data());
  1520.                     }
  1521.                 }
  1522.             }
  1523.             else {
  1524.                 if (level == 0) {
  1525.                     DWORD resourceType = entry[i].Id;
  1526.                     if (resourceType < 16) {
  1527.                         OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  1528.                     }
  1529.                     else {
  1530.                         OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  1531.                     }
  1532.                 }
  1533.                 else {
  1534.                     OUTPUT("ID: %d\n", entry[i].Id);
  1535.                 }
  1536.             }
  1537.  
  1538.             if (entry[i].DataIsDirectory) {
  1539.                 auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)baseResourceDir + entry[i].OffsetToDirectory);
  1540.                 if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1541.                     ProcessResourceDirectory32(nextDir, level + 1,
  1542.                         level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type,
  1543.                         baseResourceDir, resourceTypes, analyzer);
  1544.                 }
  1545.             }
  1546.             else {
  1547.                 auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)baseResourceDir + entry[i].OffsetToData);
  1548.                 if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  1549.                     for (int indent = 0; indent < level + 1; indent++) {
  1550.                         OUTPUT("\t");
  1551.                     }
  1552.                     OUTPUT("Size: %d bytes, RVA: 0x%X\n", dataEntry->Size, dataEntry->OffsetToData);
  1553.  
  1554.                     // Special handling for Version resources
  1555.                     if (type && wcscmp(type, L"Version") == 0) {
  1556.                         auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  1557.                             dataEntry->OffsetToData,
  1558.                             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1559.                             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1560.                             analyzer.lpFileContent);
  1561.  
  1562.                         if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  1563.                             auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40);
  1564.                             if (versionInfo->dwSignature == 0xFEEF04BD) {
  1565.                                 for (int indent = 0; indent < level + 2; indent++) {
  1566.                                     OUTPUT("\t");
  1567.                                 }
  1568.                                 OUTPUT("File Version: %d.%d.%d.%d\n",
  1569.                                     HIWORD(versionInfo->dwFileVersionMS),
  1570.                                     LOWORD(versionInfo->dwFileVersionMS),
  1571.                                     HIWORD(versionInfo->dwFileVersionLS),
  1572.                                     LOWORD(versionInfo->dwFileVersionLS));
  1573.                             }
  1574.                         }
  1575.                     }
  1576.                 }
  1577.             }
  1578.         }
  1579.     }
  1580.  
  1581.     void ParseResourceDirectory32(const PEAnalyzer& analyzer) {
  1582.         const auto& resourceDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1583.         if (!resourceDir.VirtualAddress || !resourceDir.Size) return;
  1584.  
  1585.         if (!PEHelpers::IsRvaValid(resourceDir.VirtualAddress, analyzer.fileSize,
  1586.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1587.             OUTPUT("[-] Invalid resource directory RVA!\n");
  1588.             return;
  1589.         }
  1590.  
  1591.         OUTPUT("\n[+] RESOURCE DIRECTORY (32-bit)\n");
  1592.         auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  1593.             resourceDir.VirtualAddress,
  1594.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1595.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1596.             analyzer.lpFileContent);
  1597.  
  1598.         if (!pResourceDir || IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  1599.             OUTPUT("[-] Invalid or corrupted resource directory\n");
  1600.             return;
  1601.         }
  1602.  
  1603.         const wchar_t* resourceTypes[] = {
  1604.             L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  1605.             L"Menu",        L"Dialog",      L"String",      L"FontDir",
  1606.             L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  1607.             L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  1608.         };
  1609.  
  1610.         ProcessResourceDirectory32(pResourceDir, 0, nullptr, pResourceDir, resourceTypes, analyzer);
  1611.     }
  1612.  
  1613.     void ParseResourceDirectory64(const PEAnalyzer& analyzer) {
  1614.         // Similar to ParseResourceDirectory32 but using 64-bit structures
  1615.         const auto& resourceDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  1616.         // Rest of implementation follows same pattern as 32-bit version
  1617.     }
  1618.  
  1619.     void ParseResourceDirectory(const PEAnalyzer& analyzer) {
  1620.         if (analyzer.is64Bit) {
  1621.             ParseResourceDirectory64(analyzer);
  1622.         }
  1623.         else {
  1624.             ParseResourceDirectory32(analyzer);
  1625.         }
  1626.     }
  1627.  
  1628.     void ParseDebugDirectory32(const PEAnalyzer& analyzer) {
  1629.         const auto& debugDir = analyzer.pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1630.         if (!debugDir.VirtualAddress || !debugDir.Size) return;
  1631.  
  1632.         if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, analyzer.fileSize,
  1633.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32))) {
  1634.             OUTPUT("[-] Invalid debug directory RVA!\n");
  1635.             return;
  1636.         }
  1637.  
  1638.         OUTPUT("\n[+] DEBUG DIRECTORY (32-bit)\n");
  1639.         auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  1640.             debugDir.VirtualAddress,
  1641.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders32),
  1642.             analyzer.pNtHeaders32->FileHeader.NumberOfSections,
  1643.             analyzer.lpFileContent);
  1644.  
  1645.         if (!pDebugDir || IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1646.             OUTPUT("[-] Invalid debug directory structure!\n");
  1647.             return;
  1648.         }
  1649.  
  1650.         DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  1651.         for (DWORD i = 0; i < numEntries; i++) {
  1652.             OUTPUT("\tDebug Entry %d:\n", i + 1);
  1653.             OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  1654.             OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  1655.             OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  1656.             OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  1657.             OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  1658.  
  1659.             switch (pDebugDir[i].Type) {
  1660.             case IMAGE_DEBUG_TYPE_COFF:
  1661.                 OUTPUT(" (COFF)\n"); break;
  1662.             case IMAGE_DEBUG_TYPE_CODEVIEW:
  1663.                 OUTPUT(" (CodeView)\n"); break;
  1664.             case IMAGE_DEBUG_TYPE_FPO:
  1665.                 OUTPUT(" (FPO)\n"); break;
  1666.             case IMAGE_DEBUG_TYPE_MISC:
  1667.                 OUTPUT(" (Misc)\n"); break;
  1668.             case IMAGE_DEBUG_TYPE_EXCEPTION:
  1669.                 OUTPUT(" (Exception)\n"); break;
  1670.             case IMAGE_DEBUG_TYPE_FIXUP:
  1671.                 OUTPUT(" (Fixup)\n"); break;
  1672.             case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1673.                 OUTPUT(" (OMAP to Src)\n"); break;
  1674.             case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1675.                 OUTPUT(" (OMAP from Src)\n"); break;
  1676.             case IMAGE_DEBUG_TYPE_BORLAND:
  1677.                 OUTPUT(" (Borland)\n"); break;
  1678.             default:
  1679.                 OUTPUT(" (Unknown)\n"); break;
  1680.             }
  1681.  
  1682.             OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  1683.             OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  1684.             OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  1685.  
  1686.             // Special handling for CodeView debug information
  1687.             if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1688.                 pDebugDir[i].PointerToRawData != 0 &&
  1689.                 pDebugDir[i].SizeOfData >= sizeof(DWORD)) {
  1690.  
  1691.                 auto pCVHeader = (DWORD*)((BYTE*)analyzer.lpFileContent + pDebugDir[i].PointerToRawData);
  1692.                 if (!IsBadReadPtr(pCVHeader, sizeof(DWORD))) {
  1693.                     switch (*pCVHeader) {
  1694.                     case 0x53445352: // 'RSDS'
  1695.                         if (pDebugDir[i].SizeOfData >= (sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + 1)) {
  1696.                             auto pCVData = (char*)(pCVHeader + 1);
  1697.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  1698.                                 auto guid = (GUID*)pCVData;
  1699.                                 DWORD age = *(DWORD*)(pCVData + 16);
  1700.                                 const char* pdbPath = pCVData + 20;
  1701.  
  1702.                                 OUTPUT("\tPDB Information:\n");
  1703.                                 OUTPUT("\tGUID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
  1704.                                     guid->Data1, guid->Data2, guid->Data3,
  1705.                                     guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
  1706.                                     guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
  1707.                                 OUTPUT("\tAge: %d\n", age);
  1708.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1709.                             }
  1710.                         }
  1711.                         break;
  1712.  
  1713.                     case 0x3031424E: // 'NB10'
  1714.                         if (pDebugDir[i].SizeOfData >= 16) {
  1715.                             auto pNB10Data = (char*)(pCVHeader + 1);
  1716.                             DWORD offset = *(DWORD*)pNB10Data;
  1717.                             DWORD timestamp = *(DWORD*)(pNB10Data + 4);
  1718.                             DWORD age = *(DWORD*)(pNB10Data + 8);
  1719.                             const char* pdbPath = pNB10Data + 12;
  1720.  
  1721.                             OUTPUT("\tPDB Information (NB10):\n");
  1722.                             OUTPUT("\tOffset: 0x%X\n", offset);
  1723.                             OUTPUT("\tTimestamp: 0x%X\n", timestamp);
  1724.                             OUTPUT("\tAge: %d\n", age);
  1725.                             OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1726.                         }
  1727.                         break;
  1728.                     }
  1729.                 }
  1730.             }
  1731.         }
  1732.     }
  1733.  
  1734.     void ParseDebugDirectory64(const PEAnalyzer& analyzer) {
  1735.         const auto& debugDir = analyzer.pNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  1736.         if (!debugDir.VirtualAddress || !debugDir.Size) return;
  1737.  
  1738.         if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, analyzer.fileSize,
  1739.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64))) {
  1740.             OUTPUT("[-] Invalid debug directory RVA!\n");
  1741.             return;
  1742.         }
  1743.  
  1744.         OUTPUT("\n[+] DEBUG DIRECTORY (64-bit)\n");
  1745.         // Rest of implementation follows same pattern as 32-bit version
  1746.         // Just using pNtHeaders64 instead of pNtHeaders32
  1747.         auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  1748.             debugDir.VirtualAddress,
  1749.             IMAGE_FIRST_SECTION(analyzer.pNtHeaders64),
  1750.             analyzer.pNtHeaders64->FileHeader.NumberOfSections,
  1751.             analyzer.lpFileContent);
  1752.  
  1753.         if (!pDebugDir || IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  1754.             OUTPUT("[-] Invalid debug directory structure!\n");
  1755.             return;
  1756.         }
  1757.  
  1758.         DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  1759.         for (DWORD i = 0; i < numEntries; i++) {
  1760.             OUTPUT("\tDebug Entry %d:\n", i + 1);
  1761.             OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  1762.             OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  1763.             OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  1764.             OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  1765.             OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  1766.  
  1767.             switch (pDebugDir[i].Type) {
  1768.             case IMAGE_DEBUG_TYPE_COFF:
  1769.                 OUTPUT(" (COFF)\n"); break;
  1770.             case IMAGE_DEBUG_TYPE_CODEVIEW:
  1771.                 OUTPUT(" (CodeView)\n"); break;
  1772.             case IMAGE_DEBUG_TYPE_FPO:
  1773.                 OUTPUT(" (FPO)\n"); break;
  1774.             case IMAGE_DEBUG_TYPE_MISC:
  1775.                 OUTPUT(" (Misc)\n"); break;
  1776.             case IMAGE_DEBUG_TYPE_EXCEPTION:
  1777.                 OUTPUT(" (Exception)\n"); break;
  1778.             case IMAGE_DEBUG_TYPE_FIXUP:
  1779.                 OUTPUT(" (Fixup)\n"); break;
  1780.             case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1781.                 OUTPUT(" (OMAP to Src)\n"); break;
  1782.             case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1783.                 OUTPUT(" (OMAP from Src)\n"); break;
  1784.             case IMAGE_DEBUG_TYPE_BORLAND:
  1785.                 OUTPUT(" (Borland)\n"); break;
  1786.             default:
  1787.                 OUTPUT(" (Unknown)\n"); break;
  1788.             }
  1789.  
  1790.             OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  1791.             OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  1792.             OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  1793.  
  1794.             // Special handling for CodeView debug information
  1795.             if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  1796.                 pDebugDir[i].PointerToRawData != 0 &&
  1797.                 pDebugDir[i].SizeOfData >= sizeof(DWORD)) {
  1798.  
  1799.                 auto pCVHeader = (DWORD*)((BYTE*)analyzer.lpFileContent + pDebugDir[i].PointerToRawData);
  1800.                 if (!IsBadReadPtr(pCVHeader, sizeof(DWORD))) {
  1801.                     switch (*pCVHeader) {
  1802.                     case 0x53445352: // 'RSDS'
  1803.                         if (pDebugDir[i].SizeOfData >= (sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + 1)) {
  1804.                             auto pCVData = (char*)(pCVHeader + 1);
  1805.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  1806.                                 auto guid = (GUID*)pCVData;
  1807.                                 DWORD age = *(DWORD*)(pCVData + 16);
  1808.                                 const char* pdbPath = pCVData + 20;
  1809.  
  1810.                                 OUTPUT("\tPDB Information:\n");
  1811.                                 OUTPUT("\tGUID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
  1812.                                     guid->Data1, guid->Data2, guid->Data3,
  1813.                                     guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
  1814.                                     guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
  1815.                                 OUTPUT("\tAge: %d\n", age);
  1816.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1817.                             }
  1818.                         }
  1819.                         break;
  1820.  
  1821.                     case 0x3031424E: // 'NB10'
  1822.                         if (pDebugDir[i].SizeOfData >= 16) {
  1823.                             auto pNB10Data = (char*)(pCVHeader + 1);
  1824.                             DWORD offset = *(DWORD*)pNB10Data;
  1825.                             DWORD timestamp = *(DWORD*)(pNB10Data + 4);
  1826.                             DWORD age = *(DWORD*)(pNB10Data + 8);
  1827.                             const char* pdbPath = pNB10Data + 12;
  1828.  
  1829.                             OUTPUT("\tPDB Information (NB10):\n");
  1830.                             OUTPUT("\tOffset: 0x%X\n", offset);
  1831.                             OUTPUT("\tTimestamp: 0x%X\n", timestamp);
  1832.                             OUTPUT("\tAge: %d\n", age);
  1833.                             OUTPUT("\tPDB Path: %s\n\n", pdbPath);
  1834.                         }
  1835.                         break;
  1836.                     }
  1837.                 }
  1838.             }
  1839.         }
  1840.     }
  1841. // ... [Same implementation as ParseDebugDirectory32]
  1842.  
  1843.     void ParseDebugDirectory(const PEAnalyzer& analyzer) {
  1844.         if (analyzer.is64Bit) {
  1845.             ParseDebugDirectory64(analyzer);
  1846.         }
  1847.         else {
  1848.             ParseDebugDirectory32(analyzer);
  1849.         }
  1850.     }
  1851.  
  1852.     void AnalyzePEFile(const wchar_t* filePathW) {
  1853.         OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  1854.         ShowProgress(10);
  1855.  
  1856.         PEAnalyzer analyzer;
  1857.         if (!PEParser::InitializePEAnalyzer(analyzer, filePathW)) {
  1858.             SetStatusText(L"Failed to initialize PE analysis!");
  1859.             return;
  1860.         }
  1861.  
  1862.         ShowProgress(20);
  1863.  
  1864.         // Basic PE Information
  1865.         OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  1866.         OUTPUT("[+] Architecture: %s\n\n", analyzer.is64Bit ? "x64" : "x86");
  1867.  
  1868.         // DOS Header
  1869.         OUTPUT("[+] DOS HEADER\n");
  1870.         OUTPUT("\te_magic    : 0x%X\n", analyzer.pDosHeader->e_magic);
  1871.         OUTPUT("\te_cblp     : 0x%X\n", analyzer.pDosHeader->e_cblp);
  1872.         OUTPUT("\te_cp       : 0x%X\n", analyzer.pDosHeader->e_cp);
  1873.         OUTPUT("\te_crlc     : 0x%X\n", analyzer.pDosHeader->e_crlc);
  1874.         OUTPUT("\te_cparhdr  : 0x%X\n", analyzer.pDosHeader->e_cparhdr);
  1875.         OUTPUT("\te_minalloc : 0x%X\n", analyzer.pDosHeader->e_minalloc);
  1876.         OUTPUT("\te_maxalloc : 0x%X\n", analyzer.pDosHeader->e_maxalloc);
  1877.         OUTPUT("\te_ss       : 0x%X\n", analyzer.pDosHeader->e_ss);
  1878.         OUTPUT("\te_sp       : 0x%X\n", analyzer.pDosHeader->e_sp);
  1879.         OUTPUT("\te_csum     : 0x%X\n", analyzer.pDosHeader->e_csum);
  1880.         OUTPUT("\te_ip       : 0x%X\n", analyzer.pDosHeader->e_ip);
  1881.         OUTPUT("\te_cs       : 0x%X\n", analyzer.pDosHeader->e_cs);
  1882.         OUTPUT("\te_lfarlc   : 0x%X\n", analyzer.pDosHeader->e_lfarlc);
  1883.         OUTPUT("\te_ovno     : 0x%X\n", analyzer.pDosHeader->e_ovno);
  1884.         OUTPUT("\te_oemid    : 0x%X\n", analyzer.pDosHeader->e_oemid);
  1885.         OUTPUT("\te_oeminfo  : 0x%X\n", analyzer.pDosHeader->e_oeminfo);
  1886.         OUTPUT("\te_lfanew   : 0x%X\n\n", analyzer.pDosHeader->e_lfanew);
  1887.  
  1888.         ShowProgress(30);
  1889.  
  1890.         // NT Headers
  1891.         if (analyzer.is64Bit) {
  1892.             OUTPUT("[+] NT HEADER (64-bit)\n");
  1893.             OUTPUT("\tSignature: 0x%X\n\n", analyzer.pNtHeaders64->Signature);
  1894.  
  1895.             OUTPUT("[+] FILE HEADER\n");
  1896.             OUTPUT("\tMachine: 0x%X\n", analyzer.pNtHeaders64->FileHeader.Machine);
  1897.             OUTPUT("\tNumberOfSections: 0x%X\n", analyzer.pNtHeaders64->FileHeader.NumberOfSections);
  1898.             OUTPUT("\tTimeDateStamp: 0x%X\n", analyzer.pNtHeaders64->FileHeader.TimeDateStamp);
  1899.             OUTPUT("\tPointerToSymbolTable: 0x%X\n", analyzer.pNtHeaders64->FileHeader.PointerToSymbolTable);
  1900.             OUTPUT("\tNumberOfSymbols: 0x%X\n", analyzer.pNtHeaders64->FileHeader.NumberOfSymbols);
  1901.             OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", analyzer.pNtHeaders64->FileHeader.SizeOfOptionalHeader);
  1902.             OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1903.                 analyzer.pNtHeaders64->FileHeader.Characteristics,
  1904.                 PEHelpers::GetImageCharacteristics(analyzer.pNtHeaders64->FileHeader.Characteristics).c_str());
  1905.  
  1906.             OUTPUT("[+] OPTIONAL HEADER\n");
  1907.             OUTPUT("\tMagic: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.Magic);
  1908.             OUTPUT("\tAddressOfEntryPoint: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.AddressOfEntryPoint);
  1909.             OUTPUT("\tImageBase: 0x%llX\n", analyzer.pNtHeaders64->OptionalHeader.ImageBase);
  1910.             OUTPUT("\tSectionAlignment: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SectionAlignment);
  1911.             OUTPUT("\tFileAlignment: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.FileAlignment);
  1912.             OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorOperatingSystemVersion);
  1913.             OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorOperatingSystemVersion);
  1914.             OUTPUT("\tMajorImageVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorImageVersion);
  1915.             OUTPUT("\tMinorImageVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorImageVersion);
  1916.             OUTPUT("\tMajorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MajorSubsystemVersion);
  1917.             OUTPUT("\tMinorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.MinorSubsystemVersion);
  1918.             OUTPUT("\tWin32VersionValue: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.Win32VersionValue);
  1919.             OUTPUT("\tSizeOfImage: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SizeOfImage);
  1920.             OUTPUT("\tSizeOfHeaders: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.SizeOfHeaders);
  1921.             OUTPUT("\tCheckSum: 0x%X\n", analyzer.pNtHeaders64->OptionalHeader.CheckSum);
  1922.             OUTPUT("\tSubsystem: 0x%X %s\n\n",
  1923.                 analyzer.pNtHeaders64->OptionalHeader.Subsystem,
  1924.                 PEHelpers::GetSubsystem(analyzer.pNtHeaders64->OptionalHeader.Subsystem).c_str());
  1925.         }
  1926.         else {
  1927.             // Similar output for 32-bit headers using analyzer.pNtHeaders32
  1928.             if (analyzer.is64Bit) {
  1929.                 OUTPUT("[+] NT HEADER (64-bit)\n");
  1930.                 OUTPUT("\tSignature: 0x%X\n\n", analyzer.pNtHeaders32->Signature);
  1931.  
  1932.                 OUTPUT("[+] FILE HEADER\n");
  1933.                 OUTPUT("\tMachine: 0x%X\n", analyzer.pNtHeaders32->FileHeader.Machine);
  1934.                 OUTPUT("\tNumberOfSections: 0x%X\n", analyzer.pNtHeaders32->FileHeader.NumberOfSections);
  1935.                 OUTPUT("\tTimeDateStamp: 0x%X\n", analyzer.pNtHeaders32->FileHeader.TimeDateStamp);
  1936.                 OUTPUT("\tPointerToSymbolTable: 0x%X\n", analyzer.pNtHeaders32->FileHeader.PointerToSymbolTable);
  1937.                 OUTPUT("\tNumberOfSymbols: 0x%X\n", analyzer.pNtHeaders32->FileHeader.NumberOfSymbols);
  1938.                 OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", analyzer.pNtHeaders32->FileHeader.SizeOfOptionalHeader);
  1939.                 OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  1940.                     analyzer.pNtHeaders32->FileHeader.Characteristics,
  1941.                     PEHelpers::GetImageCharacteristics(analyzer.pNtHeaders32->FileHeader.Characteristics).c_str());
  1942.  
  1943.                 OUTPUT("[+] OPTIONAL HEADER\n");
  1944.                 OUTPUT("\tMagic: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.Magic);
  1945.                 OUTPUT("\tAddressOfEntryPoint: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.AddressOfEntryPoint);
  1946.                 OUTPUT("\tImageBase: 0x%llX\n", analyzer.pNtHeaders32->OptionalHeader.ImageBase);
  1947.                 OUTPUT("\tSectionAlignment: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SectionAlignment);
  1948.                 OUTPUT("\tFileAlignment: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.FileAlignment);
  1949.                 OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorOperatingSystemVersion);
  1950.                 OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorOperatingSystemVersion);
  1951.                 OUTPUT("\tMajorImageVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorImageVersion);
  1952.                 OUTPUT("\tMinorImageVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorImageVersion);
  1953.                 OUTPUT("\tMajorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MajorSubsystemVersion);
  1954.                 OUTPUT("\tMinorSubsystemVersion: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.MinorSubsystemVersion);
  1955.                 OUTPUT("\tWin32VersionValue: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.Win32VersionValue);
  1956.                 OUTPUT("\tSizeOfImage: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SizeOfImage);
  1957.                 OUTPUT("\tSizeOfHeaders: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.SizeOfHeaders);
  1958.                 OUTPUT("\tCheckSum: 0x%X\n", analyzer.pNtHeaders32->OptionalHeader.CheckSum);
  1959.                 OUTPUT("\tSubsystem: 0x%X %s\n\n",
  1960.                     analyzer.pNtHeaders32->OptionalHeader.Subsystem,
  1961.                     PEHelpers::GetSubsystem(analyzer.pNtHeaders32->OptionalHeader.Subsystem).c_str());
  1962.                 // ... [32-bit header output code]
  1963.             }
  1964.  
  1965.             ShowProgress(40);
  1966.  
  1967.             // Parse Data Directories
  1968.             OUTPUT("[+] DATA DIRECTORIES\n");
  1969.             const IMAGE_DATA_DIRECTORY* dataDirectories = analyzer.is64Bit ?
  1970.                 analyzer.pNtHeaders64->OptionalHeader.DataDirectory :
  1971.                 analyzer.pNtHeaders32->OptionalHeader.DataDirectory;
  1972.  
  1973.             for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  1974.                 if (dataDirectories[i].VirtualAddress != 0) {
  1975.                     OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  1976.                     OUTPUT("\t\tVirtualAddress: 0x%X\n", dataDirectories[i].VirtualAddress);
  1977.                     OUTPUT("\t\tSize: 0x%X\n", dataDirectories[i].Size);
  1978.                 }
  1979.             }
  1980.             OUTPUT("\n");
  1981.  
  1982.             ShowProgress(50);
  1983.  
  1984.             // Parse Sections
  1985.             PEParser::ParseSections(analyzer);
  1986.             ShowProgress(60);
  1987.  
  1988.             // Parse Import Directory
  1989.             PEParser::ParseImportDirectory(analyzer);
  1990.             ShowProgress(70);
  1991.  
  1992.             // Parse Export Directory
  1993.             PEParser::ParseExportDirectory(analyzer);
  1994.             ShowProgress(80);
  1995.  
  1996.             // Parse Resource Directory
  1997.             PEParser::ParseResourceDirectory(analyzer);
  1998.             ShowProgress(90);
  1999.  
  2000.             // Parse Debug Directory
  2001.             PEParser::ParseDebugDirectory(analyzer);
  2002.             ShowProgress(100);
  2003.  
  2004.             SetStatusText(L"Analysis complete");
  2005.             ShowWindow(g_hProgressBar, SW_HIDE);
  2006.  
  2007.     // Add Section Parser if not already defined
  2008.     void ParseSections(const PEAnalyzer & analyzer) {
  2009.         OUTPUT("[+] SECTION HEADERS\n");
  2010.  
  2011.         PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(
  2012.             analyzer.is64Bit ?
  2013.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders64) :
  2014.             reinterpret_cast<PIMAGE_NT_HEADERS>(analyzer.pNtHeaders32));
  2015.  
  2016.         WORD numberOfSections = analyzer.is64Bit ?
  2017.             analyzer.pNtHeaders64->FileHeader.NumberOfSections :
  2018.             analyzer.pNtHeaders32->FileHeader.NumberOfSections;
  2019.  
  2020.         for (WORD i = 0; i < numberOfSections; i++, pSection++) {
  2021.             if (IsBadReadPtr(pSection, sizeof(IMAGE_SECTION_HEADER))) {
  2022.                 OUTPUT("[-] Invalid section header detected!\n");
  2023.                 break;
  2024.             }
  2025.  
  2026.             char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2027.             memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  2028.  
  2029.             // Ensure section name is printable
  2030.             for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  2031.                 if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  2032.                     sectionName[j] = '\0';
  2033.                 }
  2034.             }
  2035.  
  2036.             wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2037.             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  2038.                 sectionName, -1,
  2039.                 wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  2040.  
  2041.             OUTPUT("\tSECTION: %s\n", wideSectionName);
  2042.             OUTPUT("\t\tVirtualSize: 0x%X\n", pSection->Misc.VirtualSize);
  2043.             OUTPUT("\t\tVirtualAddress: 0x%X\n", pSection->VirtualAddress);
  2044.             OUTPUT("\t\tSizeOfRawData: 0x%X\n", pSection->SizeOfRawData);
  2045.             OUTPUT("\t\tPointerToRawData: 0x%X\n", pSection->PointerToRawData);
  2046.             OUTPUT("\t\tPointerToRelocations: 0x%X\n", pSection->PointerToRelocations);
  2047.             OUTPUT("\t\tPointerToLinenumbers: 0x%X\n", pSection->PointerToLinenumbers);
  2048.             OUTPUT("\t\tNumberOfRelocations: 0x%X\n", pSection->NumberOfRelocations);
  2049.             OUTPUT("\t\tNumberOfLinenumbers: 0x%X\n", pSection->NumberOfLinenumbers);
  2050.             OUTPUT("\t\tCharacteristics: 0x%X %s\n\n",
  2051.                 pSection->Characteristics,
  2052.                 PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  2053.         }
  2054.     }
  2055. }
  2056.  
  2057. UpdateEditControl();
  2058. }
  2059.  
  2060.     // Helper function to safely get file size
  2061.     DWORD GetFileSize(const wchar_t* filePath) {
  2062.         HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ,
  2063.             nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  2064.  
  2065.         if (hFile == INVALID_HANDLE_VALUE) {
  2066.             return 0;
  2067.         }
  2068.  
  2069.         DWORD fileSize = ::GetFileSize(hFile, nullptr);
  2070.         CloseHandle(hFile);
  2071.         return fileSize;
  2072.     }
  2073. // new code upto here ending here ^^
  2074. //
  2075. //######################################################################################
  2076. //######################################################################################
  2077. //        ##    endroughxfer - urldump #1#
  2078. //        ##    <EOF><EOF>
  2079. //######################################################################################
  2080. //######################################################################################
  2081.     //end adding here
  2082.  
  2083.     //commented below out vv
  2084.     /*void AnalyzePEFile(const wchar_t* filePathW) {
  2085.         OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  2086.  
  2087.         // Initialize all variables at the start
  2088.         HANDLE hFile = INVALID_HANDLE_VALUE;
  2089.         HANDLE hFileMapping = nullptr;
  2090.         LPVOID lpFileContent = nullptr;
  2091.  
  2092.         FileMapper mapper;
  2093.         if (!mapper.Initialize(filePathW)) {
  2094.             SetStatusText(L"Failed to open file!");
  2095.             OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
  2096.             return;
  2097.         }
  2098.  
  2099.         ShowProgress(20);
  2100.  
  2101.         hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
  2102.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  2103.         if (hFile == INVALID_HANDLE_VALUE) {
  2104.             OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  2105.             return;
  2106.         }
  2107.  
  2108.         DWORD fileSize = GetFileSize(hFile, nullptr);
  2109.         if (fileSize == INVALID_FILE_SIZE) {
  2110.             CloseHandle(hFile);
  2111.             OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
  2112.             return;
  2113.         }
  2114.  
  2115.         hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  2116.         if (!hFileMapping) {
  2117.             CloseHandle(hFile);
  2118.             OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
  2119.             return;
  2120.         }
  2121.  
  2122.         lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  2123.         if (!lpFileContent) {
  2124.             CloseHandle(hFileMapping);
  2125.             CloseHandle(hFile);
  2126.             OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
  2127.             return;
  2128.         }
  2129.  
  2130.         // Declare pNtHeaders here, outside the do-while loop.
  2131.         PIMAGE_NT_HEADERS pNtHeaders = nullptr; // Initialize to nullptr
  2132.  
  2133.         do {
  2134.             const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
  2135.             if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  2136.                 OUTPUT("[-] Invalid DOS signature!\r\n");
  2137.                 break;
  2138.             }
  2139.             ShowProgress(30);
  2140.             pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>( // Assign pNtHeaders here
  2141.                 static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
  2142.             if (IsBadReadPtr(pNtHeaders, sizeof(IMAGE_NT_HEADERS)) ||
  2143.                 pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  2144.                 OUTPUT("[-] Invalid NT signature!\r\n");
  2145.                 break;
  2146.             }
  2147.             bool is64Bit = PEHelpers::Is64BitPE(pNtHeaders);
  2148.             PIMAGE_NT_HEADERS32 pNtHeaders32 = nullptr;
  2149.             PIMAGE_NT_HEADERS64 pNtHeaders64 = nullptr;
  2150.             if (is64Bit) {
  2151.                 auto pNtHeaders64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(pNtHeaders);
  2152.             }
  2153.             else {
  2154.                 auto pNtHeaders32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(pNtHeaders);
  2155.             }
  2156.             DWORD_PTR imageBase = PEHelpers::GetImageBase(pNtHeaders);
  2157.             DWORD sizeOfImage = PEHelpers::GetSizeOfImage(pNtHeaders);
  2158.             if (pNtHeaders->FileHeader.NumberOfSections > 96) {
  2159.                 OUTPUT("[-] Suspicious number of sections detected!\n");
  2160.                 break;
  2161.             }
  2162.             //Move this check here after pNtHeaders is defined
  2163.             if (!PEHelpers::ValidateFileSize(pNtHeaders->OptionalHeader.SizeOfHeaders, fileSize)) {
  2164.                 OUTPUT("[-] Invalid image size detected!\n");
  2165.                 return;
  2166.             }
  2167.  
  2168.             OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  2169.             OUTPUT("[+] Architecture: %s\n\n", is64Bit ? "x64" : "x86");
  2170.             OUTPUT("[+] DOS HEADER\n");
  2171.             OUTPUT("\te_magic    : 0x%X\n", pImageDosHeader->e_magic);
  2172.             OUTPUT("\te_cblp     : 0x%X\n", pImageDosHeader->e_cblp);
  2173.             OUTPUT("\te_cp       : 0x%X\n", pImageDosHeader->e_cp);
  2174.             OUTPUT("\te_crlc     : 0x%X\n", pImageDosHeader->e_crlc);
  2175.             OUTPUT("\te_cparhdr  : 0x%X\n", pImageDosHeader->e_cparhdr);
  2176.             OUTPUT("\te_minalloc : 0x%X\n", pImageDosHeader->e_minalloc);
  2177.             OUTPUT("\te_maxalloc : 0x%X\n", pImageDosHeader->e_maxalloc);
  2178.             OUTPUT("\te_ss       : 0x%X\n", pImageDosHeader->e_ss);
  2179.             OUTPUT("\te_sp       : 0x%X\n", pImageDosHeader->e_sp);
  2180.             OUTPUT("\te_csum     : 0x%X\n", pImageDosHeader->e_csum);
  2181.             OUTPUT("\te_ip       : 0x%X\n", pImageDosHeader->e_ip);
  2182.             OUTPUT("\te_cs       : 0x%X\n", pImageDosHeader->e_cs);
  2183.             OUTPUT("\te_lfarlc   : 0x%X\n", pImageDosHeader->e_lfarlc);
  2184.             OUTPUT("\te_ovno     : 0x%X\n", pImageDosHeader->e_ovno);
  2185.             OUTPUT("\te_oemid    : 0x%X\n", pImageDosHeader->e_oemid);
  2186.             OUTPUT("\te_oeminfo  : 0x%X\n", pImageDosHeader->e_oeminfo);
  2187.             OUTPUT("\te_lfanew   : 0x%X\n\n", pImageDosHeader->e_lfanew);
  2188.             OUTPUT("[+] NT HEADER\n");
  2189.             OUTPUT("\tSignature  : 0x%X\n\n", pNtHeaders->Signature);
  2190.  
  2191.             ShowProgress(40);
  2192.  
  2193.             OUTPUT("[+] FILE HEADER\n");
  2194.             OUTPUT("\tMachine: 0x%X\n", pNtHeaders->FileHeader.Machine);
  2195.             OUTPUT("\tNumberOfSections: 0x%X\n", pNtHeaders->FileHeader.NumberOfSections);
  2196.             OUTPUT("\tTimeDateStamp: 0x%X\n", pNtHeaders->FileHeader.TimeDateStamp);
  2197.             OUTPUT("\tPointerToSymbolTable: 0x%X\n", pNtHeaders->FileHeader.PointerToSymbolTable);
  2198.             OUTPUT("\tNumberOfSymbols: 0x%X\n", pNtHeaders->FileHeader.NumberOfSymbols);
  2199.             OUTPUT("\tSizeOfOptionalHeader: 0x%X\n", pNtHeaders->FileHeader.SizeOfOptionalHeader);
  2200.             OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  2201.                 pNtHeaders->FileHeader.Characteristics,
  2202.                 PEHelpers::GetImageCharacteristics(pNtHeaders->FileHeader.Characteristics).c_str());
  2203.  
  2204.             ShowProgress(50);
  2205.  
  2206.             OUTPUT("[+] OPTIONAL HEADER\n");
  2207.             OUTPUT("\tMagic: 0x%X\n", pNtHeaders->OptionalHeader.Magic);
  2208.             OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pNtHeaders->OptionalHeader.AddressOfEntryPoint);
  2209.             OUTPUT("\tImageBase: 0x%p\n", (void*)imageBase);
  2210.             OUTPUT("\tSectionAlignment: 0x%X\n", pNtHeaders->OptionalHeader.SectionAlignment);
  2211.             OUTPUT("\tFileAlignment: 0x%X\n", pNtHeaders->OptionalHeader.FileAlignment);
  2212.             OUTPUT("\tMajorOperatingSystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  2213.             OUTPUT("\tMinorOperatingSystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  2214.             OUTPUT("\tMajorImageVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorImageVersion);
  2215.             OUTPUT("\tMinorImageVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorImageVersion);
  2216.             OUTPUT("\tMajorSubsystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MajorSubsystemVersion);
  2217.             OUTPUT("\tMinorSubsystemVersion: 0x%X\n", pNtHeaders->OptionalHeader.MinorSubsystemVersion);
  2218.             OUTPUT("\tWin32VersionValue: 0x%X\n", pNtHeaders->OptionalHeader.Win32VersionValue);
  2219.             OUTPUT("\tSizeOfImage: 0x%X\n", sizeOfImage);
  2220.             OUTPUT("\tSizeOfHeaders: 0x%X\n", pNtHeaders->OptionalHeader.SizeOfHeaders);
  2221.             OUTPUT("\tCheckSum: 0x%X\n", pNtHeaders->OptionalHeader.CheckSum);
  2222.             OUTPUT("\tSubsystem: 0x%X %s\n",
  2223.                 pNtHeaders->OptionalHeader.Subsystem,
  2224.                 PEHelpers::GetSubsystem(pNtHeaders->OptionalHeader.Subsystem).c_str());
  2225.  
  2226.             OUTPUT("\n[+] DATA DIRECTORIES\n");
  2227.             for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  2228.                 const auto& dir = pNtHeaders->OptionalHeader.DataDirectory[i];
  2229.                 if (dir.VirtualAddress != 0) {
  2230.                     if (!PEHelpers::IsRvaValid(dir.VirtualAddress, fileSize, pNtHeaders)) {
  2231.                         OUTPUT("\t%s: Invalid RVA detected!\n", PEHelpers::GetDataDirectoryName(i).c_str());
  2232.                         continue;
  2233.                     }
  2234.                     OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  2235.                     OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
  2236.                     OUTPUT("\t\tSize: 0x%X\n", dir.Size);
  2237.                 }
  2238.             }
  2239.  
  2240.             ShowProgress(60);
  2241.             OUTPUT("\n[+] SECTION HEADERS\n");
  2242.             auto pSection = IMAGE_FIRST_SECTION(pNtHeaders);
  2243.             for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  2244.                 if (IsBadReadPtr(pSection, sizeof(IMAGE_SECTION_HEADER))) {
  2245.                     OUTPUT("[-] Invalid section header detected!\n");
  2246.                     break;
  2247.                 }
  2248.                 char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2249.                 memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  2250.                 for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  2251.                     if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  2252.                         sectionName[j] = '\0';
  2253.                     }
  2254.                 }
  2255.                 wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2256.                 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  2257.                     sectionName, -1,
  2258.                     wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  2259.                 OUTPUT("\tSECTION: %s\n", wideSectionName);
  2260.                 OUTPUT("\t\tVirtualSize: 0x%X\n", pSection->Misc.VirtualSize);
  2261.                 OUTPUT("\t\tVirtualAddress: 0x%X\n", pSection->VirtualAddress);
  2262.                 OUTPUT("\t\tSizeOfRawData: 0x%X\n", pSection->SizeOfRawData);
  2263.                 OUTPUT("\t\tPointerToRawData: 0x%X\n", pSection->PointerToRawData);
  2264.                 OUTPUT("\t\tPointerToRelocations: 0x%X\n", pSection->PointerToRelocations);
  2265.                 OUTPUT("\t\tPointerToLinenumbers: 0x%X\n", pSection->PointerToLinenumbers);
  2266.                 OUTPUT("\t\tNumberOfRelocations: 0x%X\n", pSection->NumberOfRelocations);
  2267.                 OUTPUT("\t\tNumberOfLinenumbers: 0x%X\n", pSection->NumberOfLinenumbers);
  2268.                 OUTPUT("\t\tCharacteristics: 0x%X %s\n\n",
  2269.                     pSection->Characteristics,
  2270.                     PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  2271.             }
  2272.  
  2273.             ShowProgress(70);
  2274.  
  2275.             const auto& importDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  2276.             if (importDir.VirtualAddress && importDir.Size) {
  2277.                 if (!PEHelpers::IsRvaValid(importDir.VirtualAddress, fileSize, pNtHeaders)) {
  2278.                     OUTPUT("[-] Invalid import directory RVA!\n");
  2279.                     break;
  2280.                 }
  2281.                 OUTPUT("\n[+] IMPORT DIRECTORY\n");
  2282.                 auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  2283.                     importDir.VirtualAddress,
  2284.                     IMAGE_FIRST_SECTION(pNtHeaders),
  2285.                     pNtHeaders->FileHeader.NumberOfSections,
  2286.                     lpFileContent);
  2287.                 if (pImportDesc) {
  2288.                     while (pImportDesc->Name != 0) {
  2289.                         if (IsBadReadPtr(pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
  2290.                             OUTPUT("[-] Invalid import descriptor detected!\n");
  2291.                             break;
  2292.                         }
  2293.                         const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  2294.                             pImportDesc->Name,
  2295.                             IMAGE_FIRST_SECTION(pNtHeaders),
  2296.                             pNtHeaders->FileHeader.NumberOfSections,
  2297.                             lpFileContent);
  2298.                         if (dllName && !IsBadReadPtr(dllName, 1)) {
  2299.                             std::vector<wchar_t> wideDllName(MAX_PATH);
  2300.                             MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  2301.                             OUTPUT("\n\tDLL NAME: %s\n", wideDllName.data());
  2302.                             OUTPUT("\tCharacteristics: 0x%X\n", pImportDesc->Characteristics);
  2303.                             OUTPUT("\tTimeDateStamp: 0x%X\n", pImportDesc->TimeDateStamp);
  2304.                             OUTPUT("\tForwarderChain: 0x%X\n", pImportDesc->ForwarderChain);
  2305.                             OUTPUT("\tFirstThunk: 0x%X\n", pImportDesc->FirstThunk);
  2306.                             OUTPUT("\n\tImported Functions:\n");
  2307.  
  2308.                             if (is64Bit) {
  2309.                                 auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  2310.                                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  2311.                                     IMAGE_FIRST_SECTION(pNtHeaders),
  2312.                                     pNtHeaders->FileHeader.NumberOfSections,
  2313.                                     lpFileContent);
  2314.                                 while (pThunk && pThunk->u1.AddressOfData) {
  2315.                                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)) {
  2316.                                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  2317.                                             (DWORD)pThunk->u1.AddressOfData,
  2318.                                             IMAGE_FIRST_SECTION(pNtHeaders),
  2319.                                             pNtHeaders->FileHeader.NumberOfSections,
  2320.                                             lpFileContent);
  2321.                                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  2322.                                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  2323.                                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  2324.                                                 wideFuncName.data(), MAX_PATH);
  2325.                                             OUTPUT("\t\t%s\n", wideFuncName.data());
  2326.                                         }
  2327.                                     }
  2328.                                     else {
  2329.                                         OUTPUT("\t\tOrdinal: %lld\n", pThunk->u1.Ordinal & 0xFFFF);
  2330.                                     }
  2331.                                     pThunk++;
  2332.                                 }
  2333.                             }
  2334.                             else {
  2335.                                 auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  2336.                                     pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  2337.                                     IMAGE_FIRST_SECTION(pNtHeaders),
  2338.                                     pNtHeaders->FileHeader.NumberOfSections,
  2339.                                     lpFileContent);
  2340.                                 while (pThunk && pThunk->u1.AddressOfData) {
  2341.                                     if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) {
  2342.                                         auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  2343.                                             pThunk->u1.AddressOfData,
  2344.                                             IMAGE_FIRST_SECTION(pNtHeaders),
  2345.                                             pNtHeaders->FileHeader.NumberOfSections,
  2346.                                             lpFileContent);
  2347.                                         if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  2348.                                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  2349.                                             MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  2350.                                                 wideFuncName.data(), MAX_PATH);
  2351.                                             OUTPUT("\t\t%s\n", wideFuncName.data());
  2352.                                         }
  2353.                                     }
  2354.                                     else {
  2355.                                         OUTPUT("\t\tOrdinal: %d\n", pThunk->u1.Ordinal & 0xFFFF);
  2356.                                     }
  2357.                                     pThunk++;
  2358.                                 }
  2359.                             }
  2360.                         }
  2361.                         pImportDesc++;
  2362.                     }
  2363.                 }
  2364.             }
  2365.  
  2366.             ShowProgress(80);
  2367.  
  2368.             const auto& exportDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  2369.             if (exportDir.VirtualAddress && exportDir.Size) {
  2370.                 if (!PEHelpers::IsRvaValid(exportDir.VirtualAddress, fileSize, pNtHeaders)) {
  2371.                     OUTPUT("[-] Invalid export directory RVA!\n");
  2372.                     break;
  2373.                 }
  2374.                 OUTPUT("\n[+] EXPORT DIRECTORY\n");
  2375.                 auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  2376.                     exportDir.VirtualAddress,
  2377.                     IMAGE_FIRST_SECTION(pNtHeaders),
  2378.                     pNtHeaders->FileHeader.NumberOfSections,
  2379.                     lpFileContent);
  2380.                 if (pExportDir && !IsBadReadPtr(pExportDir, sizeof(IMAGE_EXPORT_DIRECTORY))) {
  2381.                     OUTPUT("\tCharacteristics: 0x%X\n", pExportDir->Characteristics);
  2382.                     OUTPUT("\tTimeDateStamp: 0x%X\n", pExportDir->TimeDateStamp);
  2383.                     OUTPUT("\tMajorVersion: %d\n", pExportDir->MajorVersion);
  2384.                     OUTPUT("\tMinorVersion: %d\n", pExportDir->MinorVersion);
  2385.                     OUTPUT("\tName: 0x%X\n", pExportDir->Name);
  2386.                     OUTPUT("\tBase: %d\n", pExportDir->Base);
  2387.                     OUTPUT("\tNumberOfFunctions: %d\n", pExportDir->NumberOfFunctions);
  2388.                     OUTPUT("\tNumberOfNames: %d\n", pExportDir->NumberOfNames);
  2389.                     OUTPUT("\tAddressOfFunctions: 0x%X\n", pExportDir->AddressOfFunctions);
  2390.                     OUTPUT("\tAddressOfNames: 0x%X\n", pExportDir->AddressOfNames);
  2391.                     OUTPUT("\tAddressOfNameOrdinals: 0x%X\n\n", pExportDir->AddressOfNameOrdinals);
  2392.  
  2393.                     auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  2394.                         pExportDir->AddressOfFunctions,
  2395.                         IMAGE_FIRST_SECTION(pNtHeaders),
  2396.                         pNtHeaders->FileHeader.NumberOfSections,
  2397.                         lpFileContent);
  2398.                     auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  2399.                         pExportDir->AddressOfNames,
  2400.                         IMAGE_FIRST_SECTION(pNtHeaders),
  2401.                         pNtHeaders->FileHeader.NumberOfSections,
  2402.                         lpFileContent);
  2403.                     auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  2404.                         pExportDir->AddressOfNameOrdinals,
  2405.                         IMAGE_FIRST_SECTION(pNtHeaders),
  2406.                         pNtHeaders->FileHeader.NumberOfSections,
  2407.                         lpFileContent);
  2408.  
  2409.                     if (pNames && pNameOrdinals && pFunctions) {
  2410.                         OUTPUT("\tExported Functions:\n\n");
  2411.                         for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  2412.                             if (IsBadReadPtr(pNames + i, sizeof(DWORD)) ||
  2413.                                 IsBadReadPtr(pNameOrdinals + i, sizeof(WORD))) {
  2414.                                 break;
  2415.                             }
  2416.  
  2417.                             const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  2418.                                 pNames[i],
  2419.                                 IMAGE_FIRST_SECTION(pNtHeaders),
  2420.                                 pNtHeaders->FileHeader.NumberOfSections,
  2421.                                 lpFileContent);
  2422.  
  2423.                             if (functionName && !IsBadReadPtr(functionName, 1)) {
  2424.                                 WORD ordinal = pNameOrdinals[i];
  2425.                                 if (ordinal < pExportDir->NumberOfFunctions) {
  2426.                                     DWORD functionRva = pFunctions[ordinal];
  2427.                                     if (functionRva >= exportDir.VirtualAddress &&
  2428.                                         functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  2429.                                         const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  2430.                                             functionRva,
  2431.                                             IMAGE_FIRST_SECTION(pNtHeaders),
  2432.                                             pNtHeaders->FileHeader.NumberOfSections,
  2433.                                             lpFileContent);
  2434.                                         if (forwardName && !IsBadReadPtr(forwardName, 1)) {
  2435.                                             std::vector<wchar_t> wideForwardName(MAX_PATH);
  2436.                                             MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  2437.                                                 wideForwardName.data(), MAX_PATH);
  2438.                                             OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  2439.                                                 functionName,
  2440.                                                 ordinal + pExportDir->Base,
  2441.                                                 wideForwardName.data());
  2442.                                         }
  2443.                                     }
  2444.                                     else {
  2445.                                         OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  2446.                                             functionName,
  2447.                                             ordinal + pExportDir->Base,
  2448.                                             functionRva);
  2449.                                     }
  2450.                                 }
  2451.                             }
  2452.                         }
  2453.                     }
  2454.                 }
  2455.             }
  2456.  
  2457.             ShowProgress(90);
  2458.  
  2459.             const auto& resourceDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  2460.             if (resourceDir.VirtualAddress && resourceDir.Size) {
  2461.                 if (!PEHelpers::IsRvaValid(resourceDir.VirtualAddress, fileSize, pNtHeaders)) {
  2462.                     OUTPUT("[-] Invalid resource directory RVA!\n");
  2463.                     break;
  2464.                 }
  2465.                 OUTPUT("\n[+] RESOURCE DIRECTORY\n");
  2466.                 auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  2467.                     resourceDir.VirtualAddress,
  2468.                     IMAGE_FIRST_SECTION(pNtHeaders),
  2469.                     pNtHeaders->FileHeader.NumberOfSections,
  2470.                     lpFileContent);
  2471.                 if (pResourceDir && !IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  2472.                     const wchar_t* resourceTypes[] = {
  2473.                         L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  2474.                         L"Menu",        L"Dialog",      L"String",      L"FontDir",
  2475.                         L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  2476.                         L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  2477.                     };
  2478.                     ProcessResourceDirectory(pResourceDir, 0, nullptr,
  2479.                         pResourceDir, resourceTypes, pNtHeaders, lpFileContent);
  2480.                 }
  2481.                 else {
  2482.                     OUTPUT("[-] Invalid or corrupted resource directory\n");
  2483.                 }
  2484.             }
  2485.  
  2486.             const auto& debugDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  2487.             if (debugDir.VirtualAddress && debugDir.Size) {
  2488.                 if (!PEHelpers::IsRvaValid(debugDir.VirtualAddress, fileSize, pNtHeaders)) {
  2489.                     OUTPUT("[-] Invalid debug directory RVA!\n");
  2490.                     break;
  2491.                 }
  2492.                 OUTPUT("\n[+] DEBUG DIRECTORY\n");
  2493.                 auto pDebugDir = (PIMAGE_DEBUG_DIRECTORY)PEHelpers::GetRvaPtr(
  2494.                     debugDir.VirtualAddress,
  2495.                     IMAGE_FIRST_SECTION(pNtHeaders),
  2496.                     pNtHeaders->FileHeader.NumberOfSections,
  2497.                     lpFileContent);
  2498.                 if (pDebugDir && !IsBadReadPtr(pDebugDir, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  2499.                     DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16);
  2500.                     for (DWORD i = 0; i < numEntries; i++) {
  2501.                         OUTPUT("\tCharacteristics: 0x%X\n", pDebugDir[i].Characteristics);
  2502.                         OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDir[i].TimeDateStamp);
  2503.                         OUTPUT("\tMajorVersion: %d\n", pDebugDir[i].MajorVersion);
  2504.                         OUTPUT("\tMinorVersion: %d\n", pDebugDir[i].MinorVersion);
  2505.                         OUTPUT("\tType: 0x%X", pDebugDir[i].Type);
  2506.                         switch (pDebugDir[i].Type) {
  2507.                         case IMAGE_DEBUG_TYPE_COFF:
  2508.                             OUTPUT(" (COFF)\n"); break;
  2509.                         case IMAGE_DEBUG_TYPE_CODEVIEW:
  2510.                             OUTPUT(" (CodeView)\n"); break;
  2511.                         case IMAGE_DEBUG_TYPE_FPO:
  2512.                             OUTPUT(" (FPO)\n"); break;
  2513.                         case IMAGE_DEBUG_TYPE_MISC:
  2514.                             OUTPUT(" (Misc)\n"); break;
  2515.                         case IMAGE_DEBUG_TYPE_EXCEPTION:
  2516.                             OUTPUT(" (Exception)\n"); break;
  2517.                         default:
  2518.                             OUTPUT(" (Unknown)\n"); break;
  2519.                         }
  2520.                         OUTPUT("\tSizeOfData: 0x%X\n", pDebugDir[i].SizeOfData);
  2521.                         OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDir[i].AddressOfRawData);
  2522.                         OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDir[i].PointerToRawData);
  2523.  
  2524.                         if (pDebugDir[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  2525.                             pDebugDir[i].PointerToRawData != 0 &&
  2526.                             pDebugDir[i].SizeOfData >= 24) {
  2527.                             auto pCVHeader = (DWORD*)((BYTE*)lpFileContent + pDebugDir[i].PointerToRawData);
  2528.                             if (!IsBadReadPtr(pCVHeader, sizeof(DWORD)) && *pCVHeader == 0x53445352) {
  2529.                                 auto pCVData = (char*)(pCVHeader + 1);
  2530.                                 if (!IsBadReadPtr(pCVData + 16, 1)) {
  2531.                                     std::vector<wchar_t> pdbPath(MAX_PATH);
  2532.                                     MultiByteToWideChar(CP_ACP, 0, pCVData + 16, -1,
  2533.                                         pdbPath.data(), MAX_PATH);
  2534.                                     OUTPUT("\tPDB Path: %s\n\n", pdbPath.data());
  2535.                                 }
  2536.                             }
  2537.                         }
  2538.                     }
  2539.                 }
  2540.             }
  2541.  
  2542.             ShowProgress(100);
  2543.             SetStatusText(L"Analysis complete");
  2544.             ShowWindow(g_hProgressBar, SW_HIDE);
  2545.  
  2546.         } while (false); // End of the do-while loop that replaced goto
  2547.  
  2548.         // Cleanup
  2549.         if (lpFileContent) UnmapViewOfFile(lpFileContent);
  2550.         if (hFileMapping) CloseHandle(hFileMapping);
  2551.         if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
  2552.         UpdateEditControl();
  2553.     }*/
  2554.  
  2555.  
  2556.     /*OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  2557.  
  2558.     FileMapper mapper;
  2559.     if (!mapper.Initialize(filePathW)) {
  2560.         SetStatusText(L"Failed to open file!");
  2561.         OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
  2562.         return;
  2563.     }
  2564.  
  2565.     ShowProgress(20);  // After initial file opening
  2566.  
  2567.  
  2568.     // Open and read file
  2569.     HANDLE hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
  2570.         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  2571.     if (hFile == INVALID_HANDLE_VALUE) {
  2572.         OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  2573.         return;
  2574.     }
  2575.  
  2576.     DWORD fileSize = GetFileSize(hFile, nullptr);
  2577.     if (fileSize == INVALID_FILE_SIZE) {
  2578.         CloseHandle(hFile);
  2579.         OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
  2580.         return;
  2581.     }
  2582.  
  2583.     HANDLE hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  2584.     if (!hFileMapping) {
  2585.         CloseHandle(hFile);
  2586.         OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
  2587.         return;
  2588.     }
  2589.  
  2590.     LPVOID lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  2591.     if (!lpFileContent) {
  2592.         CloseHandle(hFileMapping);
  2593.         CloseHandle(hFile);
  2594.         OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
  2595.         return;
  2596.     }
  2597.  
  2598.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
  2599.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  2600.         OUTPUT("[-] Invalid DOS signature!\r\n");
  2601.         return;
  2602.     }
  2603.  
  2604.     ShowProgress(30);
  2605.  
  2606.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
  2607.         static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
  2608.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  2609.         OUTPUT("[-] Invalid NT signature!\r\n");
  2610.         return;
  2611.     }
  2612.  
  2613.     // Add right after this line:
  2614. // OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  2615.  
  2616. // Add PE Image Information and Architecture
  2617.     OUTPUT("[+] PE IMAGE INFORMATION\n\n");
  2618.     // Replace the Architecture output line with this:
  2619.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  2620.         OUTPUT("[+] Architecture: x86\n\n");
  2621.     }
  2622.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
  2623.         OUTPUT("[+] Architecture: x64\n\n");
  2624.     }
  2625.     else {
  2626.         OUTPUT("[+] Architecture: Unknown\n\n");
  2627.     }
  2628.  
  2629.     // Add complete DOS Header information
  2630.     OUTPUT("[+] DOS HEADER\n");
  2631.     OUTPUT("\te_magic    : 0x%X\n", pImageDosHeader->e_magic);
  2632.     OUTPUT("\te_cblp     : 0x%X\n", pImageDosHeader->e_cblp);
  2633.     OUTPUT("\te_cp       : 0x%X\n", pImageDosHeader->e_cp);
  2634.     OUTPUT("\te_crlc     : 0x%X\n", pImageDosHeader->e_crlc);
  2635.     OUTPUT("\te_cparhdr  : 0x%X\n", pImageDosHeader->e_cparhdr);
  2636.     OUTPUT("\te_minalloc : 0x%X\n", pImageDosHeader->e_minalloc);
  2637.     OUTPUT("\te_maxalloc : 0x%X\n", pImageDosHeader->e_maxalloc);
  2638.     OUTPUT("\te_ss       : 0x%X\n", pImageDosHeader->e_ss);
  2639.     OUTPUT("\te_sp       : 0x%X\n", pImageDosHeader->e_sp);
  2640.     OUTPUT("\te_csum     : 0x%X\n", pImageDosHeader->e_csum);
  2641.     OUTPUT("\te_ip       : 0x%X\n", pImageDosHeader->e_ip);
  2642.     OUTPUT("\te_cs       : 0x%X\n", pImageDosHeader->e_cs);
  2643.     OUTPUT("\te_lfarlc   : 0x%X\n", pImageDosHeader->e_lfarlc);
  2644.     OUTPUT("\te_ovno     : 0x%X\n", pImageDosHeader->e_ovno);
  2645.     OUTPUT("\te_oemid    : 0x%X\n", pImageDosHeader->e_oemid);
  2646.     OUTPUT("\te_oeminfo  : 0x%X\n", pImageDosHeader->e_oeminfo);
  2647.     OUTPUT("\te_lfanew   : 0x%X\n\n", pImageDosHeader->e_lfanew);
  2648.  
  2649.     // Add NT Header signature before the existing PE FILE HEADER section
  2650.     OUTPUT("[+] NT HEADER\n");
  2651.     OUTPUT("\tSignature  : 0x%X\n\n", pImageNtHeaders->Signature);
  2652.  
  2653.     // The rest of your existing code continues here...
  2654.     // OUTPUT("[+] PE FILE HEADER\n");
  2655.  
  2656.     ShowProgress(40);
  2657.  
  2658.     // Print File Header Information
  2659.     OUTPUT("[+] PE FILE HEADER\n");
  2660.     OUTPUT("\tMachine: 0x%X\n", pImageNtHeaders->FileHeader.Machine);
  2661.     OUTPUT("\tNumberOfSections: 0x%X\n", pImageNtHeaders->FileHeader.NumberOfSections);
  2662.     OUTPUT("\tTimeDateStamp: 0x%X\n", pImageNtHeaders->FileHeader.TimeDateStamp);
  2663.     OUTPUT("\tPointerToSymbolTable: 0x%X\r\n",
  2664.         static_cast<DWORD>(pImageNtHeaders->FileHeader.PointerToSymbolTable));
  2665.     OUTPUT("\tNumberOfSymbols: 0x%X\r\n",
  2666.         static_cast<DWORD>(pImageNtHeaders->FileHeader.NumberOfSymbols));
  2667.     OUTPUT("\tSizeOfOptionalHeader: 0x%X\r\n",
  2668.         static_cast<DWORD>(pImageNtHeaders->FileHeader.SizeOfOptionalHeader));
  2669.     OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  2670.         pImageNtHeaders->FileHeader.Characteristics,
  2671.         PEHelpers::GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics).c_str());
  2672.  
  2673.     ShowProgress(50);
  2674.  
  2675.     // Print Optional Header Information
  2676.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  2677.     OUTPUT("\tMagic: 0x%X\n", pImageNtHeaders->OptionalHeader.Magic);
  2678.     OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  2679.     OUTPUT("\tImageBase: 0x%llX\n", (ULONGLONG)pImageNtHeaders->OptionalHeader.ImageBase);
  2680.     OUTPUT("\tSectionAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.SectionAlignment);
  2681.     OUTPUT("\tFileAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.FileAlignment);
  2682.  
  2683.     // Added missing Optional Header fields
  2684.     OUTPUT("\tMajorOperatingSystemVersion: 0x%X\r\n",
  2685.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion));
  2686.     OUTPUT("\tMinorOperatingSystemVersion: 0x%X\r\n",
  2687.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion));
  2688.     OUTPUT("\tMajorImageVersion: 0x%X\r\n",
  2689.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorImageVersion));
  2690.     OUTPUT("\tMinorImageVersion: 0x%X\r\n",
  2691.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorImageVersion));
  2692.     OUTPUT("\tMajorSubsystemVersion: 0x%X\r\n",
  2693.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MajorSubsystemVersion));
  2694.     OUTPUT("\tMinorSubsystemVersion: 0x%X\r\n",
  2695.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.MinorSubsystemVersion));
  2696.     OUTPUT("\tWin32VersionValue: 0x%X\r\n",
  2697.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Win32VersionValue));
  2698.     OUTPUT("\tSizeOfImage: 0x%X\r\n",
  2699.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfImage));
  2700.     OUTPUT("\tSizeOfHeaders: 0x%X\r\n",
  2701.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.SizeOfHeaders));
  2702.     OUTPUT("\tCheckSum: 0x%X\r\n",
  2703.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.CheckSum));
  2704.     OUTPUT("\tSubsystem: 0x%X %s\r\n",
  2705.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.Subsystem),
  2706.         PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
  2707.     OUTPUT("\tDllCharacteristics: 0x%X\r\n",
  2708.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.DllCharacteristics));
  2709.     OUTPUT("\tSizeOfStackReserve: 0x%llX\r\n",
  2710.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackReserve));
  2711.     OUTPUT("\tSizeOfStackCommit: 0x%llX\r\n",
  2712.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfStackCommit));
  2713.     OUTPUT("\tSizeOfHeapReserve: 0x%llX\r\n",
  2714.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapReserve));
  2715.     OUTPUT("\tSizeOfHeapCommit: 0x%llX\r\n",
  2716.         static_cast<ULONGLONG>(pImageNtHeaders->OptionalHeader.SizeOfHeapCommit));
  2717.     OUTPUT("\tLoaderFlags: 0x%X\r\n",
  2718.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.LoaderFlags));
  2719.     OUTPUT("\tNumberOfRvaAndSizes: 0x%X\r\n\r\n",
  2720.         static_cast<DWORD>(pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes));
  2721.  
  2722.     OUTPUT("\tSubsystem: 0x%X %s\n\n",
  2723.         pImageNtHeaders->OptionalHeader.Subsystem,
  2724.         PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
  2725.  
  2726.     // Print Data Directories
  2727.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  2728.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  2729.         const auto& dir = pImageNtHeaders->OptionalHeader.DataDirectory[i];
  2730.         if (dir.VirtualAddress != 0) {
  2731.             OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  2732.             OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
  2733.             OUTPUT("\t\tSize: 0x%X\n", dir.Size);
  2734.         }
  2735.     }
  2736.  
  2737.     // Analyze Sections
  2738.     OUTPUT("\n[+] PE IMAGE SECTIONS\r\n");
  2739.     auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  2740.     for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  2741.         // Create a null-terminated string from the section name
  2742.         char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2743.         memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  2744.  
  2745.         // Remove any non-printable characters
  2746.         for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  2747.             if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  2748.                 sectionName[j] = '\0';
  2749.             }
  2750.         }
  2751.  
  2752.         // Convert to wide string
  2753.         wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  2754.         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  2755.             sectionName, -1,
  2756.             wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  2757.  
  2758.         OUTPUT("\tSECTION : %s\r\n", wideSectionName);
  2759.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\r\n", pSection->Misc.PhysicalAddress);
  2760.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\r\n", pSection->Misc.VirtualSize);
  2761.         OUTPUT("\t\tVirtualAddress : 0x%X\r\n", pSection->VirtualAddress);
  2762.         OUTPUT("\t\tSizeOfRawData : 0x%X\r\n", pSection->SizeOfRawData);
  2763.         OUTPUT("\t\tPointerToRawData : 0x%X\r\n", pSection->PointerToRawData);
  2764.         OUTPUT("\t\tPointerToRelocations : 0x%X\r\n", pSection->PointerToRelocations);
  2765.         OUTPUT("\t\tPointerToLinenumbers : 0x%X\r\n", pSection->PointerToLinenumbers);
  2766.         OUTPUT("\t\tNumberOfRelocations : 0x%X\r\n", pSection->NumberOfRelocations);
  2767.         OUTPUT("\t\tNumberOfLinenumbers : 0x%X\r\n", pSection->NumberOfLinenumbers);
  2768.         OUTPUT("\t\tCharacteristics : 0x%X %s\r\n\r\n",
  2769.             pSection->Characteristics,
  2770.             PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  2771.     }
  2772.  
  2773.     ShowProgress(60);
  2774.  
  2775.     // Analyze Imports
  2776.     // Then modify the Import section like this:
  2777.     const auto& importDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  2778.     if (importDir.VirtualAddress && importDir.Size) {
  2779.         OUTPUT("\n[+] IMPORTED DLLS AND FUNCTIONS\r\n");
  2780.         auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)PEHelpers::GetRvaPtr(
  2781.             importDir.VirtualAddress,
  2782.             IMAGE_FIRST_SECTION(pImageNtHeaders),
  2783.             pImageNtHeaders->FileHeader.NumberOfSections,
  2784.             lpFileContent);
  2785.  
  2786.         bool is64Bit = Is64BitPE(pImageNtHeaders);
  2787.  
  2788.         while (pImportDesc && pImportDesc->Name != 0) {
  2789.             const char* dllName = (const char*)PEHelpers::GetRvaPtr(
  2790.                 pImportDesc->Name,
  2791.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  2792.                 pImageNtHeaders->FileHeader.NumberOfSections,
  2793.                 lpFileContent);
  2794.  
  2795.             if (dllName) {
  2796.                 std::vector<wchar_t> wideDllName(MAX_PATH);
  2797.                 MultiByteToWideChar(CP_ACP, 0, dllName, -1, wideDllName.data(), MAX_PATH);
  2798.  
  2799.                 OUTPUT("\n\tDLL NAME : %s\r\n", wideDllName.data());
  2800.                 OUTPUT("\tCharacteristics : 0x%X\r\n", pImportDesc->Characteristics);
  2801.                 OUTPUT("\tOriginalFirstThunk : 0x%X\r\n", pImportDesc->OriginalFirstThunk);
  2802.                 OUTPUT("\tTimeDateStamp : 0x%X\r\n", pImportDesc->TimeDateStamp);
  2803.                 OUTPUT("\tForwarderChain : 0x%X\r\n", pImportDesc->ForwarderChain);
  2804.                 OUTPUT("\tFirstThunk : 0x%X\r\n", pImportDesc->FirstThunk);
  2805.  
  2806.                 OUTPUT("\n\tImported Functions :\r\n\r\n");
  2807.  
  2808.                 ULONGLONG ordinalFlag = is64Bit ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32;
  2809.  
  2810.                 if (is64Bit) {
  2811.                     auto pThunk = (PIMAGE_THUNK_DATA64)PEHelpers::GetRvaPtr(
  2812.                         pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  2813.                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  2814.                         pImageNtHeaders->FileHeader.NumberOfSections,
  2815.                         lpFileContent);
  2816.  
  2817.                     while (pThunk && pThunk->u1.AddressOfData) {
  2818.                         if (!(pThunk->u1.Ordinal & ordinalFlag)) {
  2819.                             auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  2820.                                 (DWORD)pThunk->u1.AddressOfData,
  2821.                                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  2822.                                 pImageNtHeaders->FileHeader.NumberOfSections,
  2823.                                 lpFileContent);
  2824.  
  2825.                             if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  2826.                                 std::vector<wchar_t> wideFuncName(MAX_PATH);
  2827.                                 MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  2828.                                     wideFuncName.data(), MAX_PATH);
  2829.                                 OUTPUT("\t\t%s\r\n", wideFuncName.data());
  2830.                             }
  2831.                         }
  2832.                         else {
  2833.                             OUTPUT("\t\tOrdinal: %lld\r\n", pThunk->u1.Ordinal & 0xFFFF);
  2834.                         }
  2835.                         pThunk++;
  2836.                     }
  2837.                 }
  2838.                 else {
  2839.                     auto pThunk = (PIMAGE_THUNK_DATA32)PEHelpers::GetRvaPtr(
  2840.                         pImportDesc->OriginalFirstThunk ? pImportDesc->OriginalFirstThunk : pImportDesc->FirstThunk,
  2841.                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  2842.                         pImageNtHeaders->FileHeader.NumberOfSections,
  2843.                         lpFileContent);
  2844.  
  2845.                     while (pThunk && pThunk->u1.AddressOfData) {
  2846.                         if (!(pThunk->u1.Ordinal & ordinalFlag)) {
  2847.                             auto pImportByName = (PIMAGE_IMPORT_BY_NAME)PEHelpers::GetRvaPtr(
  2848.                                 pThunk->u1.AddressOfData,
  2849.                                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  2850.                                 pImageNtHeaders->FileHeader.NumberOfSections,
  2851.                                 lpFileContent);
  2852.  
  2853.                             if (pImportByName && !IsBadReadPtr(pImportByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
  2854.                                 std::vector<wchar_t> wideFuncName(MAX_PATH);
  2855.                                 MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  2856.                                     wideFuncName.data(), MAX_PATH);
  2857.                                 OUTPUT("\t\t%s\r\n", wideFuncName.data());
  2858.                             }
  2859.                         }
  2860.                         else {
  2861.                             OUTPUT("\t\tOrdinal: %d\r\n", pThunk->u1.Ordinal & 0xFFFF);
  2862.                         }
  2863.                         pThunk++;
  2864.                     }
  2865.                 }
  2866.             }
  2867.             pImportDesc++;
  2868.         }
  2869.     }
  2870.  
  2871.         ShowProgress(70);
  2872.  
  2873.         // In your AnalyzePEFile function, add this code after the imports section (before the cleanup label):
  2874.  
  2875.         // Handle Exports
  2876.         const auto& exportDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  2877.         if (exportDir.VirtualAddress && exportDir.Size) {
  2878.             OUTPUT("\n[+] EXPORTED FUNCTIONS\n");
  2879.             auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)PEHelpers::GetRvaPtr(
  2880.                 exportDir.VirtualAddress,
  2881.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  2882.                 pImageNtHeaders->FileHeader.NumberOfSections,
  2883.                 lpFileContent);
  2884.  
  2885.             if (pExportDir) {
  2886.                 // ... (existing code)
  2887.  
  2888.                 auto pFunctions = (PDWORD)PEHelpers::GetRvaPtr(
  2889.                     pExportDir->AddressOfFunctions,
  2890.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  2891.                     pImageNtHeaders->FileHeader.NumberOfSections,
  2892.                     lpFileContent);
  2893.  
  2894.                 auto pNames = (PDWORD)PEHelpers::GetRvaPtr(
  2895.                     pExportDir->AddressOfNames,
  2896.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  2897.                     pImageNtHeaders->FileHeader.NumberOfSections,
  2898.                     lpFileContent);
  2899.  
  2900.                 auto pNameOrdinals = (PWORD)PEHelpers::GetRvaPtr(
  2901.                     pExportDir->AddressOfNameOrdinals,
  2902.                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  2903.                     pImageNtHeaders->FileHeader.NumberOfSections,
  2904.                     lpFileContent);
  2905.  
  2906.                 if (pNames && pNameOrdinals && pFunctions) {
  2907.                     for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
  2908.                         const char* functionName = (const char*)PEHelpers::GetRvaPtr(
  2909.                             pNames[i],
  2910.                             IMAGE_FIRST_SECTION(pImageNtHeaders),
  2911.                             pImageNtHeaders->FileHeader.NumberOfSections,
  2912.                             lpFileContent);
  2913.  
  2914.                         if (functionName) {
  2915.                             WORD ordinal = pNameOrdinals[i];
  2916.                             DWORD functionRva = pFunctions[ordinal];
  2917.  
  2918.                             std::vector<wchar_t> wideFuncName(MAX_PATH);
  2919.                             MultiByteToWideChar(CP_ACP, 0, functionName, -1,
  2920.                                 wideFuncName.data(), MAX_PATH);
  2921.  
  2922.                             // Check if it's a forwarded export
  2923.                             if (functionRva >= exportDir.VirtualAddress &&
  2924.                                 functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  2925.                                 // This is a forwarded export
  2926.                                 const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  2927.                                     functionRva,
  2928.                                     IMAGE_FIRST_SECTION(pImageNtHeaders),
  2929.                                     pImageNtHeaders->FileHeader.NumberOfSections,
  2930.                                     lpFileContent);
  2931.  
  2932.                                 if (forwardName) {
  2933.                                     std::vector<wchar_t> wideForwardName(MAX_PATH);
  2934.                                     MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  2935.                                         wideForwardName.data(), MAX_PATH);
  2936.                                     OUTPUT("\t\t%s (Ordinal: %d) -> Forward to: %s\n",
  2937.                                         wideFuncName.data(),
  2938.                                         ordinal + pExportDir->Base,
  2939.                                         wideForwardName.data());
  2940.                                 }
  2941.                             }
  2942.                             else {
  2943.                                 OUTPUT("\t\t%s (Ordinal: %d, RVA: 0x%08X)\n",
  2944.                                     wideFuncName.data(),
  2945.                                     ordinal + pExportDir->Base,
  2946.                                     functionRva);
  2947.                             }
  2948.                         }
  2949.                     }
  2950.  
  2951.                     // Check for exports by ordinal only (no names)
  2952.                     for (DWORD i = 0; i < pExportDir->NumberOfFunctions; i++) {
  2953.                         if (pFunctions[i] != 0) {
  2954.                             bool hasName = false;
  2955.                             for (DWORD j = 0; j < pExportDir->NumberOfNames; j++) {
  2956.                                 if (pNameOrdinals[j] == i) {
  2957.                                     hasName = true;
  2958.                                     break;
  2959.                                 }
  2960.                             }
  2961.  
  2962.                             if (!hasName) {
  2963.                                 DWORD functionRva = pFunctions[i];
  2964.                                 if (functionRva >= exportDir.VirtualAddress &&
  2965.                                     functionRva < (exportDir.VirtualAddress + exportDir.Size)) {
  2966.                                     // This is a forwarded export
  2967.                                     const char* forwardName = (const char*)PEHelpers::GetRvaPtr(
  2968.                                         functionRva,
  2969.                                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  2970.                                         pImageNtHeaders->FileHeader.NumberOfSections,
  2971.                                         lpFileContent);
  2972.  
  2973.                                     if (forwardName) {
  2974.                                         std::vector<wchar_t> wideForwardName(MAX_PATH);
  2975.                                         MultiByteToWideChar(CP_ACP, 0, forwardName, -1,
  2976.                                             wideForwardName.data(), MAX_PATH);
  2977.                                         OUTPUT("\t\tOrdinal: %d -> Forward to: %s\n",
  2978.                                             i + pExportDir->Base,
  2979.                                             wideForwardName.data());
  2980.                                     }
  2981.                                 }
  2982.                                 else {
  2983.                                     OUTPUT("\t\tOrdinal: %d (RVA: 0x%08X)\n",
  2984.                                         i + pExportDir->Base,
  2985.                                         functionRva);
  2986.                                 }
  2987.                             }
  2988.                         }
  2989.                     }
  2990.                 }
  2991.             }
  2992.         }
  2993.  
  2994.         ShowProgress(80);
  2995.  
  2996.         // Add after export directory analysis and before ShowProgress(100)
  2997.  
  2998.         // Resource Directory Analysis
  2999.         const auto& resourceDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  3000.         if (resourceDir.VirtualAddress && resourceDir.Size) {
  3001.             OUTPUT("\n[+] RESOURCE DIRECTORY\n");
  3002.             auto pResourceDir = (PIMAGE_RESOURCE_DIRECTORY)PEHelpers::GetRvaPtr(
  3003.                 resourceDir.VirtualAddress,
  3004.                 IMAGE_FIRST_SECTION(pImageNtHeaders),
  3005.                 pImageNtHeaders->FileHeader.NumberOfSections,
  3006.                 lpFileContent);
  3007.  
  3008.             if (pResourceDir && !IsBadReadPtr(pResourceDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  3009.                 OUTPUT("\tCharacteristics: 0x%X\n", pResourceDir->Characteristics);
  3010.                 OUTPUT("\tTimeDateStamp: 0x%X\n", pResourceDir->TimeDateStamp);
  3011.                 OUTPUT("\tMajorVersion: %d\n", pResourceDir->MajorVersion);
  3012.                 OUTPUT("\tMinorVersion: %d\n", pResourceDir->MinorVersion);
  3013.                 OUTPUT("\tNumberOfNamedEntries: %d\n", pResourceDir->NumberOfNamedEntries);
  3014.                 OUTPUT("\tNumberOfIdEntries: %d\n\n", pResourceDir->NumberOfIdEntries);
  3015.  
  3016.                 const wchar_t* resourceTypes[] = {
  3017.                     L"Unknown",     L"Cursor",      L"Bitmap",      L"Icon",
  3018.                     L"Menu",        L"Dialog",      L"String",      L"FontDir",
  3019.                     L"Font",        L"Accelerator", L"RCData",      L"MessageTable",
  3020.                     L"GroupCursor", L"GroupIcon",   L"Version",     L"DlgInclude"
  3021.                 };
  3022.  
  3023.                 auto ProcessResourceDirectory = [&](PIMAGE_RESOURCE_DIRECTORY resDir, int level, const wchar_t* type = nullptr) {
  3024.                     if (IsBadReadPtr(resDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  3025.                         return;
  3026.                     }
  3027.  
  3028.                     auto entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir + 1);
  3029.                     WORD totalEntries = resDir->NumberOfNamedEntries + resDir->NumberOfIdEntries;
  3030.  
  3031.                     for (WORD i = 0; i < totalEntries; i++) {
  3032.                         if (IsBadReadPtr(entry + i, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
  3033.                             break;
  3034.                         }
  3035.  
  3036.                         for (int indent = 0; indent < level; indent++) {
  3037.                             OUTPUT("\t");
  3038.                         }
  3039.  
  3040.                         if (entry[i].NameIsString) {
  3041.                             auto nameEntry = (PIMAGE_RESOURCE_DIR_STRING_U)((BYTE*)pResourceDir + entry[i].NameOffset);
  3042.                             if (!IsBadReadPtr(nameEntry, sizeof(IMAGE_RESOURCE_DIR_STRING_U))) {
  3043.                                 std::vector<wchar_t> resourceName(nameEntry->Length + 1);
  3044.                                 wcsncpy_s(resourceName.data(), nameEntry->Length + 1,
  3045.                                     nameEntry->NameString, nameEntry->Length);
  3046.                                 resourceName[nameEntry->Length] = L'\0';
  3047.  
  3048.                                 if (level == 0) {
  3049.                                     OUTPUT("Resource Type: Custom (%s)\n", resourceName.data());
  3050.                                 }
  3051.                                 else {
  3052.                                     OUTPUT("Name: %s\n", resourceName.data());
  3053.                                 }
  3054.                             }
  3055.                         }
  3056.                         else {
  3057.                             if (level == 0) {
  3058.                                 DWORD resourceType = entry[i].Id;
  3059.                                 if (resourceType < 16) {
  3060.                                     OUTPUT("Resource Type: %s (ID: %d)\n", resourceTypes[resourceType], resourceType);
  3061.                                 }
  3062.                                 else {
  3063.                                     OUTPUT("Resource Type: Custom (ID: %d)\n", resourceType);
  3064.                                 }
  3065.                             }
  3066.                             else {
  3067.                                 OUTPUT("ID: %d\n", entry[i].Id);
  3068.                             }
  3069.                         }
  3070.  
  3071.                         if (entry[i].DataIsDirectory) {
  3072.                             auto nextDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pResourceDir + entry[i].OffsetToDirectory);
  3073.                             if (!IsBadReadPtr(nextDir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
  3074.                                 ProcessResourceDirectory(nextDir, level + 1,
  3075.                                     level == 0 ? resourceTypes[min(entry[i].Id, 15)] : type);
  3076.                             }
  3077.                         }
  3078.                         else {
  3079.                             auto dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE*)pResourceDir + entry[i].OffsetToData);
  3080.                             if (!IsBadReadPtr(dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
  3081.                                 for (int indent = 0; indent < level + 1; indent++) {
  3082.                                     OUTPUT("\t");
  3083.                                 }
  3084.                                 OUTPUT("Size: %d bytes, RVA: 0x%X\n",
  3085.                                     dataEntry->Size, dataEntry->OffsetToData);
  3086.  
  3087.                                 // For Version Info resources, we can extract more details
  3088.                                 if (type && wcscmp(type, L"Version") == 0) {
  3089.                                     auto versionData = (BYTE*)PEHelpers::GetRvaPtr(
  3090.                                         dataEntry->OffsetToData,
  3091.                                         IMAGE_FIRST_SECTION(pImageNtHeaders),
  3092.                                         pImageNtHeaders->FileHeader.NumberOfSections,
  3093.                                         lpFileContent);
  3094.  
  3095.                                     if (versionData && !IsBadReadPtr(versionData, sizeof(VS_FIXEDFILEINFO))) {
  3096.                                         auto versionInfo = (VS_FIXEDFILEINFO*)(versionData + 40); // Skip VS_VERSION_INFO header
  3097.                                         if (versionInfo->dwSignature == 0xFEEF04BD) {
  3098.                                             for (int indent = 0; indent < level + 2; indent++) {
  3099.                                                 OUTPUT("\t");
  3100.                                             }
  3101.                                             OUTPUT("File Version: %d.%d.%d.%d\n",
  3102.                                                 HIWORD(versionInfo->dwFileVersionMS),
  3103.                                                 LOWORD(versionInfo->dwFileVersionMS),
  3104.                                                 HIWORD(versionInfo->dwFileVersionLS),
  3105.                                                 LOWORD(versionInfo->dwFileVersionLS));
  3106.                                         }
  3107.                                     }
  3108.                                 }
  3109.                             }
  3110.                         }
  3111.                     }
  3112.                 };
  3113.  
  3114.                 ProcessResourceDirectory(pResourceDir, 0);
  3115.             }
  3116.             else {
  3117.                 OUTPUT("[-] Invalid or corrupted resource directory\n");
  3118.             }
  3119.         }
  3120.  
  3121.         ShowProgress(90);
  3122.  
  3123.         // Debug Directory Analysis
  3124.         const auto& debugDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  3125.         if (debugDir.VirtualAddress && debugDir.Size) {
  3126.             OUTPUT("\n[+] DEBUG DIRECTORY\n");
  3127.             auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  3128.             PIMAGE_SECTION_HEADER pDebugSection = nullptr;
  3129.  
  3130.             // Find the section containing the debug directory
  3131.             for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  3132.                 if (debugDir.VirtualAddress >= pSection->VirtualAddress &&
  3133.                     debugDir.VirtualAddress < (pSection->VirtualAddress + pSection->Misc.VirtualSize)) {
  3134.                     pDebugSection = pSection;
  3135.                     break;
  3136.                 }
  3137.             }
  3138.  
  3139.             if (!pDebugSection) {
  3140.                 OUTPUT("[-] Could not find debug section\n");
  3141.             }
  3142.             else {
  3143.                 // Calculate the correct offset for both 32-bit and 64-bit PE files
  3144.                 DWORD debugDirOffset = pDebugSection->PointerToRawData +
  3145.                     (debugDir.VirtualAddress - pDebugSection->VirtualAddress);
  3146.  
  3147.                 auto pDebugDirectory = reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
  3148.                     (BYTE*)lpFileContent + debugDirOffset);
  3149.  
  3150.                 // Safely process debug entries
  3151.                 DWORD numEntries = min(debugDir.Size / sizeof(IMAGE_DEBUG_DIRECTORY), 16); // Limit entries to prevent overflow
  3152.  
  3153.                 for (DWORD i = 0; i < numEntries; i++) {
  3154.                     if (IsBadReadPtr(pDebugDirectory + i, sizeof(IMAGE_DEBUG_DIRECTORY))) {
  3155.                         OUTPUT("[-] Invalid debug directory entry detected\n");
  3156.                         break;
  3157.                     }
  3158.  
  3159.                     OUTPUT("\tCharacteristics: 0x%X\n", pDebugDirectory[i].Characteristics);
  3160.                     OUTPUT("\tTimeDateStamp: 0x%X\n", pDebugDirectory[i].TimeDateStamp);
  3161.                     OUTPUT("\tMajorVersion: %d\n", pDebugDirectory[i].MajorVersion);
  3162.                     OUTPUT("\tMinorVersion: %d\n", pDebugDirectory[i].MinorVersion);
  3163.                     OUTPUT("\tType: 0x%X", pDebugDirectory[i].Type);
  3164.  
  3165.                     // Process debug type
  3166.                     switch (pDebugDirectory[i].Type) {
  3167.                     case IMAGE_DEBUG_TYPE_COFF:
  3168.                         OUTPUT(" (COFF)\n"); break;
  3169.                     case IMAGE_DEBUG_TYPE_CODEVIEW:
  3170.                         OUTPUT(" (CodeView)\n"); break;
  3171.                     case IMAGE_DEBUG_TYPE_FPO:
  3172.                         OUTPUT(" (FPO)\n"); break;
  3173.                     case IMAGE_DEBUG_TYPE_MISC:
  3174.                         OUTPUT(" (Misc)\n"); break;
  3175.                     case IMAGE_DEBUG_TYPE_EXCEPTION:
  3176.                         OUTPUT(" (Exception)\n"); break;
  3177.                     default:
  3178.                         OUTPUT(" (Unknown)\n"); break;
  3179.                     }
  3180.  
  3181.                     OUTPUT("\tSizeOfData: 0x%X\n", pDebugDirectory[i].SizeOfData);
  3182.                     OUTPUT("\tAddressOfRawData: 0x%X\n", pDebugDirectory[i].AddressOfRawData);
  3183.                     OUTPUT("\tPointerToRawData: 0x%X\n\n", pDebugDirectory[i].PointerToRawData);
  3184.  
  3185.                     // Process CodeView information if available
  3186.                     if (pDebugDirectory[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW &&
  3187.                         pDebugDirectory[i].PointerToRawData != 0 &&
  3188.                         pDebugDirectory[i].SizeOfData >= 24) { // Minimum size for CodeView data
  3189.  
  3190.                         auto pCVHeader = reinterpret_cast<DWORD*>(
  3191.                             (BYTE*)lpFileContent + pDebugDirectory[i].PointerToRawData);
  3192.  
  3193.                         if (!IsBadReadPtr(pCVHeader, sizeof(DWORD)) && *pCVHeader == 0x53445352) {
  3194.                             auto pCVData = reinterpret_cast<char*>(pCVHeader + 1);
  3195.                             if (!IsBadReadPtr(pCVData + 16, 1)) {
  3196.                                 std::vector<wchar_t> pdbPath(MAX_PATH);
  3197.                                 MultiByteToWideChar(CP_ACP, 0, pCVData + 16, -1,
  3198.                                     pdbPath.data(), MAX_PATH);
  3199.                                 OUTPUT("\tPDB Path: %s\n\n", pdbPath.data());
  3200.                             }
  3201.                         }
  3202.                     }
  3203.                 }
  3204.             }
  3205.         }
  3206.  
  3207.         // Continue with ShowProgress(100)...
  3208.  
  3209.         // In your AnalyzePEFile function, at the end:
  3210.         ShowProgress(100);
  3211.         SetStatusText(L"Analysis complete");
  3212.         ShowWindow(g_hProgressBar, SW_HIDE);  // Optional: hide progress bar when done
  3213.  
  3214.     cleanup:
  3215.         if (lpFileContent) {
  3216.             UnmapViewOfFile(lpFileContent);
  3217.         }
  3218.         if (hFileMapping) {
  3219.             CloseHandle(hFileMapping);
  3220.         }
  3221.         if (hFile) {
  3222.             CloseHandle(hFile);
  3223.         }
  3224.  
  3225.         UpdateEditControl();
  3226. }*/
  3227.  
  3228. /*
  3229. //use below vv ALWAYS
  3230. void AnalyzePEFile(const wchar_t* filePathW) {
  3231.     OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  3232.  
  3233.     LPVOID lpFileContent = GetFileContent(filePathW);
  3234.     if (!lpFileContent) {
  3235.         OUTPUT("[-] Failed to read file content!\n");
  3236.         return;
  3237.     }
  3238.  
  3239.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  3240.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  3241.         OUTPUT("[-] Invalid DOS signature!\n");
  3242.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3243.         return;
  3244.     }
  3245.  
  3246.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  3247.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  3248.         OUTPUT("[-] Invalid NT signature!\n");
  3249.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3250.         return;
  3251.     }
  3252.  
  3253.     //UpdateEditControl(); //added just now remove line!
  3254.  
  3255.     OUTPUT("[+] PE FILE HEADER\n");
  3256.     OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  3257.     OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  3258.     OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  3259.     OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  3260.     OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  3261.     OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  3262.     OUTPUT("\tCharacteristics : 0x%X %s\n\n", (uintptr_t)pImageNtHeaders->FileHeader.Characteristics, GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  3263.  
  3264.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  3265.     OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  3266.     OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  3267.     OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  3268.     OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  3269.     OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  3270.     OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  3271.     OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  3272.     OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  3273.     OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  3274.     OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  3275.     OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  3276.     OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  3277.     OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  3278.     OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  3279.     OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  3280.     OUTPUT("\tSubsystem : 0x%X %s\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem, GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  3281.     OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  3282.     OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  3283.     OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  3284.     OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  3285.     OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  3286.     OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  3287.     OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  3288.  
  3289.     //UpdateEditControl(); //added just now remove line!
  3290.  
  3291.     GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  3292.  
  3293.     const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  3294.     const auto pImageImportSection = GetSections(pImageSectionHeader, pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  3295.  
  3296.     if (!pImageImportSection) {
  3297.         OUTPUT("[-] Error: Could not find import section!\n");
  3298.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3299.         return;
  3300.     }
  3301.  
  3302.     const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>((DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  3303.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  3304.         GetImports32(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  3305.     }
  3306.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
  3307.         GetImports64(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  3308.     }
  3309.     else {
  3310.         OUTPUT("[-] Unsupported architecture!\n");
  3311.     }
  3312.  
  3313.     HeapFree(GetProcessHeap(), 0, lpFileContent);
  3314.     UpdateEditControl();
  3315. }
  3316.  
  3317. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory) {
  3318.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  3319.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory) {
  3320.         if (pImageDataDirectory->VirtualAddress == 0) continue;
  3321.         OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->VirtualAddress);
  3322.         OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->Size);
  3323.     }
  3324. }
  3325.  
  3326. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader, int NumberOfSections, DWORD dImportAddress) {
  3327.     PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  3328.     OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  3329.     for (int i = 0; i < NumberOfSections; ++i) {
  3330.         const auto pCurrentSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  3331.         OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  3332.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  3333.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  3334.         OUTPUT("\t\tVirtualAddress : 0x%X\n", (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  3335.         OUTPUT("\t\tSizeOfRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  3336.         OUTPUT("\t\tPointerToRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  3337.         OUTPUT("\t\tCharacteristics : 0x%X %s\n", (uintptr_t)pCurrentSectionHeader->Characteristics, GetSectionProtection(pCurrentSectionHeader->Characteristics));
  3338.  
  3339.         if (dImportAddress >= pCurrentSectionHeader->VirtualAddress && dImportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize) {
  3340.             pImageImportHeader = pCurrentSectionHeader;
  3341.         }
  3342.     }
  3343.     return pImageImportHeader;
  3344. }
  3345.  
  3346. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  3347.     OUTPUT("\n[+] IMPORTED DLL\n");
  3348.     while (pImageImportDescriptor->Name != 0) {
  3349.         OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  3350.         if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  3351.             ++pImageImportDescriptor;
  3352.             continue;
  3353.         }
  3354.         auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA32>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  3355.         while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  3356.             const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  3357.             if (pImageImportByName) {
  3358.                 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  3359.             }
  3360.             pOriginalFirstThunk++;
  3361.         }
  3362.         pImageImportDescriptor++;
  3363.     }
  3364. }
  3365.  
  3366. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  3367.     OUTPUT("\n[+] IMPORTED DLL\n");
  3368.     while (pImageImportDescriptor->Name != 0) {
  3369.         OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  3370.         if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  3371.             ++pImageImportDescriptor;
  3372.             continue;
  3373.         }
  3374.         auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  3375.         while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  3376.             const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  3377.             if (pImageImportByName) {
  3378.                 OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  3379.             }
  3380.             pOriginalFirstThunk++;
  3381.         }
  3382.         pImageImportDescriptor++;
  3383.     }
  3384. }
  3385. //use above ^^ ALWAYS
  3386. */
  3387.  
  3388.  
  3389. /*
  3390. // older-orig-deprecated vv
  3391. // Main PE Analysis function
  3392. void AnalyzePEFile(const wchar_t* filePathW)
  3393. {
  3394.     //WCHAR filePathW[MAX_PATH];
  3395.     //MultiByteToWideChar(CP_ACP, 0, filePathA, -1, filePathW, MAX_PATH);
  3396.     OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  3397.     //AppendToOutput(L"[+] Starting PE Analysis for: %ls\n\n", filePathW);
  3398.  
  3399.     // Get file content
  3400.     LPVOID lpFileContent = GetFileContent(filePathW);
  3401.     if (!lpFileContent)
  3402.     {
  3403.         OUTPUT("[-] Failed to read file content!\n");
  3404.         return;
  3405.     }
  3406.  
  3407.     // Get DOS header
  3408.     const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  3409.     if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
  3410.     {
  3411.         OUTPUT("[-] Invalid DOS signature!\n");
  3412.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3413.         return;
  3414.     }
  3415.  
  3416.     // Get NT headers
  3417.     const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  3418.     if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
  3419.     {
  3420.         OUTPUT("[-] Invalid NT signature!\n");
  3421.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3422.         return;
  3423.     }
  3424.  
  3425.     // Display File Header information
  3426.     OUTPUT("[+] PE FILE HEADER\n");
  3427.     OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  3428.     OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  3429.     OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  3430.     OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  3431.     OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  3432.     OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  3433.     OUTPUT("\tCharacteristics : 0x%X %s\n\n",
  3434.         (uintptr_t)pImageNtHeaders->FileHeader.Characteristics,
  3435.         GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  3436.  
  3437.     // Display Optional Header information
  3438.     OUTPUT("[+] PE OPTIONAL HEADER\n");
  3439.     OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  3440.     OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  3441.     OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  3442.     OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  3443.     OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  3444.     OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  3445.     OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  3446.     OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  3447.     OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  3448.     OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  3449.     OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  3450.     OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  3451.     OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  3452.     OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  3453.     OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  3454.     OUTPUT("\tSubsystem : 0x%X %s\n",
  3455.         (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem,
  3456.         GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  3457.     OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  3458.     OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  3459.     OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  3460.     OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  3461.     OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  3462.     OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  3463.     OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  3464.  
  3465.     // Get Data Directories
  3466.     GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  3467.  
  3468.     // Get the import section
  3469.     const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
  3470.         (DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  3471.  
  3472.     const auto pImageImportSection = GetSections(
  3473.         pImageSectionHeader,
  3474.         pImageNtHeaders->FileHeader.NumberOfSections,
  3475.         pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  3476.  
  3477.     if (!pImageImportSection)
  3478.     {
  3479.         OUTPUT("[-] Error: Could not find import section!\n");
  3480.         HeapFree(GetProcessHeap(), 0, lpFileContent);
  3481.         return;
  3482.     }
  3483.  
  3484.     // Get imports based on architecture
  3485.     const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
  3486.         (DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  3487.  
  3488.     if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
  3489.     {
  3490.         GetImports32(
  3491.             pImageImportDescriptor,
  3492.             (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  3493.             pImageImportSection);
  3494.     }
  3495.     else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
  3496.     {
  3497.         GetImports64(
  3498.             pImageImportDescriptor,
  3499.             (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  3500.             pImageImportSection);
  3501.     }
  3502.     else
  3503.     {
  3504.         OUTPUT("[-] Unsupported architecture!\n");
  3505.     }
  3506.  
  3507.     // Cleanup
  3508.     HeapFree(GetProcessHeap(), 0, lpFileContent);
  3509.  
  3510.     // Update the GUI with the analysis results
  3511.     UpdateEditControl();
  3512. }
  3513.  
  3514. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory)
  3515. {
  3516.     OUTPUT("[+] PE DATA DIRECTORIES\n");
  3517.     for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory)
  3518.     {
  3519.         if (pImageDataDirectory->VirtualAddress == 0)
  3520.             continue;
  3521.  
  3522.         OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n",
  3523.             GetDataDirectoryName(i),
  3524.             (uintptr_t)pImageDataDirectory->VirtualAddress);
  3525.         OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n",
  3526.             GetDataDirectoryName(i),
  3527.             (uintptr_t)pImageDataDirectory->Size);
  3528.     }
  3529. }
  3530.  
  3531. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  3532.     int NumberOfSections, DWORD dImportAddress)
  3533. {
  3534.     PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  3535.  
  3536.     OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  3537.  
  3538.     for (int i = 0; i < NumberOfSections; ++i)
  3539.     {
  3540.         const auto pCurrentSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader +
  3541.             i * sizeof(IMAGE_SECTION_HEADER));
  3542.  
  3543.         OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  3544.         OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n",
  3545.             (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  3546.         OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n",
  3547.             (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  3548.         OUTPUT("\t\tVirtualAddress : 0x%X\n",
  3549.             (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  3550.         OUTPUT("\t\tSizeOfRawData : 0x%X\n",
  3551.             (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  3552.         OUTPUT("\t\tPointerToRawData : 0x%X\n",
  3553.             (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  3554.         OUTPUT("\t\tPointerToRelocations : 0x%X\n",
  3555.             (uintptr_t)pCurrentSectionHeader->PointerToRelocations);
  3556.         OUTPUT("\t\tPointerToLinenumbers : 0x%X\n",
  3557.             (uintptr_t)pCurrentSectionHeader->PointerToLinenumbers);
  3558.         OUTPUT("\t\tNumberOfRelocations : 0x%X\n",
  3559.             (uintptr_t)pCurrentSectionHeader->NumberOfRelocations);
  3560.         OUTPUT("\t\tNumberOfLinenumbers : 0x%X\n",
  3561.             (uintptr_t)pCurrentSectionHeader->NumberOfLinenumbers);
  3562.         OUTPUT("\t\tCharacteristics : 0x%X %s\n",
  3563.             (uintptr_t)pCurrentSectionHeader->Characteristics,
  3564.             GetSectionProtection(pCurrentSectionHeader->Characteristics));
  3565.  
  3566.         if (dImportAddress >= pCurrentSectionHeader->VirtualAddress &&
  3567.             dImportAddress < pCurrentSectionHeader->VirtualAddress +
  3568.             pCurrentSectionHeader->Misc.VirtualSize)
  3569.         {
  3570.             pImageImportHeader = pCurrentSectionHeader;
  3571.         }
  3572.     }
  3573.  
  3574.     return pImageImportHeader;
  3575. }
  3576. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  3577.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  3578. {
  3579.     OUTPUT("\n[+] IMPORTED DLL\n");
  3580.  
  3581.     while (pImageImportDescriptor->Name != 0)
  3582.     {
  3583.         OUTPUT("\n\tDLL NAME : %s\n",
  3584.             (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  3585.         OUTPUT("\tCharacteristics : 0x%X\n",
  3586.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  3587.         OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  3588.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  3589.         OUTPUT("\tTimeDateStamp : 0x%X\n",
  3590.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  3591.         OUTPUT("\tForwarderChain : 0x%X\n",
  3592.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  3593.         OUTPUT("\tFirstThunk : 0x%X\n",
  3594.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  3595.  
  3596.         if (pImageImportDescriptor->OriginalFirstThunk == 0)
  3597.         {
  3598.             ++pImageImportDescriptor;
  3599.             continue;
  3600.         }
  3601.  
  3602.         auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA32)(dRawOffset +
  3603.             (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  3604.  
  3605.         OUTPUT("\n\tImported Functions : \n\n");
  3606.  
  3607.         while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  3608.         {
  3609.             if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG32)
  3610.             {
  3611.                 ++pOriginalFirstThrunk;
  3612.                 continue;
  3613.             }
  3614.  
  3615.             const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(dRawOffset +
  3616.                 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  3617.  
  3618.             if (pImageImportByName == nullptr)
  3619.             {
  3620.                 ++pOriginalFirstThrunk;
  3621.                 continue;
  3622.             }
  3623.  
  3624.             if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
  3625.             {
  3626.                 OUTPUT("\t\t0x%X (Ordinal) : %s\n",
  3627.                     (uintptr_t)pOriginalFirstThrunk->u1.AddressOfData,
  3628.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  3629.             }
  3630.             else
  3631.             {
  3632.                 OUTPUT("\t\t%s\n",
  3633.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  3634.             }
  3635.  
  3636.             ++pOriginalFirstThrunk;
  3637.         }
  3638.  
  3639.         ++pImageImportDescriptor;
  3640.     }
  3641. }
  3642.  
  3643. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  3644.     DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  3645. {
  3646.     OUTPUT("\n[+] IMPORTED DLL\n");
  3647.  
  3648.     while (pImageImportDescriptor->Name != 0)
  3649.     {
  3650.         OUTPUT("\n\tDLL NAME : %s\n",
  3651.             (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  3652.         OUTPUT("\tCharacteristics : 0x%X\n",
  3653.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  3654.         OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  3655.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  3656.         OUTPUT("\tTimeDateStamp : 0x%X\n",
  3657.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  3658.         OUTPUT("\tForwarderChain : 0x%X\n",
  3659.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  3660.         OUTPUT("\tFirstThunk : 0x%X\n",
  3661.             (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  3662.  
  3663.         if (pImageImportDescriptor->OriginalFirstThunk == 0)
  3664.         {
  3665.             ++pImageImportDescriptor;
  3666.             continue;
  3667.         }
  3668.  
  3669.         auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA64)(dRawOffset +
  3670.             (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  3671.  
  3672.         OUTPUT("\n\tImported Functions : \n\n");
  3673.  
  3674.         while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  3675.         {
  3676.             if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG64)
  3677.             {
  3678.                 ++pOriginalFirstThrunk;
  3679.                 continue;
  3680.             }
  3681.  
  3682.             const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dRawOffset +
  3683.                 (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  3684.  
  3685.             if (pImageImportByName == nullptr)
  3686.             {
  3687.                 ++pOriginalFirstThrunk;
  3688.                 continue;
  3689.             }
  3690.  
  3691.             if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
  3692.             {
  3693.                 OUTPUT("\t\t0x%llX (Ordinal) : %s\n",
  3694.                     pOriginalFirstThrunk->u1.AddressOfData,
  3695.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  3696.             }
  3697.             else
  3698.             {
  3699.                 OUTPUT("\t\t%s\n",
  3700.                     (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  3701.             }
  3702.  
  3703.             ++pOriginalFirstThrunk;
  3704.         }
  3705.  
  3706.         ++pImageImportDescriptor;
  3707.     }
  3708. }
  3709. // older-orig-deprecated ^^
  3710. */
  3711.  
  3712. //filePathW
  3713. //lpFilePath
  3714.     HANDLE GetFileContent(const wchar_t* lpFilePath) {
  3715.         HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  3716.         if (hFile == INVALID_HANDLE_VALUE) return nullptr;
  3717.         DWORD fileSize = GetFileSize(hFile, nullptr);
  3718.         auto lpFileContent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileSize);
  3719.         DWORD bytesRead;
  3720.         ReadFile(hFile, lpFileContent, fileSize, &bytesRead, nullptr);
  3721.         CloseHandle(hFile);
  3722.         return lpFileContent;
  3723.     }
  3724.  
  3725.     void UpdateEditControl() {
  3726.         SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  3727.         SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  3728.         SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  3729.     }
Add Comment
Please, Sign In to add comment