Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #70, СЕНТЯБРЬ 2006 г.

В прятки с мистером Бондом

Андрей Семенюченко

Спецвыпуск: Хакер, номер #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;

Назад на стр. 070-046-4  Содержание  Вперед на стр. 070-046-6