I would like to create a Windows 10/11 Pro 64-Bit assembly source code, that can than proceed by YASM Assembler to form a Windows Executable (.exe Application) so small as possible. For Resources under the GitHub: corkami.
But I don't know which one is best for 64-bit. The solution should contain Assembly text/code with comments that explain how to do so.
E.g.: "You have to set the IAT for more as one Symbols" ...
The solution should be "not" link with other Tool-chains. This means: C:\yasm -f bin -o output.exe input.asm
.
As a bonus, the source should be compile with C:\nasm -f bin -o output.exe input.asm
.
In an answer, it is enough to show the way/steps, to display a MessageBox, and *ExitProcess *call.
Optional, __imp__ShowMessageBoxA is an Export-Symbol from the FPC (Free-Pascal-Compiler) Windows .DLL library file. The assembly should contain this snippet:
EntryPoint:
sub rsp, 4 * 8
mov ecx, 0 // HWND
mov rdx, [lpText] // LPCTSTR
mov r8, [lpCapt] // LPCTSTR
mov r9d, 2 // UINT
call [__imp__ShowMessageBoxA]
xor ecx, ecx
call [__imp__ExitProcess]
lpText db "this and that", 0
lpCapt db "Caption", 0
hnExitProcess:
dw 0
db 'ExitProcess', 0
hnShowMessageBoxA:
dw 0
db 'ShowMessageBoxA', 0
I tried to use a Example from corkami, but I am lost.
I tried to create flat binary File with yasm.exe -f bin or nasm.exe -f bin which does bring me no Compiler-Errors. The result of yasm -f bin output.exe was the Windows Loader Message: "Symbol ShowMessageBoxA was not found in output.exe". I created a .DLL that was formed by FPC (Free Pascal Compiler) with C:\fpc kalle32.pas :
library kalle32;
uses Windows;
procedure ShowMessageA(h: HWND; t,c: LPCTSTR; u: UINT); stdcall; export;
begin
// this will not show
MessageBoxA(h,t,c,u);
end;
begin
// this message box will not display on start up on DLL load
MessageBoxA(0,'Test Message','Caption',0);
end.
I would like to write assembly Code that can compiled with yasm.exe or nasm.exe under the Command Line/Console/Terminal to an executable.
@Margaret Bloom: the smallest/full reproduce example is this one:
BITS 64
%define align(n,r) (((n+(r-1))/r)*r)
; DOS Header
dw 'MZ' ; e_magic
dw 0 ; [UNUSED] e_cblp
dw 0 ; [UNUSED] c_cp
dw 0 ; [UNUSED] e_crlc
dw 0 ; [UNUSED] e_cparhdr
dw 0 ; [UNUSED] e_minalloc
dw 0 ; [UNUSED] e_maxalloc
dw 0 ; [UNUSED] e_ss
dw 0 ; [UNUSED] e_sp
dw 0 ; [UNUSED] e_csum
dw 0 ; [UNUSED] e_ip
dw 0 ; [UNUSED] e_cs
dw 0 ; [UNUSED] e_lfarlc
dw 0 ; [UNUSED] e_ovno
times 4 dw 0 ; [UNUSED] e_res
dw 0 ; [UNUSED] e_oemid
dw 0 ; [UNUSED] e_oeminfo
times 10 dw 0 ; [UNUSED] e_res2
dd pe_hdr ; e_lfanew
; PE Header
pe_hdr:
dw 'PE', 0 ; Signature
; Image File Header
dw 0x8664 ; Machine
dw 0x01 ; NumberOfSections
dd 0 ; [UNUSED] TimeDateStamp
dd 0 ; PointerToSymbolTable
dd 0 ; NumberOfSymbols
dw opt_hdr_size ; SizeOfOptionalHeader
dw 0x22 ; Characteristics
; Optional Header, COFF Standard Fields
opt_hdr:
dw 0x020b ; Magic (PE32+)
db 0x0e ; MajorLinkerVersion
db 0x16 ; MinorLinkerVersion
dd code_size ; SizeOfCode
dd 0 ; SizeOfInitializedData
dd 0 ; SizeOfUninitializedData
dd entry ; AddressOfEntryPoint
dd iatbl ; BaseOfCode
; Optional Header, NT Additional Fields
dq 0x000140000000 ; ImageBase
dd 0x10 ; SectionAlignment
dd 0x10 ; FileAlignment
dw 0x06 ; MajorOperatingSystemVersion
dw 0 ; MinorOperatingSystemVersion
dw 0 ; MajorImageVersion
dw 0 ; MinorImageVersion
dw 0x06 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion
dd 0 ; Reserved1
dd file_size ; SizeOfImage
dd hdr_size ; SizeOfHeaders
dd 0 ; CheckSum
dw 0x02 ; Subsystem (Windows GUI)
dw 0x8160 ; DllCharacteristics
dq 0x100000 ; SizeOfStackReserve
dq 0x1000 ; SizeOfStackCommit
dq 0x100000 ; SizeOfHeapReserve
dq 0x1000 ; SizeOfHeapCommit
dd 0 ; LoaderFlags
dd 0x02 ; NumberOfRvaAndSizes
; Optional Header, Data Directories
dd 0 ; Export, RVA
dd 0 ; Export, Size
dd itbl ; Import, RVA
dd itbl_size ; Import, Size
opt_hdr_size equ $-opt_hdr
; Section Table
section_name db '.' ; Name
times 8-($-section_name) db 0
dd sect_size ; VirtualSize
dd iatbl ; VirtualAddress
dd code_size ; SizeOfRawData
dd iatbl ; PointerToRawData
dd 0 ; PointerToRelocations
dd 0 ; PointerToLinenumbers
dw 0 ; NumberOfRelocations
dw 0 ; NumberOfLinenumbers
dd 0x60000020 ; Characteristics
hdr_size equ $-$$
code:
; Import Address Directory
iatbl:
dq symbol
dq 0
iatbl_size equ $-iatbl
; Strings
title:
db "Hallo Welt !!!", 0
content:
db "ABCDEFGHIJKL", 0
; Entry
entry:
; the comment block there are my interest in - why does it not work
mov r9d, 0x00240040 ; uType
lea r8, [rel title] ; lpCaption
lea rdx, [rel content] ; lpText
xor ecx, ecx ; hWnd
jmp [rel iatbl] ; MessageBoxN
times align($-$$,16)-($-$$) db 0xcc
; Import Directory
itbl:
dq intbl ; OriginalFirstThunk
dd 0 ; TimeDateStamp
dd dll_name ; ForwarderChain
dd iatbl ; Name
dq 0 ; FirstThunk
itbl_size equ $-itbl
; Import Name Table
intbl:
dq symbol
dq 0
; Symbol
symbol:
dw 0x0294 ; [UNUSED] Function Order
db 'MessageBoxA', 0 ; Function Name
dll_name:
db 'USER32.dll', 0
db 0
sect_size equ $-code
times align($-$$,16)-($-$$) db 0
code_size equ $-code
file_size equ $-$$
I would extend the Assembly Script above so, that I can use more than one win32api Functions. So, I would use a second, third, ... Function from my own .DLL Files on ground of the existing Code above.
The following code will do what I want. It can be compiled with NASM, and it (the resulting flat image executable .EXE) shows a Ansi-, and a Unicode Version of MessageBoxA/W described in the Microsoft documentation. This can be used to create a Flat Image on the fly with NASM assembly.
SECTIONS equ 2
TIME_DATE equ 0
IMAGE_BASE equ 0x000140000000 ;0x400000 ; org
SECTION_ALIGNMENT equ 0x200
FILE_ALIGNMENT equ 0x200
BSS_SIZE equ 0
%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))
bits 64
org IMAGE_BASE
section .text
;;******************************************************************************************************
;; if the header is part of the image, define it as section .text because .text is put
;; first in the image, and rename the code section as section .code
header:
dw "MZ" ; e_magic
dw 0 ; e_cblp
dw 0 ; e_cp
dw 0 ; e_crlc
dw 0 ; e_cparhdr
dw 0 ; e_minalloc
dw 0 ; e_maxalloc
dw 0 ; e_ss
dw 0 ; e_sp
dw 0 ; e_csum
dw 0 ; e_ip
dw 0 ; e_cs
dw 0 ; e_lsarlc
dw 0 ; e_ovno
dq 0 ; e_res
dw 0 ; e_oemid
dw 0 ; e_oeminfo
dd 0,0,0,0,0 ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew
imageHeader:
dd "PE" ; Signature
dw 0x8664 ; Machine
dw SECTIONS ; NumberOfSections
dd TIME_DATE ; TimeDateStamp
dd 0 ; PointerToSymbolTable
dd 0 ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x022 ; Characteristics
optionalHeader:
dw 0x20B ; Magic
db 0 ; MajorLinkerVersion
db 0 ; MinorLinkerVersion
dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
dd nagoa_round(RAW_DATA.SIZE) ; SizeOfInitializedData
dd nagoa_round(BSS_SIZE) ; SizeOfUninitializedData
dd entryPoint ; AddressOfEntryPoint
dd code ; BaseOfCode
;dd data - IMAGE_BASE ; BaseOfData
dq IMAGE_BASE ; ImageBase
dd SECTION_ALIGNMENT ; SectionAlignment
dd FILE_ALIGNMENT ; FileAlignment
dw 4 ; MajorOperatingSystemVersion
dw 0 ; MinorOperatingSystemVersion
dw 0 ; MajorImageVersion
dw 0 ; MinorImageVersion
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion
dd 0 ; Win32VersionValue
dd (RAW_HEADER.SIZE + RAW_CODE.SIZE + RAW_DATA.SIZE); SizeOfImage
dd RAW_HEADER.SIZE ; SizeOfHeaders
dd 0 ; CheckSum
dw 2 ; Subsystem
dw 0 ; DllCharacteristics
dq 0x40000 ; SizeOfStackReserve
dq 0x6000 ; SizeOfStackCommit
dq 0x100000 ; SizeOfHeapReserve
dq 0x1000 ; SizeOfHeapCommit
dd 0 ; LoaderFlags
dd 16 ; NumberOfRvaAndSizes
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd Import_Directory_Table, Import_Directory_Table_Size ; IMAGE_DIRECTORY_ENTRY_IMPORT
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
;dd Import_Address_Table, Import_Address_Table_Size ; IMAGE_DIRECTORY_ENTRY_IAT
dd 0,0
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0 ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0 ; reserved
optionalHeader.SIZE equ $ - optionalHeader
sectionHeaders:
db ".text", 0, 0, 0 ; Name
dd nagoa_round(RAW_CODE.SIZE) ; VirtualSize
dd code ; VirtualAddress
dd RAW_CODE.SIZE ; SizeOfRawData
dd RAW_CODE.OFFSET ; PointerToRawData
dd 0 ; PointerToRelocations
dd 0 ; PointerToLinenumbers
dw 0 ; NumberOfRelocations
dw 0 ; NumberOfLinenumbers
dd 0x60000020 ; Characteristics
db ".data", 0, 0, 0 ; Name
dd nagoa_round(RAW_DATA.SIZE) ; VirtualSize
dd data ; VirtualAddress
dd RAW_DATA.SIZE ; SizeOfRawData
dd RAW_DATA.OFFSET ; PointerToRawData
dd 0 ; PointerToRelocations
dd 0 ; PointerToLinenumbers
dw 0 ; NumberOfRelocations
dw 0 ; NumberOfLinenumbers
dd 0xC0000040 ; Characteristics
align FILE_ALIGNMENT, db 0
RAW_HEADER.SIZE equ $ - header
;;******************************************************************************************************
;; F I R S T . c o d e S E C T I O N
;;******************************************************************************************************
VS_CODE EQU ( ( ( 1 + ( (RAW_HEADER.SIZE-1) >> 12 ) ) * SECTION_ALIGNMENT ) )
section .code vstart=VS_CODE
code:
entryPoint:
mov rcx,500
call [rel Sleep]
mov r9d, 0x00240040 ; uType
lea r8, [rel title] ; lpCaption
lea rdx, [rel content] ; lpText
xor ecx, ecx ; hWnd
call [rel MessageBoxA]
mov rcx,500
call [rel Sleep]
mov r9d, 0x00240040 ; uType
lea r8, [rel TITLE_W] ; lpCaption
lea rdx, [rel CONTENT_W] ; lpText
xor ecx, ecx ; hWnd
call [rel MessageBoxW]
jmp [rel ExitProcess]
align SECTION_ALIGNMENT, db 0
;;******************************************************************************************************
;; F I R S T . d a t a S E C T I O N
;;******************************************************************************************************
VS_DATA EQU ( VS_CODE + ( ( 1 + ( (RAW_CODE.SIZE-1) >> 12 ) ) * SECTION_ALIGNMENT ) )
section .data vstart=VS_DATA
data :
Import_Address_Table:
DLL_1:
Sleep: dq I_Sleep
ExitProcess: dq I_ExitProcess
GetStdHandle: dq I_GetStdHandle
dq 0
DLL_2:
MessageBoxA dq I_MessageBoxA
MessageBoxW dq I_MessageBoxW
dq 0
Import_Address_Table_Size equ $ - Import_Address_Table
align 0x20, db 0
Import_Directory_Table:
KERNEL32.originalfthk dd DLL_1_thunk_table
KERNEL32.timedate dd 0
KERNEL32.forwarder dd 0
KERNEL32.name dd dll_name_1
KERNEL32.firstthunk dd DLL_1
USER32.originalfthk dd DLL_2_thunk_table
USER32.timedate dd 0
USER32.forwarder dd 0
USER32.name dd dll_name_2
USER32.firstthunk dd DLL_2
align 0x20, db 0 ; should be always at the end of Import_Directory_Table
Import_Directory_Table_Size equ $ - Import_Directory_Table
DLL_1_thunk_table :
dq I_Sleep
dq I_ExitProcess
dq I_GetStdHandle
dq 0
DLL_2_thunk_table :
dq I_MessageBoxA
dq I_MessageBoxW
dq 0
I_Sleep:
dw 0
db 'Sleep', 0
align 2 , db 0
I_ExitProcess:
dw 0
db 'ExitProcess', 0
align 2 , db 0
I_GetStdHandle:
dw 0
db 'GetStdHandle', 0
align 2 , db 0
I_MessageBoxA:
dw 0
db 'MessageBoxA', 0
align 2 , db 0
I_MessageBoxW:
dw 0
db 'MessageBoxW', 0
align 2 , db 0
dll_name_1: db 'kernel32.dll', 0
dll_name_2: db 'user32.dll', 0
STRING_TABLE:
%define u(x) __?utf16le?__(x)
%define w(x) __?utf32le?__(x)
title:
db "Hello world !!!", 0
align 2 , db 0
content:
db "ABCDEFGHIJKL", 0
align 2 , db 0
TITLE_W:
dw u("Hello World !!! in Unicode"),0
align 2 , db 0
CONTENT_W:
db u("ABCDEFGHIJKL"), 0
align 2 , db 0
align SECTION_ALIGNMENT, db 0
;;******************************************************************************************************
;; L A S T . c o d e S E C T I O N
;;******************************************************************************************************
section .code
align FILE_ALIGNMENT, db 0
RAW_CODE.OFFSET equ RAW_HEADER.SIZE
RAW_CODE.SIZE equ $ - $$
;;******************************************************************************************************
;; L A S T . d a t a S E C T I O N
;;******************************************************************************************************
section .data
align FILE_ALIGNMENT, db 0
RAW_DATA.OFFSET equ RAW_CODE.OFFSET + RAW_CODE.SIZE
RAW_DATA.SIZE equ $ - $$
;;******************************************************************************************************
IMAGE_END equ $
;; -- eof --