2015-11-10 2 views
4

Я прочитал и перешел к правилу справа налево, чтобы декодировать указатели на функции.Синтаксис синтаксиса объявления указателя функции

Для экс:

int (*(*fun_one)(char *,double))[9][20]; 

является: fun_one является указатель на функцию, ожидая (символ *, двойной) и возвращающую указатель на массив (размер 9) из массива (размер 20) ИНТ.

Так что

const char code[] = "\x31\xc0"; 

int main(){ 
    ((void(*)())code)(); 
} 

"код ?? возвращает указатель на функцию, возвращающую пустота ... ???? насчет после этого снаружи()"

I я совершенно смущен этим.

+1

Что вы подразумеваете под * frame *? – haccks

ответ

3
const char code[] = "\x31\xc0"; 

int main(){ 
    ((void(*)())code)(); 
} 

Вот как это работает. Переменная code распадается на адрес первого элемента (\x31).

Этот адрес затем будет передан на адрес функции, принимающей неопределенные аргументы, и ничего не возвращает.

Это покрывает весь бит ((void(*)())code) и, там, вы в основном сконструировали указатель функции, указывающий на вашу строку.

() затем просто звонки функция, на которую вы указываете.

Если вы используете таргетинг Intel, 31 c0 разбирает xor eax, eax, но я не ожидаю большой радости, когда он убежит от конца буфера, он, скорее всего, резко упадет. \x00, обозначающий конец строки, является первым битом инструкции add, но, что касается этого, нет никакой гарантии.

Добавление ret инструкцию к концу строки может сделать его более безопасным, но вы, возможно, придется изучить сгенерированный код ассемблера для сам вызов, чтобы выяснить которыйret следует использовать.

2

Это не указатель на функцию декларации, это указатель на функцию отливать и вызов.

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

Итак, каков тип внутри актеров? Это void (*)(). Другими словами, указатель на функцию, которая возвращает void и ничего не принимает (на самом деле может принимать аргументы, благодаря наследию C, но в данном случае это не так). Ничего, ничего.

После того, как имя * будет отправлено, если это объявление, но поскольку оно отлито, тип стоит отдельно, и нет имени вообще.

2

Вы сбиты с толку, потому что это не объявление указателя функции, а бросок, за которым следует вызов функции.

(void (*)()) code 

Это бросает code на указатель на функцию, принимающую неопределенное количество аргументов не вернувшихся ничего.

((void (*)()) code) 

Это полное выражение выше, заключенное в круглые скобки; результатом является указатель на функцию.

(void (*)() code)(); 

Эта функция вызывает функцию, в которой указатель функции «создан» точками заливки.

Это эффективно пытается вызвать некоторый машинный код, построенный в code - здесь вы опускаете остальное, но 31 c0 является обычным xor eax,eax.

+0

wow вы не только объяснили, но даже расшифровали шестнадцатеричный код дампа. Это замечательно. Благодаря ! – Haswell

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