由于以一种奇怪的方式使用 push/pop,您的代码不必要地难以遵循,但是在 strace -f ./a.out 下运行您的程序以跟踪系统调用显示:
... dynamic linker and libc init stuff before main() is called ...
execve("/bin/sh", ["/bin/sh", "\211\307\350\t\222\1", "\367", "\367", 0x100000000, "\350\10"], [/* 0 vars */]) = -1 EFAULT (Bad address)
exit_group(0) = ?
+++ exited with 0 +++
所以在我的系统上,execve 返回错误,但程序成功退出。 IDK 你如何得到/bin/sh: 0: Can't open ????。您的问题没有包含足够的信息来重现您的结果。但也许当你尝试时,堆栈碰巧包含不同的垃圾。我用gcc -g foo.S 构建了它。
在main 未能返回后,执行落入main 之后的任何 CRT 函数,该函数以 RET 指令结束。它也必须为零 eax,因为在 SYSCALL 之后它将是 -EFAULT。
不管怎样,你的 asm 就相当于这个无用的代码:
int main(void) {
const char *p = "/bin/sh";
execve(p, &p, NULL);
}
注意push %rsp; pop %rsi 等同于mov %rsp, %rsi。所以 RSI 持有指向 CALL 写入“返回地址”的堆栈内存的指针。
在此之后的另一个 POP 取消引用堆栈指针并将指向字符串的指针加载到 RDI 中。
使用 CALL 来推送字符串的地址真的很讨厌。 IDK 你为什么要这样做。像普通人一样使用 MOV。
如何正确地做到这一点
# build with gcc -no-pie -g shell.S
#include <asm/unistd.h> // for __NR_execve
// #include <sys/syscall.h> // or include this glibc header for SYS_execve
main: # main(argc, argv, envp)
mov $shell, %edi # filename = shell
# argv = main's argv, already in rsi (not on the stack like in _start)
# leave RDX = envp
# xor %edx, %edx # envp = NULL
mov $__NR_execve, %eax # execve
syscall # execve(shell, argv, envp)
ret # in case the syscall fails
.section .rodata
shell:
.string "/bin/sh"
这行得通,不会做任何奇怪的事情。
或者,以一种与位置无关的平面二进制文件的方式工作,并且不使用 main() 的 argv,因为您添加了该请求:
#include <asm/unistd.h> // for __NR_execve
// #include <sys/syscall.h> // or include this glibc header for SYS_execve
.globl main
main:
lea shell(%rip), %rdi # filename = shell
xor %edx, %edx # envp = NULL
push %rdx # or push $0
push %rdi
mov %rsp, %rsi # argv = { $shell, NULL } that we just pushed
mov $__NR_execve, %eax # execve(
syscall
ret # in case the syscall fails
shell: # still part of the .text section, and we don't use the absolute address of the label, only for a RIP-relative LEA.
.string "/bin/sh"
您的 RSI=RSP 想法不错,但是您忘记在 argv[] 数组的末尾添加一个终止 NULL 指针。
在main 之外,将envp[] 作为参数,我们没有已经构造的envp[] 可以在任何方便的地方访问,所以只需传递NULL。在 Linux 上,这相当于将一个有效指针传递给一个空的以 NULL 结尾的数组,即一个指向内存中 8 字节 0 的指针。