В прятки с мистером Бондом Андрей Семенюченко Спецвыпуск: Хакер, номер #070, стр. 070-046-5 Использование таблиц импорта/экспорта является предпочтительным, поскольку не приходится писать на ассемблере и использовать команду JUMP, зависящую от процессора. Единственное, что нам нужно знать, — это описание PE-заголовка и структура раздела импорта. Если коротко, то таблица импорта содержит списки адресов функций, импортируемых из различных dll. Данные адреса попадают в таблицу после загрузки в память исполняемого файла. Чтобы заменить определенную функцию, надо лишь изменить ее адрес в разделе импорта на адрес нашей функции. Нужно заметить, что наша функция должна полностью совпадать с той функцией, которую мы хотим заменить, то есть все параметры и возвращаемое значение должны совпадать. Рассмотрим пример по замене адреса функции завершения работы системы ExitWindowsEx в таблице импорта на адрес нашей функции: // Определим переменную, в которую будет записан адрес ExitWindowsEx DWORD ExitW_Addr; // Главная dll-функция содержит вызов нужной нам функции по замене адреса в таблице импорта Substitute(). Она будет вызвана, поскольку, когда система подключает dll к какому-либо процессу, сначала вызывается главная dll и выполняет то, что у нее находится в DLL_PROCESS_ATTACH. BOOL APIENTRY DllMain(HANDLE hm, DWORD my_f, LPVOID lpcd) { if(my_f == DLL_PROCESS_ATTACH) Substitute(); return TRUE; } // А вот описание уже знакомой функции Substitute(), которая ищет в таблице импорта нужный адрес(.idata) и меняет его на адрес нашей функции. void Substitute (void) { // Стандартные структуры описания PE-заголовка BYTE *pimage = (BYTE*)GetModuleHandle(NULL); BYTE *pidata; IMAGE_DOS_HEADER *imdh; IMAGE_OPTIONAL_HEADER *imoh; IMAGE_SECTION_HEADER *imsh; IMAGE_IMPORT_DESCRIPTOR *imid; DWORD *imsd; // Получим указатели на стандартные структуры PE-заголовка imdh = (IMAGE_DOS_HEADER*)pimage; imoh = (IMAGE_OPTIONAL_HEADER*)(pimage + imdh->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER)); imsh = (IMAGE_SECTION_HEADER*)((BYTE*)imoh + sizeof(IMAGE_OPTIONAL_HEADER)); //Проверка на наличие у программы PE-заголовка if (imdh->e_magic != 0x5A4D) { printf("Это не PE-заголовок"); return -1; } //Ищем секцию .idata for(int i=0; i<16; i++) if(strcmp((char*)((imsh+ i)->Name) , ".idata") == 0) break; if(i==16) { printf("Невозможно найти секцию .idata"); return -1; } // Получаем адрес секции .idata imid = (IMAGE_IMPORT_DESCRIPTOR*)(pimage + (imsh +i)->VirtualAddress ); // Получаем абсолютный адрес функции для перехвата ExitW_Addr = (DWORD)GetProcAddress( GetModuleHandle("user32.dll"), "ExitWindowsEx"); if(ExitW_Addr == 0) { printf(NULL, "Невозможно получить ExitW_Addr"); return -1; } // Поскольку ExitWindowsEx описана в user32.dll, будем искать соответствие для этой библиотеки while(imid->Name) { if(strcmp((char*)(pimage + imid->Name), "USER32.dll") ==0 ) break; |