Recent

Author Topic: PE Dump / PEDUMP / PE Viewer utility  (Read 11149 times)

440bx

  • Hero Member
  • *****
  • Posts: 3944
PE Dump / PEDUMP / PE Viewer utility
« on: September 03, 2019, 12:09:55 am »
UPDATE (November 2022)

The latest version of this utility, v1.30 is attached to the post
https://forum.lazarus.freepascal.org/index.php/topic,46617.msg459635.html#msg459635

This version supersedes all previous versions and is the preferred version. More information about it is provided in the above link.
END UPDATE



UPDATE (July 2022)

use the UPDATE (November 2022) above instead.

The latest version of this utility, v1.20 is attached to the post https://forum.lazarus.freepascal.org/index.php/topic,46617.msg448906.html#msg448906

This version supersedes all previous versions and is the preferred version. More information about it is provided in the above link.
END UPDATE



UPDATE (May, 2020):

use the UPDATE (November 2022) above instead.

The latest version of this utility, v1.10 is attached to the post https://forum.lazarus.freepascal.org/index.php/topic,46617.msg361962.html#msg361962
END UPDATE



UPDATE (March, 2020):

use the UPDATE (November 2022) above instead.

This is version 1.00

IF you want to dump PE files applicable to the ARM32 and ARM64 architecture then use version 1.02 found in a later post (not 1.01).  Note: the ARM32/64 has a few minor bugs that have _not_ been corrected.

version 1.02 is attached to the post https://forum.lazarus.freepascal.org/index.php/topic,46617.msg354933.html#msg354933
END UPDATE



Hello,

I decided to share one of my personal utilities.  This utility is a PE dump program that outputs the contents of a PE file (.exe, .dll and, various other extensions.)

I'll disappoint you upfront, source is _not_ included nor do I intend to make it available in the near future.

I originally wrote this utility in C because no existing PE file dump program provided the level of detail I needed. After getting somewhat familiar with FPC, I thought it would be a good and simple exercise to port it to Pascal, this is the result.

What follows is _not_ an explanation of the PE file structure, only a short explanation, for those interested, on of how to use the program and interpret its output.

1. to execute the program, simply type

PeBytesF <executable>

the program always dumps the entire PE file.  There are _no_ switches to control what is dumped, it always dumps _everything_.  Note that in some cases, though rare, the resulting dump can be as large as half a gigabyte.

The output is _very_ detailed.  The program inspects and identifies _every_ byte that is part of the PE specification.

In spite of that, it is reasonably quick. Outputting about 110,000 lines per second on an average machine, in most cases it executes in a few seconds but, in some cases, Chrome_child.dll being one of them, it can take anywhere between 20 to 30 seconds depending on how fast the machine is.

What follows are a few examples of its output and what it means.

Quote

     40.0000                - DOS HEADER -

     40.0000         0  [  2]                        DOS signature : 5a4d     (MZ)

     40.0002         2  [  2]           bytes on last page of file :   90     (   144)
     40.0004         4  [  2]                           page count :    3
     40.0006         6  [  2]                    relocations count :    0
     40.0008         8  [  2]         size of header in paragraphs :    4
     40.000a         a  [  2]      minimum extra paragraphs needed :    0
     40.000c         c  [  2]         maximum memory in paragraphs : ffff     (65,535)

     40.000e         e  [  2]                  initial relative SS :    0
     40.0010        10  [  2]                           initial SP :   b8
     40.0012        12  [  2]                             checksum :    0
     40.0014        14  [  2]                           initial IP :    0
     40.0016        16  [  2]                  initial relative CS :    0
In the above,

1. The first column is the virtual address where the field will be located in memory if the exe/dll is loaded at its preferred load address.

2. The second column is the field's file offset.  This file offset can be used to locate and edit the value of the field in a hex editor (one of the reasons I wrote this utility.)

3. The third column is the field size in bytes.  All fields that are "additional" information, that is, information _not present_ in the PE file are in brackets.

4. Columns 4 (label) and 5 (field value) are self explanatory.

5. values in parentheses are alternative interpretation of the previous column's value - usually simply showing a hex value in decimal but, as shown for the DOS signature, the alternative interpretation is a string in that particular case.

Note that the "DOS HEADER" title has a virtual address but _no_ file offset nor size.  This is to make it even more obvious that it is just a header and the text shown on that line is _not_ present in the PE file. 


Other formatting conventions
Quote
    40.0084                 - IMAGE_FILE_HEADER -

    40.0084        84  [2]                              Machine :      8664
    40.0084 +                          IMAGE_FILE_MACHINE_AMD64

    40.0086        86  [2]                   Number of sections :        11    (    17)

    40.0088        88  [4]                      Time Date Stamp : 5ad8.467e    (2018/04/19 7:34:22)

    40.008c        8c  [4]              Pointer to symbol table :  744.cc00
    40.0090        90  [4]                    Number of symbols :      c19e    (49,566)

    40.0094        94  [2]              Size of optional header :        f0    (   240)

    40.0096        96  [2]                      Characteristics :        27
    40.0096 +                        IMAGE_FILE_RELOCS_STRIPPED           1
    40.0096 +                       IMAGE_FILE_EXECUTABLE_IMAGE           2
    40.0096 +                     IMAGE_FILE_LINE_NUMS_STRIPPED           4
    40.0096 +                    IMAGE_FILE_LARGE_ADDRESS_AWARE          20
In the above,

1. If a field's value has a mnemonic, as is the case for the value of the "Machine" field, the mnemonic text _always_ appears _below_ it.

2. The "Characteristics" field is broken into its constituent bit fields and the mnemonics corresponding to each bit is _always_ on a separate line.

Note also that, the virtual address of each mnemonic is the same as that of the complete field.  To make it more evident that they are a "piece" of the field above them, each virtual address is followed by a "+" sign.  That indicates those lines are simply interpretations of the line above.

More formatting conventions,
Quote
     40.0098                 - IMAGE_OPTIONAL_HEADER -

     40.0098        98  [2]                                Magic :      20b
     40.0098 +                     IMAGE_NT_OPTIONAL_HDR64_MAGIC
...
...
     40.00a8        a8  [4]                      Entry point rva :     14e0    [Va:     40.14e0] [FO:      ae0] [   .text]
     40.00ac        ac  [4]                   Base of code (rva) :     1000    [Va:     40.1000] [FO:      600] [   .text]
In the above, note the following:

1. Every RVA (relative virtual address) is followed by 3 bracketed fields, the first is its equivalent virtual address, the second is the field's file offset that corresponds to that virtual address and the third is the name of the section that contains that virtual address.

In the above example, the hex value 14e0 corresponds to a virtual address of 40.14e0 and a file offset of ae0 which is found in the .text section.   This information is shown for every RVA found in the PE file and it is one of the reasons this program's output can occasionally be very large.

Similarly, some PE fields are VA (virtual addresses) instead of RVAs (as in the case of TLS callbacks), in those cases, the first field is the VA's equivalent RVA.

and more....
Quote
    40.02f0                SECTION: 10 of 17

    40.02f0       2f0  [8]                                 Name : /4
             752.6920  [15]                                       .debug_aranges

    40.02f8       2f8  [4]                         Virtual size :      85a0    (34,208)

    40.02fc       2fc  [4]           (Relative) Virtual address :   74.a000

    40.0300       300  [4]                     Size of raw data :      8600    (34,304)

    40.0304       304  [4]      File offset/pointer to raw data :   72.5000
    40.0308       308  [4]   File offset/pointer to relocations :         0
    40.030c       30c  [4]   File offset/pointer to linenumbers :         0

    40.0310       310  [2]                Number of relocations :         0
    40.0312       312  [2]                Number of linenumbers :         0

    40.0314       314  [4]                      Characteristics : 4250.0040
    40.0314 +                          SCN_CNT_INITIALIZED_DATA          40
    40.0314 +                                 SCN_ALIGN_16BYTES     5
    40.0314 +                               SCN_MEM_DISCARDABLE    200.0000
    40.0314 +                                      SCN_MEM_READ   4000.0000
In the above,

Note that the DWARF debug section name is shown under the "Name" field _but_ no virtual address is shown, only a file offset.  This indicates a value (in this case the name of the DWARF debug section) that is _not_ mapped by the Windows loader.  IOW, if a program wants to read that value, it will have to load that part of the file _itself_, which means, it will be loaded somewhere/anywhere in the virtual address space, thus making the value of the virtual address impossible to predict by just inspecting the PE file.

This occurs with debugging information and also with security certificates.


other important considerations:

Most PE files have a hint name table and an import address table.  Those tables, in the PE file, are usually but not always identical.  When the table are identical, this causes this program to output the Hint-Name fields twice.  Once for the Hint Name Table and a second time for the Import Address Table.

There are some exceptions, among them:

1. The Borland linker does not populate the hint name table.  As a result, for Borland executables, only an Import Address Table is shown.

2. If the executable is bound then the Import Address Table consists of virtual addresses instead of references to hint names.

The second case is very easy to recognize, it appears as follows:
Quote

  78ca.bc94             - IMPORTS DIRECTORY - number of import descriptors : 4

  78ca.bc94                 IMPORT descriptor :  1  -  Library : ntdll.dll

  78ca.bc94  8.a694  [ 4]            Hint name table :    8.bd10    [Va:   78ca.bd10] [FO: 8.a710] [  .rdata]

  78ca.bc98  8.a698  [ 4]            Time Date Stamp : ffff.ffff
  78ca.bc9c  8.a69c  [ 4]            Forwarder chain : ffff.ffff

  78ca.bca0  8.a6a0  [ 4]           Library name rva :    8.bd00    [Va:   78ca.bd00] [FO: 8.a700] [  .rdata]
  78ca.bd00  8.a700  [10]       Imports library name : ntdll.dll

  78ca.bca4  8.a6a4  [ 4]       Import address table :    8.2000    [Va:   78ca.2000] [FO: 8.0a00] [  .rdata]


  78ca.bd10                 HINT NAME TABLE      : 91 entries

  78ca.bd10  8.a710  [8]             8.c740    [Va:   78ca.c740] [FO: 8.b140] [  .rdata]
  78ca.c740                                                           8.b140  [ 2]        Hint: 34b
  78ca.c742                                                           8.b142  [12]        Name: RtlFreeHeap

  78ca.bd18  8.a718  [8]             8.c74e    [Va:   78ca.c74e] [FO: 8.b14e] [  .rdata]
  78ca.c74e                                                           8.b14e  [ 2]        Hint: 79f
  78ca.c750                                                           8.b150  [11]        Name: swprintf_s

  78ca.bd20  8.a720  [8]             8.c75c    [Va:   78ca.c75c] [FO: 8.b15c] [  .rdata]
  78ca.c75c                                                           8.b15c  [ 2]        Hint: 3a3
  78ca.c75e                                                           8.b15e  [21]        Name: RtlInitUnicodeString
...
...
more hint name table entries
...
...
   78ca.2000                 IMPORT ADDRESS TABLE : 91 entries

   78ca.2000  8.0a00  [8]          78ea.3200
   78ca.2008  8.0a08  [8]          78e9.7350
   78ca.2010  8.0a10  [8]          78ea.5280
   78ca.2018  8.0a18  [8]          78e9.15b0
   78ca.2020  8.0a20  [8]          78e7.7f70
   78ca.2028  8.0a28  [8]          78ea.1430
   78ca.2030  8.0a30  [8]          78ea.1400
   78ca.2038  8.0a38  [8]          78ea.1630
   78ca.2040  8.0a40  [8]          78ea.1480
   78ca.2048  8.0a48  [8]          78e7.6eac
   78ca.2050  8.0a50  [8]          78ed.f370
   78ca.2058  8.0a58  [8]          78ea.3000
   78ca.2060  8.0a60  [8]          78ea.2fc0
   78ca.2068  8.0a68  [8]          78ea.4d40
In the above, when both, the hint name table and the Import Address Table are present and the executable is not bound then, the tables will have the same information.  When the executable is bound, the Hint Name Table will point to Hint-Name pairs while the Import Address Table will contain pointers to where the functions they import are supposed to be found.

Since this post may be reaching the limit of what the forum software allows, additional information will continue in posts after this one.

Download and enjoy.

PS: I would like this program/utility to be available ONLY as an attachment to this post.  IOW, don't re-post it anywhere else.  Thank you.











« Last Edit: January 31, 2023, 12:09:38 pm by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: PE Dump utility
« Reply #1 on: September 03, 2019, 04:02:50 am »
it's a bit odd:
I decided to share one of my personal utilities.
...
PS: I would like this program/utility to be available ONLY as an attachment to this post.  IOW, don't re-post it anywhere else.  Thank you.

Overall, currently supplied (with fpc/lazarus) objdump.exe provides all the pieces of information.
Likely it didn't do when you started the tool, but these days...

objdump.exe has at least one advantage over your tool - it can be distributed :)
« Last Edit: September 03, 2019, 04:10:35 am by skalogryz »

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump utility
« Reply #2 on: September 03, 2019, 05:07:01 am »
it's a bit odd:
I decided to share one of my personal utilities.
...
PS: I would like this program/utility to be available ONLY as an attachment to this post.  IOW, don't re-post it anywhere else.  Thank you.
I don't see it as odd. My primary intention is to share it with FPC users.

Overall, currently supplied (with fpc/lazarus) objdump.exe provides all the pieces of information.
Likely it didn't do when you started the tool, but these days...
objdump does not come _remotely_ close to the level of detail this program outputs.  That said, objdump does dump the DWARF/stabs debug sections which this utility doesn't, it only outputs the COFF symbols if present.  For Windows PE files on x86 (32 and 64 bit), that is the _only_ feature objdump has over this program.  I didn't include it because I don't need it (never had to manually edit debug symbols.)

In addition to that, objdump is _very_ slow and, at the time of this writing, has a number of bugs.  Also, the output of objdump is very poorly formatted to the point of being close to  incomprehensible and, it cannot be used as a roadmap to edit a PE file, too much information missing (no file offsets, no field sizes, tables are not output in raw format, only "cooked", making it unusable for hex editing.)

objdump.exe has at least one advantage over your tool - it can be distributed :)
That much is true but, anyone who wants this tool can come get it here.

That said, while I expected the number of downloads to be quite low since it is a somewhat specialized utility, I am a little bit surprised that, as I write this, not even one download so far.  It surprises me that so few people are interested in understanding the internal format of their programs.

It's there for whoever wants it and wants to use it to find out what's in their PE files or, to learn about the PE format (x86, 32 and 64 bit only.)


« Last Edit: December 14, 2021, 04:05:39 am by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: PE Dump utility
« Reply #3 on: September 03, 2019, 05:44:32 am »
That said, while I expected the number of downloads to be quite low since it is a somewhat specialized utility, I am a little bit surprised that, as I write this, not even one download so far.  It surprises me that so few people are interested in understanding the internal format of their programs.
you've to wait for 24 hours before making any conclusions. FPC users are on a different time zones.

Besides that, can you name any FPC related utility that comes without sources? and/or cannot be freely distributed?

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump utility
« Reply #4 on: September 03, 2019, 06:12:23 am »
Besides that, can you name any FPC related utility that comes without sources? and/or cannot be freely distributed?
I readily concede those points.  My intention is to make the utility available to anyone who needs it, not to provide the source for it, which would open it to being "bastardized" and/or "cannibalized".

As far as its distribution, The main reason I don't want it distributed anywhere else is, because the copy attached to the forum post is the _only_ copy I can reasonably expect to be the original, unadulterated, copy.  IOW, it is a reasonable attempt to protect potential users and, for that protection to be effective, the potential user should get it from the first post's attachment.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: PE Dump utility
« Reply #5 on: September 03, 2019, 07:10:43 am »
As far as its distribution, The main reason I don't want it distributed anywhere else is, because the copy attached to the forum post is the _only_ copy I can reasonably expect to be the original, unadulterated, copy.  IOW, it is a reasonable attempt to protect potential users and, for that protection to be effective, the potential user should get it from the first post's attachment.
have you considered Code Signing?

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump utility
« Reply #6 on: September 03, 2019, 07:33:01 am »
have you considered Code Signing?
That's a reasonable suggestion.  In the case of this utility, I simply want to make it available, someone who downloads responsibly should simply get it from the first post in this thread, that's the "signing".
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: PE Dump / PEDUMP utility
« Reply #7 on: March 28, 2020, 01:55:26 pm »
I've finally gotten around to test this.

Just so you know: if I change the machine type of an AArch64 executable ($AA64) to $8664 and that of an ARM executable ($01C4 or $01C0) to $014C (both executables generated with Visual Studio) then your program correctly prints the contents of both executables except for the Exception dictionary (which is to be expected).  :-[

So in principle you could allow the use of your program for any machine type (because most of PE/COFF is "standardized" across all supported machine types), but disable certain dictionaries (mainly Exception and Relocation) for unknown architectures (because the ARM executable crashes your program in the Exception dictionary). This would already be a huge help for me. :)

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump / PEDUMP utility
« Reply #8 on: March 28, 2020, 02:15:46 pm »
So in principle you could allow the use of your program for any machine type (because most of PE/COFF is "standardized" across all supported machine types), but disable certain dictionaries (mainly Exception and Relocation) for unknown architectures (because the ARM executable crashes your program in the Exception dictionary). This would already be a huge help for me. :)
My biggest problem in allowing other architectures is that I don't have a good test suite for them.  That's the main reason I limited it to Intel/AMD architecture.

I can make a custom version for you that would process other architectures while disabling architecture specific features, such as outputting some image directories.  Be aware that if I do that, you're the tester.  One of the concerns I had with other architectures is endianness.  Any PE file file coming from a big endian architecture will probably yield a mess.

Also, in that case, I'd rely on you to let me know the  IMAGE_FILE_HEADER "Machine" id and IMAGE_OPTIONAL_HEADER "Magic" you'd like the program to accept.  One thing that would help me produce a version with the features you want, would be for you to post some sample (small, of course) executables you'd like the utility to process.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump / PEDUMP utility
« Reply #9 on: March 29, 2020, 04:27:43 am »
Attached to this post is a PEDUMP version of PeBytesF that accepts 32bit ARM PE files. 

UPDATE (March 2020):
This is version 1.01.  It only handles ARM32 PE files targeted at WinCE.  Version 1.02 below, can handle those and also dumps ARM64 PE files, thus it is preferable over this one.  Note: neither v1.01 nor v1.02 are well tested.
END UPDATE

At this time, it cannot dump/format the exceptions directory for those executables.  It detects the presence of the directory and outputs a line under the directory header informing that formatting that directory is not supported for that platform.

The interpretation of how relocations on the ARM platform should be formatted is completely untested.  However, the algorithm used to format the relocations for intel based executables _should_ produce a correct interpretation.

Overall, this version, unlike the version attached to the first post, is barely tested.
« Last Edit: March 31, 2020, 04:38:50 pm by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: PE Dump / PEDUMP utility
« Reply #10 on: March 29, 2020, 01:24:31 pm »
Thank you, however this will only work for WinCE binaries (Machine Type IMAGE_FILE_MACHINE_ARM = $01C0). What I need is Machine Type IMAGE_FILE_MACHINE_ARMNT ($01C4) and IMAGE_FILE_MACHINE_ARM64 ($AA64). I have attached an archive with a simple binary for each of the two targets (just in case you can't get VS to work ;) ).

And regarding Big Endian targets: Windows never worked on any big endian targets. Even PowerPC was used in Little Endian mode. But even then you should be able to check for the IMAGE_FILE_BYTES_REVERSED_HI/LO flag in the File header flags field which is supposed to be set for Big Endian images.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump / PEDUMP utility
« Reply #11 on: March 29, 2020, 01:35:03 pm »
I have attached an archive with a simple binary for each of the two targets (just in case you can't get VS to work ;) ).
Perfect!.  That's what I really needed. :)  Ignore my request for such files in my post in the other thread.


And regarding Big Endian targets: Windows never worked on any big endian targets.

Even PowerPC was used in Little Endian mode. But even then you should be able to check for the IMAGE_FILE_BYTES_REVERSED_HI/LO flag in the File header flags field which is supposed to be set for Big Endian images.
For some reason, writing code to reverse bytes makes watching paint dry sound exciting.
« Last Edit: March 29, 2020, 02:26:21 pm by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: PE Dump / PEDUMP utility
« Reply #12 on: March 29, 2020, 02:12:23 pm »
I have attached an archive with a simple binary for each of the two targets (just in case you can't get VS to work ;) ).
Perfect!.  That's what I really needed. :)  Ignore my request for such files in my post in the other thread.

And regarding Big Endian targets: Windows never worked on any big endian targets.

Windows NT and 2000 on Alpha, iirc. But yes, it has been a while. NT4 times, and beta's for W2000 at the most I think.
« Last Edit: March 29, 2020, 02:57:41 pm by marcov »

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: PE Dump / PEDUMP utility
« Reply #13 on: March 29, 2020, 02:36:24 pm »
UPDATE (March, 2020):
This is version 1.02.  It can handle PE files that v1.01 cannot.  Thus it is the version you want if you are interested in dumping ARM32 and/or ARM64 PE files.
END UPDATE

@PascalDragon,

Attached is a version that handles the additional machine types you mentioned.

One important thing: your Aarch64 test file showed that MS has added some more fields to the LOAD_CONFIG_DIRECTORY since I wrote my PE viewer.  I will find out what those are (as usual, their web site has not been updated to reflect the additional fields) and add them to the LOAD_CONFIG definition.  My consolation is, not even Dumpbin dumps it fully (at least not the version I have from VS2017.)  The result is that the LOAD_CONFIG record is truncated, the fields at the bottom are just not shown, at least the _size_ field is correct <chuckle>.

HTH.



« Last Edit: December 14, 2021, 04:07:57 am by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: PE Dump / PEDUMP utility
« Reply #14 on: March 30, 2020, 09:53:27 am »
Windows NT and 2000 on Alpha, iirc. But yes, it has been a while. NT4 times, and beta's for W2000 at the most I think.

Nope. As the Alpha was a Bi-Endian machine (like ARM, MIPS and PowerPC) Microsoft chose to run them in little endian mode. ;)

@PascalDragon,

Attached is a version that handles the additional machine types you mentioned.

Thank you! Will test that when I'm back home. :)

By the way: in case you're interested and bored here is an archive containing Alpha, MIPS and PowerPC binaries. ;)

 

TinyPortal © 2005-2018