How do you reliably extract appended data in a Portable Executable?

  • (I was asked in relation with this question)
    – Ange
    May 6, 2013 at 11:01

3 Answers 3


Just to clarify: the appended data - also called overlay - is the part of a PE file that is not covered by the header.

enter image description here

Because of some tricky conditions in the PE file format, it might be difficult to determine in some extreme case, so it's better to rely on a robust library such as pefile.

Here is a simple Python script that relies on pefile to extract the appended data:

import pefile
import sys

filename = sys.argv[1]
with open(filename, "rb") as s:
    r = s.read()

pe = pefile.PE(filename)
offset = pe.get_overlay_data_start_offset()

with open(filename + ".app", "wb") as t:

use with your filename as argument.

Personally, I usually do it with Hiew - as Hiew is faster to start than anything else, and also PE-robust:

  1. go at appended data start
    1. in Hex or ASM mode, press F8 to view PE header information
    2. Alt+F2 to go at appended data start
  2. select until the end
    1. Keypad-* to start selection
    2. Ctrl+End to go at bottom of the file
    3. Keypad-* again to finish selection
  3. F2 to write selection to file
  • 2
    You may want to skip an existing Authenticode signature as well.
    – 0xC0000022L
    May 6, 2013 at 13:53
  • no, the Authenticode signature must be last in the file or it will fail validation. You cannot (any more) append data after the signature. May 7, 2013 at 17:11
  • There could be a signature at the end of the appended data, so one might not want to select until the bottom of the file.
    – Ange
    May 7, 2013 at 18:40
  • 1
    if there is a signature then it'll be recorded in the data directory, so you have the start offset and size there, its pretty simple
    – evlncrn8
    Oct 11, 2014 at 22:50
  • asciinema.org/a/171993
    – evandrix
    Apr 7, 2021 at 0:11

It is not that hard to do manually.

  1. Find the PE header from the MZ header and determine the location of the section table.
  2. Walk the section table, and determine the maximum value of PointerToRawData + SizeOfRawData. (note: these values are subject to alignment using the FileAlignment member of the IMAGE_OPTIONAL_HEADER).

  3. Use the determined maximum as the file offset to the overlay data.

Note that some installers/file formats do not actually use this calculation, but they instead have a small trailer at the end of file which points to the beginning of the payload. For example, ZIP file format works like that - that's why a self-extracting ZIP can be extracted irregardless of whether the unpacker stub is PE, DOS MZ, ELF, Mach-O or anything else.

  • no, this is not sufficient. SizeOfRawData can have any value, even gigabytes large in a small file. It's bound by VirtualSize at that point. Accurately determining the end of the image is not trivial. May 6, 2013 at 19:13
  • @peterferrie What would be a good algorithm? I am actually trying to implement one. pefile does it roughly as suggested here. May 13, 2014 at 8:12
  • @Veitch, my answer to your other question now has sample code and a description, which should be what you need. May 13, 2014 at 22:35

Another option is the mewrev/pe Go package:

package main

import (

func main() {
   file, e := pe.Open("vs_BuildTools.exe")
   if e != nil {
   y, e := file.Overlay()
   if e != nil {
   ioutil.WriteFile("vs_BuildTools.overlay", y, os.ModePerm)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.