首页 > 解决方案 > 无法执行位于 WSL 中程序数据段中的汇编代码

问题描述

此程序覆盖主函数的返回地址,以指向编码的 x86-64 汇编指令的字符数组。这些指令只是对 NOP 进行编码,然后是系统调用 exit(1)。

char shellcode[] = "\x90\x48\x31\xc0\x48\x89\xc7\x48\xff\xc7\x04\x3c\x0f\x05";
void main() {
      long int *ret;
      ret = (long int *)&ret + 2;
      (*ret) = (long int)shellcode;
}

它是用

gcc program.c -o program.exe -fno-stack-protector -z execstack

在 WSL 上。(来自 Microsoft Store 的 Ubuntu 应用程序)

-z execstack标志应该使堆栈以及程序的所有其他可写部分成为可执行的。

由于全局字符数组位于汇编代码的 .data 中,因此它应该是可执行的。在 Linux VM 上运行程序时确实如此,但显然不是在 WSL 上?在 WSL 上,控制仍然正确地重定向到 NOP,但是如果您尝试执行该指令(可能是从不可执行的页面获取代码),它会出现段错误。从 main 返回后运行 gdb 会显示:

=> 0x8004010 <shellcode>:        nop
   0x8004011 <shellcode+1>:      xor    %rax,%rax
(gdb) si
Program received signal SIGSEGV, Segmentation fault.

是什么导致了 WSL 和真正的 Linux 之间的这种不一致?WSL 是否强制执行严格的W^X,甚至覆盖-z execstack

是否还有其他 Windows 安全功能在起作用?我不知道它是 WSL 1 还是 2,但 uname -a 输出是:

Linux LAPTOP-M91FQN9V 4.4.0-18362-Microsoft #836-Microsoft Mon May 05 16:04:00 PST 2020 x86_64 x86_64 x86_64 GNU/Linux

当 Linux VM 上没有发生同样的情况时,是什么阻止了指令运行?

标签: cassemblyx86-64windows-subsystem-for-linuxshellcode

解决方案


推荐阅读