Home

Awesome

Windows PE File Tools for PHP

A command-line tool and a set of PHP classes to easily extract information, modify files, and even construct files from scratch in the Windows Portable Executable (PE) file format (i.e. EXEs, DLLs, etc).

Binary Files Tutorial:  The PE File Format & More video

The above video covers binary file structures and the PE file format binary structures. The end of the video briefly demonstrates using the command-line tools from this repository.

Donate Discord

Features

Use Cases

Getting Started

Download or clone this repository. PHP 7.x or later is required. 64-bit PHP 7.2 or later is recommended. Windows is recommended too (but not required). The PHP GD library is required for some parts of the WinPEUtils class.

When working with the PE file format for the first time ever, obtaining or building an artifact library containing samples of PE files to reference later with various tools is highly recommended (see "More Tools" below). This is especially true if building any software that interacts with the PE file format (e.g. a class like WinPEFile). Check out the curated Windows PE Artifact Library or build an artifact library with this command:

php pe_tools.php artifacts find C:\ "" Y 6

That command will use 6 CPU cores and scan all of the C: drive for executables under 15MB to construct an artifact library and JSON manifest. Rare artifacts are noted at the end of a scan. It takes approximately 15 minutes to scan 50,000 executable files (*.exe, *.dll, *.ocx, etc) across an entire system using a Core i7 with SSD drives. This process only needs to complete successfully one time and provides an excellent reference resource later on while working with PE files.

The pe_tools.php command-line application is question-answer enabled. Just running it will provide an interactive experience:

php pe_tools.php

Here's the full list of available commands that pe_tools.php supports:

artifacts:  Manage and find artifacts

  find:     Find interesting artifacts
  missing:  List missing artifacts
  origins:  Generate an origin text file for new artifact files


extract:  Extract information and binary data

  info:          Get detailed information about a PE file
  dos-stub:      Write the MS-DOS stub to a file
  sections:      Write raw image sections to files
  resources:     Write resources table items to files (icons, cursors, etc.)
  version-info:  Get version information from the PE file resources table
  certificates:  Write raw Authenticode certificates to files


calculate:  Perform various calculations

  rva:       Get information about a RVA in a PE file
  checksum:  Calculate the relevant checksum for a file
  hashes:    Calculate Authenticode-compatible PE hashes for a file


modify:  Perform various useful modifications

  clear-certs:          Remove Authenticode certificates
  clear-debug:          Remove debug directory
  clear-bound-imports:  Remove rare bound imports
  clear-checksums:      Clear MS-DOS and NE/PE checksums
  sanitize-dos-stub:    Apply a sanitized MS-DOS stub
  set-min-os:           Set the minimum OS version required
  set-min-subsystem:    Set the minimum OS subsystem version required
  set-app-icon:         Add or overwrite the application icon resource
  set-manifest:         Add or overwrite the application manifest resource
  set-version-info:     Add or overwrite the application version resource
  create-hook-dll:      Generate a hook DLL
  hook:                 Apply a hook DLL
  unhook:               Remove a hook DLL
  add-section:          Adds a new section
  expand-last-section:  Expand the last section
  delete-section:       Deletes a section
  apply-checksum:       Apply MS-DOS/NE/PE checksum

Example usage of the WinPEFile PHP class:

<?php
	require_once "support/win_pe_file.php";

	$srcfile = "peview.exe";

	// Validation is optional but saves loading the entire file into RAM if the file isn't valid.
	$result = WinPEFile::ValidateFile($srcfile);
	if (!$result["success"])
	{
		var_dump($result);

		exit();
	}

	// Parse the file.
	$data = file_get_contents($srcfile);

	$options = array();

	$winpe = new WinPEFile();
	$result = $winpe->Parse($data, $options);
	if (!$result["success"])
	{
		var_dump($result);

		exit();
	}

	// Sanitize the DOS stub.
	$result = $winpe->SanitizeDOSStub($data);
	if (!$result["success"])
	{
		var_dump($result);

		exit();
	}

	// Strip debug directory.
	$result = $winpe->ClearDebugDirectory($data);
	if (!$result["success"])
	{
		var_dump($result);

		exit();
	}

	// Strip Authenticode certificate(s).
	$result = $winpe->ClearCertificates($data);
	if (!$result["success"])
	{
		var_dump($result);

		exit();
	}

	// Update the checksum.
	$winpe->UpdateChecksum($data);

	// Write out the modified executable.
	file_put_contents("peview_modified.exe", $data);
?>

Additional examples can be found in the documentation for the various PHP classes. Also, the source code to pe_tools.php has plenty of working examples as well.

Documentation

Hooking Executables

Creating a functional hook DLL usually requires knowledge of the relevant Windows API(s) to hook, a C or C++ compiler, and a lot of patience. Your first hook DLLs will probably fail. A simple starting point is to hook something like CreateFileA() in kernel32.dll and have it write out each file being opened by the application to a log file. Don't forget to pass the original call onto the intended function and don't get stuck in an infinite loop!

Of course, once the hook DLL is created, applying said hook DLL to an existing PE file comes with all kinds of caveats. Detours by Microsoft Research and EasyHook are two popular options to develop and apply a hook DLL and both options are certainly useful. Both tools modify the Import Address Table (IAT) of the EXE and loaded DLLs during runtime so that the hooks are always correctly installed into all IATs.

The WinPEUtils class and pe_tools.php take a different, far more unique approach: Automatically create a brand new, carefully named DLL from scratch that uses either real export forwarding (NT only) or simulated export forwarding (for Win9x/Me compatibility) to point at the correct DLL and function. Then apply the newly generated DLL by replacing all of the references to the original file inside the original executable (e.g. replace the string "kernel32.dll" with "12xiasoa.dll"). Of note, the name for the new DLL is the same length as the original DLL name. If all goes well, the application remains largely unaware that it has had some of its functions redirected elsewhere by abusing the Windows loader. Undoing a hook is as simple as replacing a few strings.

Example usage:

php pe_tools.php modify create-hook-dll C:\Windows\System32\kernel32.dll myhook.dll .\hooktest\ N
php pe_tools.php modify hook .\path\to\myapp.exe "" kernel32.dll .\hooktest\in8rej1f.dll
php pe_tools.php modify apply-checksum .\path\to\myapp.exe ""

php pe_tools.php modify unhook .\path\to\myapp.exe "" kernel32.dll in8rej1f.dll
php pe_tools.php modify apply-checksum .\path\to\myapp.exe ""

The first command above creates the hook DLL and generates a randomly named file in the destination directory (e.g. 'in8rej1f.dll'). The second command applies the hook DLL and imported DLLs to the specified executable, replacing references to 'kernel32.dll' with 'in8rej1f.dll'. The Windows loader will load 'in8rej1f.dll' instead of 'kernel32.dll'. The 'in8rej1f.dll' file contains export forwards to the original DLLs, with the hooked functions taking priority. The third command updates the PE checksum so it is valid, which is not required but still a good idea.

The fourth and fifth commands undo the changes to the application.

More Tools

When working with the PE file format for the first time, you will need tools. Lots of weird, esoteric tools that only run on Windows (and sometimes Wine).