;; Program that takes an output file to which it writes elf64 headers and the contents of a second file which is assumed to be a text section. die: mov rax, 60 ; syscall: exit mov rdi, 0 ; status: 0 syscall ret fopen: mov rax, 2 ; syscall: open mov rsi, 0 ; flags: O_RDONLY mov rdx, 0 ; mode syscall ret fopen_write: mov rax, 2 ; syscall: open mov rsi, 0x241 ; flags: O_WRONLY | O_CREAT | O_TRUNC mov rdx, 0o644 ; mode: rw-r--r-- syscall ret ;; rdi: fd ;; rsi: buffer fstat: mov rax, 5 ; syscall: fstat syscall ret fsize: push rdi push rsi call fstat pop rsi pop rdi mov rax, [rsi + 48] ; st_size ret ;; rdi: src ;; rsi: dst ;; rdx: len memcpy: .memcpy_loop: test rdx, rdx jz .memcpy_done mov al, byte [rdi] mov byte [rsi], al inc rsi inc rdi dec rdx jmp .memcpy_loop .memcpy_done: ret ;; variables: ;; +0 buffer: [u8; 0x1000] ;; +0x1000 bytes_read: u32 ;; +0x1004 in_size: u32 ;; +0x1008 in_fd: u32 ;; +0x100c out_fd: u32 ;; +0x1010 argc: u32 ;; +0x1018 argv: *const *const u8 global _start _start: mov eax, dword [rsp] ; argc lea rbx, [rsp + 8] ; argv sub rsp, 0x4000 ; reserve stack space mov r15, rsp ; r15 = pointer to our state mov dword [r15 + 0x1010], eax ; store argc mov qword [r15 + 0x1018], rbx ; store argv cmp eax, 3 jl die ;; open output file mov rdi, [r15 + 0x1018] ; rdi = argv add rdi, 8 ; rdi = argv[1] mov rdi, [rdi] ; rdi = pointer to argv[1] call fopen_write mov dword [r15 + 0x100c], eax ; store out_fd ;; open input file and get size mov rdi, [r15 + 0x1018] ; rdi = argv add rdi, 16 ; rdi = argv[2] mov rdi, [rdi] ; rdi = pointer to argv[2] call fopen mov dword [r15 + 0x1008], eax ; store in_fd mov edi, eax ; rdi = in_fd lea rsi, [r15] ; rsi = pointer to statbuf call fsize mov dword [r15 + 0x1004], eax ; store in_size ;; copy elf header to scratch space mov rdi, 0x400000 mov rsi, r15 mov rdx, 0x40 call memcpy ;; copy program header to scratch space mov rdi, 0x400040 lea rsi, [r15 + 0x40] mov rdx, 0x38 call memcpy ;; write p_filesz and p_memsz to 0x78 + in_size mov rax, 0x78 add eax, dword [r15 + 0x1004] ; rax = 0x78 + in_size mov dword [r15 + 0x60], eax ; write p_filesz mov dword [r15 + 0x68], eax ; write p_memsz ;; write e_entry to point at 0x40 + 0x38 + in_size - 5 sub rax, 5 add rax, 0x400000 mov dword [r15 + 24], eax ; write e_entry ;; write Ehdr and Phdr to output file mov edi, dword [r15 + 0x100c] ; rdi = out_fd mov rsi, r15 ; rsi = buffer mov rdx, 0x78 ; size of Ehdr + Phdr mov rax, 1 ; syscall: write syscall ;; copy text section from input file to output file .copy_loop: mov edi, dword [r15 + 0x1008] ; rdi = in_fd mov rsi, r15 ; rsi = pointer to buffer mov rdx, 0x1000 ; rdx = size of buffer mov rax, 0 ; syscall: read syscall test rax, rax jle die mov dword [r15 + 0x1000], eax ; store number of bytes read mov edi, dword [r15 + 0x100c] ; rdi = out_fd mov rsi, r15 ; rsi = pointer to buffer mov edx, dword [r15 + 0x1000] ; rdx = number of bytes read mov rax, 1 ; syscall: write syscall cmp dword [r15 + 0x1000], 0x1000 ; if we read less than 0x1000 bytes, we are done je .copy_loop call die