首页 > 解决方案 > 为什么这个堆栈字符串不会在 macOS 上的 x64 NASM 中打印?

问题描述

我已经能够sys_write在 macOS 上使用 to stdout 成功打印字符串。但是,我无法使用execvesyscall打印此堆栈字符串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

目前,我的回报是来自 EFAULT 状态码execve

屏幕截图中显示的内存布局是字符串“This is a test”,后跟用于终止的空字节。

更新:跟踪输出:execve("/bin/echo", [0x6863652f6e69622f, 0x6f, 0x7420612073696874, 0x747365], NULL) = -1 EFAULT (Bad address) 在此处输入图像描述

标签: stringmacosassemblystacknasm

解决方案


execve需要 3 个参数:一个char*和两个char *[]数组,每个数组都由一个 NULL 指针终止。

你的第一个参数很好。它指向一个以零结尾的 ASCII 字符数组,这是一个有效的路径。

argv是 a char[],不是char *[],因为您传递的值与您的第一个 arg 相同!因此,当系统调用将数据解释为要复制到新进程的 arg 数组中的指针数组时,它会找到一个无效指针0x6863652f6e69622f作为第一个指针。(该指针的字节是 ASCII 代码。)

跟踪输出非常清楚。

您的第三个是 NULL,而不是指向NULL 的指针。Linux 支持这一点,将 NULL 视为空数组。我不知道 MacOS 有没有;如果在将有效的argv[]集合 RDX 传递给指向堆栈上某处的 qword 0 的指针后仍然得到 EFAULT。

保留现有的设置代码,您可以将最后一部分更改为

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[]andargv[]由相同的 NULL 指针终止。如果你想要一个非空的envp,你就不能这样做。

如果这应该是 shellcode,你将需要push 0用推送一个异或零寄存器来替换,看起来你可以简化一些其他的东西。但先让它工作。


推荐阅读