Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

ВОПРОС-ОТВЕТ 

Как подменить функцию API?

Автор: Павел Блудов

Демонстрационное приложение (WTL Dialog) HookAPI (100kb) Требует наличия звуковой карты. Методы 3, 4 и 5 не будут работать под windows9x/ME.

Демонстрационное приложение (WTL Dialog) HookAPI2 (20kb) Требует наличия WinSockets 1.0.

Переопределение с помощью препроцессора 

#include <windows.h>

WINUSERAPI BOOL WINAPI MyMessageBeep(IN UINT uType) {

 //Your code here

}

#define MessageBeep MyMessageBeep
 

Теперь если в коде программы встретится MessageBeep препроцессор заменит ее на нашу MyMessageBeep. Очень просто.

Но что если хочется добавить немного своей логики в уже откомпилированный код, изменить работу чужой библиотеки, пересобрать которую нет никакой возможности? Иными словами, заставить уже откомпилированный код вызвать нашу функцию вместо стандартной. Это вполне реально. Давайте поближе рассмотрим, как под Windows процедуры одного модуля используют процедуры другого.

Модификация таблиц импорта/экспорта

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

Код вызова процедуры из другого модуля выглядит примерно так:

call dword ptr [__imp__MessageBeep@4 (004404cc)]

И, если изменить значение по этому адресу, можно подменить оригинальнкю функцию своей. Для этого нам понадобится:

• Отыскать таблицу импорта функций для нужного нам модуля

• Отыскать там указатель на перехватываемую функцию

• Снять с этого участка памяти утрибут ReadOnly

• Записать указатель на нашу функцию

• Вернуть защиту обратно

HRESULT ApiHijackImports(HMODULE hModule, LPSTR szVictim, LPSTR szEntry, LPVOID pHijacker, LPVOID *ppOrig) {

 // Check args

 if (::IsBadStringPtrA(szVictim, –1) || (!IIS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) || ::IsBadCodePtr(FARPROC(pHijacker))) {

return E_INVALIDARG;

 }

 PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);

 if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) {

return E_INVALIDARG;

 }

 PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew);

 if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) || IMAGE_NT_SIGNATURE != pNTHeaders->Signature) {

return E_INVALIDARG;

 }

 HRESULT hr = E_UNEXPECTED;

 // Locate the victim

 IMAGE_DATA_DIRECTORY& impDir =

pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

 PIMAGE_IMPORT_DESCRIPTOR pImpDesc =

MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress),

pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;

 while (pImpDesc < pEnd) {

if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) {

if (0 == pImpDesc->OriginalFirstThunk) {

// no import names table

return E_UNEXPECTED;

}

// Locate the entry

PIMAGE_THUNK_DATA pNamesTable =

MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);

if (IS_INTRESOURCE(szEntry)) {

// By ordinal

while(pNamesTable->u1.AddressOfData) {

if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) && WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal)) {

hr = S_OK;

break;

}

pNamesTable++;

}

} else {

  • Читать дальше
  • 1
  • ...
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: