151 lines
3.8 KiB
NASM
151 lines
3.8 KiB
NASM
;; 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|