汇编工作,但 shellcode 不工作

Assembly works, but shellcode does not

我有一个 x64 处理器,我正在研究 shell代码。
我有以下代码:

section .text
  global _start

_start:
   push rax
   mov rbx, 0x68732f6e69622f2f
   shr rbx, 0x8
   push rbx
   mov rdi, rsp
   ;mov rdi, com

   mov al, 59
   syscall

当使用 foolowing 命令编译时:

nasm -g -f elf64 execve.asm  

并链接到:

ld execve.o -o execve

运行没问题。它打开一个shell。如果我从中得到 shell 代码:

"\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"

并使用这个 C 程序:

int main(void)
{
    const char shellcode[] = "\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05";

    (*(void (*)()) shellcode)();

    return 0;

} 编译它:

gcc -fno-stack-protector -z execstack -o ex2 ex.c

如果 运行 它 returns 一个分段错误,但它应该执行一个 shell。为什么? 感谢帮助!

您遗漏了 \x6e

这会导致 segv,因为 exec 失败并且在系统调用之后没有 return。

您的独立程序集取决于寄存器 rsirdx 被清零。 (从http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/可以看出 sys_execve 通过寄存器 rdirsirdx 接受三个参数,如果 rdi 是正确的文件名并且 Linux 也会接受它rsirdx 为零)。

程序启动时可能会出现这种情况,但当您运行 程序中间。

因此,如果 rsirdx 中有垃圾,系统调用将失败并且指令流 将继续执行它在 syscall 指令之后找到的垃圾字节,最终导致崩溃(这确实是你的情况,正如你所看到的,如果你 运行 程序通过 gdb )

使系统调用成功的最简单方法是将第二个和第三个参数清零:

section .text
  global _start

_start:
   xor rax, rax
   xor rsi, rsi ; zero 2nd argument
   xor rdx, rdx ; zero 3rd argument
   push rax
   mov rbx, 0x68732f6e69622f2f
   shr rbx, 0x8
   push rbx
   mov rdi, rsp

   mov al, 59
   syscall

对应的C代码:

int main(void)
{
 char shellcode[] =

"\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\x50\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
;
    ((void (*)()) shellcode)();
    return 0;
}