To help myself explore the x64 PE (Portable Executable) file format for Windows, I created a series of step-by-step exercises for myself:

  1. Start with an idiomatic example. What's the regular way of doing this?
  2. Bindump that executable, create an assembly file that is just the binary, and assemble that to make sure I get the same result.
  3. Marking up the asm data with locations, pointers and other information to validate I know how it's put together. Continuing to build the same exe.
  4. Once I'm comfortable with my understanding of the initial example, then I can start to add things and experiment.

The files are all written in fasm. Except in a couple places where noted in the source file, each builds on the last on you can examine the change by diffing the two files.

File Description
00_pe_return_00.asm Simple idiomatic fasm example. Returns 42.
00_pe_return_01.asm Assembled bindump of 00_pe_return_00.exe
00_pe_return_02.asm Label important PE locations; print to verify
00_pe_return_03.asm Calculate padding; Name values; Replace addresses with labels.
00_pe_return_04.asm Dissassemble code at 'start' label.
00_pe_return_05.asm Calculate rip-relative addresses replacing hard-coded value.
00_pe_return_06.asm Alternative: Replace pointers with absolute addresses.
01_pe_printf_00.asm Add msvcrt.dll and call printf to 00_pe_return_05.asm
01_pe_printf_01.asm Add BSS section.
01_pe_printf_02.asm Print call return address from stack. (Demo stack offset.)
02_pe_messagebox_00.asm Add GUI Subsystem, call GetModuleNameA and MessageBoxA
02_pe_messagebox_01.asm Put IDATA into CODE section; Remove padding; Remove DOS program
02_pe_messagebox_02.asm Let assembler calculate rip-relative addresses inside section.
02_pe_messagebox_03.asm Embed BSS inside CODE section.

-- Mike Acton (Engine Director)