void(*)()在代码中是什么意思

What does void(*)() mean in code

本文关键字:是什么 意思 void 代码      更新时间:2023-10-16

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

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

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

完整代码段如下:-

#include <stdio.h>
#include <string.h>
char *shellcode = "x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
          "x6ex89xe3x50x53x89xe1xb0x0bxcdx80";
int main(void)
{
fprintf(stdout,"Length: %dn",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}

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

 typedef void plainsig_t(void);

然后简单地对进行编码

 (*(plainsig_t*)shellcode) ();

对于函数指针,您不需要取消引用它们,因此只编写代码会更短:

 ((plainsig_t*) shellcode) ();

其基本上调用机器代码位于CCD_ 2存储区内的函数。

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

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

在C中,它意味着指向函数的指针,返回void,并接受未指定类型的未指定数量的参数。

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

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

void(*)()的意思是"指向不带参数的void函数的指针"

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

shellcode强制转换为这样一个函数指针,取消对指针的引用(实际上没有必要),然后调用该函数。

它是一个函数指针。类型说明符与声明匹配;因此函数CCD_ 6具有类型CCD_;并且指向函数CCD_ 8的指针具有类型CCD_。

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

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

在C中,变量被声明为int foo;,来声明一个函数,我们使用int foo( );。这意味着函数的返回类型是int。要声明一个指针,我们使用*foo

在表达式(*(void(*)())0)()中,我们可以看到

  1. 假设变量fp是一个函数指针,我们可以使用(*fp)( );来调用函数,因为fp是函数指针,而*fp是指针指向的函数,所以(*fp)( );可以调用函数。

  2. 假设fp是一个指向非返回值类型的指针,那么调用它的方式是shellcode0,那么fp变量的类型是void (*)( )

  3. 如果要将此类型强制转换为常量shellcode,则使用( void (*)() ) shellcode

  4. 现在外壳代码被转换为类型,为了调用外壳代码,我们使用

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


注意:我们可以使用typedef来替换上面表达式的类型名称

例如:typedef void (*ff)( );因此,调用函数的方式可以写成:

(*(ff) shellcode ) ( );

发件人:https://www.codetd.com/en/article/14043929