Необходимо у конкретной exe'шки каждый раз при её запуске перехватывать пару функций и вместо них выполнять свой код. Подскажите, пожалуйста, как это реализовать?
заменить а exe-шке код этих функций на свой или на вызов своего из динамически подгружаемой dll примерно так Код (Text): push '.dll' push 'name' push esp call [LoadLibraryA] add esp, 8 test eax, eax jz exit push 'Name' push 'Func' push esp push eax call [GetProcAddress] add esp, 8 test eax, eax jz exit jmp eax exit: ret XXX//XXX количество байт параметров
ну так и быть напишу еще один пост. вот так. примерно. зависит от задачи Код (Text): push eax push ecx push edx push 0 push '.dll' push 'name' push esp call [LoadLibraryA] add esp, 8 test eax, eax jz exit push 'Name' push 'Func' push esp push eax call [GetProcAddress] add esp, 8 test eax, eax jz exit pop edx pop edx pop ecx xchg [esp], eax ret exit: pop eax pop edx pop ecx pop eax ret 0xNNNN по сути это не поменяет ни одного регистра со входа на выходе при ошибке или вызове твоей dll. А функции вообще в данном случае лучше по ординалу экспортировать Код (Text): push 1 push eax call [GetProcAddress] и LoadLibrary с GetProcAddress можно заменить не очень большим числом команд, но это ты уж сам. (писать влом)
max7C4, Изменять саму ехе-шку не вижу смысла, т.к. производитель наровит выпустить новую версию, а мне надо всего пара функций (CreateFile, WriteFile, ReadFile, CloseHandle). Думаю написать отдельный exe-файл, который будет сам запускать приложение-жертву и будет хукать некоторые функции в нем. Вот только на что заменить код функций в другом процессе через WriteProcessMemory, чтобы этот код вызывал событие/передавал данные в другой процесс, я ума не приложу...
думаю таже отговорка. производитель выпустит новую и свою exe придется переписывать т.к. функции сдвинуться и/или изменятся.
А чего сложного то? Заменяешь функцию на свою, она у тебя будет делать то, чего тебе надо (например, сохранять входящие переменные в логфайл какой-нибудь, затем вызывать оригинальную функцию, вообщем чего угодно) Передавать данные в другой процесс можно кучей способов, например через memory mapped файлы. Поповоду перехвата API функций куча статей есть, в том числе на этом сайте.
стало понятней. спасибо. меняю вопрос: как из одного процесса заставить подгрузиться специальную dll-шку в другой процесс, handle которого известен.
Пробую делать так, как написано в 22ой главе. Внедрение DLL и перехват API-вызовов Джеффри Рихтера "Windows для профессионалов" DLL уже загружается в чужой процесс. Единственное, не могу разобраться с "Перехватом API-вызовов с использованием раздела импорта". В Си я не специалист, только мельком его знаю. Для меня проще паскаль или асм. Переделал этот код в Паскал'евский. Код (Text): void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) { ULONG ulSize; PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(hmodCallor, TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); if (pImportDesc == NULL) return,; // в этом модуле нет раздела импорта // находим дескриптор раздела импорм со ссылками // на функции DLL (вызываемого модуля) for (; pImportDesc->Name; pImportDesc++) { PSTR pszModName = (PSiR) ((PBYFE) hmodCaller + pImportDcsc->Name); if (lstrcmpiA(pszModName, pszCalleeModName) == 0) break; } if (pImportDesc->Name == 0) // этот модуль не импортирует никаких функций из данной DLL return; // получаем таблицу адресов импорта (IAT) для функций DLL PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) ((PBYTE} hirodCaller + pImportDesc->FirstThunk); // заменяем адреса исходных функций адресами своих функций for (; pThunk->u1.Function; pThunk++) { // получаем адрес адреса функции PROC* ppfn = (PROC*) &pThunk->u1.Function; // та ли это функция, которая нас итересует? BOOL fFound = (*ppfn == pfnCurrent); // см. текст программы-примера, в котором // содержится трюковый код для Windows 98 if (fFound) { // адреса сходятся, изменяем адрес в разделе импорта WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL ); return; // получилось, выходим } } // если мы попали сюда, значит, в разделе импорта // нет ссылки на нужную функцию } Код (Text): Const IMAGE_DIRECTORY_ENTRY_EXPORT = 0; IMAGE_DIRECTORY_ENTRY_IMPORT = 1; IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; IMAGE_DIRECTORY_ENTRY_SECURITY = 4; IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; IMAGE_DIRECTORY_ENTRY_DEBUG = 6; IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7; IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; IMAGE_DIRECTORY_ENTRY_TLS = 9; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; IMAGE_DIRECTORY_ENTRY_IAT = 12; IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; Type PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR; IMAGE_IMPORT_DESCRIPTOR = record Characteristics: DWORD; TimeDateStamp: DWORD; ForwarderChain: DWORD; Name1: DWORD; FirstThunk: DWORD; End; PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME; IMAGE_IMPORT_BY_NAME = record Hint: WORD; Name1: DWORD; End; Function ReplaceIATEntryInOneMod(pszCallModName: PChar; pfnCurrent, pfnNew: pointer; hmodCaller: THandle): boolean; Var ulSize: cardinal; pImportDesc: PIMAGE_IMPORT_DESCRIPTOR; pszModName: PChar; pThunk: PIMAGE_IMPORT_BY_NAME; ppfn: pointer; bFound: boolean; Temp: cardinal; Begin Result := false; pImportDesc := ImageDirectoryEntryToData(hmodCaller, true, IMAGE_DIRECTORY_ENTRY_IMPORT, ulSize); IF pImportDesc = nil then Exit; While pImportDesc.Name1 <> 0 do Begin pszModName := pointer(hmodCaller + pImportDesc.Name1); IF (lstrcmpiA(pszModName, pszCallModName) = 0) then break; Inc(pImportDesc, sizeof(pImportDesc)); End; IF (pImportDesc.Name1 = 0) then Exit; pThunk := pointer(hmodCaller + pImportDesc.FirstThunk); While pThunk.Name1 <> 0 do Begin ppfn := pointer(pThunk^.Name1); bFound := ppfn = pfnCurrent; IF bFound then Begin WriteProcessMemory(GetCurrentProcess, ppfn, @pfnNew, sizeof(pfnNew), Temp); Result := true; break; End; Inc(pThunk, 4); End; End; Пожалуйста, помогите найти ошибку. Вместо имеющихся 78 функций, импортируемых модулем из kernel32, код перебирает только 12. проверял.
bendme, Код (Text): Var hMainModule: THandle; Procedure Replace(module, func: string; pNew: pointer); Var pOrig: pointer; Begin pOrig := GetProcAddress(GetModuleHandle(PChar(module)), PChar(func)); ReplaceIATEntryInOneMod(PChar(module), pOrig, pNew, hMainModule); End; Procedure Init; Begin hMainModule := GetModuleHandle('EXE.EXE'); Replace('Kernel32.dll', 'CreateFileA', @New_CreateFileA); Replace('Kernel32.dll', 'ReadFile', @New_ReadFile); Replace('Kernel32.dll', 'WriteFile', @New_WriteFile); Replace('Kernel32.dll', 'CloseHandle', @New_CloseHandle); End;