|
| 1 | +# 154 lines 89 code 34 comments 31 blanks |
| 2 | +# SPDX-FileCopyrightText: 2017 Jeremiah Orians <jeremiah@pdp10.guru> |
| 3 | +# SPDX-FileCopyrightText: 2023 Andrius Štikonas <andrius@stikonas.eu> |
| 4 | +# |
| 5 | +# SPDX-License-Identifier: GPL-3.0-or-later |
| 6 | + |
| 7 | +## ELF Header |
| 8 | +#:ELF_base |
| 9 | +7F 45 4C 46 ## e_ident[EI_MAG0-3] ELF's magic number |
| 10 | + |
| 11 | +02 ## e_ident[EI_CLASS] Indicating 64 bit |
| 12 | +01 ## e_ident[EI_DATA] Indicating little endianness |
| 13 | +01 ## e_ident[EI_VERSION] Indicating original elf |
| 14 | + |
| 15 | +03 ## e_ident[EI_OSABI] Set at 3 because FreeBSD is strict |
| 16 | +00 ## e_ident[EI_ABIVERSION] Set at 0 because none cares |
| 17 | + |
| 18 | +00 00 00 00 00 00 00 ## e_ident[EI_PAD] |
| 19 | +02 00 ## e_type Indicating Executable |
| 20 | +3E 00 ## e_machine Indicating AMD64 |
| 21 | +01 00 00 00 ## e_version Indicating original elf |
| 22 | + |
| 23 | +78 00 60 00 00 00 00 00 ## e_entry Address of the entry point (Number of bytes this header is + Base Address) |
| 24 | +40 00 00 00 00 00 00 00 ## e_phoff Address of program header table |
| 25 | +00 00 00 00 00 00 00 00 ## e_shoff Address of section header table |
| 26 | + |
| 27 | +00 00 00 00 ## e_flags |
| 28 | +40 00 ## e_ehsize Indicating our 64 Byte header |
| 29 | + |
| 30 | +38 00 ## e_phentsize size of a program header table |
| 31 | +01 00 ## e_phnum number of entries in program table |
| 32 | + |
| 33 | +00 00 ## e_shentsize size of a section header table |
| 34 | +00 00 ## e_shnum number of entries in section table |
| 35 | + |
| 36 | +00 00 ## e_shstrndx index of the section names |
| 37 | + |
| 38 | +## Program Header |
| 39 | +#:ELF_program_headers |
| 40 | +01 00 00 00 ## p_type |
| 41 | +01 00 00 00 ## p_flags: PF-X = 1 |
| 42 | +00 00 00 00 00 00 00 00 ## p_offset |
| 43 | + |
| 44 | +00 00 60 00 00 00 00 00 ## p_vaddr |
| 45 | +00 00 60 00 00 00 00 00 ## p_physaddr |
| 46 | + |
| 47 | +E5 00 00 00 00 00 00 00 ## p_filesz |
| 48 | +E5 00 00 00 00 00 00 00 ## p_memsz |
| 49 | + |
| 50 | +01 00 00 00 00 00 00 00 ## Required alignment |
| 51 | + |
| 52 | +#:ELF_text |
| 53 | + |
| 54 | +# Where the ELF Header is going to hit |
| 55 | +# Simply jump to _start |
| 56 | +# Our main function |
| 57 | +#:_start (0x600078) |
| 58 | + 58 ; pop_rax # Get the number of arguments |
| 59 | + 5F ; pop_rdi # Get the program name |
| 60 | + 5F ; pop_rdi # Get the actual input name |
| 61 | + 31F6 ; xor_esi,esi # prepare read_only, rsi = 0 |
| 62 | + 6A 02 ; push !2 # prepare syscall number |
| 63 | + 58 ; pop_rax # the syscall number for open() |
| 64 | + 99 ; cdq # Extra sure, rdx = 0 |
| 65 | + 0F05 ; syscall # Now open that damn file |
| 66 | + 5F ; pop_rdi # Get the actual output name |
| 67 | + 50 ; push_rax # Preserve the file pointer we were given |
| 68 | + 66BE 4102 ; mov_si, @577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC |
| 69 | + 66BA C001 ; mov_dx, @448 # Prepare file as RWX for owner only (700 in octal) |
| 70 | + 6A 02 ; push !2 # prepare syscall number |
| 71 | + 58 ; pop_rax # the syscall number for open() |
| 72 | + 0F05 ; syscall # Now open that damn file |
| 73 | + 93 ; xchg_ebx,eax # Preserve the file pointer we were given |
| 74 | + 99 ; cdq # rdx = 0 since file descriptor is nonnegative |
| 75 | + FFC2 ; inc_edx # rdx = 1 (count for read/write) |
| 76 | + |
| 77 | +#:loop_reset_all (0x600096) |
| 78 | + 31ED ; xor_ebp,ebp # ebp = 0 (no prior hex val) |
| 79 | + |
| 80 | +# Comment tracking is done with ecx. |
| 81 | +# ecx is decremented if we hit a |
| 82 | +# comment (';' or '#') and reset |
| 83 | +# if we hit a new-line. |
| 84 | +#:loop_reset_comment (0x600098) |
| 85 | + 52 ; push_rdx |
| 86 | + 59 ; pop_rcx # Set no current comment |
| 87 | +#:loop_add_comment (0x60009A) |
| 88 | + FFC9 ; dec_ecx |
| 89 | +#:loop (0x60009C) |
| 90 | + |
| 91 | + # Read a byte |
| 92 | + 5F ; pop_rdi # Get infile |
| 93 | + 54 ; push_rsp |
| 94 | + 5E ; pop_rsi # Set buffer |
| 95 | + # rdx is already set to 1. |
| 96 | + 31C0 ; xor_eax,eax # Set read syscall in rax |
| 97 | + 51 ; push_rcx # Save comment tracking |
| 98 | + 0F05 ; syscall # Do the actual read |
| 99 | + 59 ; pop_rcx # Restore comment tracking |
| 100 | + 57 ; push_rdi # Re-save infile |
| 101 | + 85C0 ; test_eax,eax # Check what we got |
| 102 | + 75 06 ; jne !cont # No EOF |
| 103 | + |
| 104 | + # Exit successfully |
| 105 | + B0 3C ; mov_al, !60 # Set exit syscall in rax |
| 106 | + 31FF ; xor_edi,edi # Set return success (rdi = 0) |
| 107 | + 0F05 ; syscall # Exit |
| 108 | + |
| 109 | +#:cont (0x6000B0) |
| 110 | + 8A06 ; mov_al,[rsi] # Move prog byte in eax |
| 111 | + |
| 112 | + # New line check |
| 113 | + 3C 0A ; cmp_al, !10 # Check new-line |
| 114 | + 74 E2 ; je !loop_reset_comment # If new-line, end comment handling |
| 115 | + |
| 116 | + # In comment check |
| 117 | + 85C9 ; test_ecx,ecx # Skip byte if we are in a comment |
| 118 | + 75 E2 ; jne !loop |
| 119 | + |
| 120 | + # Start comment check |
| 121 | + 3C 23 ; cmp_al, !35 # Start of '#' comment |
| 122 | + 74 DC ; je !loop_add_comment |
| 123 | + |
| 124 | + 3C 3B ; cmp_al, !59 # Start of ';' comment |
| 125 | + 74 D8 ; je !loop_add_comment |
| 126 | + |
| 127 | + # Start of hex str to int |
| 128 | + 2C 30 ; sub_al, !48 # Subtract ascii '0' from al |
| 129 | + 2C 0A ; sub_al, !10 # Check for value in '0'-'9' |
| 130 | + 72 08 ; jb !write # We have hex value, write it |
| 131 | + |
| 132 | + 2C 07 ; sub_al, !7 # Subtract ('A'-'0') from al |
| 133 | + 24 DF ; and_al, !0xDF # Remove lower case bit |
| 134 | + 3C 07 ; cmp_al, !7 # Check for value 'A'-'F' |
| 135 | + 73 CC ; jae !loop # We have hex value, write it |
| 136 | + |
| 137 | +#:write (0x6000D0) |
| 138 | + C1E5 04 ; shl_ebp, !4 # Shift up existing hex digit |
| 139 | + 04 0A ; add_al, !10 # Finish converting ascii to raw value |
| 140 | + 01C5 ; add_ebp,eax # Combine the hex digits |
| 141 | + |
| 142 | + # Check if this is first digit in hex val |
| 143 | + F7DB ; neg_ebx # Flip sign of r10 to indicate we got a digit |
| 144 | + 7C C1 ; jl !loop # Negative -> first digit, get another one |
| 145 | + |
| 146 | + # We have both digits in low byte of ebp, good to write |
| 147 | + 892E ; mov_[rsi],ebp # Move edge to buffer |
| 148 | + 89DF ; mov_edi,ebx # Move outfile to rdi |
| 149 | + B0 01 ; mov_al, !1 # Set write syscall in rax |
| 150 | + 0F05 ; syscall # Do the write |
| 151 | + EB B1 ; jmp !loop_reset_all # Start a fresh byte |
| 152 | + |
| 153 | +#:ELF_end (0x6000E5) |
| 154 | + |
0 commit comments