summaryrefslogtreecommitdiff
path: root/sh.s
diff options
context:
space:
mode:
Diffstat (limited to 'sh.s')
-rw-r--r--sh.s384
1 files changed, 384 insertions, 0 deletions
diff --git a/sh.s b/sh.s
new file mode 100644
index 0000000..e993a30
--- /dev/null
+++ b/sh.s
@@ -0,0 +1,384 @@
+section .text
+ global _start
+
+_start:
+ ; TODO: handle interrupt signal
+
+ push rbp
+ mov rbp, rsp
+ sub rsp, 0x110
+ mov r15, rsp
+ sub rsp, 0x110
+ mov r9, rsp
+ sub rsp, 0x110
+ mov rbx, rsp
+
+ mov rax, 0x1
+ mov rdi, 0x1
+ mov rsi, msg
+ mov rdx, 0x1b
+ syscall
+
+ jmp parse_path
+
+rloop:
+ mov rax, 0x1
+ mov rdi, 0x1
+ mov rsi, prompt
+ mov rdx, 0xd
+ syscall
+
+ mov r8, -0x1
+ mov r12, rloopr
+ jmp bzero
+
+rloopr:
+ mov rax, 0x0
+ mov rdi, 0x0
+ mov rsi, r15
+ mov rdx, 0xff
+ syscall
+
+ ; check for quit
+ cmp byte [r15], 0x0
+ mov r12, quit
+ je weol
+
+ ; call parse
+ jmp parse
+
+exec:
+ ; fork so we don't hurt ourselves
+ mov rax, 0x39
+ syscall
+ mov dword [cpid], eax
+ cmp dword [cpid], 0x0
+ jne wait4_it
+
+ ; now that we know what to execute, do so
+ mov rax, 0x3b
+ mov rdi, r13
+ mov rsi, r14
+ mov rdx, 0x0
+ syscall
+
+ ; and now kill the child process
+ jmp quit
+
+wait4_it:
+ mov rdi, rax
+ mov rax, 0x3d
+ xor rsi, rsi ; null status pointer
+ xor rdx, rdx
+ xor rcx, rcx ; null rusage pointer
+ syscall
+
+ mov dword [cpid], -0x1
+ jmp rloop
+
+; input: none
+; output: r9 (path elements), r10 (length)
+; clobbered: r8, r12
+; other: r15 (buffer)
+parse_path:
+ mov rax, 0x2
+ mov rdi, env
+ mov rsi, 0x0
+ syscall
+ cmp rax, 0x0
+ jl quit
+
+ mov r8, -0x1
+ mov r12, parse_path2
+ jmp bzero
+
+parse_path2:
+ mov rdi, rax
+ mov rax, 0x0
+ mov rsi, r9
+ mov rdx, 0xff
+ syscall
+ cmp rax, 0x0
+ jl quit
+ mov r8, r9
+ dec r8
+
+pathfinder:
+ inc r8
+ xor rax, rax
+ mov byte al, [r8]
+ cmp al, 0x50
+ jne pathfinder
+ mov byte al, [r8+1]
+ cmp al, 0x41
+ jne pathfinder
+ mov byte al, [r8+2]
+ cmp al, 0x54
+ jne pathfinder
+ mov byte al, [r8+3]
+ cmp al, 0x48
+ jne pathfinder
+ mov byte al, [r8+4]
+ cmp al, 0x3d
+ jne pathfinder
+ mov byte al, [r8+5]
+ cmp al, 0x22
+ jne pathfinder
+ cmp al, 0x0
+ je quit
+ add r8, 0x6
+ mov r10, 0x1
+ push 0x0
+ push r8
+ dec r8
+
+pathender:
+ inc r8
+ mov al, [r8]
+ cmp al, 0x3a
+ je pathender1
+ cmp al, 0x22
+ jne pathender
+ mov byte [r8], 0x0
+ mov r9, rsp
+ jmp rloop
+
+pathender1:
+ inc r10
+ mov byte [r8], 0x0
+ lea rcx, [r8+0x1]
+ push rcx
+ jmp pathender
+
+;input: r8 (iterator), r15 (buffer), r12 (return address)
+;output: none
+bzero:
+ inc r8
+ mov byte [r8+r15], 0x0
+ cmp r8, 0xff
+ jle bzero
+ jmp r12
+
+;input: r15 (buffer)
+;output: r13 (path), r14 (arguments)
+;clobbered: r8, rax, rbx, rcx
+parse: ; needs special commands: cd exit export echo eval pwd
+ ;also needs pipes (|, >, <)
+ push 0x0
+ xor r13, r13
+ jmp strlen
+
+; go through and sub/push
+parse1:
+ cmp byte [r8+r15], 0x20
+ je subzp
+ cmp byte [r8+r15], 0x0a
+ je subz
+ cmp byte [r8+r15], 0x2f
+ je sabsf
+
+parse1r:
+ dec r8
+ cmp r8, 0x0
+ jl parse2
+ jmp parse1
+
+sabsf:
+ mov r13, 0x1
+ jmp parse1r
+
+subz:
+ mov byte [r8+r15], 0x0
+ jmp parse1
+
+subzp:
+ mov byte [r8+r15], 0x0
+ lea rax, [r8+r15+0x1]
+ push rax
+ jmp parse1
+
+parse2:
+ push rbx
+ mov r14, rsp
+ cmp r13, 0x0
+ jg parse7
+ mov r8, -0x1
+
+parse3:
+ inc r8
+ cmp r8, r10
+ je parse4
+ mov r13, r15
+ mov rcx, [r9+r8*8]
+ push r8
+ jmp concat
+
+parse4: ; not found
+ mov rax, 0x1
+ mov rdi, 0x1
+ mov rsi, nfe
+ mov rdx, 0x1a
+ syscall
+ jmp rloop
+
+parse5: ; test rbx
+ pop r8
+
+ mov rax, 0x2
+ mov rdi, rbx
+ xor rsi, rsi
+ xor rdx, rdx
+ syscall
+
+ cmp rax, 0x0
+ jl parse3
+
+ mov rdi, rax
+ mov rax, 0x3
+ syscall
+
+parse6: ; found it
+ mov r13, rbx
+ jmp exec
+
+parse7: ; absolute path
+ mov rax, 0x2
+ mov rdi, r15
+ xor rsi, rsi
+ xor rdx, rdx
+ syscall
+
+ cmp rax, 0x0
+ jl parse4
+
+ mov rdi, rax
+ mov rax, 0x3
+ syscall
+
+ mov r13, r15
+ jmp exec
+
+
+;input: r12 (return address), r15 (buffer)
+;output: r8 (length)
+strlen:
+ xor r8, r8
+
+strlen1:
+ cmp byte [r8+r15], 0x0
+ je parse1
+ cmp byte [r8+r15], 0xa
+ je parse1
+ inc r8
+ jmp strlen1
+
+; input: rcx (a), r13 (b)
+; output: rbx (string)
+; clobbered: r8, r11
+concat:
+ mov r8, -0x1
+ jmp jlen1
+
+jlen1:
+ inc r8
+ cmp byte [r8+rcx], 0x0
+ je jlen02
+ cmp byte [r8+rcx], 0xa
+ je jlen02
+ jmp jlen1
+
+jlen02:
+ dec r8
+ mov r11, -0x1
+
+jlen2:
+ inc r8
+ inc r11
+ cmp byte [r11+r13], 0x0
+ je treg
+ cmp byte [r11+r13], 0xa
+ je treg
+ jmp jlen2
+
+treg:
+ cmp r8, 0xff
+ jg boe
+ xchg r15, rbx
+ mov r8, -0x1
+ mov r12, rsinc
+ jmp bzero
+
+rsinc:
+ xchg r15, rbx
+ mov r8, -0x1
+ mov r11, -0x1
+
+join1:
+ inc r8
+ cmp byte [r8+rcx], 0x0
+ je join02
+ cmp byte [r8+rcx], 0xa
+ je join02
+ mov al, [r8+rcx]
+ mov [r8+rbx], al
+ jmp join1
+
+join02:
+ mov byte [r8+rbx], 0x2f
+join2:
+ inc r8
+ inc r11
+ cmp byte [r11+r13], 0x0
+ je parse5
+ cmp byte [r11+r13], 0xa
+ je parse5
+ mov al, [r11+r13]
+ mov [r8+rbx], al
+ jmp join2
+
+boe:
+ mov rax, 0x1
+ mov rdi, 0x1
+ mov rsi, boem
+ mov rdx, 0x1f
+ jmp quit
+
+; interrupt signal handler
+sigint:
+ cmp dword [cpid], 0x0
+ jl sigint_nc
+
+sigint_c: ; kill the child
+ mov rax, 0x3e
+ mov rdi, [cpid]
+ mov rsi, 0x2
+ syscall
+
+sigint_nc:
+ mov r12, rloop
+ jmp weol
+
+; input: r12 (return address)
+; output: none
+weol:
+ mov rax, 0x1
+ mov rdi, 0x1
+ mov rsi, eol
+ mov rdx, 0x1
+ syscall
+ jmp r12
+
+quit:
+ mov rax, 0x3c
+ mov rdi, 0x0
+ syscall
+
+section .data
+ sigs: dd 0x2
+ cpid: dd 0x0
+ eol: db 0xa
+ msg: db "Welcome to deadbeef shell", 0x21, 0x0a
+ prompt: db "[0xdeadbeef]", 0x20
+ nfe: db "Error: program not found", 0x2e, 0x0a
+ env: db "/etc/environment", 0x0
+ boem: db "Error: input overflows buffer", 0x2e, 0x0a