# SPDX-FileCopyrightText: 2019 Jeremiah Orians # SPDX-FileCopyrightText: 2022 Andrius Štikonas # # 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 54 80 04 08 # e_entry Address of the entry point 34 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 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 ## Program Header #:ELF_program_headers #:ELF_program_header__text 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 00 01 00 00 # ph_filesz 00 01 00 00 # ph_memsz 07 00 00 00 # ph_flags: PF-X|PF-W|PF-R = 7 01 00 00 00 # ph_align #:ELF_text # Where the ELF Header is going to hit # Simply jump to _start # Our main function # :_start ; (0x8048054) 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 31D2 ; xor_edx,edx # Extra sure, edx = 0 6A 05 ; push !5 # prepare to set eax to 5 58 ; pop_eax # the syscall number for open() CD 80 ; int !0x80 # Now open that damn file 89C6 ; mov_esi,eax # Preserve the file pointer we were given 5B ; pop_ebx # Get the actual output name 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 !5 # prepare to set eax to 5 58 ; pop_eax # the syscall number for open() CD 80 ; int !0x80 # Now open that damn file 89C2 ; mov_edx,eax # Preserve the file pointer we were given # Our flag for byte processing 6A FF ; push !-1 5D ; pop_ebp # ebp = -1 # temp storage for the sum 31FF ; xor_edi,edi # edi = 0 #:loop ; (0x8048077) # Read a byte E8 68000000 ; call %Read_byte # process byte E8 1B000000 ; call %hex # Deal with -1 values 85C0 ; test_eax,eax 7C F2 ; jl !loop # deal with toggle 85ED ; test_ebp,ebp # jump if ebp >= 0 7D 06 ; jge !print # process first byte of pair 89C7 ; mov_edi,eax 31ED ; xor_ebp,ebp # ebp = 0 EB E8 ; jmp !loop # process second byte of pair #:print ; (0x804808F) # update the sum and store in output C1E7 04 ; shl_edi, !4 01F8 ; add_eax,edi # flip the toggle 4D ; dec_ebp # ebp = -1 E8 39000000 ; call %write_byte EB DB ; jmp !loop #:hex ; (0x804809C) # Purge Comment Lines (#) 3C 23 ; cmp_al, !35 74 1E ; je !purge_comment # Purge Comment Lines (;) 3C 3B ; cmp_al, !59 74 1A ; je !purge_comment # deal all ascii less than 0 3C 30 ; cmp_al, !48 7C 1F ; jl !ascii_other # deal with 0-9 3C 3A ; cmp_al, !58 7C 1F ; jl !ascii_num # deal with all ascii less than A 3C 41 ; cmp_al, !65 7C 17 ; jl !ascii_other # deal with A-F 3C 47 ; cmp_al, !71 7C 1C ; jl !ascii_high # deal with all ascii less than a 3C 61 ; cmp_al, !97 7C 0F ; jl !ascii_other # deal with a-f 3C 67 ; cmp_al, !103 7C 12 ; jl !ascii_low # The rest that remains needs to be ignored EB 09 ; jmp !ascii_other #:purge_comment ; (0x80480BE) # Read a byte E8 21000000 ; call %Read_byte # Loop if not LF 3C 0A ; cmp_al, !10 75 F7 ; jne !purge_comment # Otherwise return -1 #:ascii_other ; (0x80480C7) 6A FF ; push !-1 58 ; pop_eax # return -1 C3 ; ret #:ascii_num ; (0x80480CB) 2C 30 ; sub_al, !48 C3 ; ret #:ascii_low ; (0x80480CE) 2C 20 ; sub_al, !32 # convert to uppercase #:ascii_high ; (0x80480D0) 2C 37 ; sub_al, !55 C3 ; ret # Writes byte stored in al #:write_byte ; (0x80480D3) # Print our Hex 89D3 ; mov_ebx,edx # Where are we writing to 52 ; push_edx # protect fout 6A 01 ; push !1 # prepare to set edx to 1 5A ; pop_edx # set the size of chars we want 50 ; push_eax # Move output to stack 89E1 ; mov_ecx,esp # What we are writing 6A 04 ; push !4 # prepare to set eax to 4 58 ; pop_eax # the syscall number for write CD 80 ; int !0x80 # call the Kernel 5B ; pop_ebx # deallocate stack 5A ; pop_edx # restore fout C3 ; ret #:Read_byte ; (0x80480E4) # Attempt to read 1 byte from Input file 52 ; push_edx # protect fout 6A 01 ; push !1 # prepare to set edx to 1 5A ; pop_edx # set the size of chars we want 57 ; push_edi # allocate stack 89E1 ; mov_ecx,esp # Where to put it 89F3 ; mov_ebx,esi # Where are we reading from 6A 03 ; push !3 # prepare to set eax to 3 58 ; pop_eax # the syscall number for read CD 80 ; int !0x80 # call the Kernel 85C0 ; test_eax,eax # check what we got 74 03 ; je !Done # Got EOF call it done # load byte 58 ; pop_eax # load char 5A ; pop_edx # restore fout C3 ; ret #:Done ; (0x80480F9) # program completed Successfully 31DB ; xor_ebx,ebx # All is well, ebx = 0 6A 01 ; push !1 58 ; pop_eax # put the exit syscall number in eax CD 80 ; int !0x80 # Call it a good day #:ELF_end