Monday, March 12, 2007

Tiny (and crazy) PE

I did prepare a couple of new graphics for the last training I taught with Pedram in BlackHat DC.

One of them was to illustrate a bit the structure of the header mess that leads to the small footprint of the executables in Solar Eclipse's solution to the Tiny PE challenge.

I think it's a good example of how flexible and tolerant the Windows loader is and why loading PE files is something that tends to break most tools when a file pushes the limits.

I'll comment on some of the slides on this post without going into too much detail on how or why things work, that's well explained in Solar Eclipse's page. The general format is the same I use when doing the walk-through of the PE format's main headers in a sane file in order to illustrate how the headers are laid out on the file itself.

The red zeros in the following pictures mean data beyond the file size. That data is zeroed by Windows when the file is mapped in memory and Tiny PE relies on those zeros being there, as windows will try to access data in memory at that location, beyond the end of the file. If the memory wasn't zeroed first and contained random data it would be much harder to cook up the headers in the current "compressed" layout.

This first shot just shows the DOS header and the e_lfanew field. Which points to the the start of the NT headers.



The e_lfanew field contains 4, which is the offset within the file where the NT headers can be found. That's in the middle of what would otherwise be the DOS header. In the shot of NT headers we can see some of its fields.



The NT headers contain the File and Optional headers, the next picture shows some of the fields constituting the Optional header.



As the last entry in the Optional Header one can find the array of data directories.



Now, the loader would need to locate the section headers. These normally follow after the directories of the Optional header. But in this case, as it's illustrated in the following picture, they lay in what would be the middle of the Optional Header. The location of the section headers is calculated by adding the size of the Optional header (4) to its offset (0x1C). Amusingly enough, the Windows loader does not take into account the reported size of the optional header when it reads the header itself, but it does in order to find what follows.



And here are the fields of the section header...



I haven't taken the time to illustrate the import directory and the couple of additional details missing (It's just left as an exercise of mental contortion for the reader...). The original text by Solar Eclipse provides with the rest of the info for the interested souls.

5 comments:

arkon said...

Well done job,
I think another good idea would be to use an Hex editor that lets you color different fields and setup a legend for each color and its meaning...

Anonymous said...

Doesn't the "robustness" of the WIndows PE loader end up meaning "it's full of complicated code"?

Won't this "robustness" lead to some weird-beard kernel attacks via combinations of field header offsets and stuff?

Ero Carrera said...

I think it's more robustness than "messiness". At least it does seem to handle well really broken files where other tools just break.

I haven't reversed engineered the Windows loader myself so I don't have a fully informed opinion. It's just intuition.

Emmanuel said...

I'm really amazed by your pictures. Could you tell what tool are you using to do it ?

Ero Carrera said...

I use the fantastic OmniGraffle