我已经阅读并搜索了有关解码函数指针的左右规则。
例如:
int (*(*fun_one)(char *,double))[9][20];
是:fun_one 是指向期望函数 (char *,double) 和
返回指向 int 数组(大小 20)的数组(大小 9)的指针。
那是什么
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
“代码是 ?? 返回一个指向返回 void 的函数的指针...????? 外面的 () 之后呢”
我对这个一头雾水。
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
这是它的工作原理。 code
变量将衰减到第一个元素的地址 (\x31
)。
然后该地址将被强制转换为接受不确定参数且不返回任何内容的函数的地址。
这涵盖了整个 ((void(*)( ))code)
位,到此为止,您基本上已经构造了一个指向您的字符串的函数指针。
()
然后简单地调用您指向的函数。
如果您的目标是 Intel CPU,31 c0
反汇编为 xor eax, eax
但当它运行到缓冲区,它很可能会崩溃。标记字符串结尾的 \x00
是 add
指令的第一位,但对于后面的内容,我们无法保证。
将ret
指令添加到字符串的末尾可能 使其更安全,但您可能必须检查生成的汇编代码以找出调用本身应该使用哪个 ret
。