2016-03-03 117 views
-2

这段代码是什么意思?功能指针

char code[] = "bytecode will go here!"; 
int main(int argc, char **argv) { 
    int (*func)(); /* This is pointer to function */ 
    func = (int (*)())code; /* What does this line mean? */ 
    (int)(*func)(); /* Calling function by pointer */ 
} 
+3

这是一个非常好的例子,你可能不应该这样做....函数指针转换是_almost_总是UB。 –

+1

它将'code []'数组的第一个元素的地址赋给函数指针func –

+0

这是编译吗? –

回答

3
func = (int (*)()) code; 

code,作为一个阵列,被隐式转换为指针到它的第一个元素(它衰减到这样一个指针)。这个指针然后被转换为一个指向函数的指针。

此演员阵容导致未定义的行为。但是“大部分时间”,它可能会导致一个函数指针指向数组的地址。当你调用它,然后控制跳转到这个数组。如果它包含字符串数据,则很可能会得到无效的操作码或分段错误。但是如果该数组包含一些用户输入,恶意用户可能会将(编译)代码放入其中,做各种有趣(或较不好笑)的东西。

举一个例子,考虑一下上面的代码运行在某种服务器上,通过某些网站提供用户输入。然后可以用for example /bin/sh替换该程序,从而获得该服务器上的shell访问权限。

+0

Daniel Jour,谢谢,很明显,但如果数组存储在数据段中而不是代码段中,如何执行code []数组中的代码?你能解释一下如何将函数存储在内存中吗? –

-1

这是一个shell代码示例。 这里:https://en.wikipedia.org/wiki/Shellcode

func = (int (*)()) code; /* What does this line mean? */       

FUNC是一个函数点,它指向的“代码阵列”的地址。

当func被调用时,程序将跳转到数组的地址。

+0

这是一个评论,而不是一个答案。 –

1

你所看到的有一个type punning的例子。

void print_hello() 
{ 
    printf("hello"); 
} 

int main() 
{ 
    void (*hello_func_ptr)() = &print_hello; 

    //we convert what the function points to to a string of "byte code" 
    char *func_byte_code = (char *)hello_func_ptr; 

    // prints out byte code of the function 
    printf(func_byte_code); 

    // we cast the string byte code to a function pointer 
    void (*func_from_byte_code)() = (void (*)())func_byte_code; 

    // we call the function we got from casting the byte code to a function pointer 
    (*func_from_byte_code)(); // prints "hello"! 
    return 0; 
} 

你的函数做的是取字节码字符串并将它转换回函数指针,就像我们上面所做的那样。然后可以通过解引用指针并通过添加括号和函数所需的任何参数来调用该函数来调用该函数。

当然,现在你不需要在常规编程中做这样的事情,但很少遇到特殊情况。