【问题标题】:Can't execute Shellcode --> (Speicherzugriffsfehler (Speicherabzug geschrieben))无法执行 Shellcode --> (Speicherzugriffsfehler (Speicherabzug geschrieben))
【发布时间】:2013-11-03 02:24:10
【问题描述】:

我有这个功能:

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 tutorial

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

为什么我没有得到任何东西,只有这个错误信息?

ps:我的系统是 ubuntu x86 电脑。 shellcode 应该可以使用它。我用 gcc 和 gcc-4.5 编译它,都是同样的错误...

【问题讨论】:

  • 根据谷歌翻译,该消息表明核心已转储。如果你能找到它,你可以使用 GDB 看看出了什么问题。 (gdb yourprogram some.core)
  • 您运行的是德语系统吗?否则会出现德语错误是出乎意料的,但大概你应该已经理解了……无论如何,这似乎不是一个真正的问题。
  • 您是否阅读了教程主页上的常见问题解答 #7 和 #10,并确保它们不会导致您的问题。

标签: c gcc shellcode


【解决方案1】:

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

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

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

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

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

#include <string.h>
#include <sys/mman.h>

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;
}

【讨论】:

    【解决方案2】:

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

    => 0x601060 : jmp 0x60107b

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

    gcc -z execstack source.c

    【讨论】:

    • 这不是被跳转到的,它是初始化数据段的一部分,和栈一样,也是不可执行的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多