1

我今天在一些 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

4 回答 4

8

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

 typedef void plainsig_t(void);

然后简单地编码

 (*(plainsig_t*)shellcode) ();

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

 ((plainsig_t*) shellcode) ();

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

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

于 2013-08-26T16:01:54.430 回答
6

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

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

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

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

于 2013-08-26T16:03:32.223 回答
4

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

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

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

于 2013-08-26T16:01:14.010 回答
4

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

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

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

于 2013-08-26T16:06:28.500 回答