alien_fx_fiend

~*~ Proposed Changes Experimental ~*~

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