Инфицирование PE-программ от Quark и Quantum [VLAD] (Вольный перевод - (c) DrMad, 1998-99) Переносимый формат (PE) используется в Win32, Windows NT и Win95, что делает их очень популярными и, похоже, сделает их доминирующей формой исполняемых программ в будущем. Заголовок NE, который использовался в Windows 3.11, совершенно другой по отношению к PE-заголовку, и их нельзя путать. Никакая из технологий, описанных в этом документе, не тестировалась под Windows NT, потому что никто из вирмеров (которых мы знаем) не имеет к ней доступа. В конце этого документа размещена копия PE-формата, которой не легко следовать, но доступны лишь общеизвестные ссылки. Turbo Debugger 32 (TD) - это отладчик, который использовался при создании этого текста, но SoftIce'95 тоже пойдет. Обращение к Windows 95 API -------------------------- "Нормальные" приложения обращаются к Win95 API при помощи использования таблицы импорта. Имя каждого компонета API, к которому приложение хочет обратиться, помещается в таблицу импорта. Когда приложение загружено, то данные, необходимые для вызова API помещаются в таблицу импорта. Как было объяснено в введении в Win95 (сходите и посмотрите), мы не можем модифицировать эту таблицу из за Майкрософтовской предусмотрительности. Простейшее решение этой проблемы состоит в том, чтобы вызывать kernel напрямую. Мы должны полностью обозреть вызывающую структуру Win95 и обращаться прямо в точку входа dll. Для того, чтобы получить обработчик dll/exe (называемых модулем), мы можем использовать обращение к API-функции GetModuleHandle, и не существуют еще функции для получения доступа к точке входа в модуль - включая функцию для взятия адреса API, а именно GetProcAddress. Но это сильно усложняет проблему курицы и яйца. Как мне обращаться к API, если я еще ен могу обращаться к API. Решение заключается в том, чтобы вызывать Win95 API, про которые мы знаем, что они размещаются в памяти - это API из KERNEL32.DLL - посредством обращения к адресу, по которому они всегда размещены. Немножко кода ------------- Обращение к API "нормальными" программами выглядит так: call ИМЯФУНКЦИИAPI например call CreateFileA Этот вызов ассемблируется так: db 9ah ; вызов dd ???? ; смещение в таблице переходов Код в таблице переходов выглядит так: jmp far [смещение в таблице импорта] Строка в таблице импорта заполняется адресом диспетчера функции для этой API-шки. Этот адрес доступен при помощи GetProcAddress. Диспетчер функции выглядит так: push Номер функции call Точка входа в модуль Существуют API-функции для получения точки входа любого именованного модуля, но нет системного доступа к номеру функции. Если мы обращаемся к функциям KERNEL32.DLL (которой принадлежат все функции, пригодные для инфицирования программ), тогда нам не нужно ничего более, кроме самого вызова. Мы просто помещаем номер функции в стек и обращаемся к точке входа в модуль. Проблемы -------- При завершении вируса Bizatch мы протестировали много систем. После долгих экспериментов мы пришли к выводу, что модуль KERNEL32 располагается в постоянном месте памяти - как мы и предсказывали - но это место различно для "Июньской бета-версии" и "Финального августовского релиза", который пришлось тестировать отдельно. Более того, одна функция (функция получения текущего времени/даты) имела различные порядковые номера в Июньском и Августовском релизах. Чтобы компенсировать это, я добавил код, который проверяет - находится ли KERNEL в одной из двух возможных позиций, если же KERNEL вообще не найден, то вирус просто не работает и отдает управление носителю. Адреса и номера функций ----------------------- Для Июньского релиза KERNEL располагается по адресу 0BFF93B95h, а для Августовского - по адресу 0BFF93C1Dh. Функция Июнь Август -------------------------------------------------- GetCurrentDir BFF77744 BFF77744 SetCurrentDir BFF7771D BFF7771D GetTime BFF9D0B6 BFF9D14E MessageBox BFF638D9 BFF638D9 FindFile BFF77893 BFF77893 FindNext BFF778CB BFF778CB CreateFile BFF77817 BFF77817 SetFilePointer BFF76FA0 BFF76FA0 ReadFile BFF75806 BFF75806 WriteFile BFF7580D BFF7580D CloseFile BFF7BC72 BFF7BC72 С исользованием отладчика типа Turbo Debugger 32bit из Tasm 4.0 могут быть найдены другие функции. Соглашения по вызову -------------------- Windows 95 написан на С++ и Ассемблере, в основном на С++. Но хотя Си-шные соглашения кажутся гораздо удобней для реализации, Майкрософт не использует их. Все Win95 API вызываются по правилам языка Паскаль. Например, вот пример API из help-файла для Visual C++: FARPROC GetProcAddress( HMODULE hModule, // хэндл модуля LPCSTR lpszProc // имя функции ); Сначала можно подумать, что все что вам нужно сделать - это поместить в стек хэндл следом за указателем на имя функции и обратиться к API - но нет. В соответствии с Паскалевскими соглашениями по вызовам, параметры должны помещаться в стек в обратном порядке: push offset lpszProc push dword ptr [hModule] call GetProcAddress Используя отладчик типа Turbo Debugger 32bit мы можем протрассировать обращение (по шагам) и проследовать до вызова KERNELа, как установлено ранее. Это позволит нам получить номер функции и мы можем добраться до таблицы импорта. Инфицирование PE-формата ------------------------ Поиск начала действительного РЕ-заголовка аналогичен применяемому для NE-файлов, проверкой ДОСовского поля Relocations на больше 40h и переходом на адрес, указанный двойным словом 3Ch. Если заголовок начинается с 'NE', то это программа для Windows 3.11, если 'PE', то это программа для Win32/WinNT/Win95. Внутри PE-заголовка имеется "таблица объектов", которая является наиболее важной особенностью формата с точки зрения программирования вирусов. Для добавления кода к носителю и переназначения начала управления на вирус необходимо добавить еще одно вхождение в "таблицу объектов". К счастью, Майкрософт, оьуянный идеей о выравнивании всего до 32-битной границы, так что в большинстве случаев должно быть место для дополнительного вхождения в пустом пространстве, что означает чт онет необходимости перемещать какие-либо таблицы. Обзор инфицирования PE-программ: Найдите смещение в файле для PE-заголовка Прочитайте достаточную часть PE-заголовка для расчета полного размера Прочитайте весь PE-заголовок и таблицу объектов Добавьте новый объект к таблице объектов Установите "Точку входа RVA" для нового объекта Припишите вирус к программе в рассчитанном физическом местоположении Запишите PE-заголовок назад в файл Чтобы найти таблицу объектов: Переменная "Размер заголовка" (не совпадающий с "Размером Заголовка в NT") - это размер ДОС-заголовка, РЕ-заголовка и таблицы объектов, совместно. Для того, чтобы прочитать таблицу объектов, прочитайте от начала файла HeaderSize байтов. Таблица объектов непосредственно следует за NT-заголовком. Величина "NTheadersize" показывает, как много байтов следует за полем 'flags'. Для того, чтобы получить смещение таблицы об ёектов, возьмите NTheaderSize и сложите со смещением поля флагов (24). Добавление объекта: Возьмите "количество объектов" и умножьте его на 5*8 (размер поля в таблице объектов). Это даст смещение пустого пространства для нового поля в таблице объектов. Содержимое для нового поля таблицы объектов должно быть вычислено с использованием информации для программы-носителя. RVA = ((prev RVA + prev Virtual Size)/OBJ Alignment+1) *OBJ Alignment Virtual Size = ((size of virus+buffer any space)/OBJ Alignment+1) *OBJ Alignment Physical Size = (size of virus/File Alignment+1)*File Alignment Physical Offset = prev Physical Offset + prev Physical Size Object Flags = db 40h,0,0,c0h Entrypoint RVA = RVA Увеличьте "количество объектов" на 1. Запишите вирусный код по вычисленному "физическому смещению" (Physical Offset), общим количеством Physical Size байтов. Примечания ---------- Майкрософт больше не включает информацию о РЕ-заголовках в свои CD для разработчиков. Вероятно, они надеялись, что это затруднит написание вирусов для Win95. Информация, содернжащаяся в следующей статье, была выдрана из бета-версии Win32 SDK CDROM-а. Инструменты ----------- Есть много хороших книжек по низкоуровневому программированию для Windows 95. "Недокументированный Windows 95" - необыкновенно полезная книга (она посвящена в-основном взаимоотношениям DOS и Windows), к ней и на их WWW-сайте прилагаются на утилиты, бесценные для тех, кто хочет изучать инфицирование для Win95. |