Reputation: 2527
I've been able to successfully print a string using the sys_write
to stdout on macOS. However, I cannot get this stack string to print using execve
syscall with echo
:
global _main
default rel
section .text
_main:
mov rbp, rsp
sub rsp, 32
mov rax, 'this a t'
mov [rbp-16], rax
mov rax, 'est'
mov [rbp-8], rax
mov rax, '/bin/ech'
mov [rbp-32], rax
xor rax, rax
mov al, 'o'
mov [rbp-24], rax
push 0
mov rax, 0
mov [rbp], rax
exit_program:
;rdi filename
;rsi argv
;rdx envp
lea rdi, [rbp-32]
lea rsi, [rbp-32]
mov rdx, 0
mov rax, 0x200003b
syscall
Currently, my return is EFAULT status code from execve
.
The memory layout as shown in the screenshot is the string "This is a test" followed by null bytes for termination.
UPDATE: Trace output: execve("/bin/echo", [0x6863652f6e69622f, 0x6f, 0x7420612073696874, 0x747365], NULL) = -1 EFAULT (Bad address)
Upvotes: 1
Views: 148
Reputation: 364180
execve
takes 3 args: a char*
and two char *[]
arrays, each terminated by a NULL pointer.
Your first arg is fine. It points to a zero-terminated array of ASCII characters which are a valid path.
Your argv
is a char[]
, not char *[]
, because you passed the same value as your first arg! So when the system call interprets the data as an array of pointers to copy into the new process's arg array, it finds an invalid pointer 0x6863652f6e69622f
as the first one. (The bytes of that pointer are ASCII codes.)
The trace output makes that pretty clear.
Your 3rd is NULL, not a pointer to NULL. Linux supports this, treating a NULL as an empty array. I don't know if MacOS does or not; if you still get EFAULT after passing a valid argv[]
set RDX to a pointer to a qword 0 somewhere on the stack.
Keeping your existing setup code, you could change the last part to
lea rdi, [rbp-32] ; pointer to "/bin/echo"
push 0 ; NULL terminator
mov rdx, rsp ; envp = empty array
push some_reg ; holding a pointer to "this is a test"
push rdi ; pointer to "/bin/echo" = argv[0]
mov rsi, rsp ; argv
syscall
Note that envp[]
and argv[]
are terminated by the same NULL pointer. If you wanted a non-empty envp
you couldn't do that.
If this is supposed to be shellcode, you're going to need to replace the push 0
with pushing an xor-zeroed register, and it looks like you could simplify some of the other stuff. But get it working first.
Upvotes: 2