我已经能够使用sys_write
成功打印一个字符串到stdout在macOS上。但是,我无法使用execve
和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
目前,我的回馈是来自execve
的EFAULT状态代码。
如屏幕快照所示,内存布局是字符串“ This is a test”,后跟空字节以终止。
更新:跟踪输出:execve("/bin/echo", [0x6863652f6e69622f, 0x6f, 0x7420612073696874, 0x747365], NULL) = -1 EFAULT (Bad address)
答案 0 :(得分:2)
execve
需要3个参数:一个char*
和两个char *[]
数组,每个数组都由NULL指针终止。
您的第一个arg很好。它指向一个以零结尾的ASCII字符数组,这是一个有效路径。
您的argv
是char[]
,而不是char *[]
,因为您传递的值与第一个arg相同!因此,当系统调用将数据解释为要复制到新进程的arg数组的指针数组时,它将发现无效的指针0x6863652f6e69622f
作为第一个指针。 (该指针的字节是ASCII码。)
跟踪输出清楚地表明了这一点。
您的第3个为NULL,而不是指向 NULL的指针。 Linux支持此功能,将NULL视为空数组。我不知道MacOS是否可以。如果您在传递有效的argv[]
之后仍然得到EFAULT,请将RDX设置为指向堆栈中某个位置的qword 0的指针。
保留现有的设置代码,您可以将最后一部分更改为
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
请注意,envp[]
和argv[]
由相同的NULL指针终止。如果您想要一个非空的envp
,则不能这样做。
如果这应该是shellcode,则您需要通过推送异或为零的寄存器来替换push 0
,并且看起来您可以简化其他一些内容。但是先让它工作。