Skip to content

Instantly share code, notes, and snippets.

@typeswitch-dev
Created September 2, 2022 17:07
Show Gist options
  • Select an option

  • Save typeswitch-dev/700d4d3fc5226bd9949c2da8b0306905 to your computer and use it in GitHub Desktop.

Select an option

Save typeswitch-dev/700d4d3fc5226bd9949c2da8b0306905 to your computer and use it in GitHub Desktop.

Revisions

  1. typeswitch-dev created this gist Sep 2, 2022.
    163 changes: 163 additions & 0 deletions minimal.asm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,163 @@
    org 0 ; We use "org 0" so Relative Virtual Addresses (RVAs) are easy.
    ; This means that when we want an absolute Virtual Address we have
    ; to add IMAGE_BASE to the RVA (or whatever the base of that section is)

    IMAGE_BASE equ 0x400000
    SECT_ALIGN equ 0x200
    FILE_ALIGN equ 0x200

    msdos_header:
    .magic db 'MZ'
    .cblp dw 0x0090 ; bytes on last page of file
    .cp dw 0x0003 ; pages in file
    .crlc dw 0x0000 ; relocations
    .cparhdr dw 0x0004 ; size of header in paragraphs
    .minalloc dw 0x0000 ; minimum extra paragraphs needed
    .maxalloc dw 0xFFFF ; maximum extra paragraphs needed
    .ss dw 0x0000 ; initial (relative) SS value
    .sp dw 0x00B8 ; initial SP value
    .csum dw 0x0000 ; checksum
    .ip dw 0x0000 ; initial IP value
    .cs dw 0x0000 ; initial (relative) CS value
    .lfarlc dw 0x0040 ; file address of relocation table
    .ovno dw 0x0000 ; overlay number
    .res dw 0,0,0,0 ; reserved words
    .oemid dw 0x0000 ; OEM identifier
    .oeminfo dw 0x0000 ; OEM information
    .res2 times 10 dw 0 ; reserved words
    .lfanew dd pe_header ; relative address of PE header

    bits 16
    msdos_program:
    .entry push cs
    pop ds
    mov dx, .message - .entry
    mov ah, 0x09
    int 0x21
    mov ax, 0x4C01
    int 0x21
    .message db "This program cannot be run in DOS mode.", 0xD, 0xD, 0xA, '$'
    times 0x80 + msdos_header - $ db 0x00

    pe_header:
    .magic db 'PE', 0, 0
    .machine dw 0x8664 ; x86-64
    .nsections dw 1 ; number of sections
    .timestamp dd 0 ; 32-bit timestamp for program
    .symtable dd 0 ; symbol table location (0 for image file)
    .nsymbols dd 0 ; number of symbols (0 for image file)
    .opthdrsize dw opt_header.end - opt_header ; size of "optional" header
    .chrctrstcs dw 0x0022 ; 0x0002 = IMAGE_FILE_EXECUTABLE_IMAGE
    ; 0x0020 = IMAGE_FILE_LARGE_ADDRESS_AWARE

    opt_header:
    .magic dw 0x020B ; PE32+ (i.e. a 64-bit PE file)
    .linkver db 0, 0
    .codesize dd code_section_end - code_section ; size of code section
    .datasize dd 0 ; size initialized data
    .bsssize dd 0 ; size uninitialized data
    .entry dd main ; relative address of entry point
    .codebase dd code_section ; relative address of code section
    .imagebase dq IMAGE_BASE
    .sectalign dd SECT_ALIGN ; alignment of sections in VM
    .filealign dd FILE_ALIGN ; alignment of sections in file
    .osver dw 6, 0
    .imgver dw 0, 0
    .subsysver dw 6, 0
    .win32ver dd 0
    .sizeimage dd image_end ; size of image (multiple of SECT_ALIGN)
    .sizehdrs dd headers_end ; size of headers (multiple of FILE_ALIGN)
    .checksum dd 0
    .subsystem dw 3 ; windows console subsystem (2 for gui)
    .dllchars dw 0x8140 ; 0x0040 = DLL can be relocated at load time
    ; 0x0100 = image is NX compatible
    ; 0x8000 = Terminal server aware
    .stkresv dq 0x100000
    .stkcommit dq 0x1000
    .heapresv dq 0x100000
    .heapcommit dq 0x1000
    .loaderflgs dd 0 ; reserved, must be 0
    .nrvasize dd (.end-.edata)/8 ; number of entries in "data directory"
    .edata dd 0, 0 ; (which is still part of optional header)
    .idata dd import_table
    dd import_table.end - import_table
    .res dd 0, 0
    .exn dd 0, 0
    .sec dd 0, 0
    .reloc dd 0, 0
    .debug dd 0, 0
    .arch dd 0, 0
    .gp dd 0, 0
    .tls dd 0, 0
    .lconfig dd 0, 0
    .bimport dd 0, 0
    .iat dd iat
    dd iat.end - iat
    .dimport dd 0, 0
    .com dd 0, 0
    .resvd dd 0, 0
    .end:

    code_section_header:
    .name db ".text",0,0,0
    .vsize dd code_section_end - code_section
    .vaddr dd code_section
    .psize dd code_section_end - code_section
    .paddr dd code_section
    .preloc dd 0
    .plines dd 0
    .nreloc dw 0
    .nlines dw 0
    .chars dd 0xE0000020 ; 0x00000020 = IMAGE_SCN_CNT_CODE
    ; 0x20000000 = IMAGE_SCN_MEM_EXECUTE
    ; 0x40000000 = IMAGE_SCN_MEM_READ
    ; 0x80000000 = IMAGE_SCN_MEM_WRITE
    .end align FILE_ALIGN
    headers_end: align SECT_ALIGN ; headers must be file aligned
    code_section: ; section must be section aligned
    import_table:
    .ilt dd ilt
    .ts dd 0
    .fc dd 0
    .name dd names.kernel32_dll
    .iat dd iat
    .null dd 0,0,0,0,0
    .end align 8

    ilt:
    .ExitProcess dq names.ExitProcess
    .CreateFileA dq names.CreateFileA
    .WriteFile dq names.WriteFile
    .null dq 0
    .end align 8

    iat:
    .ExitProcess dq names.ExitProcess
    .CreateFileA dq names.CreateFileA
    .WriteFile dq names.WriteFile
    .null dq 0
    .end align 8

    names: ; each entry should be aligned on an even boundary by zero-padding
    ; also a 2 byte "hint" is needed for imported function names
    ; -- using 0,0 is fine, the loader falls back to binary search
    .kernel32_dll db "kernel32.dll",0,0
    .ExitProcess db 0,0,"ExitProcess",0
    .CreateFileA db 0,0,"CreateFileA",0
    .WriteFile db 0,0,"WriteFile",0
    .end align 8

    bits 64

    ; PROGRAM ENTRY
    main: sub rsp, 32 ; "the shadow space"
    mov rcx, 42
    .bye call [rel iat.ExitProcess]
    jmp .bye

    align FILE_ALIGN
    code_section_end:

    align SECT_ALIGN
    image_end: