void(*)()在代码中的含义是什么

时间:2013-08-26 15:59:28

标签: c++ c void shellcode

我今天在一些fb配置文件中看到了这段代码,并且无法理解这是什么以及它是如何工作的: -

(*(void(*)()) shellcode)()

有人可以解释一下,上面的代码是什么意思?

下面的完整代码片段: -

#include <stdio.h>
#include <string.h>

char *shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
          "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";

int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}

4 个答案:

答案 0 :(得分:8)

它是函数指针的强制转换(没有返回结果且没有参数)。我更喜欢使用typedef来定义这些函数的签名:

 typedef void plainsig_t(void);

然后简单地编码

 (*(plainsig_t*)shellcode) ();

对于函数指针,您不需要取消引用它们,因此只需编写代码就可以了:

 ((plainsig_t*) shellcode) ();

基本上调用其机器代码位于shellcode内存区域内的函数。

顺便说一下,这不是严格的可移植C.原则上,不能保证你可以将数据指针强制转换为函数指针。 (在一些奇怪的处理器上 - 例如嵌入式微控制器,DSP,20世纪70年代的计算机 - ,代码和数据位于不同的地址空间,或者具有不同的指针大小等......)。但是大多数常见的处理器和ABI(x86-64 / Linux,ARM / Android,....)具有相同的代码和数据地址空间,并接受向数据指针的转换函数指针,反之亦然。

答案 1 :(得分:6)

这是C和C ++不同的地方。

在C中,它表示指向函数的指针,该函数返回void并获取未指定数量的未指定类型的参数。

在C ++中,它表示指向返回void且不带参数的函数的指针。

表达式作为一个整体取shellcode的地址,将其转换为指向函数类型的指针,然后调用该函数 - 即执行该字符串中的操作码。

答案 2 :(得分:4)

void(*)()表示“指向不带参数的void函数的指针。”这条线

(*(void(*)()) shellcode)();

shellcode转换为这样的函数指针,取消引用指针(实际上不需要),然后调用该函数。

答案 3 :(得分:3)

这是一个函数指针。类型说明符匹配声明;所以函数void f()的类型为void();并且指向函数void (*pf)()的指针的类型为void(*)()

请注意,与函数声明一样,它在C和C ++中的含义略有不同。在C中,空括号表示它具有未指定数量的参数,而在C ++中它表示它没有参数。但是,这不会影响代码的含义。

此代码将数组重新解释为函数并尝试调用它。据推测,该阵列包含用于打印消息或格式化硬盘驱动器等的机器代码。在大多数现代平台上,这将导致保护错误,因为静态数据(希望)默认情况下不可执行。