【问题标题】:What does ((void (*)())buf)(); mean?((void (*)())buf)(); 是什么意思?意思是?
【发布时间】:2020-05-01 05:12:35
【问题描述】:

我正在解决 picoCTF 上的二进制利用挑战,并遇到了这段代码:

((void (*)())buf)();

其中buf 是一个字符数组。

我解决了挑战,但似乎无法理解它到底在做什么。我查看了this 线程,但看不出来。

((void (*)())buf)(); 是什么意思?

【问题讨论】:

  • ((void (*)())buf)();是什么意思? 表示作者不懂typedeftypedef void (*voidFuncPtrType)(); 将使这段代码清晰。
  • @AndrewHenle 在设计 CTF 挑战时,清晰并不是真正的首要目标,甚至可以预期一些混淆作为挑战的一部分。作者很可能意识到这不是最易读的做事方式。
  • 说明你的程序有UB。
  • 这意味着C的“螺旋”类型声明规则太复杂了。几乎所有其他并非直接源自 C 的静态类型语言都使用从左到右的规则是有原因的。
  • @MasonWheeler “螺旋”是一个都市神话。该声明与相应的表达式一样多或少“螺旋”。运算符只是按优先级和从左到右的顺序应用(当然,这里没有告诉你任何新内容):“我需要取消引用它,然后调用它,结果类型为 void”:瞧,指向 void 函数的指针.

标签: c function pointers function-pointers


【解决方案1】:

void (*)() 是一种类型,该类型是“指向接受不确定参数且不返回值的函数的指针”。

(void (*)()) 是上述类型的类型转换。

(void (*)())bufbuf 转换为上述类型。

((void (*)())buf)() 调用函数(不传递参数)。

简而言之:它告诉编译器将buf 视为指向函数的指针,并调用该函数。

【讨论】:

  • 我发现cdecl 实用程序(或website)有助于将更复杂的 C 表达式翻译成英文。
  • @bta cdecl 在这里没有用处,因为语法不是声明。这是通过对先前声明的符号进行强制转换的函数调用
  • @bolov - 在整个声明中,不,但它确实解释了它的most complex part。从那里开始,解码其余部分相当简单。
  • @AvD 如果bufcopy 位于可执行地址并且代码本身与位置无关,这将起作用。它当然是不可移植的,但这应该适用于许多裸机环境以及未在堆栈和堆上设置 no-execute (NX) 位的旧 x86 操作系统。
  • @AvD:它不一定会崩溃。除非数据区域受到保护以防执行(这取决于架构和运行时环境),否则您可以使用此技巧在运行时将函数编译为数组并动态调用它。 35 年前,我第一次在 DEC Vax 上使用这个技巧来编译图灵机,以应对图灵机进化的失败实验。
【解决方案2】:

指针 buf 被转换为指向 void 函数的指针,该函数采用未指定数量的参数,然后取消引用(即调用函数)。

【讨论】:

    【解决方案3】:

    这是一个类型转换,然后是一个函数调用。首先,buf 被转换为指向返回 void 的函数的指针。最后一对括号表示该函数随后被调用。

    【讨论】:

      【解决方案4】:

      它将字符数组转换为指向不带参数并返回void的函数的指针,然后调用它。由于函数指针的工作方式,不需要取消引用指针。

      解释:

      那个“字符数组”实际上是一个机器码数组。当您将数组转换为 void (*)() 并调用它时,它会在数组内部运行机器代码。如果您提供了数组的内容,我可以为您拆解它并告诉您它在做什么。

      【讨论】:

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