Реферат: API Spying

Проблема заключается в том, что (увы!) статистика собирается не магически, её собирает наш код, внедрённый в исследуемое приложение. У этого простого факта есть три неприятных следствия:

При добавлении сбора статистики изменится скорость работы функций. Обычно это ни на что не влияет, но если в середине критичного к скорости выполнения кода мы неожиданно (для приложения и его автора) начнём запись в файл, может получиться плохо. Например, FPS упадёт раз в десять :) Но FPS – это не страшно, страшно, если вы исследуете многопоточное приложение c некорректно написанной синхронизацией, и изменение времени выполнения потоков приведет к дедлокам, падениям или просто непонятному поведению.

Помимо процессорного времени, наш код использует и другие ресурсы: память, стек, (возможно) окна, объекты ядра (файлы, события, и т.п.) и другие. В некотором фантастическом случае это может стать последней каплей, приводящей к исчерпанию доступных ресурсов потоком, процессом, или даже системой.

Если автор приложения решил позаботиться о защите своего детища, он вполне в состоянии засечь наши манипуляции, обидеться (он же не знает, что мы ничего плохого не хотели) и сделать какую-нибудь бяку. Например, откажется работать, или станет работать неправильно, или отформатирует случайно выбранный диск…

Все эти следствия в той или иной степени свойственны любой программной реализации API Spying-а, и ни в одной из этих ситуаций я не могу посоветовать вам ничего хорошего. Можно только попытаться уменьшить степень влияния и избежать столь пагубных последствий.

Предпроектные исследования: функции в Intel x86

Как вы уже, наверное, поняли, нам предстоит динамическая генерация кода функций-шпионов. Хотя ничего особо сложного в этом не будет (они действительно очень простые), небольшое теоретическое введение поможет вам понять (а мне – объяснить), как должна быть написана функция-шпион, чтобы вызов отслеживаемой функции завершился без помех.

Вызов

С точки зрения процессора вызов функции выполняет инструкция call, имеющая несколько разных форм:

call xxxxxxh

call xxxxh:xxxxxxh

call eax

call [eax]

...

Она сохраняет в стеке адрес, по которому нужно передать управление после окончания функции, и передаёт управление на начало функции.

Передача параметров

Процессор Intel x86 ничего не знает о параметрах вызываемых функций, поэтому механизм передачи параметров может быть произвольным, главное чтобы вызывающий и вызываемый код договорились о нём заранее. Мест, где можно сохранить параметры, не так уж и много: либо в регистрах, либо в стеке, либо часть там, а часть там.

ПРИМЕЧАНИЕ

Конечно, можно передавать параметры по ссылке или по значению, в прямом порядке или в обратном, но это для нас не важно, важно только то, где передаваемая информация (параметры или их адреса) находится.

Передача параметров через регистры используется в основном в двух случаях:

Компилятором для оптимизации.

Ассемблер-программистом из лени или в погоне за производительностью. Чтобы достать параметры из стека, надо написать несколько дополнительных команд, а в регистрах они сразу под рукой.

В большинстве остальных случаев параметры передаются через стек. При этом вызов функции выглядит примерно так:

push ... ; Параметр

push ... ; Ещё один параметр

push ... ; И последний параметр

call xxxxxh ; Вызов

А стек к моменту начала выполнения функции – так:

API Spying

К-во Просмотров: 989
Бесплатно скачать Реферат: API Spying