Which entries in the dos header are necessary? - dos

I am writing a PE generator, I need to know which entries in the DOS header section are necessary for execution on NT based systems.
I checked some exes on my drive and most entries in the DOS header are 0 but I am not sure if this is the norm.

On an NT system the loader just checks for the magic numbers at the beginning MZ / 0x4d 0x5a and then the member e_lfanew to get the NT header offset.

Related

DOS stub in a PE file [duplicate]

This question already has an answer here:
What's this extra bytes?
(1 answer)
Closed 2 years ago.
Lately, I analyzed some Windows executable files using a hex editor. The PE header starts at address 0x100, so there are 256 Bytes of data before the PE image actually starts. The first 256 Bytes:
I know the following about the file structure
0x00 - 0x3F: This is the MZ header (64 bytes long).
0x40 - 0x4D: These 14 bytes encode seven x86 (16 bit mode) instructions, which are used to print "This program cannot run in DOS mode.\r\r\n" to the screen, using a DOS system call (interrupt 0x21).
0x4E - 0x78: This is the string "This program cannot run in DOS mode.\r\r\n" with a dollar-sign at the end, which tells DOS that this is the end of the string.
0x79 - 0x7F: These are NULL bytes; I guess that they are inserted for alignment.
So I know what the first 128 bytes are for. My question is: What are the next 128 bytes (0x80 - 0xFF) used for? (The PE image starts after them at 0x100.)
It's the so-called undocumented "Rich header". It's a weakly encrypted block of data inserted by the Microsoft linker that indicates what Microsoft tools were used to make the executable. It includes version information from the object files linked, so includes information on what compilers, assemblers and other tools were used.
To decode the Rich header search for the Rich marker and then obtain the 32-bit encryption key that follows. Then working backwards from the Rich marker, XOR the key with the 32-bit values stored there until you find a decoded DanS marker. In between these two markers will be a list of pairs of 32-bit values. The first value of the pair identifies the Microsoft tool used, and the second value indicates how many linked object files were created using this tool. The upper 16-bit part of the tool id value indicates what kind of tool it was, and the lower 16-bit part identifies the build version of the tool.

How would one restore missing PE headers?

I have a binary file which once was a valid PE executable, but all the headers were erased (DOS-header, PE-header and sections table). I managed to guess that one section is .text since if converted to asm in IDA it shows some valid asm code. .rdata was easy to find as well since it contains some strings which correspond to program's logic. But no further progress. I guess I'm not the first one to stumble upon this problem and there are tools/methods to generate PE headers. Any suggestions?
I think you will have some problem that you couldn't fix
the entry point ( where the binary begin)
the relocation (but you can fix the base adress to skip it)
the base adress (but in general it is always the same just need to know if it x86 or x64)
the library used it and the extern functions
perhaps the resourse for instance py2exe create a resource for the python bytecode
and last things bu certainly some other if you have a tls fls in the binary

Is the pointer to the PE-header at offset 0x3c in the PE-file always set to 0x80?

Is the pointer to the PE-header at offset 0x3c in the PE-file always set to 0x80?
I wonder why this pointer would change. I guess the DOS header and stub haven't changed, since they were first written.
The PE-header starts directly after these DOS artifacts, so is the PE-pointer always set to 0x80? If not, why?
Many programs have a Rich signature which is appended after the DOS stub, pushing the NT header down by a variable amount.
It's also completely possible to use a different DOS stub, or none at all. It doesn't have to print "This program cannot be run in DOS mode", you could put a small DOS game there, a harddisk wiper, print something entirely different, whatever you want.
You can even, if you're careful, overlap the NT header with the DOS header, and thus use an offset < 0x40. This isn't even too hard, because the only parts of the DOS header that matter are e_lfanew and "MZ", everything else can be whatever necessary to make the NT header work. You'd just have to align e_lfanew with a part of the NT header that can safely have that value.
no, PE-header at offset 0x3c - this is IMAGE_DOS_HEADER.e_lfanew which can be any value >= 0x40

Is there a safe way to identify MS-DOS executable?

I'm trying to identify and filter out all MS-DOS executables files out of executable files I have.
As far as I know, PE differ from MS-DOS by the headers he have which MS-DOS doesn't have, but for some reason some of the samples I have are recognized by TrID as MS-DOS even though they are PE.
I can't find any documentation on the subject, and I searched a lot.
Thanks!
The problem with identifying MS-DOS executables is that technically Windows PECOFF executables are also valid MS-DOS executables. PECOFF executables are prefixed with an "MS-DOS Stub", which is a complete MS-DOS program that in most executables prints a message like "This program cannot be run in DOS mode".
So the first thing to is do is to look at the MS-DOS executable header, and see if if it's valid. It looks like this (from Ralf Brown's Interrupt List):
00h 2 BYTEs .EXE signature, either "MZ" or "ZM" (5A4Dh or 4D5Ah)
(see also #01593)
02h WORD number of bytes in last 512-byte page of executable
04h WORD total number of 512-byte pages in executable (includes any
partial last page)
06h WORD number of relocation entries
08h WORD header size in paragraphs
0Ah WORD minimum paragraphs of memory required to allocate in addition
to executable's size
0Ch WORD maximum paragraphs to allocate in addition to executable's size
0Eh WORD initial SS relative to start of executable
10h WORD initial SP
12h WORD checksum (one's complement of sum of all words in executable)
14h DWORD initial CS:IP relative to start of executable
18h WORD offset within header of relocation table
40h or greater for new-format (NE,LE,LX,W3,PE,etc.) executable
1Ah WORD overlay number (normally 0000h = main program)
The key values to check are at offsets 00h and 18h. The two bytes at the start of the file, the signature, must be "MZ" or 54ADh. While "ZM" also works for MS-DOS program, Windows requires that PECOFF executables use the more common "MZ" signature. The next thing to check is the 16-bit value at offset 18h. It needs to be greater than or equal to 40h for this to be an PECOFF executable.
If the values at offsets 00h and 18h check out then the next thing to do is to read the 32-bit value at offset 3Ch. This contains the offset of the actual PECOFF header. You then need to check the header stars with the signature "PE\0\0", that is, the two characters "P" and "E", followed by two 0 bytes.
Note that its possible to find other letters at the location given at offset 3Ch, like "NE", "LE", "LX" which were used for 16-bit Windows executables, VxDs, and 32-bit OS/2 executables respectively. These other executable formats also have MS-DOS stubs and locate their real headers the same way.

Which of the MS-DOS header fields are mandatory/optional?

The above is the complete list of MS-DOS header fields, but I don't know which of them are mandatory and which are optional, does anyone know?
If you're trying to create PE Image, e_magic(Magic number) and elfanew(File address of new exe header) are the only mandatory fields that you have to fill in. elfanew should point to the PE IMAGE_NT_HEADER structure.
Well back in 2006 someone wanted to create the world most tiny PE. For this he wrote a small PE Fuzzer. With the smallest codebase posible.
return 42;
He managed to get the following sizes of PE's
you are too busy to read the entire page, here is a summary of the results:
Smallest possible PE file: 97 bytes
Smallest possible PE file on Windows 2000: 133 bytes
Smallest PE file that downloads a file over WebDAV and executes it: 133 bytes
You can check his work here:
http://www.phreedom.org/research/tinype/
He also states the required header values. These are:
e_magic
e_lfanew
Machine
NumberOfSections
SizeOfOptionalHeader
Characteristics
OptionalHeader:
Magic
AddressOfEntryPoint
ImageBase
SectionAlignment
FileAlignment
MajorSubsystemVersion
SizeOfImage
SizeOfHeaders
Subsystem
SizeOfStackCommit
SizeOfHeapReserve
For MS-DOS, all of the headers are mandatory.
For Win9x and above, e_lfanew must be the offset from the start of the image to the start of the IMAGE_NT_HEADERS, and e_magic must be IMAGE_DOS_SIGNATURE ('MZ').

Resources