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



         

Идентификация локальных стековых переменных - часть 4


Ситуация серьезно осложняется тем, что в функции присутствуют и "настоящие" команды сохранения регистров, сливаясь с командами выделения памяти. Как узнать: сколько байт резервируется для локальных переменных, и резервируются ли они вообще (может, в функции локальных переменных и нет вовсе)?

Ответить на этот вопрос позволяет поиск обращений к ячейкам памяти, лежащих "выше" регистра EBP, т.е. с отрицательными относительными смещениями. Рассмотрим два примера, приведенные на листинге 110.

PUSH EBP                           PUSH EBP

PUSH ECX                           PUSH ECX

xxx                                xxx

xxx                                MOV [EBP-4],0x666

xxx                                xxx

POP ECX                            POP ECX

POP EBP                            POP EBP

RET                                RET

Листинг 110

В левом из них никакого обращения к локальным переменным не происходит вообще, а в правом наличествует конструкция "MOV [EBP-4],0x666", копирующая значение 0x666 в локальную переменную var_4. А раз есть локальная переменная, для нее кем-то должна быть выделена память. Поскольку, инструкций SUB ESP, xxx

и ADD ESP, – xxx в теле функций не наблюдается – "подозрение" падает на PUSH ECX, т.к. сохраненное содержимое регистра ECX располагается в стеке на четыре байта "выше" EBP. В данном случае "подозревается" лишь одна команда – PUSH ECX, поскольку PUSH EBP на роль "резерватора" не тянет, но как быть, если "подозреваемых" несколько?

Определить количество выделенной памяти можно по смещению самой "высокой" локальной переменной, которую удается обнаружить в теле функции. То есть, отыскав все выражения типа [EBP-xxx] выберем наибольшее смещение "xxx" – в общем случае оно равно количеству байт выделенной под локальные переменные памяти. В частностях же встречаются объявленные, но не используемые локальные переменные. Им выделяется память (хотя оптимизирующие компиляторы просто выкидывают такие переменные за ненадобностью), но ни одного обращения к ним не происходит, и описанный выше алгоритм подсчета объема резервируемой памяти дает заниженный результат.


Содержание  Назад  Вперед