Перехватывая API функции, мы увеличиваем наши возможности и граница им только наше воображение. Для прочтения данной статьи с максимальной пользой обязательны хоть начальные знания низкоуровневого программирования и знание архитектуры работы Windows.
    Сегодня я вам расскажу наиболее действенную методику перехвата API функций – сплайсинг. Сплайсинг это подмена кода функции. Конечно, есть другой метод перехвата это редактирование таблицы импорта приложения. Рассказывать буду по порядку.

Когда вы пишете в своём приложении так

Код:
Function Func1(param*:type*):restype*;stdcall;external ‘libname.dll’;

Вы импортируете функцию статически. Адрес функции прописывается в таблице импорта вашего приложения
(допустим, что адрес нашей функции $7BC56010).
адрес        значение
$00405F56  7BC56010

А при вызове функции происходит так
Push …
push …
call dword ptr

Следовательно, для перехвата функции нам надо только подменить значение по адресу $00405F56 на своё, а для вызова оригинальной функции получать адрес функции через GetProcAddress. Но приложение может также получить адрес функции через GetProcAddress и вызывать перехватываемую функцию минуя, перехватчик. Данный метод бесперспективен.
    Идём дальше. Теперь я объясню технику сплайсинга. Наша функция находится по адресу $7C80B529 и допустим, что там такой код

Код:
7C80B529	 8BFF	 mov	 edi, edi
7C80B52B	 55	 push	 ebp
7C80B52C	 8BEC	 mov	 ebp, esp
7C80B52E	 837D 08 00	 cmp	 dword ptr ss:[ebp+8], 0

Для перехвата функции от нас требуется только переписать начальный код функции, так чтобы он передавал управление нашему обработчику. Для передачи управления нашему обработчику достаточно всего лишь одной инструкции jmp на абсолютный адрес. Эта инструкция займёт всего лишь 5 байт – сам опкод этой инструкции ($E9) и значение для прыжка. Это значение вычисляется так

v=0-(s-d)
s – Смещение следующей команды
d – Требуемый адрес для jmp, т.е. адрес обработчика

Если немного переделать эту формулу, то она будет выглядеть так

Код:
v=d-FunctionAddress-5

Теперь при каждом вызове целевой функции, всегда будет передаваться управление нашему обработчику. А как теперь вызвать оригинальную функцию. При установке перехвата нам надо сохранять первые 5 байт функции. Для вызова оригинала надо восстанавливать надо функции и вызывать ее, потом снова устанавливать перехват. Объявим структуру в которой будем сохранять первые 5 байт функции:

Код:
 PFunctionRestoreData = ^ TFunctionRestoreData; 
  TFunctionRestoreData = packed record 
     Address:Pointer; 
      val1:Byte; 
      val2:DWORD; 
   end;

С вами был Pirate, удачи!

Отредактировано Pirate (2013-09-10 23:01:42)