大家好,
我正在尝试学习基本的shellcoding,我遇到了一些奇怪的事情,希望有人能向我解释。我已经用两种方式编译了以下代码:将shellcode声明为数组并将其声明为char *。当我将shellcode声明为数组时,linux检测到我正在尝试执行数据,并且我在第一条指令上遇到了段错误。但是,当我将shellcode声明为char *时,所有shellcode都会执行,并且我得到一个“Hello world!”。编译器如何以不同的方式处理这两个声明,为什么一个以shellcode结尾,它存在于不受保护的内存中?提前谢谢。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* This declaration ends in a segfault */
//char shellcode[] =
/* This declaration ends in successful execution */
char* shellcode =
/* Shellcode prints "Hello world!" and exits */
"\xeb\x1f\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\x48\x31\xc0\xb0\x01\x48\x31\xdb\xcd\x80\xe8\xdc\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21";
int main()
{
void (*f)();
f = (void (*)())shellcode;
(void)(*f)();
}
答案 0 :(得分:9)
当您将其声明为char[]
时,内存位于堆栈中。当您将其声明为char*
并为其指定字符串文字时,内存位于可执行映像本身中。 Linux不喜欢你在堆栈上执行代码,但是你可以在可执行映像的那部分执行内存。那是因为它试图避免某种类型的堆栈溢出攻击,人们可以用一些任意指令溢出堆栈然后执行它们。
您可以在Linux上使用mprotect
在Windows上设置内存区域或VirtualProtectEx
的权限。这样,您就可以明确地将内存的权限设置为可执行。
答案 1 :(得分:3)
在你的第一个案例中:
char shellcode[] =
这会将字符串文字放在堆栈上作为本地数组。堆栈和堆内存通常没有执行权限(出于明显的安全原因)。
在你的第二个案例中:
char* shellcode =
字符串存在于静态内存中 - 通常与程序二进制文件的其余部分位于同一区域 - 可执行。