Извините, если повторяюсь, но никак не могу разобраться... Пусть имеется некоторая функция в таблице импорта данной DLL. Мне нужно использовать её при патче приложения. Т.е. я не хочу жестко забивать адреса, например, GetProcAddress, а хочу брать её именно из импорта, типа для базонезависимости. Посмотрел по аналогии, как адресуются функции из импорта в ольге. Но никак не могу разобраться, по какому принципу вычисляется адрес необходимой функции. Например: FF15 DC02876F CALL DWORD PTR DS:[<&KERNEL32.CreateThread>] ; kernel32.CreateThread Вот, собсна, вопрос, что мне написать при call, чтобы вызвать, например, GetTickCount?
Honorary_BoT Я в винде 0.. и щас скажу что думаю. (возможно я вообще буду бред нести..время позднее) запускаем dumpbin для kernel32.dll c флагом /all kernel32.dll а затем с /exports kernel32.dll флаг all покажет адрес начала kernel32.dll в памяти с помощью флага exports найдёшь смещение нужной функции... потом.... база + смещение... ну итд... я гоу спать
В этом и фишка, я заведомо не знаю базу, т.к. патчу dll'ку... Может быть я бы разобрался с механизмом адресации импорта, но стопорит именно непонятная адресация call, которая с FF начинается... В справочнике как-то неясно написано по этому поводу...
Что-то найти не могу редактирование сообщений... Забыл опять же добавить, использовать надо именно таблицу импорта, без сканов и жестких забивок адресов.
Если патчишь только в памяти, то тебе надо найти таблицу импорта, найти таблицу адресов (иногда в памяти это сделать невозможно и придется читать файл с диска), в таблице адресов вычисляешь адрес ячейки, в которой хранится адрес функции. Потом вычисляешь относительное смещение и строишь команду call Гораздо проще в данном случае искать апи динамически через экспорт. Почитай туториалы билли и статью сарса на васме. В двух словах не объяснишь - в любом случае придется разбираться с таблицами.
посмотри описание таблицы импорта (FirstThunk) - в уроках ицзелиона. п.с.: блин, пока писал, пропустил, чем игра СК закончилась ((
Ну сорри, зато человку помог =) Я посмотрю ещё про импорт. Интересна как раз другая фишка - DC02876F получается просто набор цыфрабукав, всяческие косвенные поиски и по этому адресу, и этого адреса, и смещения в массиве импорта, в общем, пляски с бубном так и не выявили связь с DC02876F и реальным адресом функции =)
Да, кстати, совсем забыл. Я никуда здесь не внедряюсь =) Т.е. здесь дело не в динамике. А есть некая длл, которую я могу поковырять в PETools, посмотреть все. И на основании исследований надо получить волшебную комбинацию цифрабукв для call.
Как все запущено... это адрес ячейки (FirstThunk), в которую загрузчик виндовс поместит адрес функции. это опкод команды call dword ptr [xxx]. После этого опкода сразу идет адрес ххх. Вот DC02876F и есть адрес твоей ячейки. Вобщем, начни со статьи ицзелиона - у него там все написано, что будет до и после загрузки в таблице импорта.
Code (Text): BOOL SetNewImport(PVOID MyApiFunc, PCHAR ModuleName, DWORD RealFuncAddr) { PIMAGE_NT_HEADERS pImageNtHeaders; PIMAGE_DOS_HEADER pImageDosHeader; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor; PIMAGE_THUNK_DATA pImageThunkData; DWORD OldProtect; __try{ pImageDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(ModuleName); pImageNtHeaders = (PIMAGE_NT_HEADERS)(DWORD(pImageDosHeader) + DWORD(pImageDosHeader->e_lfanew)); if (!VirtualProtect(pImageDosHeader,pImageNtHeaders->OptionalHeader.SizeOfImage,PAGE_EXECUTE_READWRITE,&OldProtect)) {return FALSE;}; pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImageDosHeader + pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while ( pImageImportDescriptor->Name!=0) { pImageThunkData = (PIMAGE_THUNK_DATA)(DWORD(pImageDosHeader) + pImageImportDescriptor->FirstThunk); while (pImageThunkData->u1.Function) { pImageThunkData = (PIMAGE_THUNK_DATA)(DWORD(pImageThunkData) + sizeof(IMAGE_THUNK_DATA)); if (DWORD(pImageThunkData->u1.Function) == (DWORD)RealFuncAddr) *(PDWORD)(pImageThunkData) = (DWORD)(MyApiFunc); } pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)(pImageImportDescriptor)+sizeof(IMAGE_IMPORT_DESCRIPTOR)); } } __except(EXCEPTION_EXECUTE_HANDLER){return FALSE;} return TRUE; }
Honorary_BoT Самое главное условие для реализации задуманного тобой, чтобы та функция на которую ты желаешь заменить вызов CreateThread была в импорте этого приложения. Вот байты инструкции: FF15 DC02876F - второй важный момент, что адрес этой переменной берется побайтно наоборот, т.е. не 0DC02876Fh, а 6F8702DCh. Вот по этому самому адресу внутри программы находится адрес функции CreateThread. Далее берешь IDA, загружаешь файл переходишь по адресу 6F8702DCh. Мы окажемся внутри таблицы адресов импорта и в ее пределах ищещь адрес нужной тебе функции, переставлешь байтики и заменяешь байты инструкции.
А ну тоже самое можно сделать и в Olly, также Go to 6F8702DCh, ищещь нужное имя функции и правишь инструкию вызова. На самом деле знания таблицы импорта тебе здесь и не нужны.