# SPDX-FileCopyrightText: 2019 Jeremiah Orians # SPDX-FileCopyrightText: 2022 Andrius Štikonas # SPDX-FileCopyrightText: 2024 Noah Goldstein # # SPDX-License-Identifier: GPL-3.0-or-later ## ELF Header #:ELF_base 7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number 01 # e_ident[EI_CLASS] Indicating 32 bit 01 # e_ident[EI_DATA] Indicating little endianness 01 # e_ident[EI_VERSION] Indicating original elf 03 # e_ident[EI_OSABI] Set at 3 because FreeBSD is strict 00 # e_ident[EI_ABIVERSION] Set at 0 because no one cares 00 00 00 00 00 00 00 # e_ident[EI_PAD] 02 00 # e_type Indicating Executable 03 00 # e_machine Indicating x86 01 00 00 00 # e_version Indicating original elf 4C 80 04 08 # e_entry Address of the entry point 2C 00 00 00 # e_phoff Address of program header table 00 00 00 00 # e_shoff Address of section header table 00 00 00 00 # e_flags 34 00 # e_ehsize Indicating our 52 Byte header 20 00 # e_phentsize size of a program header table # The following 8 bytes are shared by both ELF header and program header. ## Program Header #:ELF_program_headers #:ELF_program_header__text 01 00 # e_phnum number of entries in program table 00 00 # e_shentsize size of a section header table 00 00 # e_shnum number of entries in section table 00 00 # e_shstrndx index of the section names # End of ELF base header # 01 00 00 00 # ph_type: PT-LOAD = 1 # 00 00 00 00 # ph_offset 00 80 04 08 # ph_vaddr 00 80 04 08 # ph_physaddr B5 00 00 00 # ph_filesz B5 00 00 00 # ph_memsz 01 00 00 00 # ph_flags: PF-X = 1 01 00 00 00 # ph_align #:ELF_text # Where the ELF Header is going to hit # Simply jump to _start # Our main function # :_start ; (0x804804C) 58 ; pop_eax # Get the number of arguments 5B ; pop_ebx # Get the program name 5B ; pop_ebx # Get the actual input name 31C9 ; xor_ecx,ecx # prepare read_only, ecx = 0 6A 05 ; push !5 # prepare to set eax to 5 58 ; pop_eax # the syscall number for open() 99 ; cdq # Extra sure, edx = 0 CD 80 ; int !0x80 # Now open that damn file 5B ; pop_ebx # Get the output name 50 ; push_eax # Preserve the file pointer we were given 66B9 4102 ; mov_cx, @577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC 66BA C001 ; mov_dx, @448 # Prepare file as RWX for owner only (700 in octal) 6A 05 ; push !0x5 # Prepare to set eax to 5 58 ; pop_eax # the syscall number for open() CD 80 ; int !0x80 # Now open that damn file 99 ; cdq # edx = 0 since file descriptor is nonnegative 42 ; inc_edx # edx = 1 (count for read/write) 97 ; xchg_eax,edi # Preserve outfile #:loop_reset_all ; (0x8048069) 31ED ; xor_ebp,ebp # ebp = 0 (no prior hex val) # Comment tracking is done with esi. # esi is decremented if we hit a # comment (';' or '#') and reset # if we hit a new-line. #:loop_reset_comment ; (0x804806B) 89D6 ; mov_esi,edx # Set no current comment #:loop_add_comment ; (0x804806D) 4E ; dec_esi #:loop ; (0x804806E) # Read a byte 5B ; pop_ebx # Get infile 89E1 ; mov_ecx,esp # Set buffer # edx is already set to 1. 6A 03 ; push !3 58 ; pop_eax # Set read syscall in eax CD 80 ; int !0x80 # Do the actual read 53 ; push_ebx # Re-save infile 85C0 ; test_eax,eax # Check what we got 75 05 ; jne !cont # No EOF # Exit successfully 40 ; inc_eax # Set exit syscall in eax 31DB ; xor_ebx,ebx # Set return success (ebx = 0) CD 80 ; int !0x80 # Exit #:cont ; (0x8048080) 8A01 ; mov_al,[ecx] # Move prog byte in eax # New line check 3C 0A ; cmp_al, !10 # Check new-line 74 E5 ; je !loop_reset_comment # If new-line, end comment handling # In comment check 85F6 ; test_esi,esi # Skip byte if we are in a comment 75 E4 ; jne !loop # Start comment check 3C 23 ; cmp_al, !35 # Start of '#' comment 74 DF ; je !loop_add_comment 3C 3B ; cmp_al, !59 # Start of ';' comment 74 DB ; je !loop_add_comment # Start of hex str to int 2C 30 ; sub_al, !48 # Subtract ascii '0' from al 2C 0A ; sub_al, !10 # Check for value in '0'-'9' 72 08 ; jb !write # We have hex value, write it 2C 07 ; sub_al, !7 # Subtract ('A'-'0') from al 24 DF ; and_al, !0xDF # Remove lower case bit 3C 07 ; cmp_al, !7 # Check for value 'A'-'F' 73 CE ; jae !loop # We don't have hex value ignore it #:write ; (0x80480A8) C1E5 04 ; shl_ebp, !4 # Shift up existing hex digit 04 0A ; add_al, !10 # Finish converting ascii to raw value 01C5 ; add_ebp,eax # Combine the hex digits # Check if this is first digit in hex val F7DF ; neg_edi # Flip sign of edi to indicate we got a digit 7C C3 ; jl !loop # Negative -> first digit, get another one # We have both digits in low byte of ebp, good to write 8929 ; mov_[ecx],ebp # Move edge to buffer 89FB ; mov_ebx,edi # Move outfile to ebx B0 04 ; mov_al, !4 # Set write syscall in eax CD 80 ; int !0x80 # Do the write EB B4 ; jmp !loop_reset_all # Start a fresh byte #:ELF_end ; (0x80480B5)