Идентификация аргументов функций - часть 12
Часто приходится решать и обратную задачу: зная смещение элемента, определять к какому по счету аргументу происходит обращение. В этом нам поможет следующая формула, элементарно выводящаяся из предыдущей:
Поскольку, перед копированием в EBP текущего значения ESP, старое значение EBP приходится сохранять в том же самом стеке, в приведенную формулу приходится вносить поправку, добавляя к размеру адреса возврата еще и размер регистра EBP (BP в 16-разрядном режиме, который все еще жив на сегодняшний день).
С точки зрения хакера главное достоинства такой адресации аргументов в том, что, увидев где-то в середине кода инструкцию типа "MOV EAX,[EBP+0x10]", можно мгновенно вычислить к какому именно аргументу происходит обращение. Однако оптимизирующие компиляторы для экономии регистра EBP адресуют аргументы непосредственно через ESP. Разница принципиальна! Значение ESP не остается постоянным на протяжении выполнения функции и изменяется всякий раз при занесении и снятии данных из стека, следовательно, не остается постоянным и смещение аргументов относительно ESP. Теперь, чтобы определить к какому именно аргументу происходит обращение, необходимо знать: чему равен ESP в данной точке программы, а для выяснения этого все его изменения приходится отслеживать от самого начала функции! Подробнее о такой "хитрой" адресации мы поговорим потом (см. "Идентификация локальных стековых переменных"), а для начала вернемся к предыдущему примеру (надо ж его "добить") и разберем вызываемую функцию:
MyFunc proc near ; CODE XREF: main+39p
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch
arg_8 = byte ptr 10h
arg_1C = dword ptr 24h
; IDA
распознала четыре аргумента, передаваемых функции. Однако,
; не стоит безоговорочно этому доверять, – если один аргумент (например, int64)
; передается в нескольких машинных словах, то IDA
ошибочно примет его не за один,
; а за несколько аргументов!
