2016-03-03 2 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

Это очень хороший пример того, что вы, вероятно, не должны делать .... function pointer casts _almost_ always UB. –

+1

присваивает адрес первого элемента массива 'code []' функции указателю func –

+0

Скомпилирует ли это? –

ответ

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

code, будучи массивом, неявно преобразуется в указатель на его первый элемент (он распадается на такой указатель). Затем этот указатель преобразуется в указатель на функцию.

Это отличное поведение вызывает неопределенное поведение. Но «большую часть времени», вероятно, приведет к указателю функции, указывающему на адрес массива. Когда вы его вызываете, тогда управление переходит к этому массиву. Если он содержит строковые данные, скорее всего, вы получите недопустимый код операции операции или сегментацию. Но если этот массив содержит какой-то пользовательский ввод, злоумышленник мог бы вставить (скомпилированный) код в него, делая всевозможные забавные (или менее забавные) вещи.

В качестве примера рассмотрим приведенный выше код, запущенный на каком-то сервере, который вводится пользователем через какой-либо веб-сайт. Затем можно заменить программу на for example /bin/sh и таким образом получить доступ к оболочке на этом сервере.

+0

Daniel Jour, спасибо, это понятно, но как может быть выполнен код из массива code [], если массив хранится в сегменте данных, но не в сегменте кода? И не могли бы вы объяснить, как функции хранятся в памяти, что делает этот трюк возможным? –

-1

Это образец кода оболочки. здесь: 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; 
} 

Какой функция не принимает строку байт-кода и преобразовать его обратно в указатель на функцию, как мы сделали выше. Затем вы можете вызвать функцию путем разыменования указателя и вызова его путем добавления скобок и любых параметров, которые выполняет функция.

Теперь, конечно, вам не нужно делать такие вещи в обычном программировании, но редко в особых случаях.

Смежные вопросы