views:

459

answers:

6

What are the requirements of a PE file (PE/COFF)? What fields should be set, which value, at a bare minimum for enabling it to "run" on Windows (i.e. executing "ret" instruction and then close, without error).

The library I am building first is the linker: Now, the problem I have is the PE file (PE/COFF). I don't know what is "required" for a PE file before it can actually execute on my platform. My testing platform is Vista. I get an error message, saying "This is not a valid Win32 executable." when I execute it by double-clicking, and I get an "Access Denied." when executing it with CLI cmd. I have two sections, .text and .data.

I've implemented the PE headers as provided by several online documents, i.e. MSDN and some other thirdparty documentation. If I use a hex-editor, it looks almost like a regular PE file. I don't use any imports, nor IAT, nor any directories in the PE header.

Edit: I've added an import table, still not a valid .exe-file, says my Windows. I've tried to use values which are also mentioned at the smallest PE-file guide. No luck. Really the only thing I can't seem to figure out is what is required and what isn't. Some guides tell me everything is required, whilst others say about deprications: and it can be zero.

I hope this is enough information. Thank you, in advance.


Raw data (as requested) of current PE header:

4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 50 45 00 00 4C 01 02 00 C8 7A 55 4B 00 00 00 00 00 00 00 00 E0 00 82 01 0B 01 0D 25 00 10 00 00 00 10 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 20 00 00 00 00 40 00 00 10 00 00 00 02 00 00 01 00 0B 00 00 00 00 00 03 00 0A 00 00 00 00 00 00 22 00 00 38 01 00 00 00 00 00 00 03 00 00 00 00 40 00 00 00 40 00 00 00 40 00 00 00 40 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00 00 00 00 00 00 10 00 00 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 2E 69 64 61 74 61 00 00 00 00 00 00 00 20 00 00 00 02 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3C 20 00 00 00 00 00 00 00 00 00 00 24 20 00 00 34 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 00 00 00 01 00 00 80 00 00 00 00 01 00 00 80 00 00 00 00
A: 

The Microsoft PE/COFF spec is the only spec I know of.

Cheeso
A: 

I don't know if it is enforced, but your checksum should probably be computed and not left at 0.

GregS
It's only enforced for drivers, where if you try to load a driver with an invalid checksum, it refuses to load.
Daniel Goldberg
It's not enforced:"DWORD CheckSumSupposedly a CRC checksum of the file. As in other Microsoft executable formats, this field is ignored and set to 0. The one exception to this rule is for trusted services and these EXEs must have a valid checksum.", MSDN.Thanks anyway.
Pindatjuh
+1  A: 

This is a complete pain to copy paste into a hex editor, so unfortunately I cannot say anything too intelligent right off the bat.

Things to notice in a PE file: Make sure your DOS header is valid. Make sure the IMAGE_OPTIONAL_HEADER is properly formatted, because despite it's name, Windows does not really like it to not be done properly.

For further information, above and beyond the MS format, lookup pe.txt, one of the best homebrew guides to the PE format I know.

If you could post just the bytes, I could try putting it in my own PE parsers and see if I can help more.

Daniel Goldberg
I used that guide (as mentioned as "thirdparty") to build my implementation. I will update it right now, containing only the bytes.
Pindatjuh
Unfortunately, I have no idea what precisely is wrong. My first idea for checking this further is creating the same program using a known "correct" program (such as visual studio) and comparing the output using a hex editor.
Daniel Goldberg
I used `sed 's/\(....\) \(....\) /\1\2:/' | xxd -r` to turn OP's hexdump back into a binary.
ephemient
+2  A: 

This article about creating tiny PE executables might be of interest: in particular, it mentions that the Win2k loader needs KERNEL32.DLL to be imported, so that might be worth investigating.

Matthew Slattery
Yea, Windows 2000 needs an import table. But anyhow, I'm running Vista: somehow it doesn't recgocnize the format.
Pindatjuh
+1  A: 

You could try a book like .NET 2.0 IL Assembler. This book has a whole chapter devoted to what a PE format executable looks like (and what a .Net PE looks like).

You could also try loading your PE files with a PE File Reader and examining the results. If the PE reader struggles with your PE, then you have a pointer to what is failing.

Here is a PE File Reading DLL I wrote (with source). There is also a GUI (with source) that uses it.

The source is completely open source (not encumbered by the GPL) so you can do what you want with it (except impose a GPL on it, which would prevent it from being completely open), including take your version closed.

Stephen Kellett
Thank you! I think I can do something with this. I've ran the GUI that uses it, it tells me "File is corrupt", but since this is open-source I can figure out why!I'll accept this answer, this helped me much and indirectly answers (it leads to the solution!) my question.
Pindatjuh
I've completely rewritten all generation code from scratch; and this time it's still an invalid PE header, says windows.Then I load the PE file into your File Reader GUI, and it tells me the exact same error "File is corrupt!". No debug information, not a clue nor anything useful I can do with. How can I fix this?
Pindatjuh
I don;t know. I've never generated PE files, only written tools to read them. I'd start of by trying to write the simplest PE file you can - something with no sections (or one section, like a resource file). Get that working, then move on to more complicated PE files that have more sections, have relocation information etc.
Stephen Kellett
A: 

What you are attempting to do is dependent upon the version of Windows you are using. For example, the way PE files were read on Windows 2000 are not the same way that Windows 7 reads them. I'm an OSX user, but on the Windows 7 I have, I am unable to manipulate PE files in ways that would work on Windows 2000 and earlier. I haven't tested XP or Vista (or others between 2000 and Win7) to see when Windows started reading PE differently. On Windows 7, every single bit of memory in the MS-DOS header and stub is ignored. The only 2 pieces that matter are the "magic number" (a WORD that is equal to "MZ") and the PE Offset, which is a DWORD that defines the place in memory for the PE header begins. I'm not sure if Windows truly ignores all other values in the MS-DOS header and stub 100% of the time, but excluding the two I just mentioned, if all other values are set to 0, a valid executable program will function properly.

In Windows 2000 and earlier, I don't know if what I mentioned above was true, but you were at that time allowed to modify the length of the MS-DOS stub (or remove it perhaps), provided that the PE Offset value was still pointing to the correct place in memory to find the PE header. On Windows 7, if you modify the length of the MS-DOS stub at all, even when PE Offset points to the correct, modified location, Windows will not run the exe and claims it is not a valid Win32 application.

4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

This is the least the MS-DOS portion of a PE file can have on Windows 7 while still having a valid, functioning executable. That bit cannot be shortened.

Hope this clears some things up.

yegg
Thank for your response. It is correct what you stated. My problem is solved, and I've got the PE file to be "a valid Win32-executable". I used the utility in the VC++ Express Edition called "dumpbin"; it showed me that I used a wrong value inside the PE Optional Header, which was the total size of the image. Instead, I used the image-file size, but I should've used the image-memory size; which fixed the problem.
Pindatjuh