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


Идентификация аргументов функций - часть 45


; Компилятор просто резервирует под локальные переменные четыре байта. Почему?

; Из чего это следует? Смотрите: IDA

распознала одну локальную переменную var_4

; но память под нее явно не резервировалась, во всяком случае команды SUB ESP,4

; не было. Постой-ка, постой, но ведь PUSH ECX

как раз и приводит к уменьшению

; регистра ESP на четыре! Ох, уж эта оптимизация!

 

mov    [ebp+var_4], 2

; Заносим в локальную переменную значение 2

 

push   offset a333  ; s

; Передаем функции strlen указатель на строку "333"

 

call   _strlen

pop    ecx

; Выталкиваем аргумент из стека

 

push   eax

; Здесь – либо мы передаем возращенное функцией strlen

значение следующей

; функции как стековый аргумент, либо временно сохраняем EAX

в стеке

; (позже выяснится, что справедливо последнее предположение)

 

push   offset a1    ; s

; Передаем функции strlen указатель на строку "1"

 

call   _strlen

pop    ecx

; Выталкиваем аргумент из стека

 

lea    edx, [ebp+var_4]

; Загружаем в EDX смещение локальной переменной var_4

 

pop    ecx

; Что-то выталкиваем из стека, но что именно? Прокручивая экран

; дизассемблера вверх, находим, что последним в стек заносился EAX,

; содержащий значение, возвращенное функцией strlen("333").

; Теперь оно помещается в регистр ECX

; (как мы помним, Borland передает через него второй слева аргумент)

; Попутно отметим для любителей fastcall-а: не всегда он приводит к одидаемому

; ускорению вызова, - у Intel 80x86 слишком мало регистров и их то и дело

; приходится сохранять в стеке.

; Передача аргумента через стек потребовала бы всего одного обращения: PUSH EAX

; здесь же мы наблюдаем два – PUSH EAX

и POP ECX!

 

call   MyFunc

; При восстановлении прототипа функции не забудьте о регистре EAX, - он

; не инициализируется явно, но хранит значение, возращенное последним вызовом

; strlen. Поскольку, компилятор Borland C++ 5.x

использует следующий список




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