Advertisement
alien_fx_fiend

PE-Explorer (GUI-based PE Header Parser) Bugs-Fixed! *FINAL RELEASE*

Nov 26th, 2024 (edited)
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 45.97 KB | Source Code | 0 0
  1. ==++Here's the full source code for (file 1/1) "main.cpp"::++=
  2. #define STRICT
  3. #define WIN32_LEAN_AND_MEAN
  4. #include <Windows.h>
  5. #include <winternl.h>
  6. #include <CommCtrl.h>
  7. #include <commdlg.h>
  8. #include <string>
  9. #include <strsafe.h>
  10. #include <sstream>
  11. #include <iomanip>
  12. #include <stdio.h>
  13. #include <vector>
  14. //#include "helpers.h"
  15. #include "resource.h"
  16. #pragma comment(lib, "comctl32.lib")
  17.  
  18. namespace PEHelpers {
  19.    std::wstring GetImageCharacteristics(DWORD characteristics) {
  20.        if (characteristics & IMAGE_FILE_DLL) return L"(DLL)";
  21.        if (characteristics & IMAGE_FILE_SYSTEM) return L"(DRIVER)";
  22.        if (characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) return L"(EXE)";
  23.        return L"(UNKNOWN)";
  24.    }
  25.  
  26.    std::wstring GetSubsystem(WORD subsystem) {
  27.        switch (subsystem) {
  28.        case IMAGE_SUBSYSTEM_NATIVE: return L"(NATIVE/DRIVER)";
  29.        case IMAGE_SUBSYSTEM_WINDOWS_GUI: return L"(GUI)";
  30.        case IMAGE_SUBSYSTEM_WINDOWS_CUI: return L"(CONSOLE)";
  31.        default: return L"(UNKNOWN)";
  32.        }
  33.    }
  34.  
  35.    std::wstring GetDataDirectoryName(int DirectoryNumber) {
  36.        switch (DirectoryNumber) {
  37.        case 0: return L"Export Table";
  38.        case 1: return L"Import Table";
  39.        case 2: return L"Resource Table";
  40.        case 3: return L"Exception Entry";
  41.        case 4: return L"Security Entry";
  42.        case 5: return L"Relocation Table";
  43.        case 6: return L"Debug Entry";
  44.        case 7: return L"Copyright Entry";
  45.        case 8: return L"Global PTR Entry";
  46.        case 9: return L"TLS Entry";
  47.        case 10: return L"Configuration Entry";
  48.        case 11: return L"Bound Import Entry";
  49.        case 12: return L"IAT";
  50.        case 13: return L"Delay Import Descriptor";
  51.        case 14: return L"COM Descriptor";
  52.        default: return L"Unknown";
  53.        }
  54.    }
  55.  
  56.    std::wstring GetSectionProtection(DWORD characteristics) {
  57.        std::wstring protection = L"(";
  58.        bool needsSeparator = false;
  59.  
  60.        if (characteristics & IMAGE_SCN_MEM_EXECUTE) {
  61.            protection += L"EXECUTE";
  62.            needsSeparator = true;
  63.        }
  64.  
  65.        if (characteristics & IMAGE_SCN_MEM_READ) {
  66.            if (needsSeparator) protection += L" | ";
  67.            protection += L"READ";
  68.            needsSeparator = true;
  69.        }
  70.  
  71.        if (characteristics & IMAGE_SCN_MEM_WRITE) {
  72.            if (needsSeparator) protection += L" | ";
  73.            protection += L"WRITE";
  74.        }
  75.  
  76.        protection += L")";
  77.        return protection;
  78.    }
  79. }
  80.  
  81. using namespace std;
  82.  
  83. // At the top of your file, change the window class name to wide string
  84. #define WINDOW_CLASS_NAME L"PEAnalyzerWindow"
  85. //const wchar_t* const WINDOW_CLASS_NAME = L"PEAnalyzerWindow";
  86.  
  87. // Use ANSI versions explicitly
  88. //#undef CreateWindow
  89. //#undef CreateWindowEx
  90. //#define CreateWindow  CreateWindowW
  91. //#define CreateWindowEx CreateWindowExW
  92.  
  93. // Helper function to replace printf with GUI output
  94. #define OUTPUT(format, ...) AppendToOutput(L##format, ##__VA_ARGS__)
  95. //#define OUTPUT(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  96. //#define printf(format, ...) AppendToOutput(format, ##__VA_ARGS__)
  97.  
  98. // Window dimensions
  99. #define WINDOW_WIDTH    1024
  100. #define WINDOW_HEIGHT   768
  101. #define EDIT_MARGIN    10
  102.  
  103. // Global variables
  104. HWND g_hMainWindow = NULL;
  105. HWND g_hEditControl = NULL;
  106. HFONT g_hFont = NULL;
  107. std::wstringstream g_OutputText;
  108. WCHAR filePathW[MAX_PATH];
  109. std::vector<wchar_t> g_OutputBuffer;
  110. std::wstring tempBuffer; // Declare tempBuffer globally
  111.  
  112. // Function declarations
  113. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  114. void CreateMainWindow(HINSTANCE hInstance);
  115. void InitializeControls(HWND hwnd);
  116. void AddMenus(HWND hwnd);
  117. void OpenFileDialog(HWND hwnd);
  118. //void AnalyzePEFile(const WCHAR* filePathW);
  119. void AnalyzePEFile(const wchar_t* filePathW);
  120. HANDLE GetFileContent(const wchar_t* lpFilePath);
  121. /*void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory);
  122. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  123.    int NumberOfSections, DWORD dImportAddress);
  124. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  125.    DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);
  126. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  127.    DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection);*/
  128. void AppendToOutput(const wchar_t* format, ...);
  129. void UpdateEditControl();
  130.  
  131. // Main window class name
  132. //const char* const WINDOW_CLASS_NAME = "PEAnalyzerWindow";
  133.  
  134. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  135.    INITCOMMONCONTROLSEX icc = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
  136.    InitCommonControlsEx(&icc);
  137.  
  138.    CreateMainWindow(hInstance);
  139.    if (!g_hMainWindow) return -1;
  140.  
  141.    ShowWindow(g_hMainWindow, nCmdShow);
  142.    UpdateWindow(g_hMainWindow);
  143.  
  144.    MSG msg = {};
  145.    while (GetMessage(&msg, NULL, 0, 0)) {
  146.        TranslateMessage(&msg);
  147.        DispatchMessage(&msg);
  148.    }
  149.  
  150.    if (g_hFont) DeleteObject(g_hFont);
  151.    return (int)msg.wParam;
  152. }
  153.  
  154. void CreateMainWindow(HINSTANCE hInstance) {
  155.    WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), 0, WindowProc, 0, 0, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, WINDOW_CLASS_NAME, NULL };
  156.    RegisterClassExW(&wc);
  157.    g_hMainWindow = CreateWindowExW(0, WINDOW_CLASS_NAME, L"PE File Analyzer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, nullptr, nullptr, hInstance, nullptr);
  158. }
  159.  
  160. void InitializeControls(HWND hwnd) {
  161.    g_hEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, EDIT_MARGIN, EDIT_MARGIN, WINDOW_WIDTH - (2 * EDIT_MARGIN), WINDOW_HEIGHT - (2 * EDIT_MARGIN), hwnd, nullptr, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), nullptr);
  162.    g_hFont = CreateFont(-14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, L"Consolas");
  163.    if (g_hFont) SendMessage(g_hEditControl, WM_SETFONT, (WPARAM)g_hFont, TRUE);
  164. }
  165.  
  166. void AddMenus(HWND hwnd) {
  167.    HMENU hMenuBar = CreateMenu();
  168.    HMENU hFileMenu = CreateMenu();
  169.    AppendMenu(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
  170.    AppendMenu(hFileMenu, MF_STRING, 1, L"&Open");
  171.    AppendMenu(hFileMenu, MF_STRING, 2, L"E&xit");
  172.    SetMenu(hwnd, hMenuBar);
  173. }
  174.  
  175. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  176.    switch (uMsg) {
  177.    case WM_CREATE: InitializeControls(hwnd); AddMenus(hwnd); return 0;
  178.    case WM_SIZE: SetWindowPos(g_hEditControl, NULL, EDIT_MARGIN, EDIT_MARGIN, LOWORD(lParam) - (2 * EDIT_MARGIN), HIWORD(lParam) - (2 * EDIT_MARGIN), SWP_NOZORDER); return 0;
  179.    case WM_COMMAND: if (LOWORD(wParam) == 1) OpenFileDialog(hwnd); if (LOWORD(wParam) == 2) PostQuitMessage(0); return 0;
  180.    case WM_DESTROY: PostQuitMessage(0); return 0;
  181.    }
  182.    return DefWindowProc(hwnd, uMsg, wParam, lParam);
  183. }
  184.  
  185. void OpenFileDialog(HWND hwnd) {
  186.    WCHAR fileName[MAX_PATH] = L"";
  187.    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 };
  188.    if (GetOpenFileNameW(&ofn)) {
  189.        SetWindowTextW(g_hEditControl, L"");
  190.        g_OutputText.str(L"");
  191.        g_OutputText.clear();
  192.        AnalyzePEFile(ofn.lpstrFile);
  193.        UpdateEditControl();
  194.    }
  195. }
  196.  
  197. class FileMapper {
  198. private:
  199.    HANDLE hFile = INVALID_HANDLE_VALUE;
  200.    HANDLE hMapping = nullptr;
  201.    LPVOID lpView = nullptr;
  202.  
  203. public:
  204.    ~FileMapper() {
  205.        if (lpView) UnmapViewOfFile(lpView);
  206.        if (hMapping) CloseHandle(hMapping);
  207.        if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
  208.    }
  209.  
  210.    bool Initialize(const wchar_t* path) {
  211.        hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr,
  212.            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  213.        if (hFile == INVALID_HANDLE_VALUE) return false;
  214.  
  215.        hMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  216.        if (!hMapping) return false;
  217.  
  218.        lpView = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  219.        return lpView != nullptr;
  220.    }
  221.  
  222.    LPVOID GetView() const { return lpView; }
  223. };
  224.  
  225. // Modified AppendToOutput to handle newlines properly:
  226. void AppendToOutput(const wchar_t* format, ...) {
  227.    std::vector<wchar_t> buffer(1024);
  228.    va_list args;
  229.    va_start(args, format);
  230.  
  231.    while (true) {
  232.        int result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  233.        if (result >= 0) break;
  234.        buffer.resize(buffer.size() * 2);
  235.    }
  236.    va_end(args);
  237.  
  238.    // Convert \n to \r\n
  239.    std::wstring output = buffer.data();
  240.    size_t pos = 0;
  241.    while ((pos = output.find(L'\n', pos)) != std::wstring::npos) {
  242.        if (pos == 0 || output[pos - 1] != L'\r') {
  243.            output.insert(pos, L"\r");
  244.            pos += 2;
  245.        }
  246.        else {
  247.            pos++;
  248.        }
  249.    }
  250.  
  251.    g_OutputText << output;
  252.    UpdateEditControl();
  253. }
  254.  
  255. /*
  256. void AppendToOutput(const wchar_t* format, ...) {
  257.    wchar_t buffer[16384]; // Ensure sufficient buffer size
  258.    va_list args;
  259.    va_start(args, format);
  260.    StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  261.    va_end(args);
  262.  
  263.    tempBuffer += buffer;
  264.  
  265.    // Update Edit Control periodically to improve performance
  266.    if (tempBuffer.size() > 8000) {
  267.        g_OutputText << tempBuffer;
  268.        tempBuffer.clear();
  269.  
  270.        SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  271.        SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  272.        SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  273.    }
  274. }
  275.  
  276.  
  277. // Final update to flush any remaining content
  278. void FlushOutput() {
  279.    if (!tempBuffer.empty()) {
  280.        g_OutputText << tempBuffer;
  281.        tempBuffer.clear();
  282.  
  283.        SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  284.        SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  285.        SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  286.    }
  287. }
  288. */
  289.  
  290.  
  291. /*
  292. //use below ^^ ALWAYS
  293. void AppendToOutput(const wchar_t* format, ...) {
  294.    va_list args;
  295.    va_start(args, format);
  296.  
  297.    // Use a vector as a dynamically resizable buffer
  298.    std::vector<wchar_t> buffer(16384); // Start with an initial size
  299.    int result = -1;
  300.  
  301.    while (true) {
  302.        // Attempt to format the string
  303.        result = _vsnwprintf(buffer.data(), buffer.size(), format, args);
  304.  
  305.        if (result >= 0 && static_cast<size_t>(result) < buffer.size()) {
  306.            // Successfully formatted within the current buffer size
  307.            break;
  308.        }
  309.  
  310.        // Resize the buffer and try again
  311.        buffer.resize(buffer.size() * 2);
  312.    }
  313.    va_end(args);
  314.  
  315.    // Convert `\n` to `\r\n` for proper display in the EditBox
  316.    std::wstring formattedOutput(buffer.data());
  317.    size_t pos = 0;
  318.    while ((pos = formattedOutput.find(L'\n', pos)) != std::wstring::npos) {
  319.        formattedOutput.replace(pos, 1, L"\r\n");
  320.        pos += 2; // Move past the replacement
  321.    }
  322.  
  323.    // Append to the global output buffer
  324.    g_OutputText << formattedOutput;
  325.  
  326.    // Update the EditBox periodically to prevent overloading
  327.    if (g_OutputText.str().size() > 8000) {
  328.        SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  329.        SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  330.        SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  331.    }
  332. }
  333. //use above ^^ ALWAYS
  334. */
  335.  
  336. //currentlatest
  337. /*void AppendToOutput(const wchar_t* format, ...) {
  338.    wchar_t buffer[4096];
  339.    va_list args;
  340.    va_start(args, format);
  341.    StringCchVPrintfW(buffer, ARRAYSIZE(buffer), format, args);
  342.    va_end(args);
  343.    g_OutputText << buffer;
  344.    SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  345.    SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  346.    SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  347. }
  348. */
  349.  
  350. //use-below-basic-failsafe-working vv
  351. //basic test function
  352. /*void AnalyzePEFile(const wchar_t* filePathW) {
  353.    OUTPUT("[+] Analyzing file: %s\n", filePathW);
  354.    LPVOID lpFileContent = GetFileContent(filePathW);
  355.    if (!lpFileContent) { OUTPUT("[-] Could not read file.\n"); return; }
  356.    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileContent;
  357.    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { OUTPUT("[-] Invalid DOS signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  358.    PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpFileContent + dosHeader->e_lfanew);
  359.    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { OUTPUT("[-] Invalid NT signature.\n"); HeapFree(GetProcessHeap(), 0, lpFileContent); return; }
  360.    OUTPUT("[+] PE file analyzed successfully.\n");
  361.    HeapFree(GetProcessHeap(), 0, lpFileContent);
  362.    UpdateEditControl();
  363. }*/
  364. //use-above-basic-failsafe-working vv
  365.  
  366. //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
  367.  
  368. void AnalyzePEFile(const wchar_t* filePathW) {
  369.    OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  370.  
  371.    FileMapper mapper;
  372.    if (!mapper.Initialize(filePathW)) {
  373.        OUTPUT("[-] Failed to open file! Error: %d\r\n", GetLastError());
  374.        return;
  375.    }
  376.  
  377.    
  378.    // Open and read file
  379.    HANDLE hFile = CreateFileW(filePathW, GENERIC_READ, FILE_SHARE_READ, nullptr,
  380.        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  381.    if (hFile == INVALID_HANDLE_VALUE) {
  382.        OUTPUT("[-] Failed to open file! Error: %d\n", GetLastError());
  383.        return;
  384.    }
  385.  
  386.    DWORD fileSize = GetFileSize(hFile, nullptr);
  387.    if (fileSize == INVALID_FILE_SIZE) {
  388.        CloseHandle(hFile);
  389.        OUTPUT("[-] Failed to get file size! Error: %d\n", GetLastError());
  390.        return;
  391.    }
  392.  
  393.    HANDLE hFileMapping = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
  394.    if (!hFileMapping) {
  395.        CloseHandle(hFile);
  396.        OUTPUT("[-] Failed to create file mapping! Error: %d\n", GetLastError());
  397.        return;
  398.    }
  399.  
  400.    LPVOID lpFileContent = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  401.    if (!lpFileContent) {
  402.        CloseHandle(hFileMapping);
  403.        CloseHandle(hFile);
  404.        OUTPUT("[-] Failed to map view of file! Error: %d\n", GetLastError());
  405.        return;
  406.    }
  407.  
  408.    const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(mapper.GetView());
  409.    if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  410.        OUTPUT("[-] Invalid DOS signature!\r\n");
  411.        return;
  412.    }
  413.  
  414.    const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
  415.        static_cast<BYTE*>(mapper.GetView()) + pImageDosHeader->e_lfanew);
  416.    if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  417.        OUTPUT("[-] Invalid NT signature!\r\n");
  418.        return;
  419.    }
  420.  
  421.    // Print File Header Information
  422.    OUTPUT("[+] PE FILE HEADER\n");
  423.    OUTPUT("\tMachine: 0x%X\n", pImageNtHeaders->FileHeader.Machine);
  424.    OUTPUT("\tNumberOfSections: 0x%X\n", pImageNtHeaders->FileHeader.NumberOfSections);
  425.    OUTPUT("\tTimeDateStamp: 0x%X\n", pImageNtHeaders->FileHeader.TimeDateStamp);
  426.    OUTPUT("\tCharacteristics: 0x%X %s\n\n",
  427.        pImageNtHeaders->FileHeader.Characteristics,
  428.        PEHelpers::GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics).c_str());
  429.  
  430.    // Print Optional Header Information
  431.    OUTPUT("[+] PE OPTIONAL HEADER\n");
  432.    OUTPUT("\tMagic: 0x%X\n", pImageNtHeaders->OptionalHeader.Magic);
  433.    OUTPUT("\tAddressOfEntryPoint: 0x%X\n", pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  434.    OUTPUT("\tImageBase: 0x%llX\n", (ULONGLONG)pImageNtHeaders->OptionalHeader.ImageBase);
  435.    OUTPUT("\tSectionAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.SectionAlignment);
  436.    OUTPUT("\tFileAlignment: 0x%X\n", pImageNtHeaders->OptionalHeader.FileAlignment);
  437.    OUTPUT("\tSubsystem: 0x%X %s\n\n",
  438.        pImageNtHeaders->OptionalHeader.Subsystem,
  439.        PEHelpers::GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem).c_str());
  440.  
  441.    // Print Data Directories
  442.    OUTPUT("[+] PE DATA DIRECTORIES\n");
  443.    for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  444.        const auto& dir = pImageNtHeaders->OptionalHeader.DataDirectory[i];
  445.        if (dir.VirtualAddress != 0) {
  446.            OUTPUT("\t%s:\n", PEHelpers::GetDataDirectoryName(i).c_str());
  447.            OUTPUT("\t\tVirtualAddress: 0x%X\n", dir.VirtualAddress);
  448.            OUTPUT("\t\tSize: 0x%X\n", dir.Size);
  449.        }
  450.    }
  451.  
  452.    // Analyze Sections
  453.    OUTPUT("[+] PE SECTIONS\r\n");
  454.    auto pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  455.    for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  456.        // Create a null-terminated string from the section name
  457.        char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  458.        memcpy(sectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME);
  459.  
  460.        // Remove any non-printable characters
  461.        for (int j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
  462.            if (!isprint(static_cast<unsigned char>(sectionName[j]))) {
  463.                sectionName[j] = '\0';
  464.            }
  465.        }
  466.  
  467.        // Convert to wide string
  468.        wchar_t wideSectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {};
  469.        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  470.            sectionName, -1,
  471.            wideSectionName, IMAGE_SIZEOF_SHORT_NAME + 1);
  472.  
  473.        OUTPUT("\tSection: %s\r\n", wideSectionName);
  474.        OUTPUT("\t\tVirtualAddress: 0x%X\r\n", pSection->VirtualAddress);
  475.        OUTPUT("\t\tVirtualSize: 0x%X\r\n", pSection->Misc.VirtualSize);
  476.        OUTPUT("\t\tRawSize: 0x%X\r\n", pSection->SizeOfRawData);
  477.        OUTPUT("\t\tCharacteristics: 0x%X %s\r\n\r\n",
  478.            pSection->Characteristics,
  479.            PEHelpers::GetSectionProtection(pSection->Characteristics).c_str());
  480.    }
  481.  
  482.    // Analyze Imports
  483.    const auto& importDir = pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  484.    if (importDir.VirtualAddress && importDir.Size) {
  485.        OUTPUT("[+] IMPORTED DLLS AND FUNCTIONS\r\n");
  486.  
  487.        // Find the section containing imports
  488.        pSection = IMAGE_FIRST_SECTION(pImageNtHeaders);
  489.        for (WORD i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
  490.            if (importDir.VirtualAddress >= pSection->VirtualAddress &&
  491.                importDir.VirtualAddress < (pSection->VirtualAddress + pSection->Misc.VirtualSize)) {
  492.  
  493.                auto rva2offset = importDir.VirtualAddress - pSection->VirtualAddress;
  494.                auto pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)lpFileContent +
  495.                    pSection->PointerToRawData + rva2offset);
  496.  
  497.                // Process each DLL
  498.                while (pImportDesc->Name) {
  499.                    // Convert DLL name properly
  500.                    char* rawDllName = (char*)lpFileContent +
  501.                        pSection->PointerToRawData +
  502.                        (pImportDesc->Name - pSection->VirtualAddress);
  503.  
  504.                    // Convert to wide string
  505.                    size_t dllNameLen = strlen(rawDllName) + 1;
  506.                    std::vector<wchar_t> wideDllName(dllNameLen);
  507.                    MultiByteToWideChar(CP_ACP, 0, rawDllName, -1, wideDllName.data(), static_cast<int>(dllNameLen));
  508.  
  509.                    OUTPUT("\n\tDLL: %s\r\n", wideDllName.data());
  510.  
  511.                    // Process functions
  512.                            // Process functions
  513.                    if (pImportDesc->OriginalFirstThunk) {
  514.                        auto pThunk = (PIMAGE_THUNK_DATA)((BYTE*)lpFileContent +
  515.                            pSection->PointerToRawData +
  516.                            (pImportDesc->OriginalFirstThunk - pSection->VirtualAddress));
  517.  
  518.                        while (pThunk->u1.AddressOfData) {
  519.                            if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
  520.                                auto pImportByName = (PIMAGE_IMPORT_BY_NAME)((BYTE*)lpFileContent +
  521.                                    pSection->PointerToRawData +
  522.                                    (pThunk->u1.AddressOfData - pSection->VirtualAddress));
  523.  
  524.                                // Convert function name properly
  525.                                std::vector<wchar_t> wideFuncName(strlen((char*)pImportByName->Name) + 1);
  526.                                MultiByteToWideChar(CP_ACP, 0, (char*)pImportByName->Name, -1,
  527.                                    wideFuncName.data(), static_cast<int>(wideFuncName.size()));
  528.  
  529.                                OUTPUT("\t\tFunction: %s\r\n", wideFuncName.data());
  530.                            }
  531.                            pThunk++;
  532.                        }
  533.                    }
  534.                    pImportDesc++;
  535.                }
  536.                break;
  537.            }
  538.        }
  539.    }
  540.  
  541. cleanup:
  542.    if (lpFileContent) {
  543.        UnmapViewOfFile(lpFileContent);
  544.    }
  545.    if (hFileMapping) {
  546.        CloseHandle(hFileMapping);
  547.    }
  548.    if (hFile) {
  549.        CloseHandle(hFile);
  550.    }
  551.  
  552.    UpdateEditControl();
  553. }
  554.  
  555. /*
  556. //use below vv ALWAYS
  557. void AnalyzePEFile(const wchar_t* filePathW) {
  558.    OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  559.  
  560.    LPVOID lpFileContent = GetFileContent(filePathW);
  561.    if (!lpFileContent) {
  562.        OUTPUT("[-] Failed to read file content!\n");
  563.        return;
  564.    }
  565.  
  566.    const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  567.    if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  568.        OUTPUT("[-] Invalid DOS signature!\n");
  569.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  570.        return;
  571.    }
  572.  
  573.    const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  574.    if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
  575.        OUTPUT("[-] Invalid NT signature!\n");
  576.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  577.        return;
  578.    }
  579.  
  580.    //UpdateEditControl(); //added just now remove line!
  581.  
  582.    OUTPUT("[+] PE FILE HEADER\n");
  583.    OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  584.    OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  585.    OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  586.    OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  587.    OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  588.    OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  589.    OUTPUT("\tCharacteristics : 0x%X %s\n\n", (uintptr_t)pImageNtHeaders->FileHeader.Characteristics, GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  590.  
  591.    OUTPUT("[+] PE OPTIONAL HEADER\n");
  592.    OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  593.    OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  594.    OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  595.    OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  596.    OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  597.    OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  598.    OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  599.    OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  600.    OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  601.    OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  602.    OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  603.    OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  604.    OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  605.    OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  606.    OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  607.    OUTPUT("\tSubsystem : 0x%X %s\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem, GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  608.    OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  609.    OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  610.    OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  611.    OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  612.    OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  613.    OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  614.    OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  615.  
  616.    //UpdateEditControl(); //added just now remove line!
  617.  
  618.    GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  619.  
  620.    const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  621.    const auto pImageImportSection = GetSections(pImageSectionHeader, pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  622.  
  623.    if (!pImageImportSection) {
  624.        OUTPUT("[-] Error: Could not find import section!\n");
  625.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  626.        return;
  627.    }
  628.  
  629.    const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>((DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  630.    if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  631.        GetImports32(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  632.    }
  633.    else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
  634.        GetImports64(pImageImportDescriptor, (DWORD)lpFileContent + pImageImportSection->PointerToRawData, pImageImportSection);
  635.    }
  636.    else {
  637.        OUTPUT("[-] Unsupported architecture!\n");
  638.    }
  639.  
  640.    HeapFree(GetProcessHeap(), 0, lpFileContent);
  641.    UpdateEditControl();
  642. }
  643.  
  644. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory) {
  645.    OUTPUT("[+] PE DATA DIRECTORIES\n");
  646.    for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory) {
  647.        if (pImageDataDirectory->VirtualAddress == 0) continue;
  648.        OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->VirtualAddress);
  649.        OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n", GetDataDirectoryName(i), (uintptr_t)pImageDataDirectory->Size);
  650.    }
  651. }
  652.  
  653. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader, int NumberOfSections, DWORD dImportAddress) {
  654.    PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  655.    OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  656.    for (int i = 0; i < NumberOfSections; ++i) {
  657.        const auto pCurrentSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>((DWORD_PTR)pImageSectionHeader + i * sizeof(IMAGE_SECTION_HEADER));
  658.        OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  659.        OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  660.        OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n", (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  661.        OUTPUT("\t\tVirtualAddress : 0x%X\n", (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  662.        OUTPUT("\t\tSizeOfRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  663.        OUTPUT("\t\tPointerToRawData : 0x%X\n", (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  664.        OUTPUT("\t\tCharacteristics : 0x%X %s\n", (uintptr_t)pCurrentSectionHeader->Characteristics, GetSectionProtection(pCurrentSectionHeader->Characteristics));
  665.  
  666.        if (dImportAddress >= pCurrentSectionHeader->VirtualAddress && dImportAddress < pCurrentSectionHeader->VirtualAddress + pCurrentSectionHeader->Misc.VirtualSize) {
  667.            pImageImportHeader = pCurrentSectionHeader;
  668.        }
  669.    }
  670.    return pImageImportHeader;
  671. }
  672.  
  673. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  674.    OUTPUT("\n[+] IMPORTED DLL\n");
  675.    while (pImageImportDescriptor->Name != 0) {
  676.        OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  677.        if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  678.            ++pImageImportDescriptor;
  679.            continue;
  680.        }
  681.        auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA32>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  682.        while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  683.            const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  684.            if (pImageImportByName) {
  685.                OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  686.            }
  687.            pOriginalFirstThunk++;
  688.        }
  689.        pImageImportDescriptor++;
  690.    }
  691. }
  692.  
  693. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor, DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection) {
  694.    OUTPUT("\n[+] IMPORTED DLL\n");
  695.    while (pImageImportDescriptor->Name != 0) {
  696.        OUTPUT("\n\tDLL NAME : %s\n", (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  697.        if (pImageImportDescriptor->OriginalFirstThunk == 0) {
  698.            ++pImageImportDescriptor;
  699.            continue;
  700.        }
  701.        auto pOriginalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  702.        while (pOriginalFirstThunk->u1.AddressOfData != 0) {
  703.            const auto pImageImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(dRawOffset + (pOriginalFirstThunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  704.            if (pImageImportByName) {
  705.                OUTPUT("\t\tFunction: %s\n", (char*)pImageImportByName->Name);
  706.            }
  707.            pOriginalFirstThunk++;
  708.        }
  709.        pImageImportDescriptor++;
  710.    }
  711. }
  712. //use above ^^ ALWAYS
  713. */
  714.  
  715.  
  716. /*
  717. // older-orig-deprecated vv
  718. // Main PE Analysis function
  719. void AnalyzePEFile(const wchar_t* filePathW)
  720. {
  721.    //WCHAR filePathW[MAX_PATH];
  722.    //MultiByteToWideChar(CP_ACP, 0, filePathA, -1, filePathW, MAX_PATH);
  723.    OUTPUT("[+] Starting PE Analysis for: %s\n\n", filePathW);
  724.    //AppendToOutput(L"[+] Starting PE Analysis for: %ls\n\n", filePathW);
  725.  
  726.    // Get file content
  727.    LPVOID lpFileContent = GetFileContent(filePathW);
  728.    if (!lpFileContent)
  729.    {
  730.        OUTPUT("[-] Failed to read file content!\n");
  731.        return;
  732.    }
  733.  
  734.    // Get DOS header
  735.    const auto pImageDosHeader = static_cast<PIMAGE_DOS_HEADER>(lpFileContent);
  736.    if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
  737.    {
  738.        OUTPUT("[-] Invalid DOS signature!\n");
  739.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  740.        return;
  741.    }
  742.  
  743.    // Get NT headers
  744.    const auto pImageNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((DWORD_PTR)lpFileContent + pImageDosHeader->e_lfanew);
  745.    if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
  746.    {
  747.        OUTPUT("[-] Invalid NT signature!\n");
  748.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  749.        return;
  750.    }
  751.  
  752.    // Display File Header information
  753.    OUTPUT("[+] PE FILE HEADER\n");
  754.    OUTPUT("\tMachine : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.Machine);
  755.    OUTPUT("\tNumberOfSections : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSections);
  756.    OUTPUT("\tTimeDateStamp : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.TimeDateStamp);
  757.    OUTPUT("\tPointerToSymbolTable : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.PointerToSymbolTable);
  758.    OUTPUT("\tNumberOfSymbols : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.NumberOfSymbols);
  759.    OUTPUT("\tSizeOfOptionalHeader : 0x%X\n", (uintptr_t)pImageNtHeaders->FileHeader.SizeOfOptionalHeader);
  760.    OUTPUT("\tCharacteristics : 0x%X %s\n\n",
  761.        (uintptr_t)pImageNtHeaders->FileHeader.Characteristics,
  762.        GetImageCharacteristics(pImageNtHeaders->FileHeader.Characteristics));
  763.  
  764.    // Display Optional Header information
  765.    OUTPUT("[+] PE OPTIONAL HEADER\n");
  766.    OUTPUT("\tMagic : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Magic);
  767.    OUTPUT("\tAddressOfEntryPoint : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.AddressOfEntryPoint);
  768.    OUTPUT("\tImageBase : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.ImageBase);
  769.    OUTPUT("\tSectionAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SectionAlignment);
  770.    OUTPUT("\tFileAlignment : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.FileAlignment);
  771.    OUTPUT("\tMajorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorOperatingSystemVersion);
  772.    OUTPUT("\tMinorOperatingSystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorOperatingSystemVersion);
  773.    OUTPUT("\tMajorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorImageVersion);
  774.    OUTPUT("\tMinorImageVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorImageVersion);
  775.    OUTPUT("\tMajorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MajorSubsystemVersion);
  776.    OUTPUT("\tMinorSubsystemVersion : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.MinorSubsystemVersion);
  777.    OUTPUT("\tWin32VersionValue : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.Win32VersionValue);
  778.    OUTPUT("\tSizeOfImage : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfImage);
  779.    OUTPUT("\tSizeOfHeaders : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeaders);
  780.    OUTPUT("\tCheckSum : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.CheckSum);
  781.    OUTPUT("\tSubsystem : 0x%X %s\n",
  782.        (uintptr_t)pImageNtHeaders->OptionalHeader.Subsystem,
  783.        GetSubsystem(pImageNtHeaders->OptionalHeader.Subsystem));
  784.    OUTPUT("\tDllCharacteristics : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.DllCharacteristics);
  785.    OUTPUT("\tSizeOfStackReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackReserve);
  786.    OUTPUT("\tSizeOfStackCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfStackCommit);
  787.    OUTPUT("\tSizeOfHeapReserve : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapReserve);
  788.    OUTPUT("\tSizeOfHeapCommit : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.SizeOfHeapCommit);
  789.    OUTPUT("\tLoaderFlags : 0x%X\n", (uintptr_t)pImageNtHeaders->OptionalHeader.LoaderFlags);
  790.    OUTPUT("\tNumberOfRvaAndSizes : 0x%X\n\n", (uintptr_t)pImageNtHeaders->OptionalHeader.NumberOfRvaAndSizes);
  791.  
  792.    // Get Data Directories
  793.    GetDataDirectories(&pImageNtHeaders->OptionalHeader.DataDirectory[0]);
  794.  
  795.    // Get the import section
  796.    const auto pImageSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
  797.        (DWORD_PTR)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
  798.  
  799.    const auto pImageImportSection = GetSections(
  800.        pImageSectionHeader,
  801.        pImageNtHeaders->FileHeader.NumberOfSections,
  802.        pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
  803.  
  804.    if (!pImageImportSection)
  805.    {
  806.        OUTPUT("[-] Error: Could not find import section!\n");
  807.        HeapFree(GetProcessHeap(), 0, lpFileContent);
  808.        return;
  809.    }
  810.  
  811.    // Get imports based on architecture
  812.    const auto pImageImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
  813.        (DWORD_PTR)lpFileContent + pImageImportSection->PointerToRawData);
  814.  
  815.    if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
  816.    {
  817.        GetImports32(
  818.            pImageImportDescriptor,
  819.            (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  820.            pImageImportSection);
  821.    }
  822.    else if (pImageNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
  823.    {
  824.        GetImports64(
  825.            pImageImportDescriptor,
  826.            (DWORD)lpFileContent + pImageImportSection->PointerToRawData,
  827.            pImageImportSection);
  828.    }
  829.    else
  830.    {
  831.        OUTPUT("[-] Unsupported architecture!\n");
  832.    }
  833.  
  834.    // Cleanup
  835.    HeapFree(GetProcessHeap(), 0, lpFileContent);
  836.  
  837.    // Update the GUI with the analysis results
  838.    UpdateEditControl();
  839. }
  840.  
  841. void GetDataDirectories(PIMAGE_DATA_DIRECTORY pImageDataDirectory)
  842. {
  843.    OUTPUT("[+] PE DATA DIRECTORIES\n");
  844.    for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i, ++pImageDataDirectory)
  845.    {
  846.        if (pImageDataDirectory->VirtualAddress == 0)
  847.            continue;
  848.  
  849.        OUTPUT("\tDataDirectory (%s) VirtualAddress : 0x%X\n",
  850.            GetDataDirectoryName(i),
  851.            (uintptr_t)pImageDataDirectory->VirtualAddress);
  852.        OUTPUT("\tDataDirectory (%s) Size : 0x%X\n\n",
  853.            GetDataDirectoryName(i),
  854.            (uintptr_t)pImageDataDirectory->Size);
  855.    }
  856. }
  857.  
  858. PIMAGE_SECTION_HEADER GetSections(const PIMAGE_SECTION_HEADER pImageSectionHeader,
  859.    int NumberOfSections, DWORD dImportAddress)
  860. {
  861.    PIMAGE_SECTION_HEADER pImageImportHeader = nullptr;
  862.  
  863.    OUTPUT("\n[+] PE IMAGE SECTIONS\n");
  864.  
  865.    for (int i = 0; i < NumberOfSections; ++i)
  866.    {
  867.        const auto pCurrentSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageSectionHeader +
  868.            i * sizeof(IMAGE_SECTION_HEADER));
  869.  
  870.        OUTPUT("\n\tSECTION : %s\n", (wchar_t*)pCurrentSectionHeader->Name);
  871.        OUTPUT("\t\tMisc (PhysicalAddress) : 0x%X\n",
  872.            (uintptr_t)pCurrentSectionHeader->Misc.PhysicalAddress);
  873.        OUTPUT("\t\tMisc (VirtualSize) : 0x%X\n",
  874.            (uintptr_t)pCurrentSectionHeader->Misc.VirtualSize);
  875.        OUTPUT("\t\tVirtualAddress : 0x%X\n",
  876.            (uintptr_t)pCurrentSectionHeader->VirtualAddress);
  877.        OUTPUT("\t\tSizeOfRawData : 0x%X\n",
  878.            (uintptr_t)pCurrentSectionHeader->SizeOfRawData);
  879.        OUTPUT("\t\tPointerToRawData : 0x%X\n",
  880.            (uintptr_t)pCurrentSectionHeader->PointerToRawData);
  881.        OUTPUT("\t\tPointerToRelocations : 0x%X\n",
  882.            (uintptr_t)pCurrentSectionHeader->PointerToRelocations);
  883.        OUTPUT("\t\tPointerToLinenumbers : 0x%X\n",
  884.            (uintptr_t)pCurrentSectionHeader->PointerToLinenumbers);
  885.        OUTPUT("\t\tNumberOfRelocations : 0x%X\n",
  886.            (uintptr_t)pCurrentSectionHeader->NumberOfRelocations);
  887.        OUTPUT("\t\tNumberOfLinenumbers : 0x%X\n",
  888.            (uintptr_t)pCurrentSectionHeader->NumberOfLinenumbers);
  889.        OUTPUT("\t\tCharacteristics : 0x%X %s\n",
  890.            (uintptr_t)pCurrentSectionHeader->Characteristics,
  891.            GetSectionProtection(pCurrentSectionHeader->Characteristics));
  892.  
  893.        if (dImportAddress >= pCurrentSectionHeader->VirtualAddress &&
  894.            dImportAddress < pCurrentSectionHeader->VirtualAddress +
  895.            pCurrentSectionHeader->Misc.VirtualSize)
  896.        {
  897.            pImageImportHeader = pCurrentSectionHeader;
  898.        }
  899.    }
  900.  
  901.    return pImageImportHeader;
  902. }
  903. void GetImports32(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  904.    DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  905. {
  906.    OUTPUT("\n[+] IMPORTED DLL\n");
  907.  
  908.    while (pImageImportDescriptor->Name != 0)
  909.    {
  910.        OUTPUT("\n\tDLL NAME : %s\n",
  911.            (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  912.        OUTPUT("\tCharacteristics : 0x%X\n",
  913.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  914.        OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  915.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  916.        OUTPUT("\tTimeDateStamp : 0x%X\n",
  917.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  918.        OUTPUT("\tForwarderChain : 0x%X\n",
  919.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  920.        OUTPUT("\tFirstThunk : 0x%X\n",
  921.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  922.  
  923.        if (pImageImportDescriptor->OriginalFirstThunk == 0)
  924.        {
  925.            ++pImageImportDescriptor;
  926.            continue;
  927.        }
  928.  
  929.        auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA32)(dRawOffset +
  930.            (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  931.  
  932.        OUTPUT("\n\tImported Functions : \n\n");
  933.  
  934.        while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  935.        {
  936.            if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG32)
  937.            {
  938.                ++pOriginalFirstThrunk;
  939.                continue;
  940.            }
  941.  
  942.            const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(dRawOffset +
  943.                (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  944.  
  945.            if (pImageImportByName == nullptr)
  946.            {
  947.                ++pOriginalFirstThrunk;
  948.                continue;
  949.            }
  950.  
  951.            if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
  952.            {
  953.                OUTPUT("\t\t0x%X (Ordinal) : %s\n",
  954.                    (uintptr_t)pOriginalFirstThrunk->u1.AddressOfData,
  955.                    (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  956.            }
  957.            else
  958.            {
  959.                OUTPUT("\t\t%s\n",
  960.                    (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  961.            }
  962.  
  963.            ++pOriginalFirstThrunk;
  964.        }
  965.  
  966.        ++pImageImportDescriptor;
  967.    }
  968. }
  969.  
  970. void GetImports64(PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor,
  971.    DWORD dRawOffset, const PIMAGE_SECTION_HEADER pImageImportSection)
  972. {
  973.    OUTPUT("\n[+] IMPORTED DLL\n");
  974.  
  975.    while (pImageImportDescriptor->Name != 0)
  976.    {
  977.        OUTPUT("\n\tDLL NAME : %s\n",
  978.            (wchar_t*)(dRawOffset + (pImageImportDescriptor->Name - pImageImportSection->VirtualAddress)));
  979.        OUTPUT("\tCharacteristics : 0x%X\n",
  980.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->Characteristics - pImageImportSection->VirtualAddress)));
  981.        OUTPUT("\tOriginalFirstThunk : 0x%X\n",
  982.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress)));
  983.        OUTPUT("\tTimeDateStamp : 0x%X\n",
  984.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->TimeDateStamp - pImageImportSection->VirtualAddress)));
  985.        OUTPUT("\tForwarderChain : 0x%X\n",
  986.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->ForwarderChain - pImageImportSection->VirtualAddress)));
  987.        OUTPUT("\tFirstThunk : 0x%X\n",
  988.            (uintptr_t)(dRawOffset + (pImageImportDescriptor->FirstThunk - pImageImportSection->VirtualAddress)));
  989.  
  990.        if (pImageImportDescriptor->OriginalFirstThunk == 0)
  991.        {
  992.            ++pImageImportDescriptor;
  993.            continue;
  994.        }
  995.  
  996.        auto pOriginalFirstThrunk = (PIMAGE_THUNK_DATA64)(dRawOffset +
  997.            (pImageImportDescriptor->OriginalFirstThunk - pImageImportSection->VirtualAddress));
  998.  
  999.        OUTPUT("\n\tImported Functions : \n\n");
  1000.  
  1001.        while (pOriginalFirstThrunk->u1.AddressOfData != 0)
  1002.        {
  1003.            if (pOriginalFirstThrunk->u1.AddressOfData >= IMAGE_ORDINAL_FLAG64)
  1004.            {
  1005.                ++pOriginalFirstThrunk;
  1006.                continue;
  1007.            }
  1008.  
  1009.            const auto pImageImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dRawOffset +
  1010.                (pOriginalFirstThrunk->u1.AddressOfData - pImageImportSection->VirtualAddress));
  1011.  
  1012.            if (pImageImportByName == nullptr)
  1013.            {
  1014.                ++pOriginalFirstThrunk;
  1015.                continue;
  1016.            }
  1017.  
  1018.            if (pOriginalFirstThrunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
  1019.            {
  1020.                OUTPUT("\t\t0x%llX (Ordinal) : %s\n",
  1021.                    pOriginalFirstThrunk->u1.AddressOfData,
  1022.                    (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  1023.            }
  1024.            else
  1025.            {
  1026.                OUTPUT("\t\t%s\n",
  1027.                    (wchar_t*)((DWORD_PTR)dRawOffset + (pImageImportByName->Name - pImageImportSection->VirtualAddress)));
  1028.            }
  1029.  
  1030.            ++pOriginalFirstThrunk;
  1031.        }
  1032.  
  1033.        ++pImageImportDescriptor;
  1034.    }
  1035. }
  1036. // older-orig-deprecated ^^
  1037. */
  1038.  
  1039. //filePathW
  1040. //lpFilePath
  1041. HANDLE GetFileContent(const wchar_t* lpFilePath) {
  1042.    HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  1043.    if (hFile == INVALID_HANDLE_VALUE) return nullptr;
  1044.    DWORD fileSize = GetFileSize(hFile, nullptr);
  1045.    auto lpFileContent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileSize);
  1046.    DWORD bytesRead;
  1047.    ReadFile(hFile, lpFileContent, fileSize, &bytesRead, nullptr);
  1048.    CloseHandle(hFile);
  1049.    return lpFileContent;
  1050. }
  1051.  
  1052. void UpdateEditControl() {
  1053.    SetWindowTextW(g_hEditControl, g_OutputText.str().c_str());
  1054.    SendMessage(g_hEditControl, EM_SETSEL, -1, -1);
  1055.    SendMessage(g_hEditControl, EM_SCROLLCARET, 0, 0);
  1056. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement