3. Определяем расположение таблицы импорта, выводим информацию об используемых DLL.
mz_head = (IMAGE_DOS_HEADER *)fBeg;
(DWORD)pe_head = (DWORD)fBeg + peOffset + sizeof(DWORD);
(DWORD)pe_opt_head = (DWORD)pe_head + sizeof(IMAGE_FILE_HEADER);
//Определяем расположение таблицы импорта в секции импорта...
DWORD ImportRVA = pe_opt_head->
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
int sect_num = -1;
//Ищем секцию с таблицей импорта...
(DWORD)sect = (DWORD)pe_opt_head + sizeof(IMAGE_OPTIONAL_HEADER);
int i;
for ( i=0; iNumberOfSections; i++)
{
if ( ImportRVA < sect->VirtualAddress )
{
sect--;
sect_num=i-1;
break;
}
sect++;
}
if (sect_num == -1)
{
Log->Lines->Add("Данная программа не использует динамические библиотеки!");
UnmapViewOfFile(fBeg);CloseHandle(fMap);
return;
}
sect++;
DWORD AfterImportSecBeg = (DWORD)fBeg + sect->PointerToRawData;
sect--;
//Получаем файловый указатель на раздел c таблицей импорта.
LPVOID ImportSecBeg;
(DWORD)ImportSecBeg = (DWORD)fBeg + sect->PointerToRawData;
//Вычисляем смещение таблицы импорта в секции
//импорта относительно ее начала (секции).
LPVOID ImportTable;
(DWORD)ImportTable = ImportRVA - sect->VirtualAddress;
(DWORD)ImportTable = (DWORD)ImportSecBeg
+ (DWORD)ImportTable;
IMAGE_IMPORT_DESCRIPTOR *DLLInfo = (IMAGE_IMPORT_DESCRIPTOR *)ImportTable;
LPVOID DLLName;
DWORD DLLCounter = 0;
//Выводим информацию об используемых DLL
while (DLLInfo->Name != NULL)
{
DLLCounter++;
(DWORD)DLLName = (DWORD)DLLInfo->Name - sect->VirtualAddress;
(DWORD)DLLName = (DWORD)ImportSecBeg + (DWORD)DLLName;
Log->Lines->Add(IntToStr(DLLCounter)+"->"+(LPSTR)DLLName);
Application->ProcessMessages();
DLLInfo++;
}
Log->Lines->Add("Всего используется "+IntToStr(DLLCounter) + " библиотек.");
4. Определяем, имеется ли в файле достаточно свободного места для размещения новой таблицы импорта.
//Вычисляем размер новой таблицы импорта:
//Суммируем количество уже используемых DLL + наша DLL + zero запись.
DWORD NewImportTableSize = sizeof(IMAGE_IMPORT_DESCRIPTOR)*(DLLCounter+2);
char dllName[] = "azx";
NewImportTableSize += strlen(dllName)+1;
//Получаем файловый указатель на конец секции импорта.
LPVOID pos;
(DWORD)pos = AfterImportSecBeg-1;
DWORD maxFree = 0;
DWORD prevPtr;
LPVOID FreePtr = NULL;
//Ищем максимальный кусок свободного места в секции...
while ( pos >= ImportSecBeg )
{
if ( *(BYTE *)pos == 0x00 )
{
prevPtr = (DWORD)pos;
while (*(BYTE *)pos == 0x00)
(DWORD)pos -= 1;
if ( ((DWORD)prevPtr - (DWORD)pos) > maxFree )
{
maxFree = ((DWORD)prevPtr - (DWORD)pos);
(DWORD)FreePtr = (DWORD)pos + 1;
}
}
(DWORD)pos -= 1;
}
//Модифицируем полученный указатель на свободный блок, т.к.
//он может указывать на завершающий нулевой DWORD
//какой-либо структуры
(LPDWORD)FreePtr +=1;
maxFree -=4;
//Проверяем объем свободного места
if ( maxFree < NewImportTableSize )
{
Log->Lines->Add("Недостаточно свободного места в таблице импорта \
для занесения информации об дополнительной библиотеке.");
UnmapViewOfFile(fBeg);
CloseHandle(fMap);
return;
}
else
Log->Lines->Add("Достаточно свободного \
места для занесения дополнительной информации.");
Application->ProcessMessages();
5. Финальная часть: Создаем в файле новую таблицу импорта и структуру IMAGE_IMPORT_BY_NAME. Записываем в файл строки с именем нашей библиотеки и импортируемой функции. Вычисляем все необходимые адреса, заносим их в структуры IMAGE_IMPORT_DESCRIPTOR, IMAGE_IMPORT_BY_NAME. Заносим в заголовок новый адрес таблицы импорта.
//1. Копируем старую таблицу импорта в новое место
memcpy(FreePtr, ImportTable, sizeof(IMAGE_IMPORT_DESCRIPTOR)*DLLCounter);
//2.1 Сохраняем строку с именем нашей DLL в старой таблице импорта
//(для экономии места)
memcpy(ImportTable, OUR_DLL_NAME, strlen(OUR_DLL_NAME));
LPDWORD zeroPtr;
(DWORD)zeroPtr = (DWORD)ImportTable + strlen(OUR_DLL_NAME);
//2.2 Сохраняем структуру IMAGE_IMPORT_BY_NAME в старой таблице импорта.
//(так же для экономии места)
IMAGE_IMPORT_BY_NAME myName;
myName.Hint = 0x00;
myName.Name[0] = 0x00;
WORD Hint = 0;
char myFuncName[] = OUR_FUNC_NAME;
hackRec patch;
patch.ZeroDword = NULL;
patch.IAT = ImportRVA + strlen(OUR_DLL_NAME) + sizeof(hackRec);
patch.IATEnd = NULL;
DWORD IIBN_Table;
memcpy(zeroPtr, &patch, sizeof(patch)); (DWORD)zeroPtr += sizeof(patch);
memcpy(zeroPtr, &Hint, sizeof(WORD)); (DWORD)zeroPtr += sizeof(WORD);
memcpy(zeroPtr, myFuncName, strlen(myFuncName)+1 );
(DWORD)zeroPtr += strlen(myFuncName)+1;
memcpy(zeroPtr, &myName, sizeof(IMAGE_IMPORT_BY_NAME) );
//2.3. Заполняем структуру IMAGE_IMPORT_DESCRIPTOR данными об нашей DLL
IMAGE_IMPORT_DESCRIPTOR myDLL;
//Вычисляем указатель на нашу структуру IMAGE_IMPORT_BY_NAME:
//это адрес начала старой таблицы импорта + длинна строки с именем
//нашей DLL + нулевой DWORD
IIBN_Table = ImportRVA + strlen( OUR_DLL_NAME ) + sizeof(DWORD);
//Указатель на таблицу Characteristics
myDLL.Characteristics = IIBN_Table;
myDLL.TimeDateStamp = NULL;
myDLL.ForwarderChain = NULL;
//Записываем адрес строки с именем файла нашей DLL
myDLL.Name = ImportRVA;
//Указатель на таблицу FirstThunk
myDLL.FirstThunk = IIBN_Table;
//Записываем в новую таблицу импорта запись о нашей DLL
LPVOID OldFreePtr = FreePtr;
(DWORD)FreePtr +=sizeof(IMAGE_IMPORT_DESCRIPTOR)*DLLCounter;
memcpy(FreePtr, &myDLL, sizeof(IMAGE_IMPORT_DESCRIPTOR));
//Создаем "финальную" нулевую запись со всеми полями равными нулю
myDLL.Characteristics = NULL;
myDLL.TimeDateStamp = NULL;
myDLL.ForwarderChain = NULL;
myDLL.Name = NULL;
myDLL.FirstThunk = NULL;
//И записываем её в конец новой таблицы импорта.
(DWORD)FreePtr +=sizeof(IMAGE_IMPORT_DESCRIPTOR)*DLLCounter;
memcpy(FreePtr, &myDLL, sizeof(IMAGE_IMPORT_DESCRIPTOR));
//3. Устанавливаем указатель на нашу таблицу импорта.
// Вычисляем RVA нашей таблицы
DWORD NewImportTableRVA = (DWORD)OldFreePtr - (DWORD)ImportSecBeg +
sect->VirtualAddress;
// Заносим его в DataDirectory
pe_opt_head->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress =
NewImportTableRVA;
pe_opt_head->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size =
(DLLCounter + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
UnmapViewOfFile(fBeg);
CloseHandle(fMap);
Вывод
Данная методика позволяет внедрять свою DLL библиотеку в программы, имеющие достаточно свободного места в секции с таблицей импорта. Приведенная программа может быть доработана в следующих направлениях:
Создание таблицы импорта в другой секции (если в секции с оригинальной таблицей не хватает места)
Создание новой секции и хранение новой таблицы импорта в ней.
Отдельное слово стоит сказать об .exe файлах, входящих в стандартную поставку Windows(таких как calc.exe, paint.exe, wordpad.exe, etc.). У них таблица импорта продублирована в начале файла, между MZ- и PE- заголовками, поэтому при модификации таких файлов необходимо в соответсвующих записях в DataDirectory обнулить адреса на эти таблицы (подробнее см. файл winnt.h, раздел Directory Entries).
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.bugtraq.ru/
... ) ФАКУЛЬТЕТ ЭЛЕКТРОНИКИ И ПРИБОРОСТРОЕНИЯ КАФЕДРА КЭС группа Э-92 ДАТА ЗАЩИТЫ апреля 1997 г. Отзыв на дипломную работу студента гр.Э-92 Сорокина Ю.В. “Разработка программы контроллера автоматически связываемых объектов для управления конструкторской документацией в среде Windows 95/NT”. Широкое использование вычислительной техники в народном хозяйстве требует увеличения производства и ...
... всего пароля. Кроме того, в каждом случае используется свой запрос сервера. Поэтому на определение паролей по Sniff-файлу потребуется значительно больше времени. Первой программой, выполняющей восстановление паролей Windows NT, была L0phtCrack (сегодняшнее название - LC5). Авторами L0phtCrack являются Peiter Mudge Zatko и Chris Wysopal из фирмы L0pht Heavy Industries, Inc. (сейчас @stake, Inc.). ...
... технология Single Worldwide Binary) — можно вводить текст на любом языке и запускать версию приложений Win32 для любого языка, используя соответствующую версию операционной системы Windows XP. + + Многоязычный пользовательский интерфейс — можно менять язык пользовательского интерфейса, чтобы работать с локализованными диалоговыми окнами, меню, файлами справки, словарями, средствами проверки ...
... от традиционных локальных сетей к сочетанию сетей интранет и экстранет с Интернетом, в результате чего особенно актуальной стала задача повышения безопасности систем. Для обеспечения безопасности вычислительной среды операционная система Windows Server 2003 предоставляет множество новых средств, а также совершенствует средства, впервые появившиеся в операционной системе Windows 2000 Server. ...
0 комментариев