GithubHelp home page GithubHelp logo

formatpe's Introduction

♟️ formatPE²

A bunch of PE and PDB parsers written in C++

💾 Pe:

This header-only library provides a convinient way to represent a PE-file as an enumerable object.

The library supports enumeration of:

  • Sections
  • Imports
  • Exports
  • Relocations
  • Exceptions
  • Bound- and delayed-imports
  • TLS-callbacks
  • Debug directory with support for CodeView PDB information

Features:

  • Zero-alloc
  • Support for both x32 and x64 files regardless of the bitness of your process
  • Support for raw PE files from disk and for loaded images in memory
  • Kernelmode support
  • Extremely fast and lightweight
  • Only one header file
  • Simplicity in usage
  • Support for C++14 and above
  • Provides additional information and access to raw PE structures if you need more!

Usage:

Just include the Pe/Pe.hpp to your project!
For the complete example of usage look at the PeTests.cpp.

#include <Windows.h>
#include <cstdio>

#include <Pe/Pe.hpp>

int main()
{
    const auto hNtdll = GetModuleHandleW(L"ntdll.dll");

    //
    // Usage:
    //   Pe::Pe[32|64|Native]::fromFile(fileContent)
    //   Pe::Pe[32|64|Native]::fromModule(hModule)
    //
    // Pe::PeNative is an alias for Pe::Pe32 or Pe::Pe64
    // depending on the current process bitness.
    //

    const auto pe = Pe::PeNative::fromModule(hNtdll);

    // Iterating over exports:
    printf("Exports:\n");
    for (const auto& exp : pe.exports())
    {
        switch (exp.type())
        {
        case Pe::ExportType::exact:
        {
            printf("  %s at %p\n", exp.name(), exp.address());
            break;
        }
        case Pe::ExportType::forwarder:
        {
            printf("  Forwarder: %s\n", exp.forwarder());
            break;
        }
        }
    }

    // Find an exported function by name:
    const auto fn = pe.exports().find("NtCreateSection");
    const void* const addr = fn.address();

    return 0;
}

🗜️ Pdb:

This library provides a typed and convinient way to download and parse PDB files using the DbgHelp library.
It distinguishes raw information from DbgHelp by tags and classifies it by predefined types.
In other words, you always know which type you deal with - so, you can't parse a struct as a function or something like that.

It supports:

  • Downloading PDBs without symsrv.dll
  • Works with the dbghelp.dll supplied with the system in C:\Windows\System32\dbghelp.dll
  • Does not require distribution of dbghelp.dll and symsrv.dll next to the application
  • Base types (int, uint, int64, uint64, int128, uint128, float, double)
  • User-defined types (UDT)
  • Structs
  • Classes and their parent classes
  • Unions
  • Interfaces
  • Pointers
  • Arrays
  • Function types, exact functions and their arguments
  • Enums
  • Bitfields
  • Constants
  • Static and dynamic members of classes and structs
  • Support for C++14 and above

Usage:

Include 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.

Important!

You must have dbghelp.dll and symsrv.dll in the folder of your application
if you plan to download symbols automatically using the symbol path like:
srv*C:\Symbols*http://msdl.microsoft.com/download/symbols

You can find these libraries in the folder of your SDK, for example:
C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000\\[x32|x64]\

But there is a way to download PDBs manually using the SymLoader class.
In this case you don't need to distribute dbghelp.dll and symsrv.dll with the library.

For the complete example of usage look at the PeTests.cpp.

#include <Pdb/Pdb.hpp>
#include <Pdb/SymLoader.h> // To download PDBs manually

int main()
{
    const std::wstring exePath = L"C:\\Windows\\System32\\ntoskrnl.exe";
    try
    {
        // Create the provider first: it initializes the DbgHelp engine:
        Pdb::Prov prov;

        // Obtain the PDB info associated with the binary:
        const auto pdbInfo = prov.getPdbInfo(exePath.c_str());

        // Use this PDB info to build a link to the file on a symbol server:
        const auto url = std::wstring(Pdb::Prov::k_microsoftSymbolServerSecure)
            + L"/" + pdbInfo.pdbUrl();

        // Select the destination where to place downloaded PDB,
        // the path will be created with all subfolders:
        const std::wstring symFolder = L"C:\\Symbols\\";

        // You can get more control over downloading:
        // derivate from the Pdb::WinInetFileDownloader or from its superclass
        // and override onStart, onReceive, onCancel, onError or onFinish -
        // and you can get HTTP codes and data size.
        Pdb::WinInetFileDownloader downloader((symFolder + pdbInfo.pdbPath()).c_str());
        const bool downloadStatus = Pdb::SymLoader::download(url.c_str(), downloader);
        if (!downloadStatus)
        {
            printf("Unable to download the PDB");
            return;
        }

        // The file was downloaded, set the search path to it for the dbghelp.dll:
        prov.setSymPath(symFolder.c_str());

        // Or you can skip all previous steps if you have
        // both dbghelp.dll and symsrv.dll in the folder of your app.
        // In this case dbghelp.dll will download symbols automatically.

        // Now we can load the image and parse its data:
        const Pdb::Mod mod(exePath.c_str());

        // Let's dump _EPROCESS with all its fields:
        const auto sym = mod.find(L"_EPROCESS").cast<Pdb::SymTypeStruct>();
        for (const auto child : sym.children())
        {
            if (child.equals<Pdb::SymDynamicMember>())
            {
                const auto field = child.cast<Pdb::SymDynamicMember>();
                const auto name = field.name();
                const auto type = field.type();
                const auto bitfield = field.bitfield();
                printf("[%u:%u], %u %ws %ws\n",
                    bitfield.present, bitfield.pos,
                    field.offset(),
                    type.name().c_str(),
                    name.c_str()
                );
            }
        }
    }
    catch (const Pdb::BadCast& e)
    {
        printf("%ws\n", e.reason().c_str());
    }
    catch (const Pdb::NotInitialized& e)
    {
        printf("%ws\n", e.reason().c_str());
    }
    catch (const Pdb::DbgHelpFailure& e)
    {
        printf("%ws Error: 0x%X\n", e.reason().c_str(), e.error());
    }
    catch (const Pdb::SymNotFound& e)
    {
        printf("%ws\n", e.reason().c_str());
    }

    return 0;
}

formatpe's People

Contributors

hoshimin avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.