alien_fx_fiend

Obtained Missing Code Needs Overall Debugging

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