динамическая подгрузка DLL-ок и перехват API
Итак, по порядку:
Есть некоторое приложение "A", к которому я успешно подключаю свою DLL-ку и которая в свою очередь хукает (через модификацию IAT) функцию "send" (из ws32_32.dll). Перехват отлично работает.
Далее в какой-то момент времени это приложение подгружает другую свою DLL:
.text:00838140 mov eax, [esp+lpLibFileName]
.text:00838144 push esi
.text:00838145 push eax ; lpLibFileName
.text:00838146 mov esi, ecx
.text:00838148 call ds:LoadLibraryA
.text:0083814E test eax, eax
.text:00838150 mov [esi+20h], eax
.text:00838153 jz short loc_8381C9
......................................
.text:00838171 mov edx, [esi+20h]
.text:00838174 push offset aFrostsend ; "ownSend"
.text:00838179 push edx ; hModule
.text:0083817A mov [esi+4], eax
.text:0083817D call edi ; GetProcAddress
И импортирует из неё функцию ownSend. Далее это приложение начинает слать траффик через эту новую функцию, которая разумеется также в итоге всё равно использует функцию "send". Но при этом мой хук слетает и попытки поставить его заново не помогают.. Через дебаггер я чётко вижу, что только что подключенная дллка шлёт пакеты через ws32_32.dll.send. Отсюда вопрос, как её можно хукнуть снова? Откуда DLL может брать адрес этой функции? Неужели также через GetProcAddress? К слову, он у меня тоже хукнут..
PEHeader := Pointer(Int64(ImageBase) + PImageDosHeader(ImageBase)._lfanew);
PImport := Pointer(PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + ImageBase);
Следовательно, для каждого модуля (длл) таблица импорта разнае.
Можешь хукать LoadLibrary в той длл, которая подгружает другую, и в пойманном LoadLibrary тоже применять свои хуки для новой IAT.
GetProcAddress имеет смысл хукать, наверное, только если тебе нужна универсальность. Если же у тебя одна длл и ты видишь, что там GetProcAddress не испльзуется, но и трогать её смысла нет.
Я так и делал.. пытался хукать и после загрузки дллки.
Оказалось вся проблема в другом. Вот таким образом запускается send из этого приложения:
CALL DWORD PTR DS:[A4162C] ; WS2_32.send
Тут понятно, адрес берётся из IAT. А вот так send запускается из этой злой библиотеки:
CALL 71A94C27 ; WS2_32.send
То есть получается адрес send захардкожен в DLL-ку? Как так может быть? И как её можно хукнуть кроме правки непосредственно этого вызова?
Это вряд ли. Библиотеки (кроме ntdll) всегда грузятся с разным базовым адресом, поэтому захардкодить адрес функции не получится. CALL 71A94C27 - тебе это показывает отладчик? Вплоне возможно, что библиотека при загрузке правит адреса по RVA (не уверен, что правильно использую термин, т.к. не силён в теории PE). Посмотри в дизассемблере.
Но в твоём случае действительно проще может быть использовать сплайсинг, как сказал bagie2 - иначе замаешся искать и править адреса в коде.