【问题标题】:Injected 64 bit shellcode wont execute syscall注入的 64 位 shellcode 不会执行系统调用
【发布时间】:2015-02-15 02:47:32
【问题描述】:

我目前正在尝试将打印 helloworld 的代码注入易受攻击的程序中。通过将代码存储在一个环境变量中并覆盖 rip 寄存器以指向该代码,我成功地注入了代码。 这是我的汇编代码和操作代码:

 0000000000000000 <_start>:
   0:   eb 17                   jmp    19 <stack_setup>

0000000000000002 <execute>:
   2:   48 31 c0                xor    %rax,%rax
   5:   b0 01                   mov    $0x1,%al
   7:   48 31 ff                xor    %rdi,%rdi
   a:   48 ff c7                inc    %rdi
   d:   5e                      pop    %rsi
   e:   b2 0f                   mov    $0xf,%dl
  10:   0f 05                   syscall 
  12:   b0 3c                   mov    $0x3c,%al
  14:   48 ff cf                dec    %rdi
  17:   0f 05                   syscall 

0000000000000019 <stack_setup>:
  19:   e8 e4 ff ff ff          callq  2 <execute>
  1e:   48                      rex.W
  1f:   65                      gs
  20:   6c                      insb   (%dx),%es:(%rdi)
  21:   6c                      insb   (%dx),%es:(%rdi)
  22:   6f                      outsl  %ds:(%rsi),(%dx)
  23:   2c 20                   sub    $0x20,%al
  25:   77 6f                   ja     96 <stack_setup+0x7d>
  27:   72 6c                   jb     95 <stack_setup+0x7c>
  29:   64 21 0a                and    %ecx,%fs:(%rdx)
  2c:   0d                      .byte 0xd

第 19 行之后的操作码用于指令 db "Hello, world!", 0x0a, 0x0d。在使用 gdb 检查 x2-x10 行中指令的执行后,我注意到它正确地准备了打印字符串 Hello, World 的参数。但是,在执行 syscall 语句后,什么也没有发生。第 x12 - x17 行的指令也是如此。

我也尝试编译和链接汇编代码以独立执行它并且它可以正常工作。除此之外,我还使用选项编译了易受攻击的程序

  -fno-stack-protector -z execstack

这样我就可以运行位于堆栈中的代码。我还禁用了 randomizing_va_space。我想问一下是否有什么我没有做才能让我成功执行我注入的代码?

【问题讨论】:

  • 你说你的 db "Hello world!", 0x0a, 0x0d 放在第 19 行之后,为什么你在程序的第一行跳到第 19 行?
  • 就是设置堆栈,这样我就可以将地址弹出到rsi寄存器中。使用对更高地址的调用可能会导致出现空字节。所以,我跳转到更高的地址,定义 Hello world,然后调用到更低的地址(因为它是二进制补码,所以不会有空字节),然后弹出包含字符串地址的堆栈顶部。
  • 程序,尤其是服务有时会重定向/重新打开其标准输出;你确定它会去你认为的地方吗?也许尝试使用 stderr 代替;它不太可能被重定向到任何地方。您是否尝试过使用自己的包装器在堆栈上运行它?
  • 我自己编写了易受攻击的程序,所以我确信我的标准输出指向哪里。困扰我的是,当我执行退出操作的系统调用时,什么也没有发生。看来我的命令没有到达内核。

标签: c gcc assembly nasm shellcode


【解决方案1】:

原因可能是write 系统调用返回了错误代码。可能有很多原因,但可能rdx 不是全为零,所以你应该在加载 15 之前 xor %rdx, %rdx (实际上你应该只加载 14,对于 "Hello, World!\n")。

无论如何,来自write 的错误将在rax 中返回,并且是一个负数(-errno),因此当你这样做时

mov    $0x3c,%al
dec    %rdi
syscall 

这将是一个无效的系统调用,并且将返回 errno 38 for ENOSYS

exit 我无论如何都要工作

xor    %rax, %rax 
mov    $0x3c,%al
syscall

我建议您使用 strace 运行该程序,并从其输出中了解为什么 write 会失败。


这是一个适用于我的 shell 代码版本:

0000000000000000 <main>:
   0:   eb 1d                   jmp    1f <stack_setup>

0000000000000002 <execute>:
   2:   48 31 c0                xor    %rax,%rax
   5:   b0 01                   mov    $0x1,%al
   7:   48 31 ff                xor    %rdi,%rdi
   a:   48 ff c7                inc    %rdi
   d:   5e                      pop    %rsi
   e:   48 31 d2                xor    %rdx,%rdx
  11:   b2 0e                   mov    $0xe,%dl
  13:   0f 05                   syscall 
  15:   48 31 c0                xor    %rax,%rax
  18:   b0 3c                   mov    $0x3c,%al
  1a:   48 ff cf                dec    %rdi
  1d:   0f 05                   syscall 

000000000000001f <stack_setup>:
  1f:   e8 de ff ff ff          callq  2 <execute>
  24:   48                      rex.W
  25:   65 6c                   gs insb (%dx),%es:(%rdi)
  27:   6c                      insb   (%dx),%es:(%rdi)
  28:   6f                      outsl  %ds:(%rsi),(%dx)
  29:   2c 20                   sub    $0x20,%al
  2b:   57                      push   %rdi
  2c:   6f                      outsl  %ds:(%rsi),(%dx)
  2d:   72 6c                   jb     9b <stack_setup+0x7c>
  2f:   64 21 0a                and    %ecx,%fs:(%rdx)

【讨论】:

  • 谢谢,我回家试试(我现在在办公室)。
  • 接受答案。你是对的,我忘了将 rdx 寄存器清零。我将其他寄存器归零,我不知道为什么我忘记了 rdx。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 2015-01-05
  • 1970-01-01
  • 2022-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多