【问题标题】:What does void(*)() mean in codevoid(*)() 在代码中是什么意思
【发布时间】:2023-03-21 11:40:01
【问题描述】:

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

【问题讨论】:

  • shellcode 被转换成一个 void 函数然后执行。
  • no... 我可以看到,它是 shell 代码,可能是后门.. 但想知道 void(*) 行是如何解释的?
  • @AdamS casted 在这里是什么意思?兄弟。
  • @Johnsmith 基本上“把这个变量当作它没有定义的东西”,因此 shellcode 中的字节将被解释为没有参数的 void 函数。
  • @jrok 你很可能无法运行,因为现在内存将无法执行。

标签: c++ c void shellcode


【解决方案1】:

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

 typedef void plainsig_t(void);

然后简单编码

 (*(plainsig_t*)shellcode) ();

对于函数指针,你不需要取消引用它们,所以只写代码会更短:

 ((plainsig_t*) shellcode) ();

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

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

【讨论】:

  • 如果没有结果,是否意味着十六进制的代码永远不会被执行,也永远不会执行任何命令?
  • @Johnsmith 没有结果意味着没有返回值。它确实被执行了。
  • @Johnsmith - 十六进制代码将执行;这就像调用一个 void 函数——一个没有 return 语句的函数。
  • 不,函数被调用并执行是因为它的副作用。
  • 感谢兄弟的精彩解释。 :)
【解决方案2】:

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

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

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

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

【讨论】:

  • 这正是为什么它应该只用两者之一来标记的原因。
  • @chris:我有点同意,但在这种情况下,它是在没有参数的情况下被调用的,所以它没有太大的区别。
【解决方案3】:

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

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

正在将shellcode 转换为这样的函数指针,解除对指针的引用(实际上不是必需的),然后调用该函数。

【讨论】:

  • 比,shellcode)()后面加*void(*)()是什么意思
  • @Johnsmith - 我想你是在写你的评论,而我正在将这些信息添加到我的答案中。 :)
  • 谢谢兄弟!解释 \m/ :)
【解决方案4】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-09
    • 2012-03-11
    • 2020-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多