{"id":19149219,"url":"https://github.com/hoshimin/formatpe","last_synced_at":"2025-04-07T10:27:42.604Z","repository":{"id":112688518,"uuid":"401487348","full_name":"HoShiMin/formatPE","owner":"HoShiMin","description":"A bunch of parsers for PE and PDB formats in C++","archived":false,"fork":false,"pushed_at":"2024-05-15T04:31:38.000Z","size":83,"stargazers_count":236,"open_issues_count":4,"forks_count":49,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-31T08:12:03.248Z","etag":null,"topics":["cpp","header-only","modern-cpp","pdb","pdb-files","pdb-parser","pdb-structure","pe","pe-analyzer","pe-applications","pe-file","pe-format","pe-parser","portable-executable"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HoShiMin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-30T21:11:22.000Z","updated_at":"2025-03-26T03:02:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"3d814fc1-7643-4141-854c-78ef545463a2","html_url":"https://github.com/HoShiMin/formatPE","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FformatPE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FformatPE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FformatPE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FformatPE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HoShiMin","download_url":"https://codeload.github.com/HoShiMin/formatPE/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247634688,"owners_count":20970584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","header-only","modern-cpp","pdb","pdb-files","pdb-parser","pdb-structure","pe","pe-analyzer","pe-applications","pe-file","pe-format","pe-parser","portable-executable"],"created_at":"2024-11-09T08:07:15.004Z","updated_at":"2025-04-07T10:27:42.568Z","avatar_url":"https://github.com/HoShiMin.png","language":"C++","readme":"# \u003cp align=\"center\"\u003e♟️ format\u003cb\u003ePE\u003c/b\u003e²\u003c/p\u003e  \n### \u003cp align=\"center\"\u003eA bunch of \u003cb\u003ePE\u003c/b\u003e and \u003cb\u003ePDB\u003c/b\u003e parsers written in C++\u003c/p\u003e\n### 💾 Pe:\nThis header-only library provides a convinient way to represent a PE-file as an enumerable object.  \n#### The library supports enumeration of:\n* Sections\n* Imports\n* Exports\n* Relocations\n* Exceptions\n* Bound- and delayed-imports\n* TLS-callbacks\n* Debug directory with support for CodeView PDB information\n\n#### Features:\n* Zero-alloc\n* Support for both x32 and x64 files regardless of the bitness of your process\n* Support for raw PE files from disk and for loaded images in memory\n* Kernelmode support\n* Extremely fast and lightweight\n* Only one header file\n* Simplicity in usage\n* Support for C++14 and above\n* Provides additional information and access to raw PE structures if you need more!\n\n#### Usage:\nJust include the **Pe/Pe.hpp** to your project!  \nFor the complete example of usage look at the [PeTests.cpp](https://github.com/HoShiMin/formatPE/blob/main/PeTests/PeTests.cpp).\n```cpp\n#include \u003cWindows.h\u003e\n#include \u003ccstdio\u003e\n\n#include \u003cPe/Pe.hpp\u003e\n\nint main()\n{\n    const auto hNtdll = GetModuleHandleW(L\"ntdll.dll\");\n\n    //\n    // Usage:\n    //   Pe::Pe[32|64|Native]::fromFile(fileContent)\n    //   Pe::Pe[32|64|Native]::fromModule(hModule)\n    //\n    // Pe::PeNative is an alias for Pe::Pe32 or Pe::Pe64\n    // depending on the current process bitness.\n    //\n\n    const auto pe = Pe::PeNative::fromModule(hNtdll);\n\n    // Iterating over exports:\n    printf(\"Exports:\\n\");\n    for (const auto\u0026 exp : pe.exports())\n    {\n        switch (exp.type())\n        {\n        case Pe::ExportType::exact:\n        {\n            printf(\"  %s at %p\\n\", exp.name(), exp.address());\n            break;\n        }\n        case Pe::ExportType::forwarder:\n        {\n            printf(\"  Forwarder: %s\\n\", exp.forwarder());\n            break;\n        }\n        }\n    }\n\n    // Find an exported function by name:\n    const auto fn = pe.exports().find(\"NtCreateSection\");\n    const void* const addr = fn.address();\n\n    return 0;\n}\n```\n---\n\n### 🗜️ Pdb:\nThis library provides a typed and convinient way to download and parse PDB files using the DbgHelp library.  \nIt distinguishes raw information from DbgHelp by tags and classifies it by predefined types.  \nIn other words, you always know which type you deal with - so, you can't parse a struct as a function or something like that.  \n#### It supports:\n* Downloading PDBs without **symsrv.dll**\n* Works with the **dbghelp.dll** supplied with the system in `C:\\Windows\\System32\\dbghelp.dll`\n* Does **not** require distribution of **dbghelp.dll** and **symsrv.dll** next to the application\n* Base types (`int`, `uint`, `int64`, `uint64`, `int128`, `uint128`, `float`, `double`)\n* User-defined types (UDT)\n* Structs\n* Classes and their parent classes\n* Unions\n* Interfaces\n* Pointers\n* Arrays\n* Function types, exact functions and their arguments\n* Enums\n* Bitfields\n* Constants\n* Static and dynamic members of classes and structs\n* Support for C++14 and above\n\n#### Usage:  \nInclude the **Pdb/Pdb.cpp** and the **Pdb/Pdb.h** to your project and (optionally) **SymLoader.cpp** and **SymLoader.h** if you want to download PDBs manually.\u003cbr\u003e\n\u003e ### Important!  \n\u003e You **must** have **dbghelp.dll** and **symsrv.dll** in the folder of your application  \n\u003e if you plan to download symbols automatically using the symbol path like:  \n\u003e `srv*C:\\Symbols*http://msdl.microsoft.com/download/symbols`\u003cbr\u003e\u003cbr\u003e\nYou can find these libraries in the folder of your SDK, for example:  \n`C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22000\\\\[x32|x64]\\`\u003cbr\u003e\u003cbr\u003e\n**But** there is a way to download PDBs **manually** using the **SymLoader** class.  \nIn this case you **don't need** to distribute **dbghelp.dll** and **symsrv.dll** with the library.\n\nFor the complete example of usage look at the [PeTests.cpp](https://github.com/HoShiMin/formatPE/blob/main/PeTests/PeTests.cpp).\n```cpp\n#include \u003cPdb/Pdb.hpp\u003e\n#include \u003cPdb/SymLoader.h\u003e // To download PDBs manually\n\nint main()\n{\n    const std::wstring exePath = L\"C:\\\\Windows\\\\System32\\\\ntoskrnl.exe\";\n    try\n    {\n        // Create the provider first: it initializes the DbgHelp engine:\n        Pdb::Prov prov;\n\n        // Obtain the PDB info associated with the binary:\n        const auto pdbInfo = prov.getPdbInfo(exePath.c_str());\n\n        // Use this PDB info to build a link to the file on a symbol server:\n        const auto url = std::wstring(Pdb::Prov::k_microsoftSymbolServerSecure)\n            + L\"/\" + pdbInfo.pdbUrl();\n\n        // Select the destination where to place downloaded PDB,\n        // the path will be created with all subfolders:\n        const std::wstring symFolder = L\"C:\\\\Symbols\\\\\";\n\n        // You can get more control over downloading:\n        // derivate from the Pdb::WinInetFileDownloader or from its superclass\n        // and override onStart, onReceive, onCancel, onError or onFinish -\n        // and you can get HTTP codes and data size.\n        Pdb::WinInetFileDownloader downloader((symFolder + pdbInfo.pdbPath()).c_str());\n        const bool downloadStatus = Pdb::SymLoader::download(url.c_str(), downloader);\n        if (!downloadStatus)\n        {\n            printf(\"Unable to download the PDB\");\n            return;\n        }\n\n        // The file was downloaded, set the search path to it for the dbghelp.dll:\n        prov.setSymPath(symFolder.c_str());\n\n        // Or you can skip all previous steps if you have\n        // both dbghelp.dll and symsrv.dll in the folder of your app.\n        // In this case dbghelp.dll will download symbols automatically.\n\n        // Now we can load the image and parse its data:\n        const Pdb::Mod mod(exePath.c_str());\n\n        // Let's dump _EPROCESS with all its fields:\n        const auto sym = mod.find(L\"_EPROCESS\").cast\u003cPdb::SymTypeStruct\u003e();\n        for (const auto child : sym.children())\n        {\n            if (child.equals\u003cPdb::SymDynamicMember\u003e())\n            {\n                const auto field = child.cast\u003cPdb::SymDynamicMember\u003e();\n                const auto name = field.name();\n                const auto type = field.type();\n                const auto bitfield = field.bitfield();\n                printf(\"[%u:%u], %u %ws %ws\\n\",\n                    bitfield.present, bitfield.pos,\n                    field.offset(),\n                    type.name().c_str(),\n                    name.c_str()\n                );\n            }\n        }\n    }\n    catch (const Pdb::BadCast\u0026 e)\n    {\n        printf(\"%ws\\n\", e.reason().c_str());\n    }\n    catch (const Pdb::NotInitialized\u0026 e)\n    {\n        printf(\"%ws\\n\", e.reason().c_str());\n    }\n    catch (const Pdb::DbgHelpFailure\u0026 e)\n    {\n        printf(\"%ws Error: 0x%X\\n\", e.reason().c_str(), e.error());\n    }\n    catch (const Pdb::SymNotFound\u0026 e)\n    {\n        printf(\"%ws\\n\", e.reason().c_str());\n    }\n\n    return 0;\n}\n```\n---\n### 🏗️ Build with CMake:\n\n```cmake\n# Link formatPE as dependency:\nadd_subdirectory(\"./formatPE/\")  # As subfolder\ntarget_link_libraries(\"TargetName\" PRIVATE \n    formatPE::Pe\n    formatPE::Pdb\n    formatPE::SymLoader\n)\n```\n\n\nOr:\n```cmake\n# Use an absolute path:\nset(formatPE_DIR \"/path/to/the/formatPE/directory/with/the/CMakeLists.txt/\")\n\nfind_package(formatPE REQUIRED) \n\ntarget_link_libraries(\"TargetName\" PRIVATE \n    formatPE::Pe\n    formatPE::Pdb\n    formatPE::SymLoader\n)\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Fformatpe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoshimin%2Fformatpe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Fformatpe/lists"}