summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.sh.s.swpbin0 -> 1024 bytes
-rw-r--r--makefile2
-rwxr-xr-xshbin0 -> 3768 bytes
-rw-r--r--sh.asm (renamed from sh.s)329
-rw-r--r--sh.obin0 -> 4048 bytes
5 files changed, 178 insertions, 153 deletions
diff --git a/.sh.s.swp b/.sh.s.swp
new file mode 100644
index 0000000..9c0da39
--- /dev/null
+++ b/.sh.s.swp
Binary files differ
diff --git a/makefile b/makefile
index 04a37e8..3725a30 100644
--- a/makefile
+++ b/makefile
@@ -1,5 +1,5 @@
all:
- nasm sh.s -f elf64 -o sh.o
+ nasm sh.asm -f elf64 -o sh.o
ld sh.o -o sh
clean:
rm -f sh.o sh
diff --git a/sh b/sh
new file mode 100755
index 0000000..b8aae89
--- /dev/null
+++ b/sh
Binary files differ
diff --git a/sh.s b/sh.asm
index edc6710..123d772 100644
--- a/sh.s
+++ b/sh.asm
@@ -1,3 +1,25 @@
+section .data
+ sigs: dd 0x2
+ cpid: dd 0x0
+ eol: db `\n`
+ msg: db "Welcome to deadbeef shell", 0x21, `\n`
+ prompt: db "[0xdeadbeef]", 0x20
+ nfe: db "Error: program not found", 0x2e, `\n`
+ env: db "/etc/environment", 0x0
+ boem: db "Error: input overflows buffer", 0x2e, `\n`
+
+ ;Syscall constants
+ sys_read equ 0x00
+ sys_write equ 0x01
+ sys_open equ 0x02
+ sys_close equ 0x03
+ stub_fork equ 0x39
+ stub_execve equ 0x3b
+ sys_exit equ 0x3c
+ sys_wait4 equ 0x3d
+ sys_kill equ 0x3e
+
+
section .text
global _start
@@ -13,376 +35,379 @@ _start:
sub rsp, 0x110
mov rbx, rsp
- mov rax, 0x1
+ mov rax, sys_write
mov rdi, 0x1
mov rsi, msg
mov rdx, 0x1b
syscall
- jmp parse_path
+ jmp _parse_path
-rloop:
- mov rax, 0x1
+_rloop:
+ mov rax, sys_write
mov rdi, 0x1
mov rsi, prompt
mov rdx, 0xd
syscall
mov r8, -0x1
- mov r12, rloopr
- jmp bzero
+ mov r12, _rloopr
+ jmp _bzero
-rloopr:
- mov rax, 0x0
+_rloopr:
+ mov rax, sys_read
mov rdi, 0x0
mov rsi, r15
mov rdx, 0xff
syscall
- ; check for quit
+ ; check for _quit
+ mov r12, _quit
cmp byte [r15], 0x0
- mov r12, quit
- je weol
+ je _weol
- ; call parse
- jmp parse
+ ; call _parse
+ jmp _parse
-exec:
+_exec:
; fork so we don't hurt ourselves
- mov rax, 0x39
+ mov rax, stub_fork
syscall
mov dword [cpid], eax
cmp dword [cpid], 0x0
- jne wait4_it
+ jne _wait4_it
; now that we know what to execute, do so
- mov rax, 0x3b
+ mov rax, stub_execve
mov rdi, r13
mov rsi, r14
mov rdx, 0x0
syscall
; and now kill the child process
- jmp quit
+ jmp _quit
-wait4_it:
+_wait4_it:
+ ;This function is obsolete, replace with 247 (sys_waitid)
mov rdi, rax
- mov rax, 0x3d
+ mov rax, sys_wait4
xor rsi, rsi ; null status pointer
xor rdx, rdx
xor rcx, rcx ; null rusage pointer
syscall
mov dword [cpid], -0x1
- jmp rloop
+ jmp _rloop
; input: none
; output: r9 (path elements), r10 (length)
; clobbered: r8, r12
; other: r15 (buffer)
-parse_path:
- mov rax, 0x2
+_parse_path:
+ mov rax, sys_open
mov rdi, env
mov rsi, 0x0
syscall
cmp rax, 0x0
- jl quit
+ jl _quit
mov r8, -0x1
- mov r12, parse_path2
- jmp bzero
+ mov r12, _parse_path2
+ jmp _bzero
-parse_path2:
+_parse_path2:
mov rdi, rax
- mov rax, 0x0
+ mov rax, sys_read
mov rsi, r9
mov rdx, 0xff
syscall
cmp rax, 0x0
- jl quit
+ jl _quit
mov r8, r9
dec r8
-pathfinder:
+_pathfinder:
inc r8
xor rax, rax
mov byte al, [r8]
- cmp al, 0x50
- jne pathfinder
+ cmp al, `P`
+ jne _pathfinder
mov byte al, [r8+1]
- cmp al, 0x41
- jne pathfinder
+ cmp al, `A`
+ jne _pathfinder
mov byte al, [r8+2]
- cmp al, 0x54
- jne pathfinder
+ cmp al, `T`
+ jne _pathfinder
mov byte al, [r8+3]
- cmp al, 0x48
- jne pathfinder
+ cmp al, `H`
+ jne _pathfinder
mov byte al, [r8+4]
- cmp al, 0x3d
- jne pathfinder
+ cmp al, `=`
+ jne _pathfinder
mov byte al, [r8+5]
- cmp al, 0x22
- jne pathfinder
+ cmp al, `"`
+ jne _pathfinder
cmp al, 0x0
- je quit
+ je _quit
add r8, 0x6
mov r10, 0x1
push 0x0
push r8
dec r8
-pathender:
+_pathender:
inc r8
mov al, [r8]
- cmp al, 0x3a
- je pathender1
- cmp al, 0x22
- jne pathender
+ cmp al, `:`
+ je _pathender1
+ cmp al, `"`
+ jne _pathender
mov byte [r8], 0x0
mov r9, rsp
- jmp rloop
+ jmp _rloop
-pathender1:
+_pathender1:
inc r10
mov byte [r8], 0x0
lea rcx, [r8+0x1]
push rcx
- jmp pathender
+ jmp _pathender
+;Writes 0s in buffer r15 until r8 is 255
;input: r8 (iterator), r15 (buffer), r12 (return address)
;output: none
-bzero:
+_bzero:
inc r8
mov byte [r8+r15], 0x0
cmp r8, 0xff
- jle bzero
+ 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
+_parse: ; needs special commands: cd exit export eval
+ ;syscall 80 is chdir, so do that first, it's easiest
+ ;It takes a path string.
;also needs pipes (|, >, <)
push 0x0
xor r13, r13
- jmp strlen
+ jmp _strlen
+;r8 holds strlen so we start at the end and parse backwards
; 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
- cmp byte [r8+r15], 0x2e
- je sabsf
-
-parse1r:
+_parse1:
+ cmp byte [r15+r8], ` `
+ je _subzp
+ cmp byte [r15+r8], `\n`
+ je _subz
+ cmp byte [r15+r8], `/`
+ je _sabsf
+ cmp byte [r15+r8], `.`
+ je _sabsf
+
+;Controls the parsing of the directory, keeps parsing each bit of the dir until
+;the end of the string or directory name
+_parse1r:
dec r8
cmp r8, 0x0
- jl parse2
- jmp parse1
+ jl _parse2
+ jmp _parse1
-sabsf:
+_sabsf:
cmp r8, 0x1
- jg parse1r
+ jg _parse1r
mov r13, 0x1
- jmp parse1r
+ jmp _parse1r
-subz:
+_subz:
mov byte [r8+r15], 0x0
- jmp parse1
+ jmp _parse1
-subzp:
+;Splits at the current position and puts the address of the argument on the stack
+_subzp:
mov byte [r8+r15], 0x0
lea rax, [r8+r15+0x1]
push rax
- jmp parse1
+ jmp _parse1
-parse2:
+_parse2:
push rbx
mov r14, rsp
cmp r13, 0x0
- jg parse7
+ jg _parse7
mov r8, -0x1
-parse3:
+_parse3:
inc r8
cmp r8, r10
- je parse4
+ je _parse4
mov r13, r15
mov rcx, [r9+r8*8]
push r8
- jmp concat
+ jmp _concat
-parse4: ; not found
- mov rax, 0x1
+_parse4: ; not found
+ mov rax, sys_write
mov rdi, 0x1
mov rsi, nfe
mov rdx, 0x1a
syscall
- jmp rloop
+ jmp _rloop
-parse5: ; test rbx
+; Checks that the program rbx exists before doing anything, this is hacky, slow
+; and should therefore be replaced by a version using sys_access with flag X_OK
+_parse5:
pop r8
- mov rax, 0x2
+ mov rax, sys_open
mov rdi, rbx
xor rsi, rsi
xor rdx, rdx
syscall
+ ;Check if it was opened successfully to check if it exists
cmp rax, 0x0
- jl parse3
-
+ jl _parse3
+
mov rdi, rax
- mov rax, 0x3
+ mov rax, sys_close
syscall
-parse6: ; found it
+; We'll fall through to here if the file is accessible, therefore we should execute it
+_parse6:
mov r13, rbx
- jmp exec
+ jmp _exec
-parse7: ; absolute path
- mov rax, 0x2
+_parse7: ; absolute path
+ mov rax, sys_open
mov rdi, r15
xor rsi, rsi
xor rdx, rdx
syscall
cmp rax, 0x0
- jl parse4
+ jl _parse4
mov rdi, rax
- mov rax, 0x3
+ mov rax, sys_close
syscall
mov r13, r15
- jmp exec
-
+ jmp _exec
+
;input: r12 (return address), r15 (buffer)
;output: r8 (length)
-strlen:
+_strlen:
xor r8, r8
-strlen1:
+_strlen1:
cmp byte [r8+r15], 0x0
- je parse1
+ je _parse1
cmp byte [r8+r15], 0xa
- je parse1
+ je _parse1
inc r8
- jmp strlen1
+ jmp _strlen1
; input: rcx (a), r13 (b)
; output: rbx (string)
; clobbered: r8, r11
-concat:
+_concat:
mov r8, -0x1
- jmp jlen1
+ jmp _jlen1
-jlen1:
+_jlen1:
inc r8
cmp byte [r8+rcx], 0x0
- je jlen02
+ je _jlen02
cmp byte [r8+rcx], 0xa
- je jlen02
- jmp jlen1
+ je _jlen02
+ jmp _jlen1
-jlen02:
+_jlen02:
dec r8
mov r11, -0x1
-jlen2:
+_jlen2:
inc r8
inc r11
cmp byte [r11+r13], 0x0
- je treg
+ je _treg
cmp byte [r11+r13], 0xa
- je treg
- jmp jlen2
+ je _treg
+ jmp _jlen2
-treg:
+_treg:
cmp r8, 0xff
- jg boe
+ jg _boe
xchg r15, rbx
mov r8, -0x1
- mov r12, rsinc
- jmp bzero
+ mov r12, _jrsinc
+ jmp _bzero
-rsinc:
+_jrsinc:
xchg r15, rbx
mov r8, -0x1
mov r11, -0x1
-join1:
+_join1:
inc r8
cmp byte [r8+rcx], 0x0
- je join02
+ je _join02
cmp byte [r8+rcx], 0xa
- je join02
+ je _join02
mov al, [r8+rcx]
mov [r8+rbx], al
- jmp join1
+ jmp _join1
-join02:
- mov byte [r8+rbx], 0x2f
-join2:
+_join02:
+ mov byte [r8+rbx], `/`
+_join2:
inc r8
inc r11
cmp byte [r11+r13], 0x0
- je parse5
- cmp byte [r11+r13], 0xa
- je parse5
+ je _parse5
+ cmp byte [r11+r13], `\n`
+ je _parse5
mov al, [r11+r13]
mov [r8+rbx], al
- jmp join2
+ jmp _join2
-boe:
- mov rax, 0x1
+_boe:
+ mov rax, sys_write
mov rdi, 0x1
mov rsi, boem
mov rdx, 0x1f
- jmp quit
+ jmp _quit
; interrupt signal handler
-sigint:
+_sigint:
cmp dword [cpid], 0x0
- jl sigint_nc
+ jl _sigint_nc
-sigint_c: ; kill the child
- mov rax, 0x3e
+__sigint_c: ; kill the child
+ mov rax, sys_kill
mov rdi, [cpid]
mov rsi, 0x2
syscall
-sigint_nc:
- mov r12, rloop
- jmp weol
+_sigint_nc:
+ mov r12, _rloop
+ jmp _weol
; input: r12 (return address)
; output: none
-weol:
- mov rax, 0x1
+; Writes end of line to the terminal
+_weol:
+ mov rax, sys_write
mov rdi, 0x1
mov rsi, eol
mov rdx, 0x1
syscall
jmp r12
-quit:
- mov rax, 0x3c
+_quit:
+ mov rax, sys_exit
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
diff --git a/sh.o b/sh.o
new file mode 100644
index 0000000..164fa55
--- /dev/null
+++ b/sh.o
Binary files differ