Фундаментальные основы хакерства


Елей и деготь оптимизирующих компиляторов - часть 2


Еще одна проблема – как достоверно определить длину тела функции? Язык Си не дает никакой возможности узнать значение этой величины, а оператор sizeof возвращает размер указателя на функцию, но не размер тела функции. Одно из возможных решений опирается на тот факт, что компиляторы, как правило

располагают функции в памяти согласно порядку их объявления в исходной программе, следовательно, длина тела функции равна разности указателей на следующую за ней функцию и указателя на данную функцию. Поскольку Windows-компиляторы представляют указатели 32-разрядными целыми числами, их можно безболезненно преобразовывать в тип "unsigned int" и выполнять над ними различные математические операции. К сожалению, оптимизирующие компиляторы не всегда располагают функции в таком простом порядке, а в некоторых случаях даже "разворачивают" их, подставляя содержимое функции на место вызова. Поэтому, соответствующие опции оптимизации (если они есть) придется отключить.

Другое коварство оптимизирующих компиляторов заключается в выкидывании ими всех, не используемых (с их точки зрения) переменных. Например, в программе, приведенной в листинге 2, в буфер buff что-то пишется, но ничто оттуда не читается! А передачу управления на буфер большинство компиляторов (в том числе и Microsoft Visual C++) распознать не в силах, вот они и опускают копирующий код, отчего происходит передача управления на неинициализированный буфер с очевидными последствиями. Если возникнут подобные проблемы, попробуйте сбросить флажок "Global optimization", а лучше отключите оптимизацию вообще (плохо, конечно, но надо).

Откомпилированная программа по-прежнему не работает? Вероятнее всего, причина в том, что компилятор вставляет в конец каждой функции вызов процедуры, контролирующий состояние стека. Именно так ведет себя Microsoft Visual C++, помещая в отладочные проекты вызов функции __chkesp (не ищите ее описания в документации – его там нет). А вызов этот, как нетрудно догадаться, относительный! К сожалению, никакого документированного способа это запретить, по-видимому, не существует, но в финальных (release) проектах Microsoft Visual C++ не контролирует состояние стека при выходе из функции, и все работает нормально.

 

 




- Начало -  - Назад -  - Вперед -



Книжный магазин