Реферат: Компьютерные вирусы
Следующий способ заражения файлов – метод переноса – по всей видимости, является самым совершенным из всех перечисленных. Вирус размножается следующим образом: при запуске инфицируемой программы тело вируса из нее считывается в память. Затем ведется поиск неинфицированной программы. В память считывается ее начало, по длине равную телу вируса. На это место записывается тело вируса. Начало программы из памяти дописывается в конец файла. Отсюда название метода – «метод переноса». После того, как вирус инфицировал один или несколько файлов, он приступает к исполнению программы, из которой запустился. Для этого он считывает начало инфицированной программы, сохраненное в конце файла, и записывает его в начало файла, восстанавливая работоспособность программы. Затем вирус удаляет код начала программы из конца файла, восстанавливая оригинальную длину файла, и исполняет программу. После завершения программы вирус вновь записывает свой код в начало файла, а оригинальное начало программы - в конец. Этим методом могут быть инфицированы даже антивирусы, которые проверяют свой код на целостность, так как запускаемая вирусом программа имеет в точности такой же код, как и до инфицирования.
Вирусы под Windows 9x.
Формат Portable Executable используется Win 32, Windows NT , Windows 95, Windows 98, что делает его очень популярным, и в будущем, возможно он станет доминирующим форматом ЕХЕ. Этот формат значительно отличается от NE – executable, используемого в Windows 3.11.
Вызов Windows API.
Обычные приложения вызывают Windows API (Application Program Interface) используя таблицу импортируемых имен. Когда приложение загружено, данные, необходимые для вызова API, заносятся в эту таблицу. В Windows 9x, благодаря предусмотрительности фирмы – производителя Microsoft, модифицировать таблицу импортируемых имен невозможно. Это проблема решается непосредственным вызовом KERNEL32. То есть необходимо полностью игнорировать структуру вызова и перейти непосредственно на точку входа DLL.
Чтобы получить описатель (Handle) DLL/ЕХЕ, можно использовать вызов АРI GetModuleHandle или другие функции для получения точек входа модуля, включая функцию получения адреса API GetProcAddress.
Как вызывать API, имея возможность вызывать его и в то же время такой возможности не имея? Ответ: вызывать API, расположение которого в памяти известно – это API в файле KERNEL32.DLL, он находится по постоянному адресу.
Вызов API приложениями выглядит приблизительно так:
сall API_FUNCTION_NAME
например:
call CreateFileA
После компиляции этот вызов выглядит так:
db 9Ah ; инструкция call
dd ???? ;смещение в таблице переходов
Код в таблице переходов похож на такой:
jmp far [offset into import table]
Смещение в таблице импортируемых имен содержит адрес диспетчера для данной функции API. Этот адрес можно получить с помощью GetProcAddress API. Диспетчер функций выглядит так:
push function value
call Module Entrypoint
Зная точки входа, можно вызывать их напрямую, минуя таблицу этого модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стандартной точке на вызовы непосредственно функций. Просто сохраняем в стеке значение функции и вызываем точку входа в модуль.
Модуль KERNEL32.DLL располагается в памяти статически – именно так и предполагалось. Но конкретное место его расположения в разных версиях Windows 9x отличается. Это было проверено. Оказалось, что одна функция (получение времени/даты) отличается номером. Для компенсации этих различий добавлена проверка двух различных мест на наличие KERNEL32.DLL. Но если KERNEL32.DLL все-таки не найден, вирус возвращает управление программе-носителю.
Адреса и номера функции.
Для June Test Release KERNEL32.DLL находится по адресу 0BFF93B95h, для August Release – по адресу 0BFF93C1Dh. Можно найти другие значения функции, используя 32-битный отладчик. В таблице 1 приведены адреса функций, которые нужны для работы вируса.
Таблица 1. Адреса некоторых функций KERNEL32.DLL
Функция |
Адрес в June Test Release |
Адрес в August Test Release |
GetCurrentDir | BFF77744h | BFF77744h |
SetCurrentDir | BFF7771Dh | BFF7771Dh |
GetTime | BFF9D0B6h | BFF9D14Eh |
MessageBox | BFF638D9h | BFF638D9h |
FindFile | BFF77893h | BFF77893h |
FindNext | BFF778CBh | BFF778CBh |
CreateFile | BFF77817h | BFF77817h |
SetFilePointer | BFF76FA0h | BFF76FA0h |
ReadFile | BFF75806h | BFF75806h |
WriteFile | BFF7580Dh | BFF7580Dh |
CloseFile | BFF7BC72h | BFF7BC72h |
Соглашения о вызовах.
Windows 9x написан на языках С++ (в основном) и Assembler. И, хотя соглашения о вызовах просты для применения, Microsoft их не использует. Все АРI под Windows 9x используют Pascal Calling Convention. Пример – АРI, описанный в файлах справки Visual C++:
FARPROC GetProcAddres (
HMODULE hModule, // описатель DLL-модуля
LPCSTR lpszProc // имя функции
);
На первый взгляд кажется, что достаточно лишь сохранить в стеке описатель DLL-модуля (он стоит перед указателем на имя функции) и вызвать API. Но это не так. Параметры, согласно Pascal Calling Convention, должны быть сохранены в стеке в обратном порядке:
Push offset lpszProc
Push dword ptr [hModule]
Call GetProcAddress
Используя 32-битный отладчик, можно оттрасировать вызов и найти вызов KERNEL32.DLL для каждого конкретного случая. Это позволит получить номер функции и обойтись без необходимой для вызова таблицы импортируемых имен.
Заражение файлов формата PE – execuatable.
Определение положения начала РЕ – заголовка происходит аналогично поиску начала NE – заголовка. Если смещение таблицы настройки адресов (поле 18h) в заголовке ЕХЕ – файла 40h или больше, то по смещению 3Ch находится смещение PE – execuatable заголовка. Сигнатура PE – execuatable («РЕ») находится, как и у NE – execuatable ЕХЕ – файла, в начале нового заголовка.
Внутри PE – заголовка находится таблица объектов. Ее формат наиболее важен по сравнению с прочими. Для добавления вирусного кода в носитель и перехвата вирусом управления необходимо добавить элемент в таблицу объектов.
Основные действия заражения PE – execuatable файла:
1. Найти смещение заголовка PE – execuatable в файле.
2. Считать достаточное количество информации из заголовка для вычисления его полного размера.
3. Считать весь PE – заголовок и таблицу объектов.
4. Добавить новый объект в таблицу объектов.
5. Установить точку входа RVA на новый объект.
6. Дописать вирус к файлу по вычисленному физическому смещению.
7. Записать измененный РЕ – заголовок в файл.
Для определения расположения таблицы объектов следует воспользоваться значением переменной «HeaderSize» (не путать с «NT headersize»), которая содержит совместный размер заголовков DOS, PE и таблицы объектов.
Для чтения таблицы объектов необходимо считать HeaderSize байт от начала файла.
Таблица объектов расположена непосредственно за NT – заголовком. Значение «NTheadersize» показывает количество байт, следующих за полем «flags». Итак, для определения смещения таблицы объектов нужно получить NТheadersize и добавить размер поля флагов (24).
Добавление объекта: получив количество объектов, умножить его на 40 (размер элемента таблицы объектов). Таким образом определяется смещение, по которому будет расположен вирус.
Данные для элемента таблицы объектов должны быть вычислены с использованием информации в предыдущем элементе (элементе носителя).
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, 2, 3, 4, 5, 6, 7, 8