以下代码(SMP Debian 4.19.260 - 1(2022 - 09 - 29)x86_64 GNU/Linux)的行为让我有些困惑:
#include <stdio.h>
const char
shellcode[]="\xb8\×01\×00\x00\x00\×48\xbe\×48\×65\×6c\x6c\×6f\×00\×00\×00\×56\×48\x89\xe6\xba\x05\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\x0f\x05";
int main(){
(*(void (*) ()) shellcode)();
return 0;
}
当我通过调试器执行程序时,我看到在将数组强制转换为函数之后执行的代码位于预期的位置,即初始化的全局区域(因为它是这样定义的),换句话说,代码在进程地址空间中非常低,肯定不在堆栈上。
然而,要在不接收SIGSEGV的情况下实际运行代码,必须使用可执行堆栈选项-z execstack编译它。如果代码不在堆栈上,为什么会发生这种情况?
- 更新日期:**
我使用了以下命令:
$ gcc testshellcode.c -o testshellcode
$ ./testshellcode
Segmentation fault
$ gcc -z execstack testshellcode.c -o testshellcode
$ ./testshellcode
Hello
我使用的是gcc (Debian 8.3.0-6) 8.3.0
。
- 找到的解决方案:execstack标志使内存中的所有**页都可执行,而不仅仅是堆栈中的页。请参阅:
Why is execstack required to execute code on the heap?
Exactly what cases does the gcc execstack flag allow and how does it enforce it?
1条答案
按热度按时间bkkx9g8r1#
1.您粘贴的代码无效:
这些应该是
\x
,而不是\×
。1.在我的系统上,用
gcc t.c -Wl,-z,execstack
编译这个代码仍然会崩溃,这是因为const char ...
被放到了.rodata
节中,而.rodata
节是一个只读段(不可执行)。您应该a)显示您使用的确切compile / link命令,B)显示您使用的编译器版本,以获得更全面的答案。
还可以查看一下
readelf -Wl ./a.out
,看看 segment 权限是什么--您的.rodata
很可能最终处于没有执行权限的段中。