【问题标题】:Why won't this stack string print in x64 NASM on macOS?为什么这个堆栈字符串不会在 macOS 上的 x64 NASM 中打印?
【发布时间】:2020-03-29 20:56:19
【问题描述】:

我已经能够使用sys_write 成功地将字符串打印到 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)

【问题讨论】:

  • @JimMischel 不幸的是没有。一种是 x86。另一个在这种情况下不起作用(尝试 rsp + 8 和 + 16 加载 cl arg)。
  • 另外,您应该检查返回值。如果execve 成功,则不会返回。如果失败,则返回 -1。您可以在调用后放置一些代码,输出一个“调用失败”的字符串。至少你可以缩小错误存在的范围。
  • @JimMischel 最后一个链接很有帮助,但我仍然有些困惑,我想是因为我不熟悉 AT&T 语法,再加上答案是使用 mov s 而不是推动 args。大多数情况下,我不确定如何正确终止参数字符串“这是一个测试”和 argv 数组本身,以及 envp。例如。我必须为 envp 推 0,然后为 0 来终止 argv,然后是堆栈数据吗?最后,我不确定他所说的“文件名”是什么意思,以及它在这里如何应用。

标签: string macos assembly stack nasm


【解决方案1】:

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

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

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

跟踪输出非常清楚。

您的第三个是 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 替换为推送一个异或零寄存器,看起来您可以简化其他一些内容。但先让它发挥作用。

【讨论】:

  • 所以问题是我需要堆栈内存的地址,它将字符串保存在连续内存中,并在“之后”使用 NULL 终止符。您的回答,加上在调试器中的更多时间,帮助我意识到了这一点。非常感谢。我还有 14 小时才能获得赏金。
猜你喜欢
  • 2020-11-08
  • 2014-08-23
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多