Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
zig-pe — Reflective PE loader written in Zig. Loads and executes native and .NET PE files directly from memory. | Kitploit
Tools/GitHubGitHub/thoxy67/zig-pe
ExploitationPost-ExploitationPenetration TestingRed TeamingPayload DevelopmentBinary Exploitation
GitHubthoxy67/zig-pe

zig-pe

Reflective PE loader written in Zig. Loads and executes native and .NET PE files directly from memory.

View Repository
6775 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

zig-pe

Reflective PE loader written in Zig. Loads and executes native and .NET PE files directly from memory.

Features

PE Loading Pipeline

  • Parse DOS and NT headers (PE32 and PE32+ at runtime)
  • Map sections into allocated memory
  • Resolve imports (name and ordinal, PE32 4-byte / PE32+ 8-byte thunks)
  • Apply base relocations (HIGHLOW, DIR64, ARM_MOV32, THUMB_MOV32)
  • Resolve delayed imports (DataDirectory[13], modern RVA format)
  • Register exception handlers (RtlAddFunctionTable, x64/ARM64 only)
  • Set per-section memory protections
  • Invoke TLS callbacks (DLL_PROCESS_ATTACH)
  • Execute entry point via CreateThread
  • Cleanup (unregister exception tables, free memory)

Advanced Security Features

  • Security Cookie Initialization (__security_cookie for /GS buffer security)
  • CFG (Control Flow Guard) - Registers valid call targets via SetProcessValidCallTargets
  • SxS / Activation Context - Activates embedded manifests for GUI applications
  • Bound Import Directory invalidation

Export Table Resolution

Utility functions for resolving exports from a loaded PE image:

  • getExportByName(base, ntheaders, name) — resolve by name
  • getExportByOrdinal(base, ntheaders, ordinal) — resolve by ordinal

Handles forwarded exports automatically by loading the target DLL (e.g., "NTDLL.RtlAllocateHeap" resolves to the actual function in ntdll.dll).

API Set Resolution

Automatically resolves Windows API sets (api-ms-win-*, ext-ms-win-*) to their actual host DLLs using the PEB ApiSetMap. This enables loading PEs that import from virtual API set DLLs.

Utility Functions

  • utils.detect_platform(buffer) — Detect if PE is 32-bit or 64-bit
  • utils.is_dotnet_assembly(ntheaders) — Check if PE is a .NET assembly
  • utils.getDotNetVersion(buffer) — Extract .NET runtime version string from metadata
  • utils.rvaToFileOffset(buffer, rva) — Convert RVA to raw file offset

Compatibility

  • Native compiled binary execution (x86, x86_64, ARM, ARM64)
  • .NET compiled binary execution via CLR hosting
  • Command-line argument passing to both native and .NET executables
  • Architecture validation (PE bitness must match host process)

Supported Machine Types

Prerequisites

  • Zig compiler (latest version recommended)
  • Windows OS (the project uses Windows-specific APIs)

Building the Project

  1. Clone the repository:

    root@kitploit:~
    git clone https://github.com/Thoxy67/zig-pe.git
    cd zig-pe
    
  2. Build the project:

    root@kitploit:~
    zig build
    

Build Options

root@kitploit:~
zig build -Ddotnet=false  # Disable .NET support (enabled by default)

Build Targets

root@kitploit:~
zig build                 # Build all targets
zig build run-putty64     # Run 64-bit native PE example
zig build run-putty32     # Run 32-bit native PE example
zig build run-dotnet      # Run .NET assembly example
zig build test            # Run unit tests

Usage

Basic Usage (Embedded PE)

root@kitploit:~
const pe = @import("pe");

pub fn main() !void {
    // Load and execute an embedded PE file
    try pe.RunPE.init(@embedFile("bin/app.exe")).run();
}

With Command-Line Arguments

root@kitploit:~
const pe = @import("pe");

pub fn main() !void {
    var loader = pe.RunPE.init(@embedFile("bin/app.exe"));
    try loader.runWithArgs(&.{ "arg1", "arg2", "arg3" });
}

Loading from File

root@kitploit:~
const std = @import("std");
const pe = @import("pe");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const file_content = try std.fs.cwd().readFileAlloc(
        allocator,
        "path/to/executable.exe",
        std.math.maxInt(usize),
    );
    defer allocator.free(file_content);

    try pe.RunPE.init(file_content).run();
}

Resolving Exports from Loaded PE

root@kitploit:~
const pe = @import("pe");

// After loading a DLL into memory...
const base: [*]const u8 = @ptrCast(loaded_base);
const ntheaders = // ... get NT headers

// Resolve by name
if (pe.getExportByName(base, ntheaders, "ExportedFunction")) |func_ptr| {
    const func: *const fn () void = @ptrCast(@alignCast(func_ptr));
    func();
}

// Resolve by ordinal
if (pe.getExportByOrdinal(base, ntheaders, 42)) |func_ptr| {
    // Use the function pointer
}

How Argument Passing Works

  • Native PEs: Arguments are passed by patching the PEB CommandLine, so GetCommandLineW() returns the provided arguments
  • .NET Assemblies: Arguments are passed directly to Main(string[] args) via CLR invocation

Security Considerations

This project involves loading and executing arbitrary code, which can be potentially dangerous. Use this loader only with trusted PE files and in controlled environments. The authors are not responsible for any misuse or damage caused by this software.

Contributing

Contributions to zig-pe are welcome! Please feel free to submit pull requests, create issues or spread the word.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • The Zig programming language community
  • Contributors to PE file format documentation

Disclaimer

This project is for educational purposes only. Ensure you have the necessary rights and permissions before loading and executing any PE file.

Download Tool
ArchitectureMachine CodeBitness
i3860x014c32-bit
AMD640x866464-bit
IA640x020064-bit
ARM (ARMNT)0x01C432-bit
ARM640xAA6464-bit