【问题标题】:Why syscall instruction doesn't execute?为什么系统调用指令不执行?
【发布时间】:2016-10-07 09:32:06
【问题描述】:
0x7fffffffeef8: xor    %rsi,%rsi
0x7fffffffeefb: xor    %rax,%rax   <- now rax is 0
0x7fffffffeefe: movabs $0xff978cd091969dd1,%rbx   <- rbx='/bin/dash'
0x7fffffffef08: neg    %rbx
0x7fffffffef0b: push   %rbx
0x7fffffffef0c: push   %rsp
0x7fffffffef0d: pop    %rdi   <- rdi is string
0x7fffffffef0e: mov    $0x3b,%al
0x7fffffffef10: syscall 

(gdb) stepi
0x00007fffffffef08 in ?? ()
(gdb) stepi
0x00007fffffffef0b in ?? ()
(gdb) stepi
0x00007fffffffef0c in ?? ()
(gdb) stepi
0x00007fffffffef0d in ?? ()
(gdb) stepi
0x00007fffffffef0e in ?? ()
(gdb) stepi
0x00007fffffffef10 in ?? ()
(gdb) stepi
0x00007fffffffef12 in ?? ()

0x7fffffffef10 中,存在系统调用指令。但是当我在 GDB 中使用 stepi 命令时,我从不执行 /bin/dash。我认为这个程序集应该执行/bin/dash。我误会了吗?

我上传了完整的汇编代码。我把xor %eax, %eax改成了xor %rax, %rax

我在汇编代码中添加了xor %rdx, %rdx。但我无法获得预期的结果。

process 1993 is executing new program: /bin/dash
[Inferior 1 (process 1993) exited normally]
(gdb) 

结果是这样的,但我想要的是$而不是(gdb)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
    char str[256];

    printf("Type sentence.\n");
    gets(str);
    printf("%s\n", str);
}

上面是插入了shell代码的程序。

我使用 Linux 16.04,x64 架构

【问题讨论】:

  • syscall 很可能确实被执行了,但它的参数在某种程度上是错误的。您没有提供minimal reproducible example,所以我们无法确定。
  • 除了al=0x3brdi = rsp 之外,您不会在代码中显示任何参数值。这甚至不足以确定调用了哪个系统调用函数。如果你足够幸运,在此之前rax 几乎为零,它将执行execve。我认为它需要 3 个参数(我不确定要检查哪些文档来检查系统调用,因为 linux 源代码中有几个类似的 C 入口点)。看起来你误解了汇编的工作原理,以及在rsi/etc 中提供价值意味着什么。
  • 我怀疑您的问题与 RDX (envp) 中的参数有关。您可能希望阅读execve 文档。我猜,当您将此代码作为程序运行时,您很幸运 RDX 恰好为 0(NULL)并且没有生成错误(如果出现错误,则返回值指示因此将在系统调用后的 RAX 中)。您可以通过strace 运行您的程序以查看系统调用、参数和返回值。您可能会发现它失败的原因。
  • 在你的程序上运行strace 说明了什么。 execve 应该有一行。在syscall 之后,RAX 中的返回值是多少?您可以通过发出以下命令来打开文本模式 windows gdb:layout asm,后跟 layout reg
  • 大多数在 shell 代码中启动 /bin/sh 的人并不是为了启动与用户的交互式终端。他们使用它来运行无需用户输入即可完成有趣事情的命令。由于您的用户输入来自文件,因此 shell 不会变成交互式的,也不会提供提示。

标签: assembly gdb 64-bit system-calls shellcode


【解决方案1】:

内存保护是一个相当复杂的主题,但前提是将代码与数据隔离开来,并将一个进程与另一个进程隔离开来。确实没有合乎逻辑的理由得到错误@7fffffffef08,因为 neg %rbx 是完全合法的指令。即使尝试在该地址执行代码也是可能的,但在这种情况下,该内存区域已映射为堆栈。因此,该区域的可执行位尚未设置,这就是您得到0x7fffffffef08 in ?? () 的原因。

但在其他程序中,那些汇编代码执行正确。

让我相信你已经做了一些事情来读取该区域的代码,从逻辑上认为它会起作用,但它不会。

【讨论】:

  • 0x00007fffffffef08 in ?? () 并不意味着有错误。 ?? 表明符号可能已从代码中删除(例如,GCC 的 -s 选项会这样做)。 ?? 只是表明正在调试的函数没有已知标签。这些stepi 中的每一个都实际执行了指令。如果 OP 使用 GDB 的 layout asm 后跟 layout reg 命令,他实际上会看到正在执行的汇编指令并注册内容。
  • 因为它是这个用户代码实际上正在执行而没有任何错误。它没有按照他的预期做,因为他没有初始化 RDX (第三个参数是 envp 与 execve 系统调用)并且系统调用可能在 RAX 失败原因(错误地址、无效参数等)
  • 如果他在不可执行的堆栈上执行代码,他会在堆栈上执行的第一条指令上得到SIGSEGV 错误。
猜你喜欢
  • 1970-01-01
  • 2015-11-05
  • 2017-03-14
  • 2014-09-28
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多