无法执行Shellcode – >(Speicherzugriffsfehler(Speicherabzug geschrieben))

我有这个function:

char code[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); } 

(此代码来自: shellcode教程 )

所以我编译并执行它,但我只得到这个消息:Speicherzugriffsfehler(Speicherabzug geschrieben)。

为什么我没有得到回报,只有这个错误信息?

ps:我的系统是ubuntu x86 pc。 shellcode应该可以使用它。 我使用gcc和gcc-4.5编译它,两个相同的错误…

默认情况下,gcc会将应用程序编译为具有不可执行的堆栈。 您所看到的是分段违规,因为您的堆栈被标记为不可执行但您正在尝试在堆栈上执行代码。 您可以通过在gdb中运行应用程序并检查它在哪里死亡来进行validation,例如:

=> 0x601060:jmp 0x60107b

这是shellcode的入口点。 为了使它不会出现段错误,您可以通过执行以下操作来禁用exectstack:

gcc -z execstack source.c

您的code变量是一个数组,它是程序初始化数据( .data )段的一部分 。 当您的程序由OS加载时,加载程序将从您的可执行文件中读取并执行加载命令。 其中一个命令是“将以下数据(名为.data的段)加载到内存中”。

通常, .data段作为非可执行段加载,这意味着无法执行那里的内存。 因此,如果您尝试通过跳转到它来执行代码,就像您一样,那么它会因分段错误而崩溃。

有几种方法可以解决这个问题。 您可以告诉链接器使.data段可执行(不是一个好主意)。 您可以告诉编译器将code变量放入.text段(用于所有程序的常规代码的段)。 您可以告诉编译器和链接器创建一个新的可执行段并将code放入其中。 所有这些都很棘手。

最好的解决方案是在运行时专门分配自己的可执行内存,并将shellcode复制到其中。 这完全避免了任何潜在的编译器/链接器问题,尽管它确实增加了一个小的运行时惩罚。 但是有些操作系统不允许内存同时可写和可执行; 因此,您首先必须使其可写,将shellcode复制到其中,然后使其可执行。

在运行时控制内存权限的方法是使用mprotect(2)调用 。 所以这是一个很好的方法:

 #include  #include  char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"; // Error checking omitted for expository purposes int main(int argc, char **argv) { // Allocate some read-write memory void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); // Copy the shellcode into the new memory memcpy(mem, shellcode, sizeof(shellcode)); // Make the memory read-execute mprotect(mem, sizeof(shellcode), PROT_READ|PROT_EXEC); // Call the shellcode int (*func)(); func = (int (*)())mem; (int)(*func)(); // Now, if we managed to return here, it would be prudent to clean up the memory: munmap(mem, sizeof(shellcode)); return 0; }