((void(*)())buf)(); 意思?


59

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

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

buf字符数组在哪里。

我解决了挑战,但似乎无法理解它到底在做什么。我看了看这个线程,但是我听不清。

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


14
什么((void (*)())buf)();意思 这意味着作者不理解typedeftypedef void (*voidFuncPtrType)();将使代码清晰。
Andrew Henle

33
@AndrewHenle在设计CTF挑战时,清晰度并不是真正的首要目标,甚至有些困惑也可以作为挑战的一部分。作者很可能意识到这不是最易读的做事方式。
ManfP

2
这意味着您的程序具有UB。
R .. GitHub停止帮助ICE

4
这意味着C的“螺旋”类型声明规则太复杂了。几乎所有其他并非直接来自C的静态类型语言都使用从左到右的规则,这是有原因的。
梅森惠勒

2
@MasonWheeler“螺旋”是一个城市神话。该声明与相应的表达式一样多或少“螺旋”。运算符仅按优先级和从左到右的顺序应用(当然,这里没有告诉您任何新内容):“我需要取消引用,然后调用它,并且结果的类型为void”:瞧,指向void函数的指针。
彼得-

Answers:


129

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

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

(void (*)())buf强制转换buf为上述类型。

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

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


15
我发现该cdecl实用程序(或网站)有助于将更复杂的C表达式翻译成英语。
bta

3
@bta cdecl在这里没有用,因为语法不是声明。这是通过对先前声明的符号进行
强制转换

3
@bolov-整个语句,不,但是它确实解释了其中最复杂的部分。从那里开始,解码其余部分非常简单。
bta

5
@AvD如果无论位于何处bufcopy都位于可执行地址,并且代码本身与位置无关,那么它将起作用。它当然是不可移植的,但是它可以在许多裸机环境以及在堆栈和堆上未设置无执行(NX)位的较旧x86操作系统上运行。
wrtlprnft

4
@AvD:不一定会崩溃。除非保护数据区域免受执行(这取决于体系结构和运行时环境),否则您可以使用此技巧在运行时将函数编译成数组并快速调用它。35年前,我在DEC Vax上首次使用此技巧来编译Turing机器,但在Turing机器发展方面的实验失败。
TonyK

11

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


9

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


7

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

一个解释:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.