【问题标题】:Calling buffer as a function in C?在C中调用缓冲区作为函数?
【发布时间】:2019-01-24 07:53:55
【问题描述】:
char buf[sizeof(shellcode)];
strcpy(buf, shellcode);
((void(*)())buf)();

我很难理解第三行的语法,我认为它正在使缓冲区成为函数?

【问题讨论】:

  • 第三行将缓冲区转换为看起来无效的函数。
  • 局部变量(包括数组)通常由编译器入栈。很少有操作系统会使堆栈可执行,因此无论如何您都不能“调用”它。
  • @Daniel。它可能只是复制一个指针,但strcpy 看起来根本不是正确的选择。
  • strcpy 将在第一个零处停止。考虑memcpy
  • 如果shellcode 包含零,它将在结束之前停止,它用于复制以nul 结尾的字符串,而不是缓冲区。如果它不包含零,它将溢出。使用memcpy

标签: c pointers


【解决方案1】:

您对第三行的看法是正确的。它采用buf,将其衰减为一个指针,然后将该指针转换为一个指向函数的指针。然后它调用该函数。这是有效的,因为void(*)() 的意思是“指向一个不接受参数并返回void 的函数的指针”,并将其包装在括号中会将其转换为强制转换。您现在有了一个指向函数的指针,您可以像调用常规函数名一样调用它。

C 标准不允许这样做,但根据编译器的工作方式,可能意味着它将buf 的地址视为内存中函数的地址并尝试调用该函数。通常这不起作用,因为操作系统会告诉 CPU 将内存区域标记为 buf 为不可执行,所以当你试图假装它是一个函数时,CPU 会抛出一个错误;让我们假设操作系统不这样做,或者你的 CPU 足够老,它不支持它。

您没有向我们展示shellcode 的内容。由于计算机中的所有内容都只是一个字节序列,包括您的计算机运行的编译二进制代码,shellcode 可能包含可执行的二进制代码。如果是这样,那么这会导致该代码开始运行。

例如,如果你编译了

void mycode()
{
    puts("Hello, world!");
}

然后您可以从生成的目标文件中提取函数mycode 的内容。如果您将这些内容放入shellcode,那么您问题中的代码将(假设编译器将函数指针和数据指针视为相同,并且操作系统或 CPU 不支持 noexec 内存)打印Hello, world! 到屏幕上。

【讨论】:

  • 感谢@Daniel H.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-05
相关资源
最近更新 更多