From 20c3bfbb99abc186def41e6d17079fcc3638b183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 16 Dec 2023 17:09:51 +0000 Subject: [PATCH] Further hex0 size reduction and calling convention fixes. --- amd64/Development/hex0.M1 | 28 ++++----------- amd64/Development/hex0.S | 24 ++++--------- amd64/Development/hex0.hex2 | 26 ++++---------- amd64/hex0.hex0 | 68 +++++++++++++++---------------------- 4 files changed, 47 insertions(+), 99 deletions(-) diff --git a/amd64/Development/hex0.M1 b/amd64/Development/hex0.M1 index 530553d..32b653c 100644 --- a/amd64/Development/hex0.M1 +++ b/amd64/Development/hex0.M1 @@ -31,7 +31,6 @@ DEFINE jmp EB DEFINE jne 75 DEFINE lea_rdx,[rip+DWORD] 488D15 DEFINE mov_edi,eax 89C7 -DEFINE mov_rbp,rsp 4889E5 DEFINE mov_rcx,rbx 4889D9 DEFINE mov_rcx,rsi 4889F1 DEFINE mov_rcx,r8 4C89C1 @@ -40,14 +39,11 @@ DEFINE mov_rcx,r12 4C89E1 DEFINE mov_rcx,r13 4C89E9 DEFINE mov_rdx,rbx 4889DA DEFINE mov_rdx,rsp 4889E2 -DEFINE mov_rsp,rbp 4889EC -DEFINE mov_rsp,r15 4C89FC DEFINE mov_r8,rsp 4989E0 DEFINE mov_r8,r15 4D89F8 DEFINE mov_r9,r15 4D89F9 DEFINE mov_r13,rcx 4989CD DEFINE mov_r15,rcx 4989CF -DEFINE mov_r15,rsp 4989E7 DEFINE mov_al,[rbx] 8A03 DEFINE mov_[rbx], C603 DEFINE mov_rbx,[rdi+BYTE] 488B5F @@ -97,7 +93,6 @@ DEFINE xor_r9,r9 4D31C9 :_start # Save non-volatile registers push_rbp - mov_rbp,rsp push_rbx push_rdi push_rsi @@ -139,11 +134,9 @@ DEFINE xor_r9,r9 4D31C9 # Get root directory push_rax # allocate stack for rootdir mov_rdx,rsp # arg2 = &rootdir - push_rax # allocate shadow stack space for UEFI function - push_rax # allocate shadow stack space for UEFI function + sub_rsp, !32 # allocate shadow stack space for UEFI function call_[rcx+BYTE] !8 # rootfs->open_volume(rootfs, &rootdir) - pop_rax # deallocate stack - pop_rax # deallocate stack + add_rsp, !32 # deallocate stack pop_rsi # get rootdir # Push command line arguments onto stack @@ -194,9 +187,7 @@ DEFINE xor_r9,r9 4D31C9 # Save variables that are needed for cleanup push_r14 # save system->boot - push_r15 # save image_handle push_rsi # save rootdir - mov_r15,rsp # save stack location for cleanup # Our flag for byte processing push !-1 @@ -305,15 +296,12 @@ DEFINE xor_r9,r9 4D31C9 push_rsp # align stack to 16 bytes push_[rsp] # align stack to 16 bytes and_rsp, !-16 # align stack to 16 bytes - push_rax # make sure next call is aligned to 16 bytes mov_rcx,r13 # arg1 = fout push !1 # size = 1 mov_rdx,rsp # arg2 = &size push_rax # allocate stack mov_r8,rsp # arg3 = &output - push_rax # allocate shadow stack space for UEFI function - push_rax # allocate shadow stack space for UEFI function - push_rax # allocate shadow stack space for UEFI function + sub_rsp, !32 # allocate shadow stack space for UEFI function call_[rcx+BYTE] !40 # fout->write() mov_rsp,[rsp+BYTE] !56 # deallocate stack @@ -328,10 +316,7 @@ DEFINE xor_r9,r9 4D31C9 push_rsp # align stack to 16 bytes push_[rsp] # align stack to 16 bytes and_rsp, !-16 # align stack to 16 bytes - push_rax # make sure next call is aligned to 16 bytes - push_rax # allocate shadow stack space for UEFI function - push_rax # allocate shadow stack space for UEFI function - push_rax # allocate shadow stack space for UEFI function + sub_rsp, !32 # allocate shadow stack space for UEFI function call_[rcx+BYTE] !32 # fin->read() mov_rsp,[rsp+BYTE] !40 # deallocate stack pop_rax # save input to rax @@ -344,9 +329,8 @@ DEFINE xor_r9,r9 4D31C9 ret # return :terminate - mov_rsp,r15 # restore stack location for cleanup + pop_rax # deallocate stack (return code of read_byte) pop_rsi # restore rootdir - pop_r15 # restore image_handle pop_r14 # restore system->boot pop_rbx # restore root_device @@ -370,6 +354,7 @@ DEFINE xor_r9,r9 4D31C9 mov_rcx,r8 # arg1 = image_handle xor_r9,r9 # arg4 = NULL call_[r14+DWORD] %288 # system->boot->close_protocol(image_handle, &guid, image_handle, 0) + add_rsp, !40 # deallocate stack # Restore non-volatile registers pop_r15 @@ -380,7 +365,6 @@ DEFINE xor_r9,r9 4D31C9 pop_rdi pop_rbx - mov_rsp,rbp # restore stack pop_rbp ret # return to UEFI diff --git a/amd64/Development/hex0.S b/amd64/Development/hex0.S index be41598..dd1f415 100644 --- a/amd64/Development/hex0.S +++ b/amd64/Development/hex0.S @@ -20,7 +20,6 @@ _start: # Save non-volatile registers push rbp - mov rbp, rsp push rbx push rdi push rsi @@ -62,11 +61,9 @@ _start: # Get root directory push rax # allocate stack for rootdir mov rdx, rsp # arg2 = &rootdir - push rax # allocate shadow stack space for UEFI function - push rax # allocate shadow stack space for UEFI function + sub rsp, 32 # allocate shadow stack space for UEFI function call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) - pop rax # deallocate stack - pop rax # deallocate stack + add rsp, 32 # deallocate stack pop rsi # get rootdir # Push command line arguments onto stack @@ -117,9 +114,7 @@ loop_options_done: # Save variables that are needed for cleanup push r14 # save system->boot - push r15 # save image_handle push rsi # save rootdir - mov r15, rsp # save stack location for cleanup # Our flag for byte processing push -1 @@ -228,15 +223,12 @@ write_byte: push rsp # align stack to 16 bytes push [rsp] # align stack to 16 bytes and rsp, -16 # align stack to 16 bytes - push rax # make sure next call is aligned to 16 bytes mov rcx, r13 # arg1 = fout push 1 # size = 1 mov rdx, rsp # arg2 = &size push rax # allocate stack mov r8, rsp # arg3 = &output - push rax # allocate shadow stack space for UEFI function - push rax # allocate shadow stack space for UEFI function - push rax # allocate shadow stack space for UEFI function + sub rsp, 32 # allocate shadow stack space for UEFI function call [rcx+40] # fout->write() mov rsp, [rsp+56] # deallocate stack @@ -251,10 +243,7 @@ read_byte: push rsp # align stack to 16 bytes push [rsp] # align stack to 16 bytes and rsp, -16 # align stack to 16 bytes - push rax # make sure next call is aligned to 16 bytes - push rax # allocate shadow stack space for UEFI function - push rax # allocate shadow stack space for UEFI function - push rax # allocate shadow stack space for UEFI function + sub rsp, 32 # allocate shadow stack space for UEFI function call [rcx+32] # fin->read() mov rsp, [rsp+40] # deallocate stack pop rax # save input to rax @@ -267,9 +256,8 @@ read_byte: ret # return terminate: - mov rsp, r15 # restore stack location for cleanup + pop rax # deallocate stack (return code of read_byte) pop rsi # restore rootdir - pop r15 # restore image_handle pop r14 # restore system->boot pop rbx # restore root_device @@ -293,6 +281,7 @@ terminate: mov rcx, r8 # arg1 = image_handle xor r9, r9 # arg4 = NULL call [r14+288] # system->boot->close_protocol(image_handle, &guid, image_handle, 0) + add rsp, 40 # deallocate stack # Restore non-volatile registers pop r15 @@ -304,7 +293,6 @@ terminate: pop rbx abort: # used for debugging only - mov rsp, rbp # restore stack pop rbp ret # return to UEFI diff --git a/amd64/Development/hex0.hex2 b/amd64/Development/hex0.hex2 index 34778c8..24172b9 100644 --- a/amd64/Development/hex0.hex2 +++ b/amd64/Development/hex0.hex2 @@ -16,7 +16,6 @@ :_start # Save non-volatile registers 55 ; push_rbp - 4889E5 ; mov_rbp,rsp 53 ; push_rbx 57 ; push_rdi 56 ; push_rsi @@ -58,11 +57,9 @@ # Get root directory 50 ; push_rax # allocate stack for rootdir 4889E2 ; mov_rdx,rsp # arg2 = &rootdir - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 08 ; call_[rcx+BYTE] !8 # rootfs->open_volume(rootfs, &rootdir) - 58 ; pop_rax # deallocate stack - 58 ; pop_rax # deallocate stack + 4883C4 20 ; add_rsp, !32 # deallocate stack 5E ; pop_rsi # save rootdir # Push command line arguments onto stack @@ -113,9 +110,7 @@ # Save variables that are needed for cleanup 4156 ; push_r14 # save system->boot - 4157 ; push_r15 # save image_handle 56 ; push_rsi # save rootdir - 4989E7 ; mov_r15,rsp # save stack location for cleanup # Our flag for byte processing 6A FF ; push !-1 @@ -224,15 +219,12 @@ 54 ; push_rsp # align stack to 16 bytes FF3424 ; push_[rsp] # align stack to 16 bytes 4883E4 F0 ; and_rsp, !-16 # align stack to 16 bytes - 50 ; push_rax # make sure next call is aligned to 16 bytes 4C89E9 ; mov_rcx,r13 # arg1 = fout 6A 01 ; push !1 # size = 1 4889E2 ; mov_rdx,rsp # arg2 = &size 50 ; push_rax # allocate stack 4989E0 ; mov_r8,rsp # arg3 = &output - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 28 ; call_[rcx+BYTE] !40 # fout->write() 488B6424 38 ; mov_rsp,[rsp+BYTE] !56 # deallocate stack @@ -247,12 +239,9 @@ 54 ; push_rsp # align stack to 16 bytes FF3424 ; push_[rsp] # align stack to 16 bytes 4883E4 F0 ; and_rsp, !-16 # align stack to 16 bytes - 50 ; push_rax # make sure next call is aligned to 16 bytes - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 20 ; call_[rcx+BYTE] !32 # fin->read() - 488B6424 10 ; mov_rsp,[rsp+BYTE] !40 # deallocate stack + 488B6424 28 ; mov_rsp,[rsp+BYTE] !40 # deallocate stack 58 ; pop_rax # save input to rax 5E ; pop_rsi # save size to rsi @@ -263,9 +252,8 @@ C3 ; ret # return :terminate - 4C89FC ; mov_rsp,r15 # restore stack location for cleanup + 58 ; pop_rax # deallocate stack (return code of read_byte) 5E ; pop_rsi # restore rootdir - 415F ; pop_r15 # restore image_handle 415E ; pop_r14 # restore system->boot 5B ; pop_rbx # restore root_device @@ -289,6 +277,7 @@ 4C89C1 ; mov_rcx,r8 # arg1 = image_handle 4D31C9 ; xor_r9,r9 # arg4 = NULL 41FF96 20010000 ; call_[r14+DWORD] %288 # system->boot->close_protocol(image_handle, &guid, image_handle, 0) + 4883C4 28 ; add_rsp, !40 # deallocate stack # Restore non-volatile registers 415F ; pop_r15 @@ -299,7 +288,6 @@ 5F ; pop_rdi 5B ; pop_rbx - 4889EC ; mov_rsp,rbp # restore stack 5D ; pop_rbp C3 ; ret # return to UEFI diff --git a/amd64/hex0.hex0 b/amd64/hex0.hex0 index d26cd69..9c9c05f 100644 --- a/amd64/hex0.hex0 +++ b/amd64/hex0.hex0 @@ -129,9 +129,9 @@ F0 00 # SizeOfOptionalHeader # [0x148] # Start of section headers 00 00 00 00 00 00 00 00 ; Name of the section (empty) but could set to ".text" -06 02 00 00 ; VirtualSize +FF 01 00 00 ; VirtualSize 00 10 00 00 ; VirtualAddress -06 02 00 00 ; SizeOfRawData +FF 01 00 00 ; SizeOfRawData 70 01 00 00 ; PointerToRawData 00 00 00 00 ; PointerToRelocations 00 00 00 00 ; PointerToLinenumbers @@ -145,7 +145,6 @@ F0 00 # SizeOfOptionalHeader # :_start # Save non-volatile registers 55 ; push_rbp - 4889E5 ; mov_rbp,rsp 53 ; push_rbx 57 ; push_rdi 56 ; push_rsi @@ -159,7 +158,7 @@ F0 00 # SizeOfOptionalHeader # Open Loaded Image protocol 4D89F9 ; mov_r9,r15 # arg4 = image_handle - 488D15 C6010000 ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL + 488D15 C2010000 ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL 4C89C9 ; mov_rcx,r9 # arg1 = image_handle 50 ; push_rax # allocate stack for image 4989E0 ; mov_r8,rsp # arg3 = &image @@ -172,7 +171,7 @@ F0 00 # SizeOfOptionalHeader # Get root file system 4D89F9 ; mov_r9,r15 # arg4 = image_handle - 488D15 B1010000 ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL + 488D15 AD010000 ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL 488B4F 18 ; mov_rcx,[rdi+BYTE] !24 # arg1 = root_device = image->device 4989CD ; mov_r13,rcx # save root_device 50 ; push_rax # allocate stack for rootfs @@ -187,18 +186,16 @@ F0 00 # SizeOfOptionalHeader # Get root directory 50 ; push_rax # allocate stack for rootdir 4889E2 ; mov_rdx,rsp # arg2 = &rootdir - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 08 ; call_[rcx+BYTE] !8 # rootfs->open_volume(rootfs, &rootdir) - 58 ; pop_rax # deallocate stack - 58 ; pop_rax # deallocate stack + 4883C4 20 ; add_rsp, !32 # deallocate stack 5E ; pop_rsi # save rootdir # Push command line arguments onto stack 488B5F 38 ; mov_rbx,[rdi+BYTE] !56 # options = image->load_options 4889DA ; mov_rdx,rbx # save beginning of load_options 48035F 30 ; add_rbx,[rdi+BYTE] !48 # go to the end of load_options -# :loop_options [_start + 0x7B] +# :loop_options [_start + 0x7C] 4839D3 ; cmp_rbx,rdx # Check if we are done 74 14 ; je !loop_options_done # We are done 4883EB 02 ; sub_rbx, !2 # --options @@ -209,7 +206,7 @@ F0 00 # SizeOfOptionalHeader 4883C3 02 ; add_rbx, !2 # ++options 53 ; push_rbx # push another argument onto stack EB E7 ; jmp !loop_options # next argument -# :loop_options_done [_start + 0x94] +# :loop_options_done [_start + 0x95] # Open file for reading 4158 ; pop_r8 # arg3 = in @@ -242,9 +239,7 @@ F0 00 # SizeOfOptionalHeader # Save variables that are needed for cleanup 4156 ; push_r14 # save system->boot - 4157 ; push_r15 # save image_handle 56 ; push_rsi # save rootdir - 4989E7 ; mov_r15,rsp # save stack location for cleanup # Our flag for byte processing 6A FF ; push !-1 @@ -253,7 +248,7 @@ F0 00 # SizeOfOptionalHeader # temp storage for the sum 31FF ; xor_edi,edi # rdi = 0 -# :loop [_start+0xE2] +# :loop [_start+0xDE] # Read a byte E8 79000000 ; call %read_byte @@ -274,7 +269,7 @@ F0 00 # SizeOfOptionalHeader EB E8 ; jmp !loop # process second byte of pair -# :print [_start+0xFA] +# :print [_start+0xF6] # update the sum and store in output C1E7 04 ; shl_edi, !4 01F8 ; add_eax,edi @@ -286,7 +281,7 @@ F0 00 # SizeOfOptionalHeader EB DA ; jmp !loop -# :hex [_start+0x108] +# :hex [_start+0x104] # Purge Comment Lines (#) 3C 23 ; cmp_al, !35 74 1E ; je !purge_comment @@ -322,7 +317,7 @@ F0 00 # SizeOfOptionalHeader # The rest that remains needs to be ignored EB 09 ; jmp !ascii_other -# :purge_comment [_start+0x12A] +# :purge_comment [_start+0x126] # Read a byte E8 31000000 ; call %read_byte @@ -332,42 +327,39 @@ F0 00 # SizeOfOptionalHeader # Otherwise return -1 -# :ascii_other [_start+0x133] +# :ascii_other [_start+0x12F] 6A FF ; push !-1 58 ; pop_rax # return = -1 C3 ; ret -# :ascii_num [_start+0x137] +# :ascii_num [_start+0x133] 2C 30 ; sub_al, !48 C3 ; ret -# :ascii_low [_start+0x13A] +# :ascii_low [_start+0x136] 2C 20 ; sub_al, !32 # convert to uppercase -# :ascii_high [_start+0x13C] +# :ascii_high [_start+0x138] 2C 37 ; sub_al, !55 C3 ; ret # Writes byte stored in al -# :write_byte [_start+0x13F] +# :write_byte [_start+0x13B] 54 ; push_rsp # align stack to 16 bytes FF3424 ; push_[rsp] # align stack to 16 bytes 4883E4 F0 ; and_rsp, !-16 # align stack to 16 bytes - 50 ; push_rax # make sure next call is aligned to 16 bytes 4C89E9 ; mov_rcx,r13 # arg1 = fout 6A 01 ; push !1 # size = 1 4889E2 ; mov_rdx,rsp # arg2 = &size 50 ; push_rax # allocate stack 4989E0 ; mov_r8,rsp # arg3 = &output - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 28 ; call_[rcx+BYTE] !40 # fout->write() 488B6424 38 ; mov_rsp,[rsp+BYTE] !56 # deallocate stack C3 ; ret # return -# :read_byte [_start+0x160] +# :read_byte [_start+0x15C] 4C89E1 ; mov_rcx,r12 # arg1 = fin 6A 01 ; push !1 # size = 1 4889E2 ; mov_rdx,rsp # arg2 = &size @@ -376,10 +368,7 @@ F0 00 # SizeOfOptionalHeader 54 ; push_rsp # align stack to 16 bytes FF3424 ; push_[rsp] # align stack to 16 bytes 4883E4 F0 ; and_rsp, !-16 # align stack to 16 bytes - 50 ; push_rax # make sure next call is aligned to 16 bytes - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function - 50 ; push_rax # allocate shadow stack space for UEFI function + 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function FF51 20 ; call_[rcx+BYTE] !32 # fin->read() 488B6424 28 ; mov_rsp,[rsp+BYTE] !40 # deallocate stack 58 ; pop_rax # save input to rax @@ -391,10 +380,9 @@ F0 00 # SizeOfOptionalHeader C3 ; ret # return -# :terminate [_start+0x188] - 4C89FC ; mov_rsp,r15 # restore stack location for cleanup +# :terminate [_start+0x184] + 58 ; pop_rax # deallocate stack (return code of read_byte) 5E ; pop_rsi # restore rootdir - 415F ; pop_r15 # restore image_handle 415E ; pop_r14 # restore system->boot 5B ; pop_rbx # restore root_device @@ -407,17 +395,18 @@ F0 00 # SizeOfOptionalHeader FF51 10 ; call_[rcx+BYTE] !16 # rootdir->close() 4D89F8 ; mov_r8,r15 # arg3 = image_handle - 488D15 48000000 ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL + 488D15 49000000 ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL 4889D9 ; mov_rcx,rbx # arg1 = root_device 4D31C9 ; xor_r9,r9 # arg4 = NULL 4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function 41FF96 20010000 ; call_[r14+DWORD] %288 # system->boot->close_protocol(root_device, &guid, image_handle, 0) 4D89F8 ; mov_r8,r15 # arg3 = image_handle - 488D15 1D000000 ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL + 488D15 1E000000 ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL 4C89C1 ; mov_rcx,r8 # arg1 = image_handle 4D31C9 ; xor_r9,r9 # arg4 = NULL 41FF96 20010000 ; call_[r14+DWORD] %288 # system->boot->close_protocol(image_handle, &guid, image_handle, 0) + 4883C4 28 ; add_rsp, !40 # deallocate stack # Restore non-volatile registers 415F ; pop_r15 @@ -428,22 +417,21 @@ F0 00 # SizeOfOptionalHeader 5F ; pop_rdi 5B ; pop_rbx - 4889EC ; mov_rsp,rbp # restore stack 5D ; pop_rbp C3 ; ret # return to UEFI # Protocol GUIDs -# :LOADED_IMAGE_PROTOCOL [_start+0x1E6] +# :LOADED_IMAGE_PROTOCOL [_start+0x1DF] A1 31 1B 5B ; %0x5b1b31a1 62 95 ; $0x9562 D2 11 ; $0x11d2 8E 3F 00 A0 C9 69 72 3B ; !0x8e !0x3f !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b -# :SIMPLE_FS_PROTOCOL [_start+0x1F6] +# :SIMPLE_FS_PROTOCOL [_start+0x1EF] 22 5B 4E 96 ; %0x964e5b22 59 64 ; $0x6459 D2 11 ; $0x11d2 8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b -# :ELF_end [_start+0x206] +# :ELF_end [_start+0x1FF]